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.processor;
21  
22  import org.apache.ws.security.SAMLTokenPrincipal;
23  import org.apache.ws.security.WSConstants;
24  import org.apache.ws.security.WSDocInfo;
25  import org.apache.ws.security.WSSConfig;
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.KerberosSecurity;
32  import org.apache.ws.security.message.token.PKIPathSecurity;
33  import org.apache.ws.security.message.token.X509Security;
34  import org.apache.ws.security.validate.Credential;
35  import org.apache.ws.security.validate.Validator;
36  import org.w3c.dom.Element;
37  
38  import java.security.cert.X509Certificate;
39  import java.util.List;
40  import javax.xml.namespace.QName;
41  
42  /**
43   * Processor implementation to handle wsse:BinarySecurityToken elements
44   */
45  public class BinarySecurityTokenProcessor implements Processor {
46      
47      /**
48       * {@inheritDoc}
49       */
50      public List<WSSecurityEngineResult> handleToken(
51          Element elem, 
52          RequestData data,
53          WSDocInfo wsDocInfo
54      ) throws WSSecurityException {
55          // See if the token has been previously processed
56          String id = elem.getAttributeNS(WSConstants.WSU_NS, "Id");
57          if (!"".equals(id)) {
58              Element foundElement = wsDocInfo.getTokenElement(id);
59              if (elem.equals(foundElement)) {
60                  WSSecurityEngineResult result = wsDocInfo.getResult(id);
61                  return java.util.Collections.singletonList(result);
62              } else if (foundElement != null) {
63                  throw new WSSecurityException(
64                      WSSecurityException.INVALID_SECURITY_TOKEN, "duplicateError"
65                  );
66              }
67          }
68          
69          BinarySecurity token = createSecurityToken(elem, data.getWssConfig());
70          X509Certificate[] certs = null;
71          Validator validator = data.getValidator(new QName(elem.getNamespaceURI(),
72                                                            elem.getLocalName()));
73          
74          if (data.getSigCrypto() == null) {
75              certs = getCertificatesTokenReference(token, data.getDecCrypto());
76          } else {
77              certs = getCertificatesTokenReference(token, data.getSigCrypto());
78          }
79          
80          WSSecurityEngineResult result = 
81              new WSSecurityEngineResult(WSConstants.BST, token, certs);
82          wsDocInfo.addTokenElement(elem);
83          result.put(WSSecurityEngineResult.TAG_ID, id);
84          
85          if (validator != null) {
86              // Hook to allow the user to validate the BinarySecurityToken
87              Credential credential = new Credential();
88              credential.setBinarySecurityToken(token);
89              credential.setCertificates(certs);
90              
91              Credential returnedCredential = validator.validate(credential, data);
92              result.put(WSSecurityEngineResult.TAG_VALIDATED_TOKEN, Boolean.TRUE);
93              result.put(WSSecurityEngineResult.TAG_SECRET, returnedCredential.getSecretKey());
94              
95              if (returnedCredential.getTransformedToken() != null) {
96                  result.put(
97                      WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN, 
98                      returnedCredential.getTransformedToken()
99                  );
100                 SAMLTokenPrincipal samlPrincipal = 
101                     new SAMLTokenPrincipal(credential.getTransformedToken());
102                 result.put(WSSecurityEngineResult.TAG_PRINCIPAL, samlPrincipal);
103             } else if (credential.getPrincipal() != null) {
104                 result.put(WSSecurityEngineResult.TAG_PRINCIPAL, credential.getPrincipal());
105             } else if (certs != null && certs[0] != null) {
106                 result.put(WSSecurityEngineResult.TAG_PRINCIPAL, certs[0].getSubjectX500Principal());
107             }
108             result.put(WSSecurityEngineResult.TAG_SUBJECT, credential.getSubject());
109         }
110         
111         wsDocInfo.addResult(result);
112         return java.util.Collections.singletonList(result);
113     }
114     
115     /**
116      * Extracts the certificate(s) from the Binary Security token reference.
117      *
118      * @param token The BinarySecurity instance corresponding to either X509Security or 
119      *              PKIPathSecurity
120      * @return The X509Certificates associated with this reference
121      * @throws WSSecurityException
122      */
123     private X509Certificate[] getCertificatesTokenReference(BinarySecurity token, Crypto crypto)
124         throws WSSecurityException {
125         if (token instanceof PKIPathSecurity) {
126             return ((PKIPathSecurity) token).getX509Certificates(crypto);
127         } else if (token instanceof X509Security) {
128             X509Certificate cert = ((X509Security) token).getX509Certificate(crypto);
129             return new X509Certificate[]{cert};
130         }
131         return null;
132     }
133 
134     /**
135      * Checks the <code>element</code> and creates appropriate binary security object.
136      *
137      * @param element The XML element that contains either a <code>BinarySecurityToken
138      *                </code> or a <code>PKIPath</code> element.
139      * @param config A WSSConfig instance
140      * @return a BinarySecurity token element
141      * @throws WSSecurityException
142      */
143     private BinarySecurity createSecurityToken(
144         Element element,
145         WSSConfig config
146     ) throws WSSecurityException {
147         String type = element.getAttribute("ValueType");
148         BinarySecurity token = null;
149         if (X509Security.X509_V3_TYPE.equals(type)) {
150             token = new X509Security(element, config.isWsiBSPCompliant());
151         } else if (PKIPathSecurity.getType().equals(type)) {
152             token = new PKIPathSecurity(element, config.isWsiBSPCompliant());
153         } else if (KerberosSecurity.isKerberosToken(type)) {
154             token = new KerberosSecurity(element, config.isWsiBSPCompliant());
155         } else {
156             token = new BinarySecurity(element, config.isWsiBSPCompliant());
157         }
158         return token;
159     }
160     
161 }