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.str;
21  
22  import java.security.cert.X509Certificate;
23  
24  import javax.xml.namespace.QName;
25  
26  import org.apache.wss4j.common.crypto.Crypto;
27  import org.apache.wss4j.common.ext.WSSecurityException;
28  import org.apache.wss4j.common.saml.SAMLKeyInfo;
29  import org.apache.wss4j.common.saml.SAMLUtil;
30  import org.apache.wss4j.common.saml.SamlAssertionWrapper;
31  import org.apache.wss4j.common.token.BinarySecurity;
32  import org.apache.wss4j.common.token.Reference;
33  import org.apache.wss4j.common.token.SecurityTokenReference;
34  import org.apache.wss4j.common.token.X509Security;
35  import org.apache.wss4j.common.util.XMLUtils;
36  import org.apache.wss4j.dom.WSConstants;
37  import org.apache.wss4j.dom.WSDocInfo;
38  import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
39  import org.apache.wss4j.dom.handler.RequestData;
40  import org.apache.wss4j.dom.saml.WSSSAMLKeyInfoProcessor;
41  import org.w3c.dom.Element;
42  
43  /**
44   * This implementation of STRParser is for parsing a SecurityTokenReference element, found in the
45   * KeyInfo element associated with an EncryptedKey element
46   */
47  public class EncryptedKeySTRParser implements STRParser {
48  
49      /**
50       * Parse a SecurityTokenReference element and extract credentials.
51       *
52       * @param parameters The parameters to parse
53       * @return the STRParserResult Object containing the parsing results
54       * @throws WSSecurityException
55       */
56      public STRParserResult parseSecurityTokenReference(STRParserParameters parameters) throws WSSecurityException {
57          if (parameters == null || parameters.getData() == null || parameters.getData().getWsDocInfo() == null
58              || parameters.getStrElement() == null) {
59              throw new WSSecurityException(
60                  WSSecurityException.ErrorCode.FAILURE, "invalidSTRParserParameter"
61              );
62          }
63  
64          SecurityTokenReference secRef =
65              new SecurityTokenReference(parameters.getStrElement(), parameters.getData().getBSPEnforcer());
66  
67          String uri = null;
68          if (secRef.getReference() != null) {
69              uri = secRef.getReference().getURI();
70              uri = XMLUtils.getIDFromReference(uri);
71          } else if (secRef.containsKeyIdentifier()) {
72              uri = secRef.getKeyIdentifierValue();
73          }
74  
75          WSSecurityEngineResult result = parameters.getData().getWsDocInfo().getResult(uri);
76          if (result != null) {
77              return processPreviousResult(result, secRef, parameters);
78          }
79  
80          return processSTR(secRef, parameters);
81      }
82  
83      /**
84       * Process a previous security result
85       */
86      private STRParserResult processPreviousResult(
87          WSSecurityEngineResult result,
88          SecurityTokenReference secRef,
89          STRParserParameters parameters
90      ) throws WSSecurityException {
91          STRParserResult parserResult = new STRParserResult();
92          RequestData data = parameters.getData();
93  
94          Integer action = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION);
95          if (action != null && WSConstants.BST == action.intValue()) {
96              BinarySecurity token =
97                  (BinarySecurity)result.get(
98                      WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN
99                  );
100             STRParserUtil.checkBinarySecurityBSPCompliance(secRef, token, data.getBSPEnforcer());
101             X509Certificate[] certs =
102                 (X509Certificate[])result.get(
103                     WSSecurityEngineResult.TAG_X509_CERTIFICATES
104                 );
105             parserResult.setCerts(certs);
106         } else if (action != null
107             && (WSConstants.ST_UNSIGNED == action.intValue() || WSConstants.ST_SIGNED == action.intValue())) {
108             SamlAssertionWrapper samlAssertion =
109                 (SamlAssertionWrapper)result.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
110             STRParserUtil.checkSamlTokenBSPCompliance(secRef, samlAssertion, data.getBSPEnforcer());
111 
112             SAMLKeyInfo keyInfo =
113                 SAMLUtil.getCredentialFromSubject(samlAssertion, new WSSSAMLKeyInfoProcessor(data),
114                         data.getSigVerCrypto());
115             parserResult.setCerts(keyInfo.getCerts());
116             parserResult.setPublicKey(keyInfo.getPublicKey());
117         } else {
118             throw new WSSecurityException(
119                 WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN,
120                 "unsupportedBinaryTokenType"
121             );
122         }
123 
124         REFERENCE_TYPE referenceType = getReferenceType(secRef);
125         if (referenceType != null) {
126             parserResult.setReferenceType(referenceType);
127         }
128         return parserResult;
129     }
130 
131     private STRParserResult processSTR(
132         SecurityTokenReference secRef, STRParserParameters parameters
133     ) throws WSSecurityException {
134         STRParserResult parserResult = new STRParserResult();
135         RequestData data = parameters.getData();
136         Element strElement = parameters.getStrElement();
137         WSDocInfo wsDocInfo = data.getWsDocInfo();
138         Crypto crypto = data.getDecCrypto();
139 
140         if (secRef.containsKeyIdentifier()) {
141             if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())
142                 || WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())) {
143                 SamlAssertionWrapper samlAssertion =
144                     STRParserUtil.getAssertionFromKeyIdentifier(
145                         secRef, strElement, data
146                     );
147                 STRParserUtil.checkSamlTokenBSPCompliance(secRef, samlAssertion, data.getBSPEnforcer());
148 
149                 SAMLKeyInfo samlKi =
150                     SAMLUtil.getCredentialFromSubject(samlAssertion,
151                             new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto());
152                 parserResult.setCerts(samlKi.getCerts());
153                 parserResult.setPublicKey(samlKi.getPublicKey());
154             } else {
155                 STRParserUtil.checkBinarySecurityBSPCompliance(secRef, null, data.getBSPEnforcer());
156                 parserResult.setCerts(secRef.getKeyIdentifier(crypto));
157             }
158         } else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
159             parserResult.setReferenceType(REFERENCE_TYPE.ISSUER_SERIAL);
160             parserResult.setCerts(secRef.getX509IssuerSerial(crypto));
161         } else if (secRef.containsReference()) {
162             Reference reference = secRef.getReference();
163             Element bstElement =
164                 STRParserUtil.getTokenElement(strElement.getOwnerDocument(), wsDocInfo, data.getCallbackHandler(),
165                                               reference.getURI(), reference.getValueType());
166 
167             // at this point ... check token type: Binary
168             QName el = new QName(bstElement.getNamespaceURI(), bstElement.getLocalName());
169             if (el.equals(WSConstants.BINARY_TOKEN)) {
170                 X509Security token = new X509Security(bstElement, data.getBSPEnforcer());
171                 STRParserUtil.checkBinarySecurityBSPCompliance(secRef, token, data.getBSPEnforcer());
172                 parserResult.setCerts(new X509Certificate[]{token.getX509Certificate(crypto)});
173             } else {
174                 throw new WSSecurityException(
175                     WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN,
176                     "unsupportedBinaryTokenType"
177                 );
178             }
179         }
180 
181         REFERENCE_TYPE referenceType = getReferenceType(secRef);
182         if (referenceType != null) {
183             parserResult.setReferenceType(referenceType);
184         }
185 
186         return parserResult;
187     }
188 
189     private REFERENCE_TYPE getReferenceType(SecurityTokenReference secRef) {
190         if (secRef.containsReference()) {
191             return REFERENCE_TYPE.DIRECT_REF;
192         } else if (secRef.containsKeyIdentifier()) {
193             if (SecurityTokenReference.THUMB_URI.equals(secRef.getKeyIdentifierValueType())) {
194                 return REFERENCE_TYPE.THUMBPRINT_SHA1;
195             } else {
196                 return REFERENCE_TYPE.KEY_IDENTIFIER;
197             }
198         }
199 
200         return null;
201     }
202 }