Package org.apache.cxf.ws.security.wss4j.policyhandlers

Source Code of org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractStaxBindingHandler

/**
* 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.cxf.ws.security.wss4j.policyhandlers;

import java.io.IOException;
import java.security.Key;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.crypto.spec.SecretKeySpec;
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.soap.SOAPException;

import org.w3c.dom.Element;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.common.classloader.ClassLoaderUtils;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.ws.policy.AssertionInfo;
import org.apache.cxf.ws.policy.AssertionInfoMap;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.cxf.ws.security.tokenstore.TokenStore;
import org.apache.neethi.Assertion;
import org.apache.wss4j.common.ConfigurationConstants;
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.SAMLCallback;
import org.apache.wss4j.common.saml.bean.KeyInfoBean;
import org.apache.wss4j.common.saml.bean.SubjectBean;
import org.apache.wss4j.common.util.KeyUtils;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.policy.SP11Constants;
import org.apache.wss4j.policy.SP12Constants;
import org.apache.wss4j.policy.SPConstants;
import org.apache.wss4j.policy.SPConstants.IncludeTokenType;
import org.apache.wss4j.policy.model.AbstractBinding;
import org.apache.wss4j.policy.model.AbstractToken;
import org.apache.wss4j.policy.model.AbstractTokenWrapper;
import org.apache.wss4j.policy.model.AlgorithmSuite.AlgorithmSuiteType;
import org.apache.wss4j.policy.model.ContentEncryptedElements;
import org.apache.wss4j.policy.model.EncryptedElements;
import org.apache.wss4j.policy.model.EncryptedParts;
import org.apache.wss4j.policy.model.Header;
import org.apache.wss4j.policy.model.IssuedToken;
import org.apache.wss4j.policy.model.KerberosToken;
import org.apache.wss4j.policy.model.KeyValueToken;
import org.apache.wss4j.policy.model.Layout;
import org.apache.wss4j.policy.model.Layout.LayoutType;
import org.apache.wss4j.policy.model.SamlToken;
import org.apache.wss4j.policy.model.SamlToken.SamlTokenType;
import org.apache.wss4j.policy.model.SignedElements;
import org.apache.wss4j.policy.model.SignedParts;
import org.apache.wss4j.policy.model.SupportingTokens;
import org.apache.wss4j.policy.model.SymmetricBinding;
import org.apache.wss4j.policy.model.UsernameToken;
import org.apache.wss4j.policy.model.UsernameToken.PasswordType;
import org.apache.wss4j.policy.model.Wss10;
import org.apache.wss4j.policy.model.Wss11;
import org.apache.wss4j.policy.model.X509Token;
import org.apache.wss4j.policy.model.X509Token.TokenType;
import org.apache.wss4j.policy.model.XPath;
import org.apache.wss4j.policy.stax.PolicyUtils;
import org.apache.wss4j.stax.ext.WSSConstants;
import org.apache.wss4j.stax.impl.securityToken.KerberosClientSecurityToken;
import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
import org.apache.xml.security.algorithms.JCEMapper;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.stax.ext.SecurePart;
import org.apache.xml.security.stax.ext.SecurePart.Modifier;
import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
import org.apache.xml.security.stax.securityEvent.SecurityEvent;
import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
import org.apache.xml.security.stax.securityToken.SecurityTokenConstants;
import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
import org.opensaml.common.SAMLVersion;

/**
*
*/
public abstract class AbstractStaxBindingHandler extends AbstractCommonBindingHandler {
    protected boolean timestampAdded;
    protected boolean signatureConfirmationAdded;
    protected Set<SecurePart> encryptedTokensList = new HashSet<SecurePart>();
   
    protected Map<AbstractToken, SecurePart> endEncSuppTokMap;
    protected Map<AbstractToken, SecurePart> endSuppTokMap;
    protected Map<AbstractToken, SecurePart> sgndEndEncSuppTokMap;
    protected Map<AbstractToken, SecurePart> sgndEndSuppTokMap;
    protected Map<String, SecurityTokenProvider<OutboundSecurityToken>> outboundTokens;
   
    private final Map<String, Object> properties;
    private AbstractBinding binding;
   
    public AbstractStaxBindingHandler(
        Map<String, Object> properties,
        SoapMessage msg,
        AbstractBinding binding,
        Map<String, SecurityTokenProvider<OutboundSecurityToken>> outboundTokens
    ) {
        super(msg);
        this.properties = properties;
        this.binding = binding;
        this.outboundTokens = outboundTokens;
    }

    protected SecurePart addUsernameToken(UsernameToken usernameToken) {
        assertToken(usernameToken);
        IncludeTokenType includeToken = usernameToken.getIncludeTokenType();
        if (!isTokenRequired(includeToken)) {
            return null;
        }

        Map<String, Object> config = getProperties();
       
        // Action
        if (config.containsKey(ConfigurationConstants.ACTION)) {
            String action = (String)config.get(ConfigurationConstants.ACTION);
            config.put(ConfigurationConstants.ACTION,
                       action + " " + ConfigurationConstants.USERNAME_TOKEN);
        } else {
            config.put(ConfigurationConstants.ACTION,
                       ConfigurationConstants.USERNAME_TOKEN);
        }

        // Password Type
        PasswordType passwordType = usernameToken.getPasswordType();
        if (passwordType == PasswordType.HashPassword) {
            config.put(ConfigurationConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
        } else if (passwordType == PasswordType.NoPassword) {
            config.put(ConfigurationConstants.PASSWORD_TYPE, WSConstants.PW_NONE);
        } else {
            config.put(ConfigurationConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
        }

        // Nonce + Created
        if (usernameToken.isNonce()) {
            config.put(ConfigurationConstants.ADD_USERNAMETOKEN_NONCE, "true");
        }
        if (usernameToken.isCreated()) {
            config.put(ConfigurationConstants.ADD_USERNAMETOKEN_CREATED, "true");
        }
       
        // Check if a CallbackHandler was specified
        if (config.get(ConfigurationConstants.PW_CALLBACK_REF) == null) {
            String password = (String)message.getContextualProperty(SecurityConstants.PASSWORD);
            if (password != null) {
                String username =
                    (String)message.getContextualProperty(SecurityConstants.USERNAME);
                UTCallbackHandler callbackHandler = new UTCallbackHandler(username, password);
                config.put(ConfigurationConstants.PW_CALLBACK_REF, callbackHandler);
            }
        }
       
        return new SecurePart(WSSConstants.TAG_wsse_UsernameToken, Modifier.Element);
    }
   
    private static class UTCallbackHandler implements CallbackHandler {
       
        private final String username;
        private final String password;
       
        public UTCallbackHandler(String username, String password) {
            this.username = username;
            this.password = password;
        }

        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            for (Callback callback : callbacks) {
                if (callback instanceof WSPasswordCallback) {
                    WSPasswordCallback pwcb = (WSPasswordCallback)callback;
                    if (pwcb.getIdentifier().equals(username)) {
                        pwcb.setPassword(password);
                    }
                }
            }
        }
       
    }
   
    protected SecurePart addKerberosToken(
        KerberosToken token, boolean signed, boolean endorsing, boolean encrypting
    ) throws WSSecurityException {
        assertToken(token);
        IncludeTokenType includeToken = token.getIncludeTokenType();
        if (!isTokenRequired(includeToken)) {
            return null;
        }

        final SecurityToken secToken = getSecurityToken();
        if (secToken == null) {
            policyNotAsserted(token, "Could not find KerberosToken");
        }
       
        // Convert to WSS4J token
        final KerberosClientSecurityToken wss4jToken =
            new KerberosClientSecurityToken(secToken.getData(), secToken.getKey(), secToken.getId()) {
           
                @Override
                public Key getSecretKey(String algorithmURI) throws XMLSecurityException {
                    if (secToken.getSecret() != null && algorithmURI != null && !"".equals(algorithmURI)) {
                        return KeyUtils.prepareSecretKey(algorithmURI, secToken.getSecret());
                    }
                    return secToken.getKey();
                }
            };
        wss4jToken.setSha1Identifier(secToken.getSHA1());
       
        final SecurityTokenProvider<OutboundSecurityToken> kerberosSecurityTokenProvider =
            new SecurityTokenProvider<OutboundSecurityToken>() {

                @Override
                public OutboundSecurityToken getSecurityToken() throws WSSecurityException {
                    return wss4jToken;
                }

                @Override
                public String getId() {
                    return wss4jToken.getId();
                }
            };
        outboundTokens.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_KERBEROS,
                           kerberosSecurityTokenProvider);
        if (encrypting) {
            outboundTokens.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION,
                               kerberosSecurityTokenProvider);
        }
        if (endorsing) {
            outboundTokens.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE,
                               kerberosSecurityTokenProvider);
        }
       
        // Action
        Map<String, Object> config = getProperties();
        String actionToPerform = ConfigurationConstants.KERBEROS_TOKEN;
       
        if (config.containsKey(ConfigurationConstants.ACTION)) {
            String action = (String)config.get(ConfigurationConstants.ACTION);
            config.put(ConfigurationConstants.ACTION, action + " " + actionToPerform);
        } else {
            config.put(ConfigurationConstants.ACTION, actionToPerform);
        }
       
        /*
        if (endorsing) {
            String action = (String)config.get(ConfigurationConstants.ACTION);
            config.put(ConfigurationConstants.ACTION,
                ConfigurationConstants.SIGNATURE_WITH_KERBEROS_TOKEN  + " " + action);
            // config.put(ConfigurationConstants.SIG_KEY_ID, "DirectReference");
        }
        */
       
        SecurePart securePart = new SecurePart(WSSConstants.TAG_wsse_BinarySecurityToken, Modifier.Element);
        securePart.setIdToSign(wss4jToken.getId());
       
        return securePart;
    }
   
    protected SecurePart addSamlToken(
        SamlToken token,
        boolean signed,
        boolean endorsing
    ) throws WSSecurityException {
        assertToken(token);
        IncludeTokenType includeToken = token.getIncludeTokenType();
        if (!isTokenRequired(includeToken)) {
            return null;
        }
       
        Map<String, Object> config = getProperties();
       
        //
        // Get the SAML CallbackHandler
        //
        Object o = message.getContextualProperty(SecurityConstants.SAML_CALLBACK_HANDLER);
   
        CallbackHandler handler = null;
        if (o instanceof CallbackHandler) {
            handler = (CallbackHandler)o;
        } else if (o instanceof String) {
            try {
                handler = (CallbackHandler)ClassLoaderUtils
                    .loadClass((String)o, this.getClass()).newInstance();
            } catch (Exception e) {
                handler = null;
            }
        }
        if (handler == null) {
            policyNotAsserted(token, "No SAML CallbackHandler available");
            return null;
        }
        config.put(ConfigurationConstants.SAML_CALLBACK_REF, handler);
       
        // Action
        String samlAction = ConfigurationConstants.SAML_TOKEN_UNSIGNED;
        if (signed || endorsing) {
            samlAction = ConfigurationConstants.SAML_TOKEN_SIGNED;
        }
       
        if (config.containsKey(ConfigurationConstants.ACTION)) {
            String action = (String)config.get(ConfigurationConstants.ACTION);
            config.put(ConfigurationConstants.ACTION, action + " " + samlAction);
        } else {
            config.put(ConfigurationConstants.ACTION, samlAction);
        }
       
        QName qname = WSSConstants.TAG_saml2_Assertion;
        SamlTokenType tokenType = token.getSamlTokenType();
        if (tokenType == SamlTokenType.WssSamlV11Token10 || tokenType == SamlTokenType.WssSamlV11Token11) {
            qname = WSSConstants.TAG_saml_Assertion;
        }
       
        return new SecurePart(qname, Modifier.Element);
    }
   
    protected SecurePart addIssuedToken(AbstractToken token, SecurityToken secToken,
                                  boolean signed, boolean endorsing) {
        assertToken(token);
        if (isTokenRequired(token.getIncludeTokenType())) {
            final Element el = secToken.getToken();
           
            if (el != null && "Assertion".equals(el.getLocalName())
                && (WSSConstants.NS_SAML.equals(el.getNamespaceURI())
                || WSSConstants.NS_SAML2.equals(el.getNamespaceURI()))) {
                String samlAction = ConfigurationConstants.SAML_TOKEN_UNSIGNED;
                if (endorsing) {
                    samlAction = ConfigurationConstants.SAML_TOKEN_SIGNED;
                }
                Map<String, Object> config = getProperties();
                if (config.containsKey(ConfigurationConstants.ACTION)) {
                    String action = (String)config.get(ConfigurationConstants.ACTION);
                    config.put(ConfigurationConstants.ACTION, action + " " + samlAction);
                } else {
                    config.put(ConfigurationConstants.ACTION, samlAction);
                }
               
                // Mock up a Subject so that the SAMLTokenOutProcessor can get access to the certificate
                final SubjectBean subjectBean;
                if (signed || endorsing) {
                    KeyInfoBean keyInfo = new KeyInfoBean();
                    keyInfo.setCertificate(secToken.getX509Certificate());
                    keyInfo.setEphemeralKey(secToken.getSecret());
                    subjectBean = new SubjectBean("", "", "");
                    subjectBean.setKeyInfo(keyInfo);
                } else {
                    subjectBean = null;
                }
               
                CallbackHandler callbackHandler = new CallbackHandler() {
   
                    @Override
                    public void handle(Callback[] callbacks) {
                        for (Callback callback : callbacks) {
                            if (callback instanceof SAMLCallback) {
                                SAMLCallback samlCallback = (SAMLCallback)callback;
                                samlCallback.setAssertionElement(el);
                                samlCallback.setSubject(subjectBean);
                               
                                if (WSConstants.SAML_NS.equals(el.getNamespaceURI())) {
                                    samlCallback.setSamlVersion(SAMLVersion.VERSION_11);
                                } else {
                                    samlCallback.setSamlVersion(SAMLVersion.VERSION_20);
                                }
                            }
                        }
                    }
                   
                };
                config.put(ConfigurationConstants.SAML_CALLBACK_REF, callbackHandler);
               
                QName qname = WSSConstants.TAG_saml2_Assertion;
                if (WSConstants.SAML_NS.equals(el.getNamespaceURI())) {
                    qname = WSSConstants.TAG_saml_Assertion;
                }
               
                return new SecurePart(qname, Modifier.Element);
            } else if (isRequestor()) {
                // An Encrypted Token...just include it as is
                Map<String, Object> config = getProperties();
                String actionToPerform = ConfigurationConstants.CUSTOM_TOKEN;
                if (config.containsKey(ConfigurationConstants.ACTION)) {
                    String action = (String)config.get(ConfigurationConstants.ACTION);
                    config.put(ConfigurationConstants.ACTION, action + " " + actionToPerform);
                } else {
                    config.put(ConfigurationConstants.ACTION, actionToPerform);
                }
            }
        }
       
        return null;
    }
   
    protected void storeSecurityToken(SecurityToken tok) {
        SecurityTokenConstants.TokenType tokenType = WSSecurityTokenConstants.EncryptedKeyToken;
        if (tok.getTokenType() != null) {
            if (tok.getTokenType().startsWith(WSSConstants.NS_KERBEROS11_TOKEN_PROFILE)) {
                tokenType = WSSecurityTokenConstants.KerberosToken;
            } else if (tok.getTokenType().startsWith(WSSConstants.NS_SAML10_TOKEN_PROFILE)
                || tok.getTokenType().startsWith(WSSConstants.NS_SAML11_TOKEN_PROFILE)) {
                tokenType = WSSecurityTokenConstants.Saml11Token;
            } else if (tok.getTokenType().startsWith(WSSConstants.NS_WSC_05_02)
                || tok.getTokenType().startsWith(WSSConstants.NS_WSC_05_12)) {
                tokenType = WSSecurityTokenConstants.SecureConversationToken;
            }
        }
       
        final Key key = tok.getKey();
        final byte[] secret = tok.getSecret();
        final X509Certificate[] certs = new X509Certificate[1];
        if (tok.getX509Certificate() != null) {
            certs[0] = tok.getX509Certificate();
        }
       
        final GenericOutboundSecurityToken encryptedKeySecurityToken =
            new GenericOutboundSecurityToken(tok.getId(), tokenType, key, certs) {
         
                @Override
                public Key getSecretKey(String algorithmURI) throws XMLSecurityException {
                    if (secret != null && algorithmURI != null && !"".equals(algorithmURI)) {
                        return KeyUtils.prepareSecretKey(algorithmURI, secret);
                    }
                    if (key != null) {
                        return key;
                    }
                    if (secret != null) {
                        String jceAlg = JCEMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
                        if (jceAlg == null || "".equals(jceAlg)) {
                            jceAlg = "HmacSHA1";
                        }
                        return new SecretKeySpec(secret, jceAlg);
                    }
               
                    return super.getSecretKey(algorithmURI);
                }
            };
       
        final SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider =
            new SecurityTokenProvider<OutboundSecurityToken>() {

                @Override
                public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
                    return encryptedKeySecurityToken;
                }

                @Override
                public String getId() {
                    return encryptedKeySecurityToken.getId();
                }
               
            };
        encryptedKeySecurityToken.setSha1Identifier(tok.getSHA1());
        outboundTokens.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION,
                           encryptedKeySecurityTokenProvider);
        outboundTokens.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE,
                           encryptedKeySecurityTokenProvider);
        outboundTokens.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_CUSTOM_TOKEN,
                           encryptedKeySecurityTokenProvider);
    }
   
    protected void configureTimestamp(AssertionInfoMap aim) {
        if (binding != null && binding.isIncludeTimestamp()) {
            timestampAdded = true;
            assertPolicy(new QName(binding.getName().getNamespaceURI(), SPConstants.INCLUDE_TIMESTAMP));
        }
    }
   
    protected void configureLayout(AssertionInfoMap aim) {
        Collection<AssertionInfo> ais = getAllAssertionsByLocalname(aim, SPConstants.LAYOUT);
        Layout layout = null;
        for (AssertionInfo ai : ais) {
            layout = (Layout)ai.getAssertion();
            Collection<AssertionInfo> layoutTypeAis = aim.get(layout.getName());
            if (layoutTypeAis != null) {
                for (AssertionInfo layoutAi : layoutTypeAis) {
                    layoutAi.setAsserted(true);
                }
            }
            ai.setAsserted(true);
        }
        if (layout != null && layout.getLayoutType() != null) {
            assertPolicy(new QName(layout.getName().getNamespaceURI(), layout.getLayoutType().name()));
        }
       
        if (!timestampAdded) {
            return;
        }
       
        Map<String, Object> config = getProperties();
        boolean timestampLast =
            layout != null && layout.getLayoutType() == LayoutType.LaxTsLast;
       
        if (config.containsKey(ConfigurationConstants.ACTION)) {
            String action = (String)config.get(ConfigurationConstants.ACTION);
            if (timestampLast) {
                config.put(ConfigurationConstants.ACTION,
                       ConfigurationConstants.TIMESTAMP + " " + action);
            } else {
                config.put(ConfigurationConstants.ACTION,
                       action + " " + ConfigurationConstants.TIMESTAMP);
            }
        } else {
            config.put(ConfigurationConstants.ACTION, ConfigurationConstants.TIMESTAMP);
        }
    }

    protected Map<String, Object> getProperties() {
        return properties;
    }

    protected void configureSignature(
        AbstractTokenWrapper wrapper, AbstractToken token, boolean attached
    ) throws WSSecurityException {
        Map<String, Object> config = getProperties();
       
        if (token instanceof X509Token) {
            X509Token x509Token = (X509Token) token;
            TokenType tokenType = x509Token.getTokenType();
            if (tokenType == TokenType.WssX509PkiPathV1Token10
                || tokenType == TokenType.WssX509PkiPathV1Token11) {
                config.put(ConfigurationConstants.USE_SINGLE_CERTIFICATE, "false");
            }
        }
       
        config.put(ConfigurationConstants.SIG_KEY_ID, getKeyIdentifierType(wrapper, token));

        // Find out do we also need to include the token as per the Inclusion requirement
        if (token instanceof X509Token
            && isTokenRequired(token.getIncludeTokenType())
            && ("IssuerSerial".equals(config.get(ConfigurationConstants.SIG_KEY_ID))
                || "Thumbprint".equals(config.get(ConfigurationConstants.SIG_KEY_ID))
                || "DirectReference".equals(config.get(ConfigurationConstants.SIG_KEY_ID)))) {
            config.put(ConfigurationConstants.INCLUDE_SIGNATURE_TOKEN, "true");
        } else {
            config.put(ConfigurationConstants.INCLUDE_SIGNATURE_TOKEN, "false");
        }

        String userNameKey = SecurityConstants.SIGNATURE_USERNAME;
        if (binding instanceof SymmetricBinding) {
            userNameKey = SecurityConstants.ENCRYPT_USERNAME;
            config.put(ConfigurationConstants.SIG_ALGO,
                       binding.getAlgorithmSuite().getSymmetricSignature());
        } else {
            config.put(ConfigurationConstants.SIG_ALGO,
                       binding.getAlgorithmSuite().getAsymmetricSignature());
        }
        String sigUser = (String)message.getContextualProperty(userNameKey);
        if (sigUser != null) {
            config.put(ConfigurationConstants.SIGNATURE_USER, sigUser);
        }

        AlgorithmSuiteType algType = binding.getAlgorithmSuite().getAlgorithmSuiteType();
        config.put(ConfigurationConstants.SIG_DIGEST_ALGO, algType.getDigest());
        // sig.setSigCanonicalization(binding.getAlgorithmSuite().getC14n().getValue());

    }
   
    protected String getKeyIdentifierType(AbstractTokenWrapper wrapper, AbstractToken token) {

        String identifier = null;
        if (token instanceof X509Token) {
            X509Token x509Token = (X509Token)token;
            if (x509Token.isRequireIssuerSerialReference()) {
                identifier = "IssuerSerial";
            } else if (x509Token.isRequireKeyIdentifierReference()) {
                identifier = "SKIKeyIdentifier";
            } else if (x509Token.isRequireThumbprintReference()) {
                identifier = "Thumbprint";
            }
        } else if (token instanceof KeyValueToken) {
            identifier = "KeyValue";
        }
       
        if (identifier != null) {
            return identifier;
        }

        if (token.getIncludeTokenType() == IncludeTokenType.INCLUDE_TOKEN_NEVER) {
            Wss10 wss = getWss10();
            if (wss == null || wss.isMustSupportRefKeyIdentifier()) {
                return "SKIKeyIdentifier";
            } else if (wss.isMustSupportRefIssuerSerial()) {
                return "IssuerSerial";
            } else if (wss instanceof Wss11
                && ((Wss11) wss).isMustSupportRefThumbprint()) {
                return "Thumbprint";
            }
        } else {
            return "DirectReference";
        }
       
        return "IssuerSerial";
    }
   
    protected Map<AbstractToken, SecurePart> handleSupportingTokens(
        Collection<Assertion> tokens,
        boolean signed,
        boolean endorse
    ) throws Exception {
        Map<AbstractToken, SecurePart> ret = new HashMap<AbstractToken, SecurePart>();
        if (tokens != null) {
            for (Assertion pa : tokens) {
                if (pa instanceof SupportingTokens) {
                    handleSupportingTokens((SupportingTokens)pa, signed, endorse, ret);
                }
            }
        }
        return ret;
    }
                                                           
    protected Map<AbstractToken, SecurePart> handleSupportingTokens(
        SupportingTokens suppTokens,
        boolean signed,
        boolean endorse
    ) throws Exception {
        return handleSupportingTokens(suppTokens, signed, endorse, new HashMap<AbstractToken, SecurePart>());
    }
                                                           
    protected Map<AbstractToken, SecurePart> handleSupportingTokens(
        SupportingTokens suppTokens,
        boolean signed,
        boolean endorse,
        Map<AbstractToken, SecurePart> ret
    ) throws Exception {
        if (suppTokens == null) {
            return ret;
        }
        for (AbstractToken token : suppTokens.getTokens()) {
            assertToken(token);
            if (!isTokenRequired(token.getIncludeTokenType())) {
                continue;
            }
           
            if (token instanceof UsernameToken) {
                handleUsernameTokenSupportingToken(
                    (UsernameToken)token, endorse, suppTokens.isEncryptedToken(), ret
                );
            /* TODO else if (isRequestor()
                && (token instanceof IssuedToken
                    || token instanceof SecureConversationToken
                    || token instanceof SecurityContextToken
                    || token instanceof KerberosToken)) {

            } */
            } else if (token instanceof IssuedToken) {
                SecurityToken sigTok = getSecurityToken();
                SecurePart securePart = addIssuedToken((IssuedToken)token, sigTok, signed, endorse);
                if (securePart != null) {
                    ret.put(token, securePart);
                    if (suppTokens.isEncryptedToken()) {
                        encryptedTokensList.add(securePart);
                    }
                }
            } else if (token instanceof KerberosToken) {
                SecurePart securePart = addKerberosToken((KerberosToken)token, signed, endorse, false);
                if (securePart != null) {
                    ret.put(token, securePart);
                    if (suppTokens.isEncryptedToken()) {
                        encryptedTokensList.add(securePart);
                    }
                }
            } else if (token instanceof X509Token || token instanceof KeyValueToken) {
                assertToken(token);
                configureSignature(suppTokens, token, false);
                if (suppTokens.isEncryptedToken()) {
                    SecurePart part =
                        new SecurePart(WSSConstants.TAG_wsse_BinarySecurityToken, Modifier.Element);
                    encryptedTokensList.add(part);
                }
                ret.put(token, new SecurePart(WSSConstants.TAG_dsig_Signature, Modifier.Element));
            } else if (token instanceof SamlToken) {
                SecurePart securePart = addSamlToken((SamlToken)token, signed, endorse);
                if (securePart != null) {
                    ret.put(token, securePart);
                    if (suppTokens.isEncryptedToken()) {
                        encryptedTokensList.add(securePart);
                    }
                }
            }
        }
        return ret;
    }

    protected void handleUsernameTokenSupportingToken(
         UsernameToken token, boolean endorse, boolean encryptedToken, Map<AbstractToken, SecurePart> ret
    ) throws Exception {
        if (endorse) {
            throw new Exception("Endorsing UsernameTokens are not supported in the streaming code");
        } else {
            SecurePart securePart = addUsernameToken(token);
            if (securePart != null) {
                ret.put(token, securePart);
                //WebLogic and WCF always encrypt these
                //See:  http://e-docs.bea.com/wls/docs103/webserv_intro/interop.html
                //encryptedTokensIdList.add(utBuilder.getId());
                if (encryptedToken
                    || MessageUtils.getContextualBoolean(message,
                                                         SecurityConstants.ALWAYS_ENCRYPT_UT,
                                                         true)) {
                    encryptedTokensList.add(securePart);
                }
            }
        }
    }
   
    protected void addSupportingTokens() throws Exception {
       
        Collection<Assertion> sgndSuppTokens =
            findAndAssertPolicy(SP12Constants.SIGNED_SUPPORTING_TOKENS);
        Map<AbstractToken, SecurePart> sigSuppTokMap =
            this.handleSupportingTokens(sgndSuppTokens, true, false);
        sgndSuppTokens = findAndAssertPolicy(SP11Constants.SIGNED_SUPPORTING_TOKENS);
        sigSuppTokMap.putAll(this.handleSupportingTokens(sgndSuppTokens, true, false));
       
        Collection<Assertion> endSuppTokens =
            findAndAssertPolicy(SP12Constants.ENDORSING_SUPPORTING_TOKENS);
        endSuppTokMap = this.handleSupportingTokens(endSuppTokens, false, true);
        endSuppTokens = findAndAssertPolicy(SP11Constants.ENDORSING_SUPPORTING_TOKENS);
        endSuppTokMap.putAll(this.handleSupportingTokens(endSuppTokens, false, true));

        Collection<Assertion> sgndEndSuppTokens
            = findAndAssertPolicy(SP12Constants.SIGNED_ENDORSING_SUPPORTING_TOKENS);
        sgndEndSuppTokMap = this.handleSupportingTokens(sgndEndSuppTokens, true, true);
        sgndEndSuppTokens = findAndAssertPolicy(SP11Constants.SIGNED_ENDORSING_SUPPORTING_TOKENS);
        sgndEndSuppTokMap.putAll(this.handleSupportingTokens(sgndEndSuppTokens, true, true));
       
        Collection<Assertion> sgndEncryptedSuppTokens
            = findAndAssertPolicy(SP12Constants.SIGNED_ENCRYPTED_SUPPORTING_TOKENS);
        Map<AbstractToken, SecurePart> sgndEncSuppTokMap =
            this.handleSupportingTokens(sgndEncryptedSuppTokens, true, false);
       
        Collection<Assertion> endorsingEncryptedSuppTokens
            = findAndAssertPolicy(SP12Constants.ENDORSING_ENCRYPTED_SUPPORTING_TOKENS);
        endEncSuppTokMap
            = this.handleSupportingTokens(endorsingEncryptedSuppTokens, false, true);

        Collection<Assertion> sgndEndEncSuppTokens
            = findAndAssertPolicy(SP12Constants.SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS);
        sgndEndEncSuppTokMap = this.handleSupportingTokens(sgndEndEncSuppTokens, true, true);

        Collection<Assertion> supportingToks
            = findAndAssertPolicy(SP12Constants.SUPPORTING_TOKENS);
        this.handleSupportingTokens(supportingToks, false, false);
        supportingToks = findAndAssertPolicy(SP11Constants.SUPPORTING_TOKENS);
        this.handleSupportingTokens(supportingToks, false, false);

        Collection<Assertion> encryptedSupportingToks
            = findAndAssertPolicy(SP12Constants.ENCRYPTED_SUPPORTING_TOKENS);
        this.handleSupportingTokens(encryptedSupportingToks, false, false);

        //Setup signature parts
        addSignatureParts(sigSuppTokMap);
        addSignatureParts(sgndEncSuppTokMap);
        addSignatureParts(sgndEndSuppTokMap);
        addSignatureParts(sgndEndEncSuppTokMap);
    }
   
    protected void addSignatureParts(Map<AbstractToken, SecurePart> tokenMap) {
        for (AbstractToken token : tokenMap.keySet()) {
            SecurePart part = tokenMap.get(token);

            String parts = "";
            Map<String, Object> config = getProperties();
            if (config.containsKey(ConfigurationConstants.SIGNATURE_PARTS)) {
                parts = (String)config.get(ConfigurationConstants.SIGNATURE_PARTS);
                if (!parts.endsWith(";")) {
                    parts += ";";
                }
            }

            QName name = part.getName();
            String action = (String)config.get(ConfigurationConstants.ACTION);
            // Don't add a signed SAML Token as a part, as it will be automatically signed by WSS4J
            if (!((WSSConstants.TAG_saml_Assertion.equals(name)
                || WSSConstants.TAG_saml2_Assertion.equals(name))
                && action != null && action.contains(ConfigurationConstants.SAML_TOKEN_SIGNED))) {
                parts += "{Element}{" +  name.getNamespaceURI() + "}" + name.getLocalPart() + ";";
            }

            config.put(ConfigurationConstants.SIGNATURE_PARTS, parts);
        }
       
    }
   
    protected void addSignatureConfirmation(List<SecurePart> sigParts) {
        Wss10 wss10 = getWss10();
       
        if (!(wss10 instanceof Wss11)
            || !((Wss11)wss10).isRequireSignatureConfirmation()) {
            //If we don't require sig confirmation simply go back :-)
            return;
        }
       
        // Enable SignatureConfirmation
        Map<String, Object> config = getProperties();
        config.put(ConfigurationConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
       
        if (sigParts != null) {
            SecurePart securePart =
                new SecurePart(WSSConstants.TAG_wsse11_SignatureConfirmation, Modifier.Element);
            sigParts.add(securePart);
        }
        signatureConfirmationAdded = true;
    }
   
    /**
     * Identifies the portions of the message to be signed
     */
    protected List<SecurePart> getSignedParts() throws SOAPException {
        SignedParts parts = null;
        SignedElements elements = null;
       
        AssertionInfoMap aim = message.get(AssertionInfoMap.class);
        Collection<AssertionInfo> ais = getAllAssertionsByLocalname(aim, SPConstants.SIGNED_PARTS);
        if (!ais.isEmpty()) {
            for (AssertionInfo ai : ais) {
                parts = (SignedParts)ai.getAssertion();
                ai.setAsserted(true);
            }           
        }
       
        ais = getAllAssertionsByLocalname(aim, SPConstants.SIGNED_ELEMENTS);
        if (!ais.isEmpty()) {
            for (AssertionInfo ai : ais) {
                elements = (SignedElements)ai.getAssertion();
                ai.setAsserted(true);
            }           
        }
       
        List<SecurePart> signedParts = new ArrayList<SecurePart>();
        if (parts != null) {
            if (parts.isBody()) {
                QName soapBody = new QName(WSSConstants.NS_SOAP12, "Body");
                SecurePart securePart = new SecurePart(soapBody, Modifier.Element);
                signedParts.add(securePart);
            }
            for (Header head : parts.getHeaders()) {
                String localName = head.getName();
                if (localName == null) {
                    localName = "*";
                }
                QName qname = new QName(head.getNamespace(), localName);
                SecurePart securePart = new SecurePart(qname, Modifier.Element);
                securePart.setRequired(false);
                signedParts.add(securePart);
            }
        }
       
        if (elements != null && elements.getXPaths() != null) {
            for (XPath xPath : elements.getXPaths()) {
                List<QName> qnames = PolicyUtils.getElementPath(xPath);
                if (!qnames.isEmpty()) {
                    SecurePart securePart =
                        new SecurePart(qnames.get(qnames.size() - 1), Modifier.Element);
                    signedParts.add(securePart);
                }
            }
        }
       
        return signedParts;
    }
   
    /**
     * Identifies the portions of the message to be encrypted
     */
    protected List<SecurePart> getEncryptedParts() throws SOAPException {
        EncryptedParts parts = null;
        EncryptedElements elements = null;
        ContentEncryptedElements celements = null;
       
        AssertionInfoMap aim = message.get(AssertionInfoMap.class);
        Collection<AssertionInfo> ais = getAllAssertionsByLocalname(aim, SPConstants.ENCRYPTED_PARTS);
        if (!ais.isEmpty()) {
            for (AssertionInfo ai : ais) {
                parts = (EncryptedParts)ai.getAssertion();
                ai.setAsserted(true);
            }           
        }
       
        ais = getAllAssertionsByLocalname(aim, SPConstants.ENCRYPTED_ELEMENTS);
        if (!ais.isEmpty()) {
            for (AssertionInfo ai : ais) {
                elements = (EncryptedElements)ai.getAssertion();
                ai.setAsserted(true);
            }           
        }
       
        ais = getAllAssertionsByLocalname(aim, SPConstants.CONTENT_ENCRYPTED_ELEMENTS);
        if (!ais.isEmpty()) {
            for (AssertionInfo ai : ais) {
                celements = (ContentEncryptedElements)ai.getAssertion();
                ai.setAsserted(true);
            }           
        }
       
        List<SecurePart> encryptedParts = new ArrayList<SecurePart>();
        if (parts != null) {
            if (parts.isBody()) {
                QName soapBody = new QName(WSSConstants.NS_SOAP12, "Body");
                SecurePart securePart = new SecurePart(soapBody, Modifier.Content);
                encryptedParts.add(securePart);
            }
            for (Header head : parts.getHeaders()) {
                String localName = head.getName();
                if (localName == null) {
                    localName = "*";
                }
                QName qname = new QName(head.getNamespace(), localName);
                SecurePart securePart = new SecurePart(qname, Modifier.Element);
                securePart.setRequired(false);
                encryptedParts.add(securePart);
            }
        }
       
        if (elements != null && elements.getXPaths() != null) {
            for (XPath xPath : elements.getXPaths()) {
                List<QName> qnames = PolicyUtils.getElementPath(xPath);
                if (!qnames.isEmpty()) {
                    SecurePart securePart =
                        new SecurePart(qnames.get(qnames.size() - 1), Modifier.Element);
                    encryptedParts.add(securePart);
                }
            }
        }
       
        if (celements != null && celements.getXPaths() != null) {
            for (XPath xPath : celements.getXPaths()) {
                List<QName> qnames = PolicyUtils.getElementPath(xPath);
                if (!qnames.isEmpty()) {
                    SecurePart securePart =
                        new SecurePart(qnames.get(qnames.size() - 1), Modifier.Content);
                    encryptedParts.add(securePart);
                }
            }
        }
       
        return encryptedParts;
    }
   
    protected static class TokenStoreCallbackHandler implements CallbackHandler {
        private CallbackHandler internal;
        private TokenStore store;
        public TokenStoreCallbackHandler(CallbackHandler in, TokenStore st) {
            internal = in;
            store = st;
        }
       
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            for (int i = 0; i < callbacks.length; i++) {
                WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
               
                String id = pc.getIdentifier();
                SecurityToken token = store.getToken(id);
                if (token != null) {
                    if (token.getSHA1() == null && pc.getKey() != null) {
                        token.setSHA1(getSHA1(pc.getKey()));
                        // Create another cache entry with the SHA1 Identifier as the key
                        // for easy retrieval
                        store.add(token.getSHA1(), token);
                    }
                    pc.setKey(token.getSecret());
                    pc.setCustomToken(token.getToken());
                    return;
                }
            }
            if (internal != null) {
                internal.handle(callbacks);
            }
        }
    }
   
    protected org.apache.xml.security.stax.securityToken.SecurityToken
    findInboundSecurityToken(SecurityEventConstants.Event event) throws XMLSecurityException {
        @SuppressWarnings("unchecked")
        final List<SecurityEvent> incomingEventList =
            (List<SecurityEvent>) message.getExchange().get(SecurityEvent.class.getName() + ".in");
        if (incomingEventList != null) {
            for (SecurityEvent incomingEvent : incomingEventList) {
                if (event == incomingEvent.getSecurityEventType()) {
                    org.apache.xml.security.stax.securityToken.SecurityToken token =
                        ((TokenSecurityEvent<?>)incomingEvent).getSecurityToken();
                    return token;
                }
            }
        }
        return null;
    }
}
TOP

Related Classes of org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractStaxBindingHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.