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  package org.apache.wss4j.stax.validate;
20  
21  import java.util.Base64;
22  
23  import jakarta.xml.bind.JAXBElement;
24  
25  import org.apache.wss4j.binding.wss10.BinarySecurityTokenType;
26  import org.apache.wss4j.common.crypto.Crypto;
27  import org.apache.wss4j.common.ext.WSSecurityException;
28  import org.apache.wss4j.common.util.AttachmentUtils;
29  import org.apache.wss4j.stax.ext.WSSConfigurationException;
30  import org.apache.wss4j.stax.ext.WSSConstants;
31  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
32  import org.apache.wss4j.stax.impl.securityToken.X509V3SecurityTokenImpl;
33  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
34  import org.apache.wss4j.stax.impl.securityToken.KerberosServiceSecurityTokenImpl;
35  import org.apache.wss4j.stax.impl.securityToken.X509PKIPathv1SecurityTokenImpl;
36  import org.apache.xml.security.binding.xop.Include;
37  import org.apache.xml.security.exceptions.XMLSecurityException;
38  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
39  import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
40  
41  public class BinarySecurityTokenValidatorImpl implements BinarySecurityTokenValidator {
42  
43      private static final transient org.slf4j.Logger LOG =
44          org.slf4j.LoggerFactory.getLogger(BinarySecurityTokenValidatorImpl.class);
45  
46      @Override
47      public InboundSecurityToken validate(final BinarySecurityTokenType binarySecurityTokenType,
48                                                   final TokenContext tokenContext)
49              throws WSSecurityException {
50  
51          //only Base64Encoding is supported
52          if (!WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING.equals(binarySecurityTokenType.getEncodingType())) {
53              throw new WSSecurityException(
54                      WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "badEncoding",
55                      new Object[] {binarySecurityTokenType.getEncodingType()});
56          }
57  
58          try {
59              byte[] securityTokenData =
60                  getBinarySecurityTokenBytes(binarySecurityTokenType, tokenContext.getWssSecurityProperties());
61  
62              if (WSSConstants.NS_X509_V3_TYPE.equals(binarySecurityTokenType.getValueType())) {
63                  Crypto crypto = getCrypto(tokenContext.getWssSecurityProperties());
64                  X509V3SecurityTokenImpl x509V3SecurityToken = new X509V3SecurityTokenImpl(
65                          tokenContext.getWsSecurityContext(),
66                          crypto,
67                          tokenContext.getWssSecurityProperties().getCallbackHandler(),
68                          securityTokenData, binarySecurityTokenType.getId(),
69                          tokenContext.getWssSecurityProperties()
70                  );
71                  x509V3SecurityToken.setElementPath(tokenContext.getElementPath());
72                  x509V3SecurityToken.setXMLSecEvent(tokenContext.getFirstXMLSecEvent());
73                  return x509V3SecurityToken;
74              } else if (WSSConstants.NS_X509_PKIPATH_V1.equals(binarySecurityTokenType.getValueType())) {
75                  Crypto crypto = getCrypto(tokenContext.getWssSecurityProperties());
76                  X509PKIPathv1SecurityTokenImpl x509PKIPathv1SecurityToken = new X509PKIPathv1SecurityTokenImpl(
77                          tokenContext.getWsSecurityContext(),
78                          crypto,
79                          tokenContext.getWssSecurityProperties().getCallbackHandler(),
80                          securityTokenData, binarySecurityTokenType.getId(),
81                          WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE,
82                          tokenContext.getWssSecurityProperties()
83                  );
84                  x509PKIPathv1SecurityToken.setElementPath(tokenContext.getElementPath());
85                  x509PKIPathv1SecurityToken.setXMLSecEvent(tokenContext.getFirstXMLSecEvent());
86                  return x509PKIPathv1SecurityToken;
87              } else if (WSSConstants.NS_GSS_KERBEROS5_AP_REQ.equals(binarySecurityTokenType.getValueType())) {
88                  KerberosServiceSecurityTokenImpl kerberosServiceSecurityToken = new KerberosServiceSecurityTokenImpl(
89                          tokenContext.getWsSecurityContext(),
90                          tokenContext.getWssSecurityProperties().getCallbackHandler(),
91                          securityTokenData, binarySecurityTokenType.getValueType(),
92                          binarySecurityTokenType.getId(),
93                          WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE
94                  );
95                  kerberosServiceSecurityToken.setElementPath(tokenContext.getElementPath());
96                  kerberosServiceSecurityToken.setXMLSecEvent(tokenContext.getFirstXMLSecEvent());
97                  return kerberosServiceSecurityToken;
98              } else {
99                  throw new WSSecurityException(
100                         WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "invalidValueType",
101                         new Object[] {binarySecurityTokenType.getValueType()});
102             }
103         } catch (XMLSecurityException e) {
104             throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, e);
105         }
106     }
107 
108     private byte[] getBinarySecurityTokenBytes(BinarySecurityTokenType binarySecurityTokenType,
109                                                WSSSecurityProperties wssSecurityProperties) throws XMLSecurityException {
110 
111         StringBuilder sb = new StringBuilder();
112 
113         for (Object obj : binarySecurityTokenType.getContent()) {
114             if (obj instanceof String) {
115                 sb.append((String)obj);
116             } else if (obj instanceof JAXBElement<?>) {
117                 JAXBElement<?> element = (JAXBElement<?>)obj;
118                 if (XMLSecurityConstants.TAG_XOP_INCLUDE.equals(element.getName())) {
119                     Include include = (Include)element.getValue();
120                     if (include != null && include.getHref() != null && include.getHref().startsWith("cid:")) {
121                         return AttachmentUtils.getBytesFromAttachment(include.getHref(),
122                                                                       wssSecurityProperties.getAttachmentCallbackHandler(),
123                                                                       true);
124                     }
125                 }
126             }
127         }
128 
129         return Base64.getMimeDecoder().decode(sb.toString());
130     }
131 
132     protected Crypto getCrypto(WSSSecurityProperties securityProperties) throws WSSConfigurationException {
133         Crypto crypto = null;
134         try {
135             crypto = securityProperties.getSignatureVerificationCrypto();
136         } catch (WSSConfigurationException e) {
137             LOG.debug(e.getMessage(), e);
138             //ignore
139         }
140         if (crypto == null) {
141             crypto = securityProperties.getDecryptionCrypto();
142         }
143         return crypto;
144     }
145 }