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.str;
21  
22  import org.apache.ws.security.WSConstants;
23  import org.apache.ws.security.WSDocInfo;
24  import org.apache.ws.security.WSSConfig;
25  import org.apache.ws.security.WSSecurityEngine;
26  import org.apache.ws.security.WSSecurityEngineResult;
27  import org.apache.ws.security.WSSecurityException;
28  import org.apache.ws.security.components.crypto.Crypto;
29  import org.apache.ws.security.handler.RequestData;
30  import org.apache.ws.security.message.token.BinarySecurity;
31  import org.apache.ws.security.message.token.SecurityTokenReference;
32  import org.apache.ws.security.message.token.X509Security;
33  import org.apache.ws.security.saml.SAMLKeyInfo;
34  import org.apache.ws.security.saml.SAMLUtil;
35  import org.apache.ws.security.saml.ext.AssertionWrapper;
36  import org.w3c.dom.Element;
37  
38  import java.security.Principal;
39  import java.security.PublicKey;
40  import java.security.cert.X509Certificate;
41  import java.util.Map;
42  
43  import javax.xml.namespace.QName;
44  
45  /**
46   * This implementation of STRParser is for parsing a SecurityTokenReference element, found in the
47   * KeyInfo element associated with an EncryptedKey element
48   */
49  public class EncryptedKeySTRParser implements STRParser {
50      
51      private static final org.apache.commons.logging.Log LOG = 
52          org.apache.commons.logging.LogFactory.getLog(EncryptedKeySTRParser.class);
53      
54      private X509Certificate[] certs;
55      
56      private REFERENCE_TYPE referenceType;
57      
58      /**
59       * Parse a SecurityTokenReference element and extract credentials.
60       * 
61       * @param strElement The SecurityTokenReference element
62       * @param data the RequestData associated with the request
63       * @param wsDocInfo The WSDocInfo object to access previous processing results
64       * @param parameters A set of implementation-specific parameters
65       * @throws WSSecurityException
66       */
67      public void parseSecurityTokenReference(
68          Element strElement,
69          RequestData data,
70          WSDocInfo wsDocInfo,
71          Map<String, Object> parameters
72      ) throws WSSecurityException {
73          Crypto crypto = data.getDecCrypto();
74          WSSConfig config = data.getWssConfig();
75          boolean bspCompliant = true;
76          if (config != null) {
77              bspCompliant = config.isWsiBSPCompliant();
78          }
79          
80          SecurityTokenReference secRef = new SecurityTokenReference(strElement, bspCompliant);
81          
82          String uri = null;
83          if (secRef.containsReference()) {
84              uri = secRef.getReference().getURI();
85              if (uri.charAt(0) == '#') {
86                  uri = uri.substring(1);
87              }
88              referenceType = REFERENCE_TYPE.DIRECT_REF;
89          } else if (secRef.containsKeyIdentifier()) {
90              uri = secRef.getKeyIdentifierValue();
91              if (SecurityTokenReference.THUMB_URI.equals(secRef.getKeyIdentifierValueType())) {
92                  referenceType = REFERENCE_TYPE.THUMBPRINT_SHA1;
93              } else {
94                  referenceType = REFERENCE_TYPE.KEY_IDENTIFIER;
95              }
96          }
97          
98          WSSecurityEngineResult result = wsDocInfo.getResult(uri);
99          if (result != null) {
100             processPreviousResult(result, secRef, data, wsDocInfo, bspCompliant);
101         } else if (secRef.containsKeyIdentifier()) {
102             if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())
103                 || WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())) {
104                 AssertionWrapper assertion = 
105                     SAMLUtil.getAssertionFromKeyIdentifier(
106                         secRef, strElement, data, wsDocInfo
107                     );
108                 if (bspCompliant) {
109                     BSPEnforcer.checkSamlTokenBSPCompliance(secRef, assertion);
110                 }
111                 SAMLKeyInfo samlKi = 
112                     SAMLUtil.getCredentialFromSubject(assertion, 
113                                                       data, wsDocInfo, bspCompliant);
114                 certs = samlKi.getCerts();
115             } else {
116                 if (bspCompliant) {
117                     BSPEnforcer.checkBinarySecurityBSPCompliance(secRef, null);
118                 }
119                 certs = secRef.getKeyIdentifier(crypto);
120             }
121         } else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
122             referenceType = REFERENCE_TYPE.ISSUER_SERIAL;
123             certs = secRef.getX509IssuerSerial(crypto);
124         } else if (secRef.containsReference()) {
125             Element bstElement = 
126                 secRef.getTokenElement(strElement.getOwnerDocument(), wsDocInfo, data.getCallbackHandler());
127 
128             // at this point ... check token type: Binary
129             QName el = new QName(bstElement.getNamespaceURI(), bstElement.getLocalName());
130             if (el.equals(WSSecurityEngine.BINARY_TOKEN)) {
131                 X509Security token = new X509Security(bstElement);
132                 if (bspCompliant) {
133                     BSPEnforcer.checkBinarySecurityBSPCompliance(secRef, token);
134                 }
135                 certs = new X509Certificate[]{token.getX509Certificate(crypto)};
136             } else {
137                 throw new WSSecurityException(
138                     WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
139                     "unsupportedBinaryTokenType",
140                     null
141                 );
142             }
143         } 
144         
145         if (LOG.isDebugEnabled() && certs != null && certs[0] != null) {
146             LOG.debug("cert: " + certs[0]);
147         }
148     }
149     
150     /**
151      * Get the X509Certificates associated with this SecurityTokenReference
152      * @return the X509Certificates associated with this SecurityTokenReference
153      */
154     public X509Certificate[] getCertificates() {
155         return certs;
156     }
157     
158     /**
159      * Get the Principal associated with this SecurityTokenReference
160      * @return the Principal associated with this SecurityTokenReference
161      */
162     public Principal getPrincipal() {
163         return null;
164     }
165     
166     /**
167      * Get the PublicKey associated with this SecurityTokenReference
168      * @return the PublicKey associated with this SecurityTokenReference
169      */
170     public PublicKey getPublicKey() {
171         return null;
172     }
173     
174     /**
175      * Get the Secret Key associated with this SecurityTokenReference
176      * @return the Secret Key associated with this SecurityTokenReference
177      */
178     public byte[] getSecretKey() {
179         return null;
180     }
181     
182     /**
183      * Get whether the returned credential is already trusted or not. This is currently
184      * applicable in the case of a credential extracted from a trusted HOK SAML Assertion,
185      * and a BinarySecurityToken that has been processed by a Validator. In these cases,
186      * the SignatureProcessor does not need to verify trust on the credential.
187      * @return true if trust has already been verified on the returned Credential
188      */
189     public boolean isTrustedCredential() {
190         return false;
191     }
192     
193     /**
194      * Get how the certificates were referenced
195      * @return how the certificates were referenced
196      */
197     public REFERENCE_TYPE getCertificatesReferenceType() {
198         return referenceType;
199     }
200     
201     /**
202      * Process a previous security result
203      */
204     private void processPreviousResult(
205         WSSecurityEngineResult result,
206         SecurityTokenReference secRef,
207         RequestData data,
208         WSDocInfo wsDocInfo,
209         boolean bspCompliant
210     ) throws WSSecurityException {
211         int action = ((Integer)result.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
212         if (WSConstants.BST == action) {
213             if (bspCompliant) {
214                 BinarySecurity token = 
215                     (BinarySecurity)result.get(
216                         WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN
217                     );
218                 BSPEnforcer.checkBinarySecurityBSPCompliance(secRef, token);
219             }
220             certs = 
221                 (X509Certificate[])result.get(
222                     WSSecurityEngineResult.TAG_X509_CERTIFICATES
223                 );
224         } else if (WSConstants.ST_UNSIGNED == action || WSConstants.ST_SIGNED == action) {
225             AssertionWrapper assertion = 
226                 (AssertionWrapper)result.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
227             if (bspCompliant) {
228                 BSPEnforcer.checkSamlTokenBSPCompliance(secRef, assertion);
229             }
230             SAMLKeyInfo keyInfo = 
231                 SAMLUtil.getCredentialFromSubject(assertion, 
232                                                   data,
233                                                   wsDocInfo, bspCompliant);
234             certs = keyInfo.getCerts();
235         } else {
236             throw new WSSecurityException(
237                 WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
238                 "unsupportedBinaryTokenType",
239                 null
240             );
241         }
242     }
243     
244 }