| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.wss4j.stax.utils; |
| |
| import java.io.IOException; |
| import java.nio.charset.StandardCharsets; |
| import java.security.Key; |
| import java.security.MessageDigest; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.NoSuchProviderException; |
| import java.security.cert.CertificateEncodingException; |
| import java.security.cert.CertificateException; |
| import java.security.cert.CertificateFactory; |
| import java.security.cert.X509Certificate; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.security.auth.callback.Callback; |
| import javax.security.auth.callback.CallbackHandler; |
| import javax.security.auth.callback.UnsupportedCallbackException; |
| import javax.xml.namespace.QName; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.events.Attribute; |
| |
| import org.apache.commons.codec.binary.Base64; |
| import org.apache.wss4j.common.crypto.Merlin; |
| import org.apache.wss4j.common.ext.WSSecurityException; |
| import org.apache.wss4j.stax.ext.WSSConstants; |
| import org.apache.wss4j.stax.ext.WSSSecurityProperties; |
| import org.apache.wss4j.stax.securityEvent.DerivedKeyTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.EncryptedKeyTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.HttpsTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.KerberosTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.KeyValueTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.RelTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.SamlTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.SecurityContextTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.UsernameTokenSecurityEvent; |
| import org.apache.wss4j.stax.securityEvent.X509TokenSecurityEvent; |
| import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants; |
| import org.apache.xml.security.exceptions.XMLSecurityException; |
| import org.apache.xml.security.stax.ext.AbstractOutputProcessor; |
| import org.apache.xml.security.stax.ext.OutputProcessorChain; |
| import org.apache.xml.security.stax.ext.SecurePart; |
| import org.apache.xml.security.stax.ext.XMLSecurityConstants; |
| import org.apache.xml.security.stax.ext.XMLSecurityUtils; |
| import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; |
| import org.apache.xml.security.stax.ext.stax.XMLSecEvent; |
| import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; |
| import org.apache.xml.security.stax.impl.EncryptionPartDef; |
| import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent; |
| import org.apache.xml.security.stax.securityToken.InboundSecurityToken; |
| import org.apache.xml.security.stax.securityToken.SecurityToken; |
| |
| public class WSSUtils extends XMLSecurityUtils { |
| |
| protected WSSUtils() { |
| super(); |
| } |
| |
| /** |
| * Executes the Callback handling. Typically used to fetch passwords |
| * |
| * @param callbackHandler |
| * @param callback |
| * @throws WSSecurityException if the callback couldn't be executed |
| */ |
| public static void doPasswordCallback(CallbackHandler callbackHandler, Callback callback) |
| throws WSSecurityException { |
| |
| if (callbackHandler == null) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCallback"); |
| } |
| try { |
| callbackHandler.handle(new Callback[]{callback}); |
| } catch (IOException | UnsupportedCallbackException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); |
| } |
| } |
| |
| /** |
| * Try to get the secret key from a CallbackHandler implementation |
| * |
| * @param callbackHandler a CallbackHandler implementation |
| * @throws WSSecurityException |
| */ |
| public static void doSecretKeyCallback(CallbackHandler callbackHandler, Callback callback, String id) |
| throws WSSecurityException { |
| |
| if (callbackHandler != null) { |
| try { |
| callbackHandler.handle(new Callback[]{callback}); |
| } catch (IOException | UnsupportedCallbackException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "noPassword"); |
| } |
| } |
| } |
| |
| public static String doPasswordDigest(byte[] nonce, String created, String password) throws WSSecurityException { |
| try { |
| byte[] b1 = nonce != null ? nonce : new byte[0]; |
| byte[] b2 = created != null ? created.getBytes(StandardCharsets.UTF_8) : new byte[0]; |
| byte[] b3 = password.getBytes(StandardCharsets.UTF_8); |
| byte[] b4 = new byte[b1.length + b2.length + b3.length]; |
| int offset = 0; |
| System.arraycopy(b1, 0, b4, offset, b1.length); |
| offset += b1.length; |
| |
| System.arraycopy(b2, 0, b4, offset, b2.length); |
| offset += b2.length; |
| |
| System.arraycopy(b3, 0, b4, offset, b3.length); |
| |
| MessageDigest sha = MessageDigest.getInstance("SHA-1"); |
| sha.reset(); |
| sha.update(b4); |
| return new String(Base64.encodeBase64(sha.digest())); |
| } catch (NoSuchAlgorithmException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "decoding.general"); |
| } |
| } |
| |
| public static String getSOAPMessageVersionNamespace(XMLSecEvent xmlSecEvent) { |
| XMLSecStartElement xmlSecStartElement = xmlSecEvent.getStartElementAtLevel(1); |
| if (xmlSecStartElement != null) { |
| if (WSSConstants.TAG_SOAP11_ENVELOPE.equals(xmlSecStartElement.getName())) { |
| return WSSConstants.NS_SOAP11; |
| } else if (WSSConstants.TAG_SOAP12_ENVELOPE.equals(xmlSecStartElement.getName())) { |
| return WSSConstants.NS_SOAP12; |
| } |
| } |
| return null; |
| } |
| |
| public static boolean isInSOAPHeader(XMLSecEvent xmlSecEvent) { |
| final List<QName> elementPath = xmlSecEvent.getElementPath(); |
| return isInSOAPHeader(elementPath); |
| } |
| |
| public static boolean isInSOAPHeader(List<QName> elementPath) { |
| if (elementPath.size() > 1) { |
| final QName secondLevelElementName = elementPath.get(1); |
| return WSSConstants.TAG_SOAP_HEADER_LN.equals(secondLevelElementName.getLocalPart()) |
| && elementPath.get(0).getNamespaceURI().equals(secondLevelElementName.getNamespaceURI()); |
| } |
| return false; |
| } |
| |
| public static boolean isInSOAPBody(XMLSecEvent xmlSecEvent) { |
| final List<QName> elementPath = xmlSecEvent.getElementPath(); |
| return isInSOAPBody(elementPath); |
| } |
| |
| public static boolean isInSOAPBody(List<QName> elementPath) { |
| if (elementPath.size() > 1) { |
| final QName secondLevelElementName = elementPath.get(1); |
| return WSSConstants.TAG_SOAP_BODY_LN.equals(secondLevelElementName.getLocalPart()) |
| && elementPath.get(0).getNamespaceURI().equals(secondLevelElementName.getNamespaceURI()); |
| } |
| return false; |
| } |
| |
| public static boolean isInSecurityHeader(XMLSecEvent xmlSecEvent, String actorOrRole) { |
| final List<QName> elementPath = xmlSecEvent.getElementPath(); |
| return isInSecurityHeader(xmlSecEvent, elementPath, actorOrRole); |
| } |
| |
| public static boolean isInSecurityHeader(XMLSecEvent xmlSecEvent, List<QName> elementPath, String actorOrRole) { |
| if (elementPath.size() > 2) { |
| final QName secondLevelElementName = elementPath.get(1); |
| return WSSConstants.TAG_WSSE_SECURITY.equals(elementPath.get(2)) |
| && isResponsibleActorOrRole(xmlSecEvent.getStartElementAtLevel(3), actorOrRole) |
| && WSSConstants.TAG_SOAP_HEADER_LN.equals(secondLevelElementName.getLocalPart()) |
| && elementPath.get(0).getNamespaceURI().equals(secondLevelElementName.getNamespaceURI()); |
| } |
| return false; |
| } |
| |
| public static boolean isSecurityHeaderElement(XMLSecEvent xmlSecEvent, String actorOrRole) { |
| if (!xmlSecEvent.isStartElement()) { |
| return false; |
| } |
| |
| final List<QName> elementPath = xmlSecEvent.getElementPath(); |
| if (elementPath.size() == 3) { |
| final QName secondLevelElementName = elementPath.get(1); |
| return WSSConstants.TAG_WSSE_SECURITY.equals(elementPath.get(2)) |
| && isResponsibleActorOrRole(xmlSecEvent.getStartElementAtLevel(3), actorOrRole) |
| && WSSConstants.TAG_SOAP_HEADER_LN.equals(secondLevelElementName.getLocalPart()) |
| && elementPath.get(0).getNamespaceURI().equals(secondLevelElementName.getNamespaceURI()); |
| } |
| return false; |
| } |
| |
| public static boolean isResponsibleActorOrRole(XMLSecStartElement xmlSecStartElement, String responsibleActor) { |
| final QName actorRole; |
| final String soapVersionNamespace = getSOAPMessageVersionNamespace(xmlSecStartElement); |
| if (WSSConstants.NS_SOAP11.equals(soapVersionNamespace)) { |
| actorRole = WSSConstants.ATT_SOAP11_ACTOR; |
| } else { |
| actorRole = WSSConstants.ATT_SOAP12_ROLE; |
| } |
| |
| String actor = null; |
| Attribute attribute = xmlSecStartElement.getAttributeByName(actorRole); |
| if (attribute != null) { |
| actor = attribute.getValue(); |
| } |
| |
| if (responsibleActor == null) { |
| return actor == null; |
| } else { |
| return responsibleActor.equals(actor); |
| } |
| } |
| |
| public static void createBinarySecurityTokenStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, |
| String referenceId, X509Certificate[] x509Certificates, |
| boolean useSingleCertificate) |
| throws XMLStreamException, XMLSecurityException { |
| String valueType; |
| if (useSingleCertificate) { |
| valueType = WSSConstants.NS_X509_V3_TYPE; |
| } else { |
| valueType = WSSConstants.NS_X509_PKIPATH_V1; |
| } |
| List<XMLSecAttribute> attributes = new ArrayList<>(3); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_ENCODING_TYPE, |
| WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, valueType)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_WSU_ID, referenceId)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_BINARY_SECURITY_TOKEN, |
| false, attributes); |
| try { |
| if (useSingleCertificate) { |
| String encodedCert = |
| new Base64(76, new byte[]{'\n'}).encodeToString(x509Certificates[0].getEncoded()); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, encodedCert); |
| } else { |
| try { |
| CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC"); |
| List<X509Certificate> certificates = Arrays.asList(x509Certificates); |
| String encodedCert = |
| new Base64(76, new byte[]{'\n'}).encodeToString(certificateFactory.generateCertPath(certificates).getEncoded()); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, encodedCert); |
| } catch (CertificateException | NoSuchProviderException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); |
| } |
| } |
| } catch (CertificateEncodingException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); |
| } |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_BINARY_SECURITY_TOKEN); |
| } |
| |
| public static void createX509SubjectKeyIdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, |
| X509Certificate[] x509Certificates) |
| throws XMLSecurityException, XMLStreamException { |
| // As per the 1.1 specification, SKI can only be used for a V3 certificate |
| if (x509Certificates[0].getVersion() != 3) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidCertForSKI"); |
| } |
| |
| List<XMLSecAttribute> attributes = new ArrayList<>(2); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_ENCODING_TYPE, |
| WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, |
| WSSConstants.NS_X509_SKI)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_KEY_IDENTIFIER, |
| false, attributes); |
| byte[] data = new Merlin().getSKIBytesFromCert(x509Certificates[0]); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, |
| new Base64(76, new byte[]{'\n'}).encodeToString(data)); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_KEY_IDENTIFIER); |
| } |
| |
| public static void createX509KeyIdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, |
| X509Certificate[] x509Certificates) |
| throws XMLStreamException, XMLSecurityException { |
| List<XMLSecAttribute> attributes = new ArrayList<>(2); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_ENCODING_TYPE, |
| WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, |
| WSSConstants.NS_X509_V3_TYPE)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_KEY_IDENTIFIER, |
| false, attributes); |
| try { |
| String encodedCert = new Base64(76, new byte[]{'\n'}).encodeToString(x509Certificates[0].getEncoded()); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, encodedCert); |
| } catch (CertificateEncodingException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); |
| } |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_KEY_IDENTIFIER); |
| } |
| |
| public static void createThumbprintKeyIdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, |
| X509Certificate[] x509Certificates) |
| throws XMLStreamException, XMLSecurityException { |
| List<XMLSecAttribute> attributes = new ArrayList<>(2); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_ENCODING_TYPE, |
| WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, |
| WSSConstants.NS_THUMBPRINT)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_KEY_IDENTIFIER, |
| false, attributes); |
| try { |
| MessageDigest sha = MessageDigest.getInstance("SHA-1"); |
| byte[] data = sha.digest(x509Certificates[0].getEncoded()); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, |
| new Base64(76, new byte[]{'\n'}).encodeToString(data)); |
| } catch (CertificateEncodingException | NoSuchAlgorithmException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); |
| } |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER); |
| } |
| |
| public static void createEncryptedKeySha1IdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, Key key) |
| throws XMLStreamException, XMLSecurityException { |
| |
| try { |
| MessageDigest sha = MessageDigest.getInstance("SHA-1"); |
| byte[] data = sha.digest(key.getEncoded()); |
| createEncryptedKeySha1IdentifierStructure(abstractOutputProcessor, outputProcessorChain, |
| new Base64(76, new byte[]{'\n'}).encodeToString(data)); |
| } catch (NoSuchAlgorithmException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); |
| } |
| } |
| |
| public static void createEncryptedKeySha1IdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, String identifier) |
| throws XMLStreamException, XMLSecurityException { |
| |
| List<XMLSecAttribute> attributes = new ArrayList<>(2); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_ENCODING_TYPE, |
| WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, |
| WSSConstants.NS_ENCRYPTED_KEY_SHA1)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER, |
| false, attributes); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, identifier); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER); |
| } |
| |
| public static void createKerberosSha1IdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, String identifier) |
| throws XMLStreamException, XMLSecurityException { |
| |
| List<XMLSecAttribute> attributes = new ArrayList<>(2); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_ENCODING_TYPE, |
| WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, |
| WSSConstants.NS_KERBEROS5_AP_REQ_SHA1)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER, |
| false, attributes); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, identifier); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER); |
| } |
| |
| public static void createBSTReferenceStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, String referenceId, |
| String valueType, boolean includedInMessage) |
| throws XMLStreamException, XMLSecurityException { |
| List<XMLSecAttribute> attributes = new ArrayList<>(2); |
| String uri = includedInMessage ? "#" + referenceId : referenceId; |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_URI, uri)); |
| if (valueType != null) { |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, valueType)); |
| } |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_REFERENCE, |
| false, attributes); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_REFERENCE); |
| } |
| |
| public static void createEmbeddedKeyIdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, |
| WSSecurityTokenConstants.TokenType tokenType, String referenceId) |
| throws XMLStreamException, XMLSecurityException { |
| List<XMLSecAttribute> attributes = new ArrayList<>(1); |
| if (WSSecurityTokenConstants.SAML_10_TOKEN.equals(tokenType) || WSSecurityTokenConstants.SAML_11_TOKEN.equals(tokenType)) { |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, WSSConstants.NS_SAML10_TYPE)); |
| } else if (WSSecurityTokenConstants.SAML_20_TOKEN.equals(tokenType)) { |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, WSSConstants.NS_SAML20_TYPE)); |
| } |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER, |
| false, attributes); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, referenceId); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER); |
| } |
| |
| public static void createSAMLKeyIdentifierStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, |
| WSSecurityTokenConstants.TokenType tokenType, String referenceId) |
| throws XMLStreamException, XMLSecurityException { |
| List<XMLSecAttribute> attributes = new ArrayList<>(1); |
| if (WSSecurityTokenConstants.SAML_10_TOKEN.equals(tokenType) || WSSecurityTokenConstants.SAML_11_TOKEN.equals(tokenType)) { |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, WSSConstants.NS_SAML10_TYPE)); |
| } else if (WSSecurityTokenConstants.SAML_20_TOKEN.equals(tokenType)) { |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, WSSConstants.NS_SAML20_TYPE)); |
| } |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER, |
| false, attributes); |
| abstractOutputProcessor.createCharactersAndOutputAsEvent(outputProcessorChain, referenceId); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_KEY_IDENTIFIER); |
| } |
| |
| public static void createUsernameTokenReferenceStructure(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain, String tokenId) |
| throws XMLStreamException, XMLSecurityException { |
| List<XMLSecAttribute> attributes = new ArrayList<>(2); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_URI, "#" + tokenId)); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, |
| WSSConstants.NS_USERNAMETOKEN_PROFILE_USERNAME_TOKEN)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_REFERENCE, |
| false, attributes); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_REFERENCE); |
| } |
| |
| public static void createReferenceListStructureForEncryption(AbstractOutputProcessor abstractOutputProcessor, |
| OutputProcessorChain outputProcessorChain) |
| throws XMLStreamException, XMLSecurityException { |
| List<EncryptionPartDef> encryptionPartDefs = |
| outputProcessorChain.getSecurityContext().getAsList(EncryptionPartDef.class); |
| if (encryptionPartDefs == null) { |
| return; |
| } |
| List<XMLSecAttribute> attributes; |
| abstractOutputProcessor.createStartElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_xenc_ReferenceList, true, null); |
| //output the references to the encrypted data: |
| Iterator<EncryptionPartDef> encryptionPartDefIterator = encryptionPartDefs.iterator(); |
| while (encryptionPartDefIterator.hasNext()) { |
| EncryptionPartDef encryptionPartDef = encryptionPartDefIterator.next(); |
| |
| attributes = new ArrayList<>(1); |
| attributes.add(abstractOutputProcessor.createAttribute( |
| XMLSecurityConstants.ATT_NULL_URI, "#" + encryptionPartDef.getEncRefId())); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_xenc_DataReference, false, attributes); |
| final String compressionAlgorithm = |
| ((WSSSecurityProperties)abstractOutputProcessor.getSecurityProperties()).getEncryptionCompressionAlgorithm(); |
| if (compressionAlgorithm != null) { |
| abstractOutputProcessor.createStartElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_dsig_Transforms, true, null); |
| attributes = new ArrayList<>(1); |
| attributes.add(abstractOutputProcessor.createAttribute( |
| XMLSecurityConstants.ATT_NULL_Algorithm, compressionAlgorithm)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform, false, attributes); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_dsig_Transforms); |
| } |
| abstractOutputProcessor.createEndElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_xenc_DataReference); |
| } |
| abstractOutputProcessor.createEndElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_xenc_ReferenceList); |
| } |
| |
| public static void createEncryptedDataStructureForAttachments( |
| AbstractOutputProcessor abstractOutputProcessor, OutputProcessorChain outputProcessorChain) |
| throws XMLStreamException, XMLSecurityException { |
| |
| List<EncryptionPartDef> encryptionPartDefs = |
| outputProcessorChain.getSecurityContext().getAsList(EncryptionPartDef.class); |
| if (encryptionPartDefs == null) { |
| return; |
| } |
| |
| Iterator<EncryptionPartDef> encryptionPartDefIterator = encryptionPartDefs.iterator(); |
| while (encryptionPartDefIterator.hasNext()) { |
| EncryptionPartDef encryptionPartDef = encryptionPartDefIterator.next(); |
| |
| if (encryptionPartDef.getCipherReferenceId() == null) { |
| continue; |
| } |
| |
| List<XMLSecAttribute> attributes = new ArrayList<>(3); |
| attributes.add(abstractOutputProcessor.createAttribute(XMLSecurityConstants.ATT_NULL_Id, |
| encryptionPartDef.getEncRefId())); |
| if (encryptionPartDef.getModifier() == SecurePart.Modifier.Element) { |
| attributes.add( |
| abstractOutputProcessor.createAttribute(XMLSecurityConstants.ATT_NULL_Type, |
| WSSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE)); |
| } else { |
| attributes.add( |
| abstractOutputProcessor.createAttribute(XMLSecurityConstants.ATT_NULL_Type, |
| WSSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY)); |
| } |
| attributes.add( |
| abstractOutputProcessor.createAttribute(XMLSecurityConstants.ATT_NULL_MimeType, |
| encryptionPartDef.getMimeType())); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_EncryptedData, true, attributes); |
| |
| attributes = new ArrayList<>(1); |
| attributes.add(abstractOutputProcessor.createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, |
| abstractOutputProcessor.getSecurityProperties().getEncryptionSymAlgorithm())); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_EncryptionMethod, false, attributes); |
| |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_EncryptionMethod); |
| |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_dsig_KeyInfo, true, null); |
| |
| attributes = new ArrayList<>(1); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_WSSE11_TOKEN_TYPE, |
| WSSConstants.NS_WSS_ENC_KEY_VALUE_TYPE)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_SECURITY_TOKEN_REFERENCE, true, attributes); |
| |
| attributes = new ArrayList<XMLSecAttribute>(1); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_URI, |
| "#" + encryptionPartDef.getKeyId())); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_REFERENCE, false, attributes); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_REFERENCE); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| WSSConstants.TAG_WSSE_SECURITY_TOKEN_REFERENCE); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_dsig_KeyInfo); |
| |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_CipherData, false, null); |
| |
| attributes = new ArrayList<>(1); |
| attributes.add(abstractOutputProcessor.createAttribute(WSSConstants.ATT_NULL_URI, |
| "cid:" + encryptionPartDef.getCipherReferenceId())); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_CipherReference, false, attributes); |
| |
| abstractOutputProcessor.createStartElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_xenc_Transforms, false, null); |
| |
| attributes = new ArrayList<>(1); |
| attributes.add(abstractOutputProcessor.createAttribute( |
| XMLSecurityConstants.ATT_NULL_Algorithm, WSSConstants.SWA_ATTACHMENT_CIPHERTEXT_TRANS)); |
| abstractOutputProcessor.createStartElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform, true, attributes); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent( |
| outputProcessorChain, XMLSecurityConstants.TAG_dsig_Transforms); |
| |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_CipherReference); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_CipherData); |
| abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, |
| XMLSecurityConstants.TAG_xenc_EncryptedData); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static TokenSecurityEvent<? extends InboundSecurityToken> |
| createTokenSecurityEvent(final InboundSecurityToken inboundSecurityToken, String correlationID) |
| throws WSSecurityException { |
| WSSecurityTokenConstants.TokenType tokenType = inboundSecurityToken.getTokenType(); |
| |
| TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent; |
| if (WSSecurityTokenConstants.X509V1Token.equals(tokenType) |
| || WSSecurityTokenConstants.X509V3Token.equals(tokenType) |
| || WSSecurityTokenConstants.X509Pkcs7Token.equals(tokenType) |
| || WSSecurityTokenConstants.X509PkiPathV1Token.equals(tokenType)) { |
| tokenSecurityEvent = new X509TokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.USERNAME_TOKEN.equals(tokenType)) { |
| tokenSecurityEvent = new UsernameTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.KERBEROS_TOKEN.equals(tokenType)) { |
| tokenSecurityEvent = new KerberosTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.SECURITY_CONTEXT_TOKEN.equals(tokenType)) { |
| tokenSecurityEvent = new SecurityContextTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.SAML_10_TOKEN.equals(tokenType) |
| || WSSecurityTokenConstants.SAML_11_TOKEN.equals(tokenType) |
| || WSSecurityTokenConstants.SAML_20_TOKEN.equals(tokenType)) { |
| tokenSecurityEvent = new SamlTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.REL_TOKEN.equals(tokenType)) { |
| tokenSecurityEvent = new RelTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.HTTPS_TOKEN.equals(tokenType)) { |
| tokenSecurityEvent = new HttpsTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.KeyValueToken.equals(tokenType)) { |
| tokenSecurityEvent = new KeyValueTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.DerivedKeyToken.equals(tokenType)) { |
| tokenSecurityEvent = new DerivedKeyTokenSecurityEvent(); |
| } else if (WSSecurityTokenConstants.EncryptedKeyToken.equals(tokenType)) { |
| tokenSecurityEvent = new EncryptedKeyTokenSecurityEvent(); |
| } else { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN); |
| } |
| ((TokenSecurityEvent<SecurityToken>)tokenSecurityEvent).setSecurityToken(inboundSecurityToken); |
| tokenSecurityEvent.setCorrelationID(correlationID); |
| return (TokenSecurityEvent<? extends InboundSecurityToken>)tokenSecurityEvent; |
| } |
| |
| public static boolean pathMatches(List<QName> path1, List<QName> path2, |
| boolean matchAnySoapNS, boolean lastElementWildCard) { |
| if (path1 == null) { |
| throw new IllegalArgumentException("Internal error"); |
| } |
| if (path2 == null || path1.size() != path2.size()) { |
| return false; |
| } |
| Iterator<QName> path1Iterator = path1.iterator(); |
| Iterator<QName> path2Iterator = path2.iterator(); |
| while (path1Iterator.hasNext()) { |
| QName qName1 = path1Iterator.next(); |
| QName qName2 = path2Iterator.next(); |
| if (matchAnySoapNS && (WSSConstants.NS_SOAP11.equals(qName1.getNamespaceURI()) |
| || WSSConstants.NS_SOAP12.equals(qName1.getNamespaceURI()))) { |
| if (!qName1.getLocalPart().equals(qName2.getLocalPart())) { |
| return false; |
| } |
| } else if (!qName1.equals(qName2)) { |
| if (!path1Iterator.hasNext() && lastElementWildCard) { |
| if (!qName1.getNamespaceURI().equals(qName2.getNamespaceURI())) { |
| return false; |
| } |
| } else { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| public static String pathAsString(List<QName> path) { |
| StringBuilder stringBuilder = new StringBuilder(); |
| Iterator<QName> pathIterator = path.iterator(); |
| while (pathIterator.hasNext()) { |
| QName qName = pathIterator.next(); |
| stringBuilder.append('/'); |
| stringBuilder.append(qName.toString()); |
| } |
| return stringBuilder.toString(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static <T extends SecurityToken> T getRootToken(T securityToken) throws XMLSecurityException { |
| T tmp = securityToken; |
| while (tmp.getKeyWrappingToken() != null) { |
| tmp = (T)tmp.getKeyWrappingToken(); |
| } |
| return tmp; |
| } |
| |
| } |