1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 package org.apache.wss4j.dom.callback;
21
22 import java.util.Collections;
23 import java.util.List;
24
25 import javax.xml.crypto.dom.DOMCryptoContext;
26
27 import org.apache.wss4j.dom.WSConstants;
28 import org.apache.wss4j.common.ext.WSSecurityException;
29 import org.apache.wss4j.common.util.XMLUtils;
30 import org.apache.wss4j.dom.util.WSSecurityUtil;
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Element;
33
34 /**
35 * This class uses a DOM-based approach to locate Elements that are referenced via an Id.
36 */
37 public class DOMCallbackLookup implements CallbackLookup {
38
39 private Document doc;
40
41 public DOMCallbackLookup(Document doc) {
42 this.doc = doc;
43 }
44
45 /**
46 * Get the DOM element that corresponds to the given id and ValueType reference. The Id can
47 * be a wsu:Id or else an Id attribute, or a SAML Id when the ValueType refers to a SAML
48 * Assertion.
49 *
50 * @param id The id of the element to locate
51 * @param valueType The ValueType attribute of the element to locate (can be null)
52 * @param checkMultipleElements If true then go through the entire tree and return
53 * null if there are multiple elements with the same Id
54 * @return the located element
55 * @throws WSSecurityException
56 */
57 public Element getElement(
58 String id, String valueType, boolean checkMultipleElements
59 ) throws WSSecurityException {
60 return getAndRegisterElement(id, valueType, checkMultipleElements, null);
61 }
62
63 /**
64 * Get the DOM element that corresponds to the given id and ValueType reference. The Id can
65 * be a wsu:Id or else an Id attribute, or a SAML Id when the ValueType refers to a SAML
66 * Assertion. The implementation is also responsible to register the retrieved Element on the
67 * DOMCryptoContext argument, so that the XML Signature implementation can find the Element.
68 *
69 * @param id The id of the element to locate
70 * @param valueType The ValueType attribute of the element to locate (can be null)
71 * @param checkMultipleElements If true then go through the entire tree and return
72 * null if there are multiple elements with the same Id
73 * @param context The DOMCryptoContext to store the Element in
74 * @return the located element
75 * @throws WSSecurityException
76 */
77 public Element getAndRegisterElement(
78 String id, String valueType, boolean checkMultipleElements, DOMCryptoContext context
79 ) throws WSSecurityException {
80 String idToMatch = XMLUtils.getIDFromReference(id);
81
82 //
83 // Try the SOAP Body first
84 //
85 Element bodyElement = getSOAPBody();
86 if (bodyElement != null) {
87 String cId = bodyElement.getAttributeNS(WSConstants.WSU_NS, "Id");
88 if (cId.equals(idToMatch)) {
89 if (context != null) {
90 context.setIdAttributeNS(bodyElement, WSConstants.WSU_NS, "Id");
91 }
92 return bodyElement;
93 }
94 }
95 // Otherwise do a general search
96 Element foundElement =
97 XMLUtils.findElementById(doc.getDocumentElement(), idToMatch, checkMultipleElements);
98 if (foundElement != null) {
99 if (context != null) {
100 if (foundElement.hasAttributeNS(WSConstants.WSU_NS, "Id")
101 && idToMatch.equals(foundElement.getAttributeNS(WSConstants.WSU_NS, "Id"))) {
102 context.setIdAttributeNS(foundElement, WSConstants.WSU_NS, "Id");
103 }
104 if (foundElement.hasAttributeNS(null, "Id")
105 && idToMatch.equals(foundElement.getAttributeNS(null, "Id"))) {
106 context.setIdAttributeNS(foundElement, null, "Id");
107 }
108 }
109 return foundElement;
110 }
111
112 //
113 // Try to find a SAML Assertion Element if the ValueType corresponds to a SAML Assertion
114 // (or is empty)
115 //
116 if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(valueType)
117 || WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(valueType)
118 || valueType == null || valueType.length() == 0) {
119 foundElement =
120 XMLUtils.findSAMLAssertionElementById(
121 doc.getDocumentElement(), idToMatch
122 );
123 if (foundElement != null) {
124 if (context != null) {
125 if (foundElement.hasAttributeNS(null, "ID")
126 && idToMatch.equals(foundElement.getAttributeNS(null, "ID"))) {
127 context.setIdAttributeNS(foundElement, null, "ID");
128 }
129 if (foundElement.hasAttributeNS(null, "AssertionID")
130 && idToMatch.equals(foundElement.getAttributeNS(null, "AssertionID"))) {
131 context.setIdAttributeNS(foundElement, null, "AssertionID");
132 }
133 }
134 return foundElement;
135 }
136 }
137
138 return null;
139 }
140
141 /**
142 * Get the DOM element(s) that correspond to the given localname/namespace.
143 * @param localname The localname of the Element(s)
144 * @param namespace The namespace of the Element(s)
145 * @return the located element(s)
146 * @throws WSSecurityException
147 */
148 public List<Element> getElements(
149 String localname, String namespace
150 ) throws WSSecurityException {
151 //
152 // Try the SOAP Body first
153 //
154 Element bodyElement = getSOAPBody();
155 if (WSConstants.ELEM_BODY.equals(localname) && bodyElement.getNamespaceURI().equals(namespace)) {
156 return Collections.singletonList(bodyElement);
157 }
158 return XMLUtils.findElements(doc.getDocumentElement(), localname, namespace);
159 }
160
161
162 /**
163 * Get the SOAP Body
164 */
165 public Element getSOAPBody() {
166 return WSSecurityUtil.findBodyElement(doc);
167 }
168 }