1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.common.token;
21
22 import java.io.IOException;
23 import java.util.Arrays;
24 import java.util.UUID;
25
26 import javax.security.auth.callback.CallbackHandler;
27 import javax.security.auth.callback.UnsupportedCallbackException;
28 import javax.xml.namespace.QName;
29
30 import org.apache.wss4j.common.WSS4JConstants;
31 import org.apache.wss4j.common.bsp.BSPEnforcer;
32 import org.apache.wss4j.common.bsp.BSPRule;
33 import org.apache.wss4j.common.ext.WSSecurityException;
34 import org.apache.wss4j.common.util.AttachmentUtils;
35 import org.apache.wss4j.common.util.DOM2Writer;
36 import org.apache.wss4j.common.util.XMLUtils;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.Node;
40 import org.w3c.dom.Text;
41
42
43
44
45 public class BinarySecurity {
46 public static final QName TOKEN_BST = new QName(WSS4JConstants.WSSE_NS, "BinarySecurityToken");
47 public static final QName TOKEN_KI = new QName(WSS4JConstants.WSSE_NS, "KeyIdentifier");
48 private static final org.slf4j.Logger LOG =
49 org.slf4j.LoggerFactory.getLogger(BinarySecurity.class);
50
51 private Element element;
52 private byte[] data;
53 private boolean storeBytesInAttachment;
54 private CallbackHandler attachmentCallbackHandler;
55
56 public CallbackHandler getAttachmentCallbackHandler() {
57 return attachmentCallbackHandler;
58 }
59
60 public void setAttachmentCallbackHandler(CallbackHandler attachmentCallbackHandler) {
61 this.attachmentCallbackHandler = attachmentCallbackHandler;
62 }
63
64
65
66
67
68
69
70 public BinarySecurity(Element elem, BSPEnforcer bspEnforcer) throws WSSecurityException {
71 element = elem;
72 QName el = new QName(element.getNamespaceURI(), element.getLocalName());
73 if (!(el.equals(TOKEN_BST) || el.equals(TOKEN_KI))) {
74 throw new WSSecurityException(
75 WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN,
76 "unhandledToken", new Object[] {el});
77 }
78 String encoding = getEncodingType();
79 if (encoding == null || encoding.length() == 0) {
80 bspEnforcer.handleBSPRule(BSPRule.R3029);
81 }
82
83 if (!WSS4JConstants.BASE64_ENCODING.equals(encoding)) {
84 bspEnforcer.handleBSPRule(BSPRule.R3030);
85 }
86
87 String valueType = getValueType();
88 if (valueType == null || valueType.length() == 0) {
89 bspEnforcer.handleBSPRule(BSPRule.R3031);
90 }
91 }
92
93
94
95
96
97
98 public BinarySecurity(Document doc) {
99 element = doc.createElementNS(WSS4JConstants.WSSE_NS, "wsse:BinarySecurityToken");
100 setEncodingType(WSS4JConstants.BASE64_ENCODING);
101 }
102
103
104
105
106
107
108 public BinarySecurity(CallbackHandler callbackHandler) throws WSSecurityException {
109 if (callbackHandler == null) {
110 LOG.debug("Trying to create a BinarySecurityToken via a null CallbackHandler");
111 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
112 }
113 TokenElementCallback[] callback = new TokenElementCallback[] {new TokenElementCallback()};
114
115 try {
116 callbackHandler.handle(callback);
117 } catch (IOException | UnsupportedCallbackException e) {
118 throw new IllegalStateException(
119 "Exception while creating a token element", e
120 );
121 }
122 element = callback[0].getTokenElement();
123 if (element == null) {
124 LOG.debug("CallbackHandler did not return a token element");
125 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
126 }
127 }
128
129
130
131
132
133 public void addWSSENamespace() {
134 XMLUtils.setNamespace(element, WSS4JConstants.WSSE_NS, WSS4JConstants.WSSE_PREFIX);
135 }
136
137
138
139
140
141 public void addWSUNamespace() {
142 element.setAttributeNS(XMLUtils.XMLNS_NS, "xmlns:" + WSS4JConstants.WSU_PREFIX, WSS4JConstants.WSU_NS);
143 }
144
145
146
147
148
149
150 public String getValueType() {
151 return element.getAttributeNS(null, "ValueType");
152 }
153
154
155
156
157
158
159 public void setValueType(String type) {
160 if (type != null) {
161 element.setAttributeNS(null, "ValueType", type);
162 }
163 }
164
165
166
167
168
169
170 public String getEncodingType() {
171 return element.getAttributeNS(null, "EncodingType");
172 }
173
174
175
176
177
178
179 public void setEncodingType(String encoding) {
180 if (encoding != null) {
181 element.setAttributeNS(null, "EncodingType", encoding);
182 }
183 }
184
185
186
187
188
189
190 public byte[] getToken() {
191 if (data != null) {
192 return data;
193 }
194 String text = XMLUtils.getElementText(element);
195 if (text == null) {
196 return new byte[0];
197 }
198
199 return org.apache.xml.security.utils.XMLUtils.decode(text);
200 }
201
202
203
204
205
206
207 public void setToken(byte[] data) throws WSSecurityException {
208 if (data == null) {
209 throw new IllegalArgumentException("data == null");
210 }
211 if (storeBytesInAttachment && attachmentCallbackHandler != null) {
212 final String attachmentId = "_" + UUID.randomUUID().toString();
213 AttachmentUtils.storeBytesInAttachment(element, element.getOwnerDocument(), attachmentId,
214 data, attachmentCallbackHandler);
215 } else {
216 Text node = getFirstNode();
217 node.setData(org.apache.xml.security.utils.XMLUtils.encodeToString(data));
218 setRawToken(data);
219 }
220 }
221
222
223
224
225 public void setRawToken(byte[] data) {
226 this.data = Arrays.copyOf(data, data.length);
227 }
228
229
230
231
232 public void encodeRawToken() {
233 if (data == null) {
234 throw new IllegalArgumentException("data == null");
235 }
236 Text node = getFirstNode();
237 node.setData(org.apache.xml.security.utils.XMLUtils.encodeToString(data));
238 }
239
240
241
242
243
244
245 private Text getFirstNode() {
246 Node node = element.getFirstChild();
247 while (node != null && Node.TEXT_NODE != node.getNodeType()) {
248 node = node.getNextSibling();
249 }
250 if (node instanceof Text) {
251 return (Text)node;
252 }
253
254
255 node = element.getFirstChild();
256 while (node != null) {
257 Node nextNode = node.getNextSibling();
258 element.removeChild(node);
259 node = nextNode;
260 }
261
262 Node textNode = element.getOwnerDocument().createTextNode("");
263 return (Text)element.appendChild(textNode);
264 }
265
266
267
268
269
270
271 public Element getElement() {
272 return element;
273 }
274
275
276
277
278
279
280 public String getID() {
281 return element.getAttributeNS(WSS4JConstants.WSU_NS, "Id");
282 }
283
284
285
286
287
288
289 public void setID(String id) {
290 element.setAttributeNS(WSS4JConstants.WSU_NS, WSS4JConstants.WSU_PREFIX + ":Id", id);
291 }
292
293
294
295
296
297
298 public String toString() {
299 return DOM2Writer.nodeToString(element);
300 }
301
302 @Override
303 public int hashCode() {
304 int result = 17;
305 byte[] token = getToken();
306 if (token != null) {
307 result = 31 * result + Arrays.hashCode(token);
308 }
309 result = 31 * result + getValueType().hashCode();
310 result = 31 * result + getEncodingType().hashCode();
311
312 return result;
313 }
314
315 @Override
316 public boolean equals(Object object) {
317 if (!(object instanceof BinarySecurity)) {
318 return false;
319 }
320 BinarySecurity binarySecurity = (BinarySecurity)object;
321
322 byte[] token = binarySecurity.getToken();
323 if (!Arrays.equals(token, getToken())) {
324 return false;
325 }
326 String valueType = binarySecurity.getValueType();
327 if (!valueType.equals(getValueType())) {
328 return false;
329 }
330 String encodingType = binarySecurity.getEncodingType();
331 return encodingType.equals(getEncodingType());
332 }
333
334 public boolean isStoreBytesInAttachment() {
335 return storeBytesInAttachment;
336 }
337
338 public void setStoreBytesInAttachment(boolean storeBytesInAttachment) {
339 this.storeBytesInAttachment = storeBytesInAttachment;
340 }
341 }