1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.message.token;
21
22 import java.security.Principal;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.Map.Entry;
27
28 import javax.xml.namespace.QName;
29
30 import org.apache.wss4j.dom.WSConstants;
31 import org.apache.wss4j.common.ext.WSSecurityException;
32 import org.apache.wss4j.common.bsp.BSPEnforcer;
33 import org.apache.wss4j.common.derivedKey.ConversationConstants;
34 import org.apache.wss4j.common.derivedKey.DerivedKeyUtils;
35 import org.apache.wss4j.common.principal.WSDerivedKeyTokenPrincipal;
36 import org.apache.wss4j.common.token.SecurityTokenReference;
37 import org.apache.wss4j.common.util.DOM2Writer;
38 import org.apache.wss4j.common.util.XMLUtils;
39 import org.apache.wss4j.dom.util.WSSecurityUtil;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.Node;
43 import org.w3c.dom.Text;
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public class DerivedKeyToken {
58
59 private static final org.slf4j.Logger LOG =
60 org.slf4j.LoggerFactory.getLogger(DerivedKeyToken.class);
61
62
63 private Element element;
64 private Element elementSecurityTokenReference;
65 private Element elementProperties;
66 private Element elementGeneration;
67 private Element elementOffset;
68 private Element elementLength;
69 private Element elementLabel;
70 private Element elementNonce;
71 private int length = 32;
72 private int offset = 0;
73 private int generation = -1;
74
75 private String ns;
76
77 private final BSPEnforcer bspEnforcer;
78
79
80
81
82
83
84 public DerivedKeyToken(Document doc) throws WSSecurityException {
85 this(ConversationConstants.DEFAULT_VERSION, doc);
86 }
87
88
89
90
91
92
93 public DerivedKeyToken(int version, Document doc) throws WSSecurityException {
94 LOG.debug("DerivedKeyToken: created");
95
96 ns = ConversationConstants.getWSCNs(version);
97 element =
98 doc.createElementNS(ns, ConversationConstants.WSC_PREFIX + ":"
99 + ConversationConstants.DERIVED_KEY_TOKEN_LN);
100 XMLUtils.setNamespace(element, ns, ConversationConstants.WSC_PREFIX);
101 bspEnforcer = new BSPEnforcer();
102 }
103
104
105
106
107
108
109
110
111 public DerivedKeyToken(Element elem, BSPEnforcer bspEnforcer) throws WSSecurityException {
112 LOG.debug("DerivedKeyToken: created : element constructor");
113 element = elem;
114 this.bspEnforcer = bspEnforcer;
115 QName el = new QName(element.getNamespaceURI(), element.getLocalName());
116
117 if (!(el.equals(ConversationConstants.DERIVED_KEY_TOKEN_QNAME_05_02)
118 || el.equals(ConversationConstants.DERIVED_KEY_TOKEN_QNAME_05_12))) {
119 throw new WSSecurityException(
120 WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN
121 );
122 }
123 elementSecurityTokenReference =
124 XMLUtils.getDirectChildElement(
125 element,
126 ConversationConstants.SECURITY_TOKEN_REFERENCE_LN,
127 WSConstants.WSSE_NS
128 );
129
130 ns = el.getNamespaceURI();
131
132 elementProperties =
133 XMLUtils.getDirectChildElement(
134 element, ConversationConstants.PROPERTIES_LN, ns
135 );
136 elementGeneration =
137 XMLUtils.getDirectChildElement(
138 element, ConversationConstants.GENERATION_LN, ns
139 );
140 elementOffset =
141 XMLUtils.getDirectChildElement(
142 element, ConversationConstants.OFFSET_LN, ns
143 );
144 elementLength =
145 XMLUtils.getDirectChildElement(
146 element, ConversationConstants.LENGTH_LN, ns
147 );
148 elementLabel =
149 XMLUtils.getDirectChildElement(
150 element, ConversationConstants.LABEL_LN, ns
151 );
152 elementNonce =
153 XMLUtils.getDirectChildElement(
154 element, ConversationConstants.NONCE_LN, ns
155 );
156
157 if (elementLength != null) {
158 Text text = getFirstNode(elementLength);
159 if (text != null) {
160 try {
161 length = Integer.parseInt(text.getData());
162 } catch (NumberFormatException ex) {
163 throw new WSSecurityException(
164 WSSecurityException.ErrorCode.FAILURE, ex, "decoding.general"
165 );
166 }
167 }
168 }
169
170 if (elementOffset != null) {
171 Text text = getFirstNode(elementOffset);
172 if (text != null) {
173 try {
174 offset = Integer.parseInt(text.getData());
175 } catch (NumberFormatException ex) {
176 throw new WSSecurityException(
177 WSSecurityException.ErrorCode.FAILURE, ex, "decoding.general"
178 );
179 }
180 }
181 }
182
183 if (elementGeneration != null) {
184 Text text = getFirstNode(elementGeneration);
185 if (text != null) {
186 try {
187 generation = Integer.parseInt(text.getData());
188 } catch (NumberFormatException ex) {
189 throw new WSSecurityException(
190 WSSecurityException.ErrorCode.FAILURE, ex, "decoding.general"
191 );
192 }
193 }
194 }
195 }
196
197
198
199
200
201 public void addWSUNamespace() {
202 element.setAttributeNS(XMLUtils.XMLNS_NS, "xmlns:" + WSConstants.WSU_PREFIX, WSConstants.WSU_NS);
203 }
204
205
206
207
208
209
210
211 public void setSecurityTokenReference(SecurityTokenReference ref) {
212 elementSecurityTokenReference = ref.getElement();
213 WSSecurityUtil.prependChildElement(element, ref.getElement());
214 }
215
216 public void setSecurityTokenReference(Element elem) {
217 elementSecurityTokenReference = elem;
218 WSSecurityUtil.prependChildElement(element, elem);
219 }
220
221
222
223
224
225
226
227 public SecurityTokenReference getSecurityTokenReference() throws WSSecurityException {
228 if (elementSecurityTokenReference != null) {
229 return new SecurityTokenReference(elementSecurityTokenReference, bspEnforcer);
230 }
231 return null;
232 }
233
234
235
236
237
238
239 public Element getSecurityTokenReferenceElement() {
240 return elementSecurityTokenReference;
241 }
242
243
244
245
246
247
248
249
250 private void addProperty(String propName, String propValue) {
251 if (elementProperties == null) {
252 elementProperties =
253 element.getOwnerDocument().createElementNS(
254 ns, ConversationConstants.WSC_PREFIX + ":" + ConversationConstants.PROPERTIES_LN
255 );
256 element.appendChild(elementProperties);
257 }
258 Element tempElement =
259 element.getOwnerDocument().createElementNS(ns, ConversationConstants.WSC_PREFIX + ":"
260 + propName);
261 tempElement.appendChild(element.getOwnerDocument().createTextNode(propValue));
262
263 elementProperties.appendChild(tempElement);
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277 public void setProperties(String name, String label, String nonce) {
278 Map<String, String> table = new HashMap<>();
279 table.put("Name", name);
280 table.put("Label", label);
281 table.put("Nonce", nonce);
282 setProperties(table);
283 }
284
285
286
287
288
289
290
291 public void setProperties(Map<String, String> properties) {
292 if (properties != null && !properties.isEmpty()) {
293 for (Entry<String, String> entry : properties.entrySet()) {
294 String propertyName = entry.getValue();
295
296
297 Element node =
298 XMLUtils.findElement(elementProperties, propertyName, ns);
299 if (node != null) {
300 Text node1 = getFirstNode(node);
301 if (node1 != null) {
302 node1.setData(properties.get(propertyName));
303 }
304 } else {
305 addProperty(propertyName, properties.get(propertyName));
306 }
307 }
308 }
309 }
310
311 public Map<String, String> getProperties() {
312 if (elementProperties != null) {
313 Map<String, String> table = new HashMap<>();
314 Node node = elementProperties.getFirstChild();
315 while (node != null) {
316 if (Node.ELEMENT_NODE == node.getNodeType()) {
317 Text text = getFirstNode((Element) node);
318 if (text != null) {
319 table.put(node.getNodeName(), text.getData());
320 }
321 }
322 node = node.getNextSibling();
323 }
324 return table;
325 }
326 return Collections.emptyMap();
327 }
328
329
330
331
332
333
334 public void setLength(int length) {
335 elementLength =
336 element.getOwnerDocument().createElementNS(
337 ns, ConversationConstants.WSC_PREFIX + ":" + ConversationConstants.LENGTH_LN
338 );
339 elementLength.appendChild(
340 element.getOwnerDocument().createTextNode(Long.toString(length))
341 );
342 element.appendChild(elementLength);
343 this.length = length;
344 }
345
346 public int getLength() {
347 return length;
348 }
349
350
351
352
353
354
355 public void setOffset(int offset) throws WSSecurityException {
356
357 if (elementGeneration == null) {
358 elementOffset =
359 element.getOwnerDocument().createElementNS(
360 ns, ConversationConstants.WSC_PREFIX + ":" + ConversationConstants.OFFSET_LN
361 );
362 elementOffset.appendChild(
363 element.getOwnerDocument().createTextNode(Integer.toString(offset))
364 );
365 element.appendChild(elementOffset);
366 } else {
367 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "offsetError");
368 }
369 this.offset = offset;
370 }
371
372 public int getOffset() {
373 return offset;
374 }
375
376
377
378
379
380
381 public void setGeneration(int generation) throws WSSecurityException {
382
383 if (elementOffset == null) {
384 elementGeneration =
385 element.getOwnerDocument().createElementNS(
386 ns, ConversationConstants.WSC_PREFIX + ":" + ConversationConstants.GENERATION_LN
387 );
388 elementGeneration.appendChild(
389 element.getOwnerDocument().createTextNode(Integer.toString(generation))
390 );
391 element.appendChild(elementGeneration);
392 } else {
393 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "offsetError");
394 }
395 this.generation = generation;
396 }
397
398 public int getGeneration() {
399 return generation;
400 }
401
402
403
404
405
406
407 public void setLabel(String label) {
408 elementLabel =
409 element.getOwnerDocument().createElementNS(
410 ns, ConversationConstants.WSC_PREFIX + ":" + ConversationConstants.LABEL_LN
411 );
412 elementLabel.appendChild(element.getOwnerDocument().createTextNode(label));
413 element.appendChild(elementLabel);
414 }
415
416
417
418
419
420
421 public void setNonce(String nonce) {
422 elementNonce =
423 element.getOwnerDocument().createElementNS(
424 ns, ConversationConstants.WSC_PREFIX + ":" + ConversationConstants.NONCE_LN
425 );
426 elementNonce.appendChild(element.getOwnerDocument().createTextNode(nonce));
427 element.appendChild(elementNonce);
428 }
429
430
431
432
433
434
435 public String getLabel() {
436 if (elementLabel != null) {
437 Text text = getFirstNode(elementLabel);
438 if (text != null) {
439 return text.getData();
440 }
441 }
442 return null;
443 }
444
445
446
447
448
449
450 public String getNonce() {
451 if (elementNonce != null) {
452 Text text = getFirstNode(elementNonce);
453 if (text != null) {
454 return text.getData();
455 }
456 }
457 return null;
458 }
459
460
461
462
463
464
465
466
467 private Text getFirstNode(Element e) {
468 Node node = e.getFirstChild();
469 return node != null && Node.TEXT_NODE == node.getNodeType() ? (Text) node : null;
470 }
471
472
473
474
475
476
477 public Element getElement() {
478 return element;
479 }
480
481
482
483
484
485
486 public String toString() {
487 return DOM2Writer.nodeToString(element);
488 }
489
490
491
492
493
494
495
496 public String getID() {
497 return element.getAttributeNS(WSConstants.WSU_NS, "Id");
498 }
499
500
501
502
503
504
505
506 public void setID(String id) {
507 element.setAttributeNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":Id", id);
508 }
509
510
511
512
513
514
515
516 public String getAlgorithm() {
517 String algo = element.getAttributeNS(ns, "Algorithm");
518 if (algo.length() == 0) {
519 return ConversationConstants.DerivationAlgorithm.P_SHA_1;
520 } else {
521 return algo;
522 }
523 }
524
525
526
527
528 public Principal createPrincipal() throws WSSecurityException {
529 WSDerivedKeyTokenPrincipal principal = new WSDerivedKeyTokenPrincipal(getID());
530 principal.setNonce(getNonce());
531 principal.setLabel(getLabel());
532 principal.setLength(getLength());
533 principal.setOffset(getOffset());
534 principal.setAlgorithm(getAlgorithm());
535
536 String basetokenId = null;
537 SecurityTokenReference securityTokenReference = getSecurityTokenReference();
538 if (securityTokenReference != null && securityTokenReference.getReference() != null) {
539 basetokenId = securityTokenReference.getReference().getURI();
540 basetokenId = XMLUtils.getIDFromReference(basetokenId);
541 } else if (securityTokenReference != null) {
542
543 basetokenId = securityTokenReference.getKeyIdentifierValue();
544 }
545 principal.setBasetokenId(basetokenId);
546
547 return principal;
548 }
549
550
551
552
553
554
555
556 public void setAlgorithm(String algo) {
557 if (algo != null) {
558 element.setAttributeNS(ns, "Algorithm", algo);
559 }
560 }
561
562
563
564
565
566
567
568 public byte[] deriveKey(int length, byte[] secret) throws WSSecurityException {
569 try {
570 byte[] nonce = org.apache.xml.security.utils.XMLUtils.decode(getNonce());
571 return DerivedKeyUtils.deriveKey(getAlgorithm(), getLabel(), length, secret, nonce, getOffset());
572 } catch (Exception e) {
573 throw new WSSecurityException(
574 WSSecurityException.ErrorCode.FAILURE, e
575 );
576 }
577 }
578
579 @Override
580 public int hashCode() {
581 int result = 17;
582 String algorithm = getAlgorithm();
583 if (algorithm != null) {
584 result = 31 * result + algorithm.hashCode();
585 }
586 try {
587 SecurityTokenReference tokenReference = getSecurityTokenReference();
588 if (tokenReference != null) {
589 result = 31 * result + tokenReference.hashCode();
590 }
591 } catch (WSSecurityException e) {
592 LOG.error(e.getMessage(), e);
593 }
594
595 Map<String, String> properties = getProperties();
596 if (!properties.isEmpty()) {
597 result = 31 * result + properties.hashCode();
598 }
599 int generation = getGeneration();
600 if (generation != -1) {
601 result = 31 * result + generation;
602 }
603 int offset = getOffset();
604 if (offset != -1) {
605 result = 31 * result + offset;
606 }
607 int length = getLength();
608 if (length != -1) {
609 result = 31 * result + length;
610 }
611 String label = getLabel();
612 if (label != null) {
613 result = 31 * result + label.hashCode();
614 }
615 String nonce = getNonce();
616 if (nonce != null) {
617 result = 31 * result + nonce.hashCode();
618 }
619
620 return result;
621 }
622
623 @Override
624 public boolean equals(Object object) {
625 if (!(object instanceof DerivedKeyToken)) {
626 return false;
627 }
628 DerivedKeyToken token = (DerivedKeyToken)object;
629 if (!compare(getAlgorithm(), token.getAlgorithm())) {
630 return false;
631 }
632 try {
633 if (getSecurityTokenReference() != null
634 && !getSecurityTokenReference().equals(token.getSecurityTokenReference())
635 || getSecurityTokenReference() == null && token.getSecurityTokenReference() != null) {
636 return false;
637 }
638 } catch (WSSecurityException e) {
639 LOG.error(e.getMessage(), e);
640 return false;
641 }
642 if (!compare(getProperties(), token.getProperties())) {
643 return false;
644 }
645 if (getGeneration() != token.getGeneration()) {
646 return false;
647 }
648 if (getOffset() != token.getOffset()) {
649 return false;
650 }
651 if (getLength() != token.getLength()) {
652 return false;
653 }
654 if (!compare(getLabel(), token.getLabel())) {
655 return false;
656 }
657 return compare(getNonce(), token.getNonce());
658 }
659
660 private boolean compare(String item1, String item2) {
661 if (item1 == null && item2 != null) {
662 return false;
663 } else if (item1 != null && !item1.equals(item2)) {
664 return false;
665 }
666 return true;
667 }
668
669 private boolean compare(Map<String, String> item1, Map<String, String> item2) {
670 if (item1 == null && item2 != null) {
671 return false;
672 } else if (item1 != null && !item1.equals(item2)) {
673 return false;
674 }
675 return true;
676 }
677 }