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