View Javadoc

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.ws.security;
21  
22  /**
23   * WSDocInfo holds information about the document to process. It provides a 
24   * method to store and access document information about BinarySecurityToken, 
25   * used Crypto, and others.
26   * 
27   * Using the Document's hash a caller can identify a document and get
28   * the stored information that me be necessary to process the document.
29   * The main usage for this is (are) the transformation functions that
30   * are called during Signature/Verification process. 
31   * 
32   * @author Werner Dittmann (Werner.Dittmann@siemens.com)
33   */
34  
35  import java.util.ArrayList;
36  import java.util.List;
37  
38  import javax.xml.crypto.dom.DOMCryptoContext;
39  
40  import org.apache.ws.security.components.crypto.Crypto;
41  import org.apache.ws.security.message.CallbackLookup;
42  import org.apache.ws.security.util.WSSecurityUtil;
43  import org.w3c.dom.Document;
44  import org.w3c.dom.Element;
45  
46  public class WSDocInfo {
47      private Document doc = null;
48      private Crypto crypto = null;
49      private List<Element> tokenList = null;
50      private List<WSSecurityEngineResult> resultsList = null;
51      private CallbackLookup callbackLookup = null;
52      private Element securityHeader = null;
53  
54      public WSDocInfo(Document doc) {
55          //
56          // This is a bit of a hack. When the Document is a SAAJ SOAPPart instance, it may
57          // be that the "owner" document of any child elements is an internal Document, rather
58          // than the SOAPPart. This is the case for the SUN SAAJ implementation.
59          //
60          if (doc != null && doc.getDocumentElement() != null) {
61              this.doc = doc.getDocumentElement().getOwnerDocument();
62          } else {
63              this.doc = doc;
64          }
65      }
66      
67      /**
68       * Clears the data stored in this object
69       */
70      public void clear() {
71          crypto = null;
72          if (tokenList != null && tokenList.size() > 0) {
73              tokenList.clear();
74          }
75          if (resultsList != null && resultsList.size() > 0) {
76              resultsList.clear();
77          }
78          
79          tokenList = null;
80          resultsList = null;
81      }
82      
83      /**
84       * Store a token element for later retrieval. Before storing the token, we check for a 
85       * previously processed token with the same (wsu/SAML) Id.
86       * @param element is the token element to store
87       */
88      public void addTokenElement(Element element) throws WSSecurityException {
89          addTokenElement(element, true);
90      }
91      
92      /**
93       * Store a token element for later retrieval. Before storing the token, we check for a 
94       * previously processed token with the same (wsu/SAML) Id.
95       * @param element is the token element to store
96       * @param checkMultipleElements check for a previously stored element with the same Id.
97       */
98      public void addTokenElement(Element element, boolean checkMultipleElements) throws WSSecurityException {
99          if (tokenList == null) {
100             tokenList = new ArrayList<Element>();
101         }
102         
103         if (checkMultipleElements) {
104             for (Element elem : tokenList) {
105                 if (compareElementsById(element, elem)) {
106                     throw new WSSecurityException(
107                         WSSecurityException.INVALID_SECURITY_TOKEN, "duplicateError"
108                     );
109                 }
110             }
111         }
112         tokenList.add(element);
113     }
114     
115     private boolean compareElementsById(Element firstElement, Element secondElement) {
116         if (firstElement.hasAttributeNS(WSConstants.WSU_NS, "Id")
117             && secondElement.hasAttributeNS(WSConstants.WSU_NS, "Id")) {
118             String id = firstElement.getAttributeNS(WSConstants.WSU_NS, "Id");
119             String id2 = secondElement.getAttributeNS(WSConstants.WSU_NS, "Id");
120             if (id.equals(id2)) {
121                 return true;
122             }
123         }
124         if (firstElement.hasAttribute("AssertionID")
125             && secondElement.hasAttribute("AssertionID")) {
126             String id = firstElement.getAttribute("AssertionID");
127             String id2 = secondElement.getAttribute("AssertionID");
128             if (id.equals(id2)) {
129                 return true;
130             }
131         }
132         if (firstElement.hasAttribute("ID") && secondElement.hasAttribute("ID")) {
133             String id = firstElement.getAttribute("ID");
134             String id2 = secondElement.getAttribute("ID");
135             if (id.equals(id2)) {
136                 return true;
137             }
138         }
139         return false;
140     }
141     
142     /**
143      * Get a token Element for the given Id. The Id can be either a wsu:Id or a 
144      * SAML AssertionID/ID. 
145      * @param uri is the (relative) uri of the id
146      * @return the token element or null if nothing found
147      */
148     public Element getTokenElement(String uri) {
149         String id = uri;
150         if (id == null) {
151             return null;
152         } else if (id.charAt(0) == '#') {
153             id = id.substring(1);
154         }
155         if (tokenList != null) {
156             for (Element elem : tokenList) {
157                 String cId = elem.getAttributeNS(WSConstants.WSU_NS, "Id");
158                 String samlId = elem.getAttribute("AssertionID");
159                 String samlId2 = elem.getAttribute("ID");
160                 if ((elem.hasAttributeNS(WSConstants.WSU_NS, "Id") && id.equals(cId)) 
161                     || (elem.hasAttribute("AssertionID") && id.equals(samlId))
162                     || (elem.hasAttribute("ID") && id.equals(samlId2))) {
163                     return elem;
164                 }
165             }
166         }
167         return null;
168     }
169 
170     /**
171      * Set all stored tokens on the DOMCryptoContext argument
172      * @param context
173      */
174     public void setTokensOnContext(DOMCryptoContext context) {
175         if (tokenList != null) {
176             for (Element elem : tokenList) {
177                 WSSecurityUtil.storeElementInContext(context, elem);
178             }
179         }
180     }
181     
182     /**
183      * Store a protection element for later retrieval. This is only used for the 
184      * creation/outbound case.
185      * @param element is the protection element to store
186      * @deprecated
187      */
188     public void addProtectionElement(Element element) {
189         if (tokenList == null) {
190             tokenList = new ArrayList<Element>();
191         }
192         tokenList.add(element);
193     }
194     
195     /**
196      * Get a protection element for the given (wsu/SAML) Id.
197      * @param uri is the (relative) uri of the id
198      * @return the protection element or null if nothing found
199      * @deprecated
200      */
201     public Element getProtectionElement(String uri) {
202         return getTokenElement(uri); 
203     }
204     
205     /**
206      * Store a WSSecurityEngineResult for later retrieval. 
207      * @param result is the WSSecurityEngineResult to store
208      */
209     public void addResult(WSSecurityEngineResult result) {
210         if (resultsList == null) {
211             resultsList = new ArrayList<WSSecurityEngineResult>();
212         }
213         resultsList.add(result);
214     }
215     
216     /**
217      * Get a WSSecurityEngineResult for the given Id.
218      * @param uri is the (relative) uri of the id
219      * @return the WSSecurityEngineResult or null if nothing found
220      */
221     public WSSecurityEngineResult getResult(String uri) {
222         String id = uri;
223         if (id == null) {
224             return null;
225         } else if (id.charAt(0) == '#') {
226             id = id.substring(1);
227         }
228         if (resultsList != null) {
229             for (WSSecurityEngineResult result : resultsList) {
230                 if (result != null) {
231                     String cId = (String)result.get(WSSecurityEngineResult.TAG_ID);
232                     if (id.equals(cId)) {
233                         return result;
234                     }
235                 }
236             }
237         }
238         return null;
239     }
240     
241     /**
242      * Get a list of WSSecurityEngineResults of the given Integer tag
243      */
244     public List<WSSecurityEngineResult> getResultsByTag(Integer tag) {
245         List<WSSecurityEngineResult> foundResults = new ArrayList<WSSecurityEngineResult>();
246         if (resultsList != null) {
247             for (WSSecurityEngineResult result : resultsList) {
248                 if (result != null) {
249                     Integer resultTag = (Integer)result.get(WSSecurityEngineResult.TAG_ACTION);
250                     if (tag.intValue() == resultTag.intValue()) {
251                         foundResults.add(result);
252                     }
253                 }
254             }
255         }
256         return foundResults;
257     }
258     
259     /**
260      * Get a WSSecurityEngineResult of the given Integer tag for the given Id
261      */
262     public WSSecurityEngineResult getResultByTag(Integer tag, String uri) {
263         String id = uri;
264         if (id == null) {
265             return null;
266         } else if (id.charAt(0) == '#') {
267             id = id.substring(1);
268         }
269         if (resultsList != null) {
270             for (WSSecurityEngineResult result : resultsList) {
271                 if (result != null) {
272                     Integer resultTag = (Integer)result.get(WSSecurityEngineResult.TAG_ACTION);
273                     String cId = (String)result.get(WSSecurityEngineResult.TAG_ID);
274                     if ((tag.intValue() == resultTag.intValue()) && id.equals(cId)) {
275                         return result;
276                     }
277                 }
278             }
279         }
280         return null;
281     }
282 
283     /**
284      * @return the signature crypto class used to process
285      *         the signature/verify
286      */
287     public Crypto getCrypto() {
288         return crypto;
289     }
290 
291     /**
292      * @return the document
293      */
294     public Document getDocument() {
295         return doc;
296     }
297 
298     /**
299      * @param crypto is the signature crypto class used to
300      *               process signature/verify
301      */
302     public void setCrypto(Crypto crypto) {
303         this.crypto = crypto;
304     }
305     
306     /**
307      * @param callbackLookup The CallbackLookup object to retrieve elements
308      */
309     public void setCallbackLookup(CallbackLookup callbackLookup) {
310         this.callbackLookup = callbackLookup;
311     }
312     
313     /**
314      * @return the CallbackLookup object to retrieve elements
315      */
316     public CallbackLookup getCallbackLookup() {
317         return callbackLookup;
318     }
319 
320     /**
321      * @return the wsse header being processed
322      */
323     public Element getSecurityHeader() {
324         return securityHeader;
325     }
326     
327     /**
328      * Sets the wsse header being processed
329      * 
330      * @param securityHeader
331      */
332     public void setSecurityHeader(Element securityHeader) {
333         this.securityHeader = securityHeader;
334     }
335 }