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.wss4j.dom.util;
21  
22  import java.util.ArrayList;
23  import java.util.LinkedHashSet;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.apache.wss4j.common.ext.WSSecurityException;
28  import org.apache.wss4j.dom.WSConstants;
29  import org.apache.wss4j.dom.WSDataRef;
30  import org.apache.wss4j.dom.WSDocInfo;
31  import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
32  import org.w3c.dom.Element;
33  import org.w3c.dom.NamedNodeMap;
34  import org.w3c.dom.Node;
35  
36  /**
37   * WS-Security Utility methods. <p/>
38   */
39  public final class SignatureUtils {
40  
41      private SignatureUtils() {
42          // Complete
43      }
44  
45      public static void verifySignedElement(Element elem, WSDocInfo wsDocInfo)
46          throws WSSecurityException {
47          verifySignedElement(elem, wsDocInfo.getResultsByTag(WSConstants.SIGN));
48      }
49  
50      public static void verifySignedElement(Element elem, List<WSSecurityEngineResult> signedResults)
51          throws WSSecurityException {
52          if (signedResults != null) {
53              for (WSSecurityEngineResult signedResult : signedResults) {
54                  @SuppressWarnings("unchecked")
55                  List<WSDataRef> dataRefs =
56                      (List<WSDataRef>)signedResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
57                  if (dataRefs != null) {
58                      for (WSDataRef dataRef : dataRefs) {
59                          if (isElementOrAncestorSigned(elem, dataRef.getProtectedElement())) {
60                              return;
61                          }
62                      }
63                  }
64              }
65          }
66  
67          throw new WSSecurityException(
68              WSSecurityException.ErrorCode.FAILED_CHECK, "elementNotSigned",
69              new Object[] {elem});
70      }
71  
72      /**
73       * Get the List of inclusive prefixes from the DOM Element argument
74       */
75      public static List<String> getInclusivePrefixes(Element target, boolean excludeVisible) {
76          Set<String> result = new LinkedHashSet<>();
77          Node parent = target;
78          while (parent.getParentNode() != null
79              && Node.DOCUMENT_NODE != parent.getParentNode().getNodeType()) {
80              parent = parent.getParentNode();
81              NamedNodeMap attributes = parent.getAttributes();
82              for (int i = 0; i < attributes.getLength(); i++) {
83                  Node attribute = attributes.item(i);
84                  if (WSConstants.XMLNS_NS.equals(attribute.getNamespaceURI())) {
85                      if ("xmlns".equals(attribute.getNodeName())) {
86                          result.add("#default");
87                      } else {
88                          result.add(attribute.getLocalName());
89                      }
90                  }
91              }
92          }
93  
94          if (excludeVisible) {
95              NamedNodeMap attributes = target.getAttributes();
96              for (int i = 0; i < attributes.getLength(); i++) {
97                  Node attribute = attributes.item(i);
98                  if (WSConstants.XMLNS_NS.equals(attribute.getNamespaceURI())) {
99                      if ("xmlns".equals(attribute.getNodeName())) {
100                         result.remove("#default");
101                     } else {
102                         result.remove(attribute.getLocalName());
103                     }
104                 }
105                 if (attribute.getPrefix() != null) {
106                     result.remove(attribute.getPrefix());
107                 }
108             }
109 
110             if (target.getPrefix() == null) {
111                 result.remove("#default");
112             } else {
113                 result.remove(target.getPrefix());
114             }
115         }
116 
117         return new ArrayList<String>(result);
118     }
119 
120     /**
121      * Does the current element or some ancestor of it correspond to the known "signedElement"?
122      */
123     private static boolean isElementOrAncestorSigned(Element elem, Element signedElement)
124         throws WSSecurityException {
125         final Element envelope = elem.getOwnerDocument().getDocumentElement();
126         Node cur = elem;
127         while (!cur.isSameNode(envelope)) {
128             if (cur.getNodeType() == Node.ELEMENT_NODE && cur.equals(signedElement)) {
129                 return true;
130             }
131             cur = cur.getParentNode();
132         }
133 
134         return false;
135     }
136 
137 }