1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.ws.security.util;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.ws.security.SOAP11Constants;
24 import org.apache.ws.security.SOAP12Constants;
25 import org.apache.ws.security.SOAPConstants;
26 import org.apache.ws.security.WSConstants;
27 import org.apache.ws.security.WSSConfig;
28
29 import org.apache.ws.security.WSSecurityException;
30 import org.apache.ws.security.handler.WSHandlerConstants;
31 import org.apache.ws.security.message.token.BinarySecurity;
32 import org.apache.ws.security.message.token.X509Security;
33 import org.apache.xml.security.algorithms.JCEMapper;
34 import org.apache.xml.security.utils.Base64;
35 import org.apache.xpath.XPathAPI;
36 import org.w3c.dom.Attr;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.NamedNodeMap;
40 import org.w3c.dom.Node;
41 import org.w3c.dom.NodeList;
42 import org.w3c.dom.Text;
43
44 import javax.crypto.Cipher;
45 import javax.crypto.NoSuchPaddingException;
46 import javax.crypto.SecretKey;
47 import javax.crypto.spec.SecretKeySpec;
48 import javax.xml.namespace.QName;
49 import javax.xml.transform.TransformerException;
50 import java.security.NoSuchAlgorithmException;
51 import java.security.NoSuchProviderException;
52 import java.util.Vector;
53
54 /***
55 * WS-Security Utility methods.
56 * <p/>
57 *
58 * @author Davanum Srinivas (dims@yahoo.com).
59 */
60 public class WSSecurityUtil {
61 private static Log log = LogFactory.getLog(WSSecurityUtil.class);
62 private static boolean doDebug = false;
63
64 static {
65 doDebug = log.isDebugEnabled();
66 }
67
68 /***
69 * Returns the first WS-Security header element for a given actor.
70 * Only one WS-Security header is allowed for an actor.
71 *
72 * @param doc
73 * @param actor
74 * @return the <code>wsse:Security</code> element or
75 * <code>null</code> if not such element found
76 * @deprecated
77 * @see getSecurityHeader(
78 WSSConfig wssConfig, Document doc, String actor, SOAPConstants sc)
79 */
80 public static Element getSecurityHeader(
81 Document doc, String actor, SOAPConstants sc) {
82 return getSecurityHeader(WSSConfig.getDefaultWSConfig(), doc, actor, sc);
83 }
84
85 /***
86 * Returns the first WS-Security header element for a given actor.
87 * Only one WS-Security header is allowed for an actor.
88 *
89 * @param doc
90 * @param actor
91 * @return the <code>wsse:Security</code> element or
92 * <code>null</code> if not such element found
93 */
94 public static Element getSecurityHeader(
95 WSSConfig wssConfig, Document doc, String actor, SOAPConstants sc) {
96
97 Element soapHeaderElement =
98 (Element) getDirectChild(doc.getFirstChild(),
99 sc.getHeaderQName().getLocalPart(),
100 sc.getEnvelopeURI());
101
102 if (soapHeaderElement == null) {
103 return null;
104 }
105
106
107 NodeList list = null;
108 int len = 0;
109 if (wssConfig.getProcessNonCompliantMessages()) {
110 for (int i = 0; len == 0 && i < WSConstants.WSSE_NS_ARRAY.length; ++i) {
111 list = soapHeaderElement.getElementsByTagNameNS(WSConstants.WSSE_NS_ARRAY[i], WSConstants.WSSE_LN);
112 len = list.getLength();
113 }
114 } else {
115 list = soapHeaderElement.getElementsByTagNameNS(wssConfig.getWsseNS(), WSConstants.WSSE_LN);
116 }
117 if (list == null) {
118 return null;
119 } else {
120 len = list.getLength();
121 }
122 Element elem;
123 Attr attr;
124 String hActor;
125 for (int i = 0; i < len; i++) {
126 elem = (Element) list.item(i);
127 attr = elem.getAttributeNodeNS(sc.getEnvelopeURI(), sc.getRoleAttributeQName().getLocalPart());
128 hActor = (attr != null) ? attr.getValue() : null;
129 if (WSSecurityUtil.isActorEqual(actor, hActor)) {
130 return elem;
131 }
132 }
133 return null;
134 }
135
136 /***
137 * Compares two actor strings and returns true if these are equal.
138 * Takes care of the null length strings and uses ignore case.
139 *
140 * @param actor
141 * @param hActor
142 * @return
143 */
144 public static boolean isActorEqual(String actor, String hActor) {
145 if ((((hActor == null) || (hActor.length() == 0))
146 && ((actor == null) || (actor.length() == 0)))
147 || ((hActor != null)
148 && (actor != null)
149 && hActor.equalsIgnoreCase(actor))) {
150 return true;
151 } else {
152 return false;
153 }
154 }
155
156 /***
157 * Gets a direct child with specified localname and namespace.
158 * <p/>
159 *
160 * @param fNode the node where to start the search
161 * @param localName local name of the child to get
162 * @param namespace the namespace of the child to get
163 * @return the node or <code>null</code> if not such node found
164 */
165 public static Node getDirectChild(Node fNode,
166 String localName,
167 String namespace) {
168 for (Node currentChild = fNode.getFirstChild();
169 currentChild != null;
170 currentChild = currentChild.getNextSibling()) {
171 if (localName.equals(currentChild.getLocalName()) &&
172 namespace.equals(currentChild.getNamespaceURI())) {
173 return currentChild;
174 }
175 }
176 return null;
177 }
178
179 /***
180 * Gets a direct child with specified localname and one of the WSSE
181 * namespaces.
182 * <p/>
183 *
184 * @param fNode the node where to start the search
185 * @param localName local name of the child to get
186 * @return the node or <code>null</code> if not such node found
187 */
188 public static Node getDirectChildWSSE(Node fNode, String localName) {
189 Node child = null;
190 for (int i = 0; child == null && i < WSConstants.WSSE_NS_ARRAY.length; ++i) {
191 child = getDirectChild(fNode, localName, WSConstants.WSSE_NS_ARRAY[i]);
192 }
193 return child;
194 }
195
196 /***
197 * Gets a direct child with specified localname and one of the WSU namespaces.
198 * <p/>
199 *
200 * @param fNode the node where to start the search
201 * @param localName local name of the child to get
202 * @return the node or <code>null</code> if not such node found
203 */
204 public static Node getDirectChildWSU(Node fNode, String localName) {
205 Node child = null;
206 for (int i = 0; child == null && i < WSConstants.WSU_NS_ARRAY.length; ++i) {
207 child = getDirectChild(fNode, localName, WSConstants.WSU_NS_ARRAY[i]);
208 }
209 return child;
210 }
211
212 /***
213 * Gets the attribute value with specified localname and WSU namespace.
214 * <p/>
215 *
216 * @param element the Element which contains the attribute
217 * @param attrName local name of the attribute
218 * @param wsuNamespace the WSU namespace of the attribute to get.
219 * Pass null to try all WSU namespaces
220 */
221 public static String getAttributeValueWSU(Element element, String attrName, String wsuNamespace) {
222 if (wsuNamespace == null) {
223 String value = null;
224 for (int i = 0; (value == null || value.length() == 0) && i < WSConstants.WSU_NS_ARRAY.length; ++i) {
225 value = element.getAttributeNS(WSConstants.WSU_NS_ARRAY[i], attrName);
226 }
227 return value;
228 } else {
229 return element.getAttributeNS(wsuNamespace, attrName);
230 }
231 }
232
233 /***
234 * Gets the attribute value with specified localname and WSSE namespace.
235 * <p/>
236 *
237 * @param element the Element which contains the attribute
238 * @param attrName local name of the attribute
239 * @param wsseNamespace the WSSE namespace of the attribute to get.
240 * Pass null to try all WSSE namespaces
241 */
242 public static String getAttributeValueWSSE(Element element, String attrName, String wsseNamespace) {
243 if (wsseNamespace == null) {
244 String value = null;
245 for (int i = 0; (value == null || value.length() == 0) && i < WSConstants.WSSE_NS_ARRAY.length; ++i) {
246 value = element.getAttributeNS(WSConstants.WSSE_NS_ARRAY[i], attrName);
247 }
248 return value;
249 } else {
250 return element.getAttributeNS(wsseNamespace, attrName);
251 }
252 }
253
254 /***
255 * return the first soap "Body" element.
256 * <p/>
257 *
258 * @param doc
259 * @return the body element or <code>null</code> if document does not
260 * contain a SOAP body
261 */
262 public static Element findBodyElement(Document doc, SOAPConstants sc) {
263 Element soapBodyElement =
264 (Element) WSSecurityUtil.getDirectChild(doc.getFirstChild(),
265 sc.getBodyQName().getLocalPart(),
266 sc.getEnvelopeURI());
267 return soapBodyElement;
268 }
269
270 /***
271 * Returns the first element that matches <code>name</code> and
272 * <code>namespace</code>.
273 * <p/>
274 * This is a replacement for a XPath lookup <code>//name</code> with
275 * the given namespace. It's somewhat faster than XPath, and we do
276 * not deal with prefixes, just with the real namespace URI
277 *
278 * @param startNode Where to start the search
279 * @param name Local name of the element
280 * @param namespace Namespace URI of the element
281 * @return The found element or <code>null</code>
282 */
283 public static Node findElement(Node startNode,
284 String name,
285 String namespace) {
286
287
288
289
290
291 if (startNode == null) {
292 return null;
293 }
294 Node startParent = startNode.getParentNode();
295 Node processedNode = null;
296
297 while (startNode != null) {
298
299 if (startNode.getNodeType() == Node.ELEMENT_NODE
300 && startNode.getLocalName().equals(name)) {
301 String ns = startNode.getNamespaceURI();
302 if (ns != null && ns.equals(namespace)) {
303 return startNode;
304 }
305
306 if ((namespace == null || namespace.length() == 0)
307 && (ns == null || ns.length() == 0)) {
308 return startNode;
309 }
310 }
311 processedNode = startNode;
312 startNode = startNode.getFirstChild();
313
314
315 if (startNode == null) {
316
317 startNode = processedNode.getNextSibling();
318 }
319
320
321 while (startNode == null) {
322 processedNode = processedNode.getParentNode();
323 if (processedNode == startParent) {
324 return null;
325 }
326
327 startNode = processedNode.getNextSibling();
328 }
329 }
330 return null;
331 }
332
333 /***
334 * Returns the first element that containes an Id with value
335 * <code>uri</code> and <code>namespace</code>.
336 * <p/>
337 * This is a replacement for a XPath Id lookup with
338 * the given namespace. It's somewhat faster than XPath, and we do
339 * not deal with prefixes, just with the real namespace URI
340 *
341 * @param startNode Where to start the search
342 * @param value Value of the Id attribute
343 * @param namespace Namespace URI of the Id
344 * @return The found element or <code>null</code>
345 */
346 public static Element findElementById(Node startNode,
347 String value,
348 String namespace) {
349
350
351
352
353
354 if (startNode == null) {
355 return null;
356 }
357 Node startParent = startNode.getParentNode();
358 Node processedNode = null;
359
360 while (startNode != null) {
361
362 if (startNode.getNodeType() == Node.ELEMENT_NODE) {
363 Element se = (Element) startNode;
364 if (se.hasAttributeNS(namespace, "Id") &&
365 value.equals(se.getAttributeNS(namespace, "Id"))) {
366 return se;
367 }
368 }
369
370 processedNode = startNode;
371 startNode = startNode.getFirstChild();
372
373
374 if (startNode == null) {
375
376 startNode = processedNode.getNextSibling();
377 }
378
379
380 while (startNode == null) {
381 processedNode = processedNode.getParentNode();
382 if (processedNode == startParent) {
383 return null;
384 }
385
386 startNode = processedNode.getNextSibling();
387 }
388 }
389 return null;
390 }
391
392 /***
393 * set the namespace if it is not set already.
394 * <p/>
395 *
396 * @param element
397 * @param namespace
398 * @param prefix
399 * @return
400 */
401 public static String setNamespace(Element element,
402 String namespace,
403 String prefix) {
404 String pre = getPrefixNS(namespace, element);
405 if (pre != null) {
406 return pre;
407 }
408 element.setAttributeNS(WSConstants.XMLNS_NS,
409 "xmlns:" + prefix, namespace);
410 return prefix;
411 }
412
413
414
415 public static String getPrefixNS(String uri, Node e) {
416 while (e != null && (e.getNodeType() == Element.ELEMENT_NODE)) {
417 NamedNodeMap attrs = e.getAttributes();
418 for (int n = 0; n < attrs.getLength(); n++) {
419 Attr a = (Attr) attrs.item(n);
420 String name;
421 if ((name = a.getName()).startsWith("xmlns:") &&
422 a.getNodeValue().equals(uri)) {
423 return name.substring(6);
424 }
425 }
426 e = e.getParentNode();
427 }
428 return null;
429 }
430
431 public static String getNamespace(String prefix, Node e) {
432 while (e != null && (e.getNodeType() == Node.ELEMENT_NODE)) {
433 Attr attr = null;
434 if (prefix == null) {
435 attr = ((Element) e).getAttributeNode("xmlns");
436 } else {
437 attr = ((Element) e).getAttributeNodeNS(WSConstants.XMLNS_NS,
438 prefix);
439 }
440 if (attr != null) return attr.getValue();
441 e = e.getParentNode();
442 }
443 return null;
444 }
445
446 /***
447 * Return a QName when passed a string like "foo:bar" by mapping
448 * the "foo" prefix to a namespace in the context of the given Node.
449 *
450 * @return a QName generated from the given string representation
451 */
452 public static QName getQNameFromString(String str, Node e) {
453 return getQNameFromString(str, e, false);
454 }
455
456 /***
457 * Return a QName when passed a string like "foo:bar" by mapping
458 * the "foo" prefix to a namespace in the context of the given Node.
459 * If default namespace is found it is returned as part of the QName.
460 *
461 * @return a QName generated from the given string representation
462 */
463 public static QName getFullQNameFromString(String str, Node e) {
464 return getQNameFromString(str, e, true);
465 }
466
467 private static QName getQNameFromString(String str,
468 Node e,
469 boolean defaultNS) {
470 if (str == null || e == null)
471 return null;
472 int idx = str.indexOf(':');
473 if (idx > -1) {
474 String prefix = str.substring(0, idx);
475 String ns = getNamespace(prefix, e);
476 if (ns == null)
477 return null;
478 return new QName(ns, str.substring(idx + 1));
479 } else {
480 if (defaultNS) {
481 String ns = getNamespace(null, e);
482 if (ns != null)
483 return new QName(ns, str);
484 }
485 return new QName("", str);
486 }
487 }
488
489 /***
490 * Return a string for a particular QName, mapping a new prefix
491 * if necessary.
492 */
493 public static String getStringForQName(QName qname, Element e) {
494 String uri = qname.getNamespaceURI();
495 String prefix = getPrefixNS(uri, e);
496 if (prefix == null) {
497 int i = 1;
498 prefix = "ns" + i;
499 while (getNamespace(prefix, e) != null) {
500 i++;
501 prefix = "ns" + i;
502 }
503 e.setAttributeNS(WSConstants.XMLNS_NS,
504 "xmlns:" + prefix, uri);
505 }
506 return prefix + ":" + qname.getLocalPart();
507 }
508
509
510 /***
511 * Search for an element given its wsu:id.
512 * <p/>
513 *
514 * @param wssConfig The WSS configuration data conating namesapce
515 * definitions, etc.
516 * @param doc the DOM document (SOAP request)
517 * @param id the Id of the element
518 * @return the found element or null if no element with the Id exists
519 * @deprecated
520 * @see getElementByWsuId(WSSConfig wssConfig, Document doc, String id)
521 */
522 public static Element getElementByWsuId(Document doc, String id) {
523 return getElementByWsuId(WSSConfig.getDefaultWSConfig(), doc, id);
524 }
525 /***
526 * Search for an element given its wsu:id.
527 * <p/>
528 *
529 * @param wssConfig The WSS configuration data conating namesapce
530 * definitions, etc.
531 * @param doc the DOM document (SOAP request)
532 * @param id the Id of the element
533 * @return the found element or null if no element with the Id exists
534 */
535 public static Element getElementByWsuId(WSSConfig wssConfig, Document doc, String id) {
536
537 if (id == null) {
538 return null;
539 }
540 id = id.trim();
541 if ((id.length() == 0) || (id.charAt(0) != '#')) {
542 return null;
543 }
544 id = id.substring(1);
545 if (wssConfig.getProcessNonCompliantMessages()) {
546 Element element = null;
547 for (int i = 0; element == null && i < WSConstants.WSU_NS_ARRAY.length; ++i) {
548 element = WSSecurityUtil.findElementById(doc.getDocumentElement(), id, WSConstants.WSU_NS_ARRAY[i]);
549 }
550 return element;
551 } else {
552 return WSSecurityUtil.findElementById(doc.getDocumentElement(), id, wssConfig.getWsuNS());
553 }
554
555 }
556
557 /***
558 * Search for an element given its generic id.
559 * <p/>
560 *
561 * @param doc the DOM document (SOAP request)
562 * @param id the Id of the element
563 * @return the found element or null if no element with the Id exists
564 */
565 public static Element getElementByGenId(Document doc, String id) {
566 if (id == null) {
567 return null;
568 }
569 id = id.trim();
570 if ((id.length() == 0) || (id.charAt(0) != '#')) {
571 return null;
572 }
573 id = id.substring(1);
574 return WSSecurityUtil.findElementById(doc.getDocumentElement(), id, null);
575 }
576
577 /***
578 * Create a BinarySecurityToken element
579 * <p/>
580 *
581 * @param doc the DOM document (SOAP request)
582 * @param wsuIdVal the value for the wsu:Id
583 * @param wssConfig The WSS configuration data conating namesapce
584 * definitions, etc.
585 * @return then BST element (DOM element)
586 * @deprecated
587 * @see createBinarySecurityToken(Document doc,
588 String wsuIdVal,
589 WSSConfig wssConfig)
590 */
591 public static Element createBinarySecurityToken(Document doc,
592 String wsuIdVal) {
593 return createBinarySecurityToken(doc, wsuIdVal,
594 WSSConfig.getDefaultWSConfig());
595 }
596
597 /***
598 * Create a BinarySecurityToken element
599 * <p/>
600 *
601 * @param doc the DOM document (SOAP request)
602 * @param wsuIdVal the value for the wsu:Id
603 * @param wssConfig The WSS configuration data conating namesapce
604 * definitions, etc.
605 * @return then BST element (DOM element)
606 */
607 public static Element createBinarySecurityToken(Document doc,
608 String wsuIdVal,
609 WSSConfig wssConfig) {
610 Element retVal = doc.createElementNS(wssConfig.getWsseNS(),
611 "wsse:BinarySecurityToken");
612 retVal.setAttributeNS(WSConstants.XMLNS_NS,
613 "xmlns:wsu", wssConfig.getWsuNS());
614 retVal.setAttributeNS(WSConstants.WSU_NS, "wsu:Id", wsuIdVal);
615 retVal.setAttributeNS(null, "ValueType", X509Security.getType(wssConfig));
616 retVal.setAttributeNS(null, "EncodingType",
617 BinarySecurity.getBase64EncodingValue(wssConfig));
618 return retVal;
619 }
620
621 /***
622 * create a new element in the same namespace
623 * <p/>
624 *
625 * @param parent for the new element
626 * @param localName of the new element
627 * @return the new element
628 */
629 private static Element createElementInSameNamespace(Element parent,
630 String localName) {
631 String prefix = parent.getPrefix();
632 if (prefix == null) {
633 prefix = "";
634 }
635 String qName = prefix + ":" + localName;
636 String nsUri = parent.getNamespaceURI();
637 return parent.getOwnerDocument().createElementNS(nsUri, qName);
638 }
639
640 /***
641 * find a child element with given namespace and local name
642 * <p/>
643 *
644 * @param parent the node to start the search
645 * @param namespaceUri of the element
646 * @param localName of the eleme
647 * @return the found element or null if the element does not exist
648 */
649 private static Element findChildElement(Element parent,
650 String namespaceUri,
651 String localName) {
652 NodeList children = parent.getChildNodes();
653 int len = children.getLength();
654 for (int i = 0; i < len; i++) {
655 Node child = children.item(i);
656 if (child.getNodeType() == Node.ELEMENT_NODE) {
657 Element elementChild = (Element) child;
658 if (namespaceUri.equals(elementChild.getNamespaceURI()) &&
659 localName.equals(elementChild.getLocalName())) {
660 return elementChild;
661 }
662 }
663 }
664 return null;
665 }
666
667 /***
668 * append a child element
669 * <p/>
670 *
671 * @param doc the DOM document (SOAP request)
672 * @param parent element of this child element
673 * @param child the element to append
674 * @return the child element
675 */
676 public static Element appendChildElement(Document doc,
677 Element parent,
678 Element child) {
679 Node whitespaceText = doc.createTextNode("\n");
680 parent.appendChild(whitespaceText);
681 parent.appendChild(child);
682 return child;
683 }
684
685 /***
686 * prepend a child element
687 * <p/>
688 *
689 * @param doc the DOM document (SOAP request)
690 * @param parent element of this child element
691 * @param child the element to append
692 * @param addWhitespace if true prepend a newline before child
693 * @return the child element
694 */
695 public static Element prependChildElement(Document doc,
696 Element parent,
697 Element child,
698 boolean addWhitespace) {
699 Node firstChild = parent.getFirstChild();
700 if (firstChild == null) {
701 parent.appendChild(child);
702 } else {
703 parent.insertBefore(child, firstChild);
704 }
705 if (addWhitespace) {
706 Node whitespaceText = doc.createTextNode("\n");
707 parent.insertBefore(whitespaceText, child);
708 }
709 return child;
710 }
711
712 /***
713 * find the first ws-security header block
714 * <p/>
715 *
716 * @param doc the DOM document (SOAP request)
717 * @param envelope the SOAP envelope
718 * @param doCreate if true create a new WSS header block if none exists
719 * @return the WSS header or null if none found and doCreate is false
720 * @deprecated
721 * @see findWsseSecurityHeaderBlock(WSSConfig wssConfig, Document doc, Element envelope, boolean doCreate)
722 */
723 public static Element findWsseSecurityHeaderBlock(Document doc, Element envelope, boolean doCreate) {
724 return findWsseSecurityHeaderBlock(WSSConfig.getDefaultWSConfig(), doc, envelope, doCreate);
725 }
726
727 /***
728 * find the first ws-security header block
729 * <p/>
730 *
731 * @param doc the DOM document (SOAP request)
732 * @param envelope the SOAP envelope
733 * @param doCreate if true create a new WSS header block if none exists
734 * @return the WSS header or null if none found and doCreate is false
735 */
736 public static Element findWsseSecurityHeaderBlock(WSSConfig wssConfig, Document doc, Element envelope, boolean doCreate) {
737 return findWsseSecurityHeaderBlock(wssConfig, doc, envelope, null, doCreate);
738 }
739
740 /***
741 * find the first ws-security header block
742 * <p/>
743 *
744 * @param doc the DOM document (SOAP request)
745 * @param envelope the SOAP envelope
746 * @param doCreate if true create a new WSS header block if none exists
747 * @return the WSS header or null if none found and doCreate is false
748 * @deprecated
749 * @see findWsseSecurityHeaderBlock(WSSConfig wssConfig,
750 Document doc,
751 Element envelope,
752 String actor,
753 boolean doCreate)
754 */
755 public static Element findWsseSecurityHeaderBlock(Document doc,
756 Element envelope,
757 String actor,
758 boolean doCreate) {
759 return findWsseSecurityHeaderBlock(WSSConfig.getDefaultWSConfig(),
760 doc,
761 envelope,
762 actor,
763 doCreate);
764 }
765 /***
766 * find a ws-security header block for a given actor
767 * <p/>
768 *
769 * @param doc the DOM document (SOAP request)
770 * @param envelope the SOAP envelope
771 * @param actor the acttoer (role) name of the WSS header
772 * @param doCreate if true create a new WSS header block if none exists
773 * @return the WSS header or null if none found and doCreate is false
774 */
775 public static Element findWsseSecurityHeaderBlock(WSSConfig wssConfig,
776 Document doc,
777 Element envelope,
778 String actor,
779 boolean doCreate) {
780 SOAPConstants sc = getSOAPConstants(envelope);
781 Element wsseSecurity = getSecurityHeader(wssConfig, doc, actor, sc);
782 if (wsseSecurity != null) {
783 return wsseSecurity;
784 }
785 Element header = findChildElement(envelope, sc.getEnvelopeURI(), sc.getHeaderQName().getLocalPart());
786 if (header == null) {
787 if (doCreate) {
788 header = createElementInSameNamespace(envelope, sc.getHeaderQName().getLocalPart());
789 header = prependChildElement(doc, envelope, header, true);
790 }
791 }
792 if (doCreate) {
793 wsseSecurity = header.getOwnerDocument().createElementNS(wssConfig.getWsseNS(), "wsse:Security");
794 wsseSecurity.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsse", wssConfig.getWsseNS());
795 return prependChildElement(doc, header, wsseSecurity, true);
796 }
797 return null;
798 }
799
800 /***
801 * create a base64 test node
802 * <p/>
803 *
804 * @param doc the DOM document (SOAP request)
805 * @param data to encode
806 * @return a Text node containing the base64 encoded data
807 */
808 public static Text createBase64EncodedTextNode(Document doc, byte data[]) {
809 return doc.createTextNode(Base64.encode(data));
810 }
811
812 /***
813 * use xpath to find a node
814 * <p/>
815 *
816 * @param contextNode node to starte the select
817 * @param xpath the xpath expression
818 * @param nsContext the context element for xpath
819 * @return the select Node
820 * @throws Exception
821 */
822 public static Node selectSingleNode(Node contextNode,
823 String xpath,
824 Element nsContext) throws Exception {
825 try {
826 return XPathAPI.selectSingleNode(contextNode, xpath, nsContext);
827 } catch (TransformerException e) {
828 throw new Exception("Unable to resolve XPath");
829 }
830 }
831
832 /***
833 * Create a namespace context with namespaces of interest
834 *
835 * @param doc the DOM document (SOAP request)
836 * @return a conext element usable for xpath requests
837 * @deprecated
838 * @see createNamespaceContext(WSSConfig wssConfig, Document doc)
839 */
840 public static Element createNamespaceContext(Document doc) {
841 return createNamespaceContext(WSSConfig.getDefaultWSConfig(), doc);
842 }
843
844 /***
845 * Create a namespace context with namespaces of interest
846 *
847 * @param doc the DOM document (SOAP request)
848 * @return a conext element usable for xpath requests
849 */
850 public static Element createNamespaceContext(WSSConfig wssConfig, Document doc) {
851 SOAPConstants sc = getSOAPConstants(doc.getDocumentElement());
852 Element nsContext = doc.createElementNS(null, "namespaceContext");
853 nsContext.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:env", sc.getEnvelopeURI());
854 nsContext.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsse", wssConfig.getWsseNS());
855 nsContext.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsu", wssConfig.getWsuNS());
856 nsContext.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:ds", WSConstants.SIG_NS);
857 nsContext.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:xenc", WSConstants.ENC_NS);
858 return nsContext;
859 }
860
861 public static SecretKey prepareSecretKey(String symEncAlgo,
862 byte[] rawKey) {
863 SecretKeySpec keySpec = new SecretKeySpec(
864 rawKey, JCEMapper.getJCEKeyAlgorithmFromURI(symEncAlgo));
865 return (SecretKey) keySpec;
866 }
867
868 public static SOAPConstants getSOAPConstants(Element startElement) {
869 Document doc = startElement.getOwnerDocument();
870 String ns = doc.getDocumentElement().getNamespaceURI();
871 if (WSConstants.URI_SOAP12_ENV.equals(ns)) {
872 return new SOAP12Constants();
873 } else {
874 return new SOAP11Constants();
875 }
876 }
877
878 public static Cipher getCipherInstance(String cipherAlgo)
879 throws WSSecurityException {
880 Cipher cipher = null;
881 try {
882 if (cipherAlgo.equalsIgnoreCase(WSConstants.KEYTRANSPORT_RSA15)) {
883 cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING", "BC");
884 } else if (
885 cipherAlgo.equalsIgnoreCase(WSConstants.KEYTRANSPORT_RSAOEP)) {
886 cipher = Cipher.getInstance("RSA/NONE/OAEPPADDING", "BC");
887 } else {
888 throw new WSSecurityException(WSSecurityException.UNSUPPORTED_ALGORITHM,
889 "unsupportedKeyTransp",
890 new Object[]{cipherAlgo});
891 }
892 } catch (NoSuchPaddingException ex) {
893 throw new WSSecurityException(WSSecurityException.UNSUPPORTED_ALGORITHM,
894 "unsupportedKeyTransp",
895 new Object[]{"No such padding: " + cipherAlgo});
896 } catch (NoSuchProviderException ex) {
897 throw new WSSecurityException(WSSecurityException.UNSUPPORTED_ALGORITHM,
898 "unsupportedKeyTransp",
899 new Object[]{"no provider: " + cipherAlgo});
900 } catch (NoSuchAlgorithmException ex) {
901 throw new WSSecurityException(WSSecurityException.UNSUPPORTED_ALGORITHM,
902 "unsupportedKeyTransp",
903 new Object[]{"No such algorithm: " + cipherAlgo});
904 }
905 return cipher;
906 }
907
908 /***
909 * Fetch the result of a given action from a given result vector
910 * <p/>
911 *
912 * @param wsResultVector The result vector to fetch an action from
913 * @param action The action to fetch
914 * @return The result fetched from the result vector, null if the result
915 * could not be found
916 */
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934 static public int decodeAction(String action, Vector actions)
935 throws WSSecurityException {
936
937 int doAction = 0;
938
939 if (action == null) {
940 return doAction;
941 }
942 String single[] = StringUtil.split(action, ' ');
943 for (int i = 0; i < single.length; i++) {
944 if (single[i].equals(WSHandlerConstants.NO_SECURITY)) {
945 doAction = WSConstants.NO_SECURITY;
946 return doAction;
947 } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN)) {
948 doAction |= WSConstants.UT;
949 actions.add(new Integer(WSConstants.UT));
950 } else if (single[i].equals(WSHandlerConstants.SIGNATURE)) {
951 doAction |= WSConstants.SIGN;
952 actions.add(new Integer(WSConstants.SIGN));
953 } else if (single[i].equals(WSHandlerConstants.ENCRYPT)) {
954 doAction |= WSConstants.ENCR;
955 actions.add(new Integer(WSConstants.ENCR));
956 } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_UNSIGNED)) {
957 doAction |= WSConstants.ST_UNSIGNED;
958 actions.add(new Integer(WSConstants.ST_UNSIGNED));
959 } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_SIGNED)) {
960 doAction |= WSConstants.ST_SIGNED;
961 actions.add(new Integer(WSConstants.ST_SIGNED));
962 } else if (single[i].equals(WSHandlerConstants.TIMESTAMP)) {
963 doAction |= WSConstants.TS;
964 actions.add(new Integer(WSConstants.TS));
965 } else if (single[i].equals(WSHandlerConstants.NO_SERIALIZATION)) {
966 doAction |= WSConstants.NO_SERIALIZE;
967 actions.add(new Integer(WSConstants.NO_SERIALIZE));
968 } else if (single[i].equals(WSHandlerConstants.SIGN_WITH_UT_KEY)) {
969 doAction |= WSConstants.UT_SIGN;
970 actions.add(new Integer(WSConstants.UT_SIGN));
971 } else {
972 throw new WSSecurityException("WSDoAllSender: Unknown action defined" + single[i]);
973 }
974 }
975 return doAction;
976 }
977 }