/** * 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.setup; import java.io.OutputStream; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.cert.X509Certificate; import java.util.List; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec; import javax.xml.stream.XMLStreamWriter; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.crypto.CryptoType; import org.apache.wss4j.common.ext.WSPasswordCallback; 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.impl.processor.output.BinarySecurityTokenOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.CustomTokenOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.DerivedKeyTokenOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.EncryptEndingOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.EncryptOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.EncryptedKeyOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.ReferenceListOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.SAMLTokenOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.SecurityContextTokenOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.SecurityHeaderOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.SecurityHeaderReorderProcessor; import org.apache.wss4j.stax.impl.processor.output.SignatureConfirmationOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.TimestampOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.UsernameTokenOutputProcessor; import org.apache.wss4j.stax.impl.processor.output.WSSSignatureOutputProcessor; import org.apache.wss4j.stax.impl.securityToken.KerberosClientSecurityToken; import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants; import org.apache.wss4j.stax.utils.WSSUtils; import org.apache.xml.security.exceptions.XMLSecurityException; import org.apache.xml.security.stax.config.JCEAlgorithmMapper; import org.apache.xml.security.stax.ext.OutboundSecurityContext; import org.apache.xml.security.stax.ext.OutputProcessor; import org.apache.xml.security.stax.ext.SecurityContext; import org.apache.xml.security.stax.ext.XMLSecurityConstants; import org.apache.xml.security.stax.impl.DocumentContextImpl; import org.apache.xml.security.stax.impl.OutboundSecurityContextImpl; import org.apache.xml.security.stax.impl.OutputProcessorChainImpl; import org.apache.xml.security.stax.impl.XMLSecurityStreamWriter; import org.apache.xml.security.stax.impl.processor.output.FinalOutputProcessor; import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken; import org.apache.xml.security.stax.impl.util.IDGenerator; import org.apache.xml.security.stax.securityEvent.SecurityEvent; import org.apache.xml.security.stax.securityEvent.SecurityEventListener; import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent; import org.apache.xml.security.stax.securityToken.OutboundSecurityToken; import org.apache.xml.security.stax.securityToken.SecurityToken; import org.apache.xml.security.stax.securityToken.SecurityTokenConstants.TokenUsage; import org.apache.xml.security.stax.securityToken.SecurityTokenProvider; /** * Outbound Streaming-WebService-Security * An instance of this class can be retrieved over the WSSec class */ public class OutboundWSSec { private final WSSSecurityProperties securityProperties; public OutboundWSSec(WSSSecurityProperties securityProperties) { this.securityProperties = securityProperties; } /** * This method is the entry point for the incoming security-engine. * Hand over a outputStream and use the returned XMLStreamWriter for further processing * * @param outputStream The original outputStream * @return A new XMLStreamWriter which does transparently the security processing. * @throws WSSecurityException thrown when a Security failure occurs */ public XMLStreamWriter processOutMessage( OutputStream outputStream, String encoding, List<SecurityEvent> requestSecurityEvents) throws WSSecurityException { return processOutMessage(outputStream, encoding, requestSecurityEvents, null); } /** * This method is the entry point for the incoming security-engine. * Hand over the original XMLStreamWriter and use the returned one for further processing * * @param xmlStreamWriter The original xmlStreamWriter * @return A new XMLStreamWriter which does transparently the security processing. * @throws WSSecurityException thrown when a Security failure occurs */ public XMLStreamWriter processOutMessage( XMLStreamWriter xmlStreamWriter, String encoding, List<SecurityEvent> requestSecurityEvents) throws WSSecurityException { return processOutMessage(xmlStreamWriter, encoding, requestSecurityEvents, null); } /** * This method is the entry point for the incoming security-engine. * Hand over a outputstream and use the returned XMLStreamWriter for further processing * * @param outputStream The original outputStream * @return A new XMLStreamWriter which does transparently the security processing. * @throws WSSecurityException thrown when a Security failure occurs */ public XMLStreamWriter processOutMessage( OutputStream outputStream, String encoding, List<SecurityEvent> requestSecurityEvents, SecurityEventListener securityEventListener) throws WSSecurityException { final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl(); outboundSecurityContext.putList(SecurityEvent.class, requestSecurityEvents); outboundSecurityContext.addSecurityEventListener(securityEventListener); return processOutMessage((Object) outputStream, encoding, outboundSecurityContext); } /** * This method is the entry point for the incoming security-engine. * Hand over the original XMLStreamWriter and use the returned one for further processing * * @param xmlStreamWriter The original outputStream * @return A new XMLStreamWriter which does transparently the security processing. * @throws WSSecurityException thrown when a Security failure occurs */ public XMLStreamWriter processOutMessage( XMLStreamWriter xmlStreamWriter, String encoding, List<SecurityEvent> requestSecurityEvents, SecurityEventListener securityEventListener) throws WSSecurityException { final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl(); outboundSecurityContext.putList(SecurityEvent.class, requestSecurityEvents); outboundSecurityContext.addSecurityEventListener(securityEventListener); return processOutMessage((Object) xmlStreamWriter, encoding, outboundSecurityContext); } /** * This method is the entry point for the incoming security-engine. * Hand over the original XMLStreamWriter and use the returned one for further processing * * @param xmlStreamWriter The original outputStream * @return A new XMLStreamWriter which does transparently the security processing. * @throws WSSecurityException thrown when a Security failure occurs */ public XMLStreamWriter processOutMessage( XMLStreamWriter xmlStreamWriter, String encoding, OutboundSecurityContext outbounSecurityContext) throws WSSecurityException { return processOutMessage((Object) xmlStreamWriter, encoding, outbounSecurityContext); } public XMLStreamWriter processOutMessage( Object output, String encoding, OutboundSecurityContext outboundSecurityContext ) throws WSSecurityException { final DocumentContextImpl documentContext = new DocumentContextImpl(); documentContext.setEncoding(encoding); OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(outboundSecurityContext, documentContext); try { final SecurityHeaderOutputProcessor securityHeaderOutputProcessor = new SecurityHeaderOutputProcessor(); initializeOutputProcessor(outputProcessorChain, securityHeaderOutputProcessor, null); ConfiguredAction configuredAction = configureActions(outputProcessorChain); // Set up appropriate keys if (configuredAction.signatureAction) { setupSignatureKey(outputProcessorChain, securityProperties, configuredAction.signedSAML); } if (configuredAction.encryptionAction) { setupEncryptionKey(outputProcessorChain, securityProperties); } if (configuredAction.kerberos) { setupKerberosKey(outputProcessorChain, securityProperties, configuredAction.signatureKerberos, configuredAction.encryptionKerberos); } if (configuredAction.derivedSignature) { String id = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE); setDerivedIdentifier(outputProcessorChain, id); } if (configuredAction.derivedEncryption) { String id = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY); if (id == null) { // Maybe not encrypting the key here... id = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION); } setDerivedIdentifier(outputProcessorChain, id); } final SecurityHeaderReorderProcessor securityHeaderReorderProcessor = new SecurityHeaderReorderProcessor(); initializeOutputProcessor(outputProcessorChain, securityHeaderReorderProcessor, null); if (output instanceof OutputStream) { final FinalOutputProcessor finalOutputProcessor = new FinalOutputProcessor((OutputStream) output, encoding); initializeOutputProcessor(outputProcessorChain, finalOutputProcessor, null); } else if (output instanceof XMLStreamWriter) { final FinalOutputProcessor finalOutputProcessor = new FinalOutputProcessor((XMLStreamWriter) output); initializeOutputProcessor(outputProcessorChain, finalOutputProcessor, null); } else { throw new IllegalArgumentException(output + " is not supported as output"); } } catch (XMLSecurityException e) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); } return new XMLSecurityStreamWriter(outputProcessorChain); } private void initializeOutputProcessor( OutputProcessorChainImpl outputProcessorChain, OutputProcessor outputProcessor, XMLSecurityConstants.Action action) throws XMLSecurityException { outputProcessor.setXMLSecurityProperties(securityProperties); outputProcessor.setAction(action); outputProcessor.init(outputProcessorChain); } private void setupSignatureKey( OutputProcessorChainImpl outputProcessorChain, WSSSecurityProperties securityProperties, boolean signedSAML ) throws XMLSecurityException { final String signatureAlgorithm = securityProperties.getSignatureAlgorithm(); GenericOutboundSecurityToken securityToken = getOutboundSecurityToken(outputProcessorChain, WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE); // First off, see if we have a supplied token with the correct keys for // (a)symmetric signature if (securityToken != null && signatureAlgorithm != null) { if (signatureAlgorithm.contains("hmac-sha") && securityToken.getSecretKey(signatureAlgorithm) != null) { return; } else if (!signatureAlgorithm.contains("hmac-sha") && securityToken.getX509Certificates() != null) { if (securityToken.getSecretKey(signatureAlgorithm) != null) { return; } else { // We have certs but no private key set. Use the CallbackHandler Key key = securityProperties.getSignatureCrypto().getPrivateKey( securityToken.getX509Certificates()[0], securityProperties.getCallbackHandler() ); securityToken.setSecretKey(signatureAlgorithm, key); return; } } } // We have no supplied key. So use the PasswordCallback to get a secret key or password String alias = securityProperties.getSignatureUser(); WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE); WSSUtils.doPasswordCallback(securityProperties.getCallbackHandler(), pwCb); String password = pwCb.getPassword(); byte[] secretKey = pwCb.getKey(); Key key = null; X509Certificate[] x509Certificates = null; try { if (password != null && securityProperties.getSignatureCrypto() != null) { key = securityProperties.getSignatureCrypto().getPrivateKey(alias, password); CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS); cryptoType.setAlias(alias); x509Certificates = securityProperties.getSignatureCrypto().getX509Certificates(cryptoType); if (x509Certificates == null || x509Certificates.length == 0) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noUserCertsFound", new Object[] {alias}); } } else if (secretKey != null) { x509Certificates = null; String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(signatureAlgorithm); key = new SecretKeySpec(secretKey, algoFamily); } else { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noPassword", new Object[] {alias}); } } catch (WSSecurityException ex) { if (signedSAML && securityProperties.getSamlCallbackHandler() != null) { // We may get the keys we require from the SAML CallbackHandler... return; } throw ex; } // Create a new outbound Signature token for the generated key / cert final String id = IDGenerator.generateID(null); final GenericOutboundSecurityToken binarySecurityToken = new GenericOutboundSecurityToken(id, WSSecurityTokenConstants.X509V3Token, key, x509Certificates); // binarySecurityToken.setSha1Identifier(reference); final SecurityTokenProvider<OutboundSecurityToken> binarySecurityTokenProvider = new SecurityTokenProvider<OutboundSecurityToken>() { @Override public OutboundSecurityToken getSecurityToken() throws WSSecurityException { return binarySecurityToken; } @Override public String getId() { return id; } }; outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(id, binarySecurityTokenProvider); outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, id); } private void setupEncryptionKey( OutputProcessorChainImpl outputProcessorChain, WSSSecurityProperties securityProperties ) throws XMLSecurityException { final String symmetricEncryptionAlgorithm = securityProperties.getEncryptionSymAlgorithm(); // First check to see if a Symmetric key is available GenericOutboundSecurityToken securityToken = getOutboundSecurityToken(outputProcessorChain, WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION); if (securityToken == null || securityToken.getSecretKey(symmetricEncryptionAlgorithm) == null) { //prepare the symmetric session key for all encryption parts String keyAlgorithm = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(securityProperties.getEncryptionSymAlgorithm()); KeyGenerator keyGen; try { keyGen = KeyGenerator.getInstance(keyAlgorithm); } catch (NoSuchAlgorithmException e) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e); } //the sun JCE provider expects the real key size for 3DES (112 or 168 bit) //whereas bouncy castle expects the block size of 128 or 192 bits if (keyAlgorithm.contains("AES")) { int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(securityProperties.getEncryptionSymAlgorithm()); keyGen.init(keyLength); } final Key symmetricKey = keyGen.generateKey(); final String symmId = IDGenerator.generateID(null); final GenericOutboundSecurityToken symmetricSecurityToken = new GenericOutboundSecurityToken(symmId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey); securityToken = symmetricSecurityToken; final SecurityTokenProvider<OutboundSecurityToken> securityTokenProvider = new SecurityTokenProvider<OutboundSecurityToken>() { @Override public OutboundSecurityToken getSecurityToken() throws XMLSecurityException { return symmetricSecurityToken; } @Override public String getId() { return symmId; } }; outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(symmId, securityTokenProvider); outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, symmId); } if (!securityProperties.isEncryptSymmetricEncryptionKey()) { // No EncryptedKey Token required here, so return return; } // Set up a security token with the certs required to encrypt the symmetric key X509Certificate[] x509Certificates = null; PublicKey publicKey = null; if (securityProperties.isUseReqSigCertForEncryption()) { X509Certificate x509Certificate = getReqSigCert(outputProcessorChain.getSecurityContext()); if (x509Certificate == null) { publicKey = getReqSigPublicKey(outputProcessorChain.getSecurityContext()); if (publicKey == null) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, "noCert"); } } else { x509Certificates = new X509Certificate[1]; x509Certificates[0] = x509Certificate; } } else if (securityProperties.getEncryptionUseThisCertificate() != null) { x509Certificates = new X509Certificate[1]; x509Certificates[0] = securityProperties.getEncryptionUseThisCertificate(); } else { CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS); cryptoType.setAlias(securityProperties.getEncryptionUser()); Crypto crypto = securityProperties.getEncryptionCrypto(); x509Certificates = crypto.getX509Certificates(cryptoType); if (x509Certificates == null || x509Certificates.length == 0) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, "noUserCertsFound", new Object[] {securityProperties.getEncryptionUser(), "encryption"}); } } // Check for Revocation if (securityProperties.isEnableRevocation() && x509Certificates != null) { Crypto crypto = securityProperties.getEncryptionCrypto(); crypto.verifyTrust(x509Certificates, true, null, null); } // Create a new outbound EncryptedKey token for the cert final String id = IDGenerator.generateID(null); final GenericOutboundSecurityToken encryptedKeyToken = new GenericOutboundSecurityToken(id, WSSecurityTokenConstants.X509V3Token, publicKey, x509Certificates); encryptedKeyToken.addWrappedToken(securityToken); securityToken.setKeyWrappingToken(encryptedKeyToken); // binarySecurityToken.setSha1Identifier(reference); final SecurityTokenProvider<OutboundSecurityToken> encryptedKeyTokenProvider = new SecurityTokenProvider<OutboundSecurityToken>() { @Override public OutboundSecurityToken getSecurityToken() throws WSSecurityException { return encryptedKeyToken; } @Override public String getId() { return id; } }; outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(id, encryptedKeyTokenProvider); outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, id); } private void setupKerberosKey( OutputProcessorChainImpl outputProcessorChain, WSSSecurityProperties securityProperties, boolean signature, boolean encryption ) throws XMLSecurityException { GenericOutboundSecurityToken securityToken = getOutboundSecurityToken(outputProcessorChain, WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_KERBEROS); String kerberosId = null; // First off, see if we have a supplied token if (securityToken == null) { // If not then generate a new key final String id = IDGenerator.generateID(null); kerberosId = id; final KerberosClientSecurityToken kerberosClientSecurityToken = new KerberosClientSecurityToken( securityProperties.getCallbackHandler(), id ); final SecurityTokenProvider<OutboundSecurityToken> kerberosSecurityTokenProvider = new SecurityTokenProvider<OutboundSecurityToken>() { @Override public OutboundSecurityToken getSecurityToken() throws WSSecurityException { return kerberosClientSecurityToken; } @Override public String getId() { return id; } }; outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(id, kerberosSecurityTokenProvider); outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_KERBEROS, id); } else { kerberosId = securityToken.getId(); } if (signature) { outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, kerberosId); } if (encryption) { outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, kerberosId); } } // Return an outbound SecurityToken object for a given id (encryption/signature) private GenericOutboundSecurityToken getOutboundSecurityToken( OutputProcessorChainImpl outputProcessorChain, String id ) throws XMLSecurityException { String tokenId = outputProcessorChain.getSecurityContext().get(id); SecurityTokenProvider<OutboundSecurityToken> signatureTokenProvider = null; if (tokenId != null) { signatureTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId); if (signatureTokenProvider != null) { return (GenericOutboundSecurityToken)signatureTokenProvider.getSecurityToken(); } } return null; } private X509Certificate getReqSigCert(SecurityContext securityContext) throws XMLSecurityException { List<SecurityEvent> securityEventList = securityContext.getAsList(SecurityEvent.class); if (securityEventList != null) { for (int i = 0; i < securityEventList.size(); i++) { SecurityEvent securityEvent = securityEventList.get(i); if (securityEvent instanceof TokenSecurityEvent) { @SuppressWarnings("unchecked") TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = (TokenSecurityEvent<? extends SecurityToken>) securityEvent; TokenUsage mainSig = WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE; if (!tokenSecurityEvent.getSecurityToken().getTokenUsages().contains(mainSig)) { continue; } X509Certificate[] x509Certificates = tokenSecurityEvent.getSecurityToken().getX509Certificates(); if (x509Certificates != null && x509Certificates.length > 0) { return x509Certificates[0]; } } } } return null; } private PublicKey getReqSigPublicKey(SecurityContext securityContext) throws XMLSecurityException { List<SecurityEvent> securityEventList = securityContext.getAsList(SecurityEvent.class); if (securityEventList != null) { for (int i = 0; i < securityEventList.size(); i++) { SecurityEvent securityEvent = securityEventList.get(i); if (securityEvent instanceof TokenSecurityEvent) { @SuppressWarnings("unchecked") TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = (TokenSecurityEvent<? extends SecurityToken>) securityEvent; TokenUsage mainSig = WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE; if (!tokenSecurityEvent.getSecurityToken().getTokenUsages().contains(mainSig)) { continue; } PublicKey publicKey = tokenSecurityEvent.getSecurityToken().getPublicKey(); if (publicKey != null) { return publicKey; } } } } return null; } private void setDerivedIdentifier(OutputProcessorChainImpl outputProcessorChain, String id) { WSSConstants.DerivedKeyTokenReference derivedKeyTokenReference = securityProperties.getDerivedKeyTokenReference(); switch (derivedKeyTokenReference) { case DirectReference: outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, id); break; case EncryptedKey: String symmId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION); outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, symmId); outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, id); break; case SecurityContextToken: outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SECURITYCONTEXTTOKEN, id); break; } } private ConfiguredAction configureActions(OutputProcessorChainImpl outputProcessorChain) throws XMLSecurityException { ConfiguredAction configuredAction = new ConfiguredAction(); //todo some combinations are not possible atm: eg Action.SIGNATURE and Action.USERNAMETOKEN_SIGNED //todo they use the same signature parts // Check to see whether we have a derived key signature, but not encryption, using // an encrypted key reference (as we only want one encrypted key here...) boolean derivedSignatureButNotDerivedEncryption = false; if (securityProperties.getDerivedKeyTokenReference() == WSSConstants.DerivedKeyTokenReference.EncryptedKey) { for (XMLSecurityConstants.Action action : securityProperties.getActions()) { if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) { derivedSignatureButNotDerivedEncryption = true; } else if (WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) { derivedSignatureButNotDerivedEncryption = false; break; } } } for (XMLSecurityConstants.Action action : securityProperties.getActions()) { if (WSSConstants.TIMESTAMP.equals(action)) { final TimestampOutputProcessor timestampOutputProcessor = new TimestampOutputProcessor(); initializeOutputProcessor(outputProcessorChain, timestampOutputProcessor, action); } else if (WSSConstants.SIGNATURE.equals(action)) { configuredAction.signatureAction = true; final BinarySecurityTokenOutputProcessor binarySecurityTokenOutputProcessor = new BinarySecurityTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, binarySecurityTokenOutputProcessor, action); final WSSSignatureOutputProcessor signatureOutputProcessor = new WSSSignatureOutputProcessor(); initializeOutputProcessor(outputProcessorChain, signatureOutputProcessor, action); } else if (WSSConstants.ENCRYPT.equals(action)) { configuredAction.encryptionAction = true; EncryptedKeyOutputProcessor encryptedKeyOutputProcessor = null; if (securityProperties.isEncryptSymmetricEncryptionKey()) { final BinarySecurityTokenOutputProcessor binarySecurityTokenOutputProcessor = new BinarySecurityTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, binarySecurityTokenOutputProcessor, action); encryptedKeyOutputProcessor = new EncryptedKeyOutputProcessor(); initializeOutputProcessor(outputProcessorChain, encryptedKeyOutputProcessor, action); } final EncryptOutputProcessor encryptOutputProcessor = new EncryptOutputProcessor(); initializeOutputProcessor(outputProcessorChain, encryptOutputProcessor, action); if (encryptedKeyOutputProcessor == null) { final ReferenceListOutputProcessor referenceListOutputProcessor = new ReferenceListOutputProcessor(); referenceListOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class.getName()); initializeOutputProcessor(outputProcessorChain, referenceListOutputProcessor, action); } } else if (WSSConstants.USERNAMETOKEN.equals(action)) { final UsernameTokenOutputProcessor usernameTokenOutputProcessor = new UsernameTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, usernameTokenOutputProcessor, action); } else if (WSSConstants.USERNAMETOKEN_SIGNED.equals(action)) { final UsernameTokenOutputProcessor usernameTokenOutputProcessor = new UsernameTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, usernameTokenOutputProcessor, action); final WSSSignatureOutputProcessor signatureOutputProcessor = new WSSSignatureOutputProcessor(); initializeOutputProcessor(outputProcessorChain, signatureOutputProcessor, action); } else if (WSSConstants.SIGNATURE_CONFIRMATION.equals(action)) { final SignatureConfirmationOutputProcessor signatureConfirmationOutputProcessor = new SignatureConfirmationOutputProcessor(); initializeOutputProcessor(outputProcessorChain, signatureConfirmationOutputProcessor, action); } else if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) { if (securityProperties.getDerivedKeyTokenReference() == WSSConstants.DerivedKeyTokenReference.EncryptedKey) { if (derivedSignatureButNotDerivedEncryption) { final EncryptedKeyOutputProcessor encryptedKeyOutputProcessor = new EncryptedKeyOutputProcessor(); initializeOutputProcessor(outputProcessorChain, encryptedKeyOutputProcessor, action); } configuredAction.encryptionAction = true; configuredAction.derivedEncryption = true; } else if (securityProperties.getDerivedKeyTokenReference() == WSSConstants.DerivedKeyTokenReference.SecurityContextToken) { final SecurityContextTokenOutputProcessor securityContextTokenOutputProcessor = new SecurityContextTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, securityContextTokenOutputProcessor, action); configuredAction.signatureAction = true; configuredAction.derivedSignature = true; } else { configuredAction.signatureAction = true; configuredAction.derivedSignature = true; } final DerivedKeyTokenOutputProcessor derivedKeyTokenOutputProcessor = new DerivedKeyTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, derivedKeyTokenOutputProcessor, action); final WSSSignatureOutputProcessor signatureOutputProcessor = new WSSSignatureOutputProcessor(); initializeOutputProcessor(outputProcessorChain, signatureOutputProcessor, action); } else if (WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) { configuredAction.encryptionAction = true; configuredAction.derivedEncryption = true; EncryptedKeyOutputProcessor encryptedKeyOutputProcessor = null; if (securityProperties.getDerivedKeyTokenReference() == WSSConstants.DerivedKeyTokenReference.EncryptedKey) { encryptedKeyOutputProcessor = new EncryptedKeyOutputProcessor(); initializeOutputProcessor(outputProcessorChain, encryptedKeyOutputProcessor, action); } else if (securityProperties.getDerivedKeyTokenReference() == WSSConstants.DerivedKeyTokenReference.SecurityContextToken) { final SecurityContextTokenOutputProcessor securityContextTokenOutputProcessor = new SecurityContextTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, securityContextTokenOutputProcessor, action); } final DerivedKeyTokenOutputProcessor derivedKeyTokenOutputProcessor = new DerivedKeyTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, derivedKeyTokenOutputProcessor, action); final EncryptOutputProcessor encryptOutputProcessor = new EncryptOutputProcessor(); initializeOutputProcessor(outputProcessorChain, encryptOutputProcessor, action); if (encryptedKeyOutputProcessor == null) { final ReferenceListOutputProcessor referenceListOutputProcessor = new ReferenceListOutputProcessor(); referenceListOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class.getName()); initializeOutputProcessor(outputProcessorChain, referenceListOutputProcessor, action); } } else if (WSSConstants.SAML_TOKEN_SIGNED.equals(action)) { configuredAction.signatureAction = true; configuredAction.signedSAML = true; final BinarySecurityTokenOutputProcessor binarySecurityTokenOutputProcessor = new BinarySecurityTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, binarySecurityTokenOutputProcessor, action); final SAMLTokenOutputProcessor samlTokenOutputProcessor = new SAMLTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, samlTokenOutputProcessor, action); final WSSSignatureOutputProcessor signatureOutputProcessor = new WSSSignatureOutputProcessor(); initializeOutputProcessor(outputProcessorChain, signatureOutputProcessor, action); } else if (WSSConstants.SAML_TOKEN_UNSIGNED.equals(action)) { final SAMLTokenOutputProcessor samlTokenOutputProcessor = new SAMLTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, samlTokenOutputProcessor, action); } else if (WSSConstants.SIGNATURE_WITH_KERBEROS_TOKEN.equals(action)) { configuredAction.kerberos = true; configuredAction.signatureKerberos = true; final BinarySecurityTokenOutputProcessor kerberosTokenOutputProcessor = new BinarySecurityTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, kerberosTokenOutputProcessor, action); final WSSSignatureOutputProcessor signatureOutputProcessor = new WSSSignatureOutputProcessor(); initializeOutputProcessor(outputProcessorChain, signatureOutputProcessor, action); } else if (WSSConstants.ENCRYPT_WITH_KERBEROS_TOKEN.equals(action)) { configuredAction.kerberos = true; configuredAction.encryptionKerberos = true; final BinarySecurityTokenOutputProcessor kerberosTokenOutputProcessor = new BinarySecurityTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, kerberosTokenOutputProcessor, action); final EncryptOutputProcessor encryptOutputProcessor = new EncryptOutputProcessor(); initializeOutputProcessor(outputProcessorChain, encryptOutputProcessor, action); } else if (WSSConstants.KERBEROS_TOKEN.equals(action)) { configuredAction.kerberos = true; final BinarySecurityTokenOutputProcessor kerberosTokenOutputProcessor = new BinarySecurityTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, kerberosTokenOutputProcessor, action); } else if (WSSConstants.CUSTOM_TOKEN.equals(action)) { final CustomTokenOutputProcessor unknownTokenOutputProcessor = new CustomTokenOutputProcessor(); initializeOutputProcessor(outputProcessorChain, unknownTokenOutputProcessor, action); } } return configuredAction; } private static class ConfiguredAction { boolean signatureAction = false; boolean encryptionAction = false; boolean signedSAML = false; boolean kerberos = false; boolean signatureKerberos = false; boolean encryptionKerberos = false; boolean derivedSignature = false; boolean derivedEncryption = false; } }