/*
 * Copyright  2003-2005 The Apache Software Foundation.
 *
 *  Licensed 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.ws.security.handler;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.action.Action;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.token.SignatureConfirmation;
import org.apache.ws.security.message.token.Timestamp;
import org.apache.ws.security.util.Loader;
import org.apache.ws.security.util.StringUtil;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.w3c.dom.Document;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;

import java.math.BigInteger;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;


/**
 * Extracted from WSDoAllReceiver and WSDoAllSender
 * Extended to all passwordless UsernameTokens and configurable identities.
 *
 * @author Davanum Srinivas (dims@yahoo.com).
 * @author Werner Dittmann (Werner.Dittmann@t-online.de).
 * @author Marcel Ammerlaan (marcel.ammerlaan@gmail.com).
 */
public abstract class WSHandler {
    public static String DONE = "done";
    private static Log log = LogFactory.getLog(WSHandler.class.getName());
    protected static final WSSecurityEngine secEngine = WSSecurityEngine.getInstance();
    protected static Hashtable cryptos = new Hashtable(5);

    private boolean doDebug = log.isDebugEnabled();

    /**                                                             
     * Performs all defined security actions to set-up the SOAP request.
     * 
     * 
     * @param doAction a set defining the actions to do 
     * @param doc   the request as DOM document 
     * @param reqData a data storage to pass values around between methods
     * @param actions a vector holding the actions to do in the order defined
     *                in the deployment file or property
     * @throws WSSecurityException
     */
    protected void doSenderAction(
            int doAction, 
            Document doc,
            RequestData reqData, 
            Vector actions, 
            boolean isRequest
    ) throws WSSecurityException {

        boolean mu = decodeMustUnderstand(reqData);

        WSSConfig wssConfig = reqData.getWssConfig();
        if (wssConfig == null) {
            wssConfig = WSSConfig.getNewInstance();
        }

        wssConfig
        .setEnableSignatureConfirmation(decodeEnableSignatureConfirmation(reqData));

        wssConfig
        .setPrecisionInMilliSeconds(decodeTimestampPrecision(reqData));
        reqData.setWssConfig(wssConfig);

        Object mc = reqData.getMsgContext();
        String actor = getString(WSHandlerConstants.ACTOR, mc);
        reqData.setActor(actor);

        WSSecHeader secHeader = new WSSecHeader(actor, mu);
        secHeader.insertSecurityHeader(doc);

        reqData.setSecHeader(secHeader);
        reqData.setSoapConstants(WSSecurityUtil.getSOAPConstants(doc
                .getDocumentElement()));
        /*
         * Here we have action, username, password, and actor, mustUnderstand.
         * Now get the action specific parameters.
         */
        if ((doAction & WSConstants.UT) == WSConstants.UT) {
            decodeUTParameter(reqData);
        }
        /*
         * Here we have action, username, password, and actor, mustUnderstand.
         * Now get the action specific parameters.
         */
        if ((doAction & WSConstants.UT_SIGN) == WSConstants.UT_SIGN) {
            decodeUTParameter(reqData);
            decodeSignatureParameter(reqData);
        }
        /*
         * Get and check the Signature specific parameters first because they
         * may be used for encryption too.
         */
        if ((doAction & WSConstants.SIGN) == WSConstants.SIGN) {
            reqData.setSigCrypto(loadSignatureCrypto(reqData));
            decodeSignatureParameter(reqData);
        }
        /*
         * If we need to handle signed SAML token then we need may of the
         * Signature parameters. The handle procedure loads the signature crypto
         * file on demand, thus don't do it here.
         */
        if ((doAction & WSConstants.ST_SIGNED) == WSConstants.ST_SIGNED) {
            decodeSignatureParameter(reqData);
        }
        /*
         * Set and check the encryption specific parameters, if necessary take
         * over signature parameters username and crypto instance.
         */
        if ((doAction & WSConstants.ENCR) == WSConstants.ENCR) {
            reqData.setEncCrypto(loadEncryptionCrypto(reqData));
            decodeEncryptionParameter(reqData);
        }
        /*
         * If after all the parsing no Signature parts defined, set here a
         * default set. This is necessary because we add SignatureConfirmation
         * and therefore the default (Body) must be set here. The default setting
         * in WSSignEnvelope doesn't work because the vector is not empty anymore.
         */
        if (reqData.getSignatureParts().isEmpty()) {
            WSEncryptionPart encP = new WSEncryptionPart(reqData.getSoapConstants()
                    .getBodyQName().getLocalPart(), reqData.getSoapConstants()
                    .getEnvelopeURI(), "Content");
            reqData.getSignatureParts().add(encP);
        }
        /*
         * If SignatureConfirmation is enabled and this is a response then
         * insert SignatureConfrmation elements, note their wsu:id in the signature
         * parts. They will be signed automatically during a (probably) defined
         * SIGN action.
         */
        if (wssConfig.isEnableSignatureConfirmation() && !isRequest) {
            String done = (String) 
                getProperty(reqData.getMsgContext(), WSHandlerConstants.SIG_CONF_DONE);
            if (!DONE.equals(done)
                && (getProperty(reqData.getMsgContext(), WSHandlerConstants.RECV_RESULTS)) 
                    != null) {
                wssConfig.getAction(WSConstants.SC).execute(this, WSConstants.SC, doc, reqData);
            }
        }
        /*
         * Here we have all necessary information to perform the requested
         * action(s).
         */
        for (int i = 0; i < actions.size(); i++) {

            int actionToDo = ((Integer) actions.get(i)).intValue();
            if (doDebug) {
                log.debug("Performing Action: " + actionToDo);
            }

            switch (actionToDo) {
            case WSConstants.UT:
            case WSConstants.ENCR:
            case WSConstants.SIGN:
            case WSConstants.ST_SIGNED:
            case WSConstants.ST_UNSIGNED:
            case WSConstants.TS:
            case WSConstants.UT_SIGN:
                wssConfig.getAction(actionToDo).execute(this, actionToDo, doc, reqData);
                break;
            case WSConstants.NO_SERIALIZE:
                reqData.setNoSerialization(true);
                break;
                //
                // Handle any "custom" actions, similarly,
                // but to preserve behavior from previous
                // versions, consume (but log) action lookup failures.
                //
            default:
                Action doit = null;
            try {
                doit = wssConfig.getAction(actionToDo);
            } catch (final WSSecurityException e) {
                log.warn(
                        "Error trying to locate a custom action (" + actionToDo + ")", 
                        e
                );
            }
            if (doit != null) {
                doit.execute(this, actionToDo, doc, reqData);
            }
            }
        }
        /*
         * If this is a request then store all signature values. Add ours to
         * already gathered values because of chained handlers, e.g. for
         * other actors.
         */

        if (wssConfig.isEnableSignatureConfirmation() 
                && isRequest
                && reqData.getSignatureValues().size() > 0) {
            Vector sigv = (Vector) 
            getProperty(reqData.getMsgContext(), WSHandlerConstants.SEND_SIGV);
            if (sigv == null) {
                sigv = new Vector();
                setProperty(reqData.getMsgContext(),
                        WSHandlerConstants.SEND_SIGV, sigv);
            }
            // sigv.add(reqData.getSignatureValues());
            sigv.addAll(reqData.getSignatureValues());
        }
    }



    protected void doReceiverAction(int doAction, RequestData reqData)
        throws WSSecurityException {

        WSSConfig wssConfig = WSSConfig.getNewInstance();
        wssConfig
        .setEnableSignatureConfirmation(decodeEnableSignatureConfirmation(reqData));
        wssConfig.setTimeStampStrict(decodeTimestampStrict(reqData));
        wssConfig.setHandleCustomPasswordTypes(decodeCustomPasswordTypes(reqData));
        reqData.setWssConfig(wssConfig);

        if ((doAction & WSConstants.SIGN) == WSConstants.SIGN) {
            decodeSignatureParameter2(reqData);
        }

        if ((doAction & WSConstants.ENCR) == WSConstants.ENCR) {
            decodeDecryptionParameter(reqData);
        }
        if ((doAction & WSConstants.NO_SERIALIZE) == WSConstants.NO_SERIALIZE) {
            reqData.setNoSerialization(true);
        }
    }

    protected boolean checkReceiverResults(Vector wsResult, Vector actions) {
        int resultActions = wsResult.size();
        int size = actions.size();

        int ai = 0;
        for (int i = 0; i < resultActions; i++) {
            final Integer actInt = (Integer) ((WSSecurityEngineResult) wsResult
                    .get(i)).get(WSSecurityEngineResult.TAG_ACTION);
            int act = actInt.intValue();
            if (act == WSConstants.SC || act == WSConstants.BST) {
                continue;
            }
            if (ai >= size || ((Integer) actions.get(ai++)).intValue() != act) {
                return false;
            }
        }

        if (ai != size) {
            return false;
        }

        return true;
    }

    protected void checkSignatureConfirmation(RequestData reqData,
            Vector wsResult) throws WSSecurityException{
        if (doDebug) {
            log.debug("Check Signature confirmation");
        }

        /*
         * First get all Signature value stored during sending the request
         */
        Vector sigv = (Vector) getProperty(reqData.getMsgContext(),
                WSHandlerConstants.SEND_SIGV);
        /*
         * Now get all results that hold a SignatureConfirmation element from
         * the current run of receiver (we can have more than one run: if we
         * have several security header blocks with different actors/roles)
         */
        Vector sigConf = new Vector();
        WSSecurityUtil.fetchAllActionResults(wsResult, WSConstants.SC, sigConf);
        /*
         * now loop over all SignatureConfirmation results and check:
         * - if there is a signature value and no Signature value generated in request: error
         * - if there is a signature value and no matching Signature value found: error
         * 
         *  If a matching value found: remove from vector of stored signature values
         */
        for (int i = 0; i < sigConf.size(); i++) {
            WSSecurityEngineResult result = 
                (WSSecurityEngineResult)sigConf.get(i);
            SignatureConfirmation sc = 
                (SignatureConfirmation)result.get(WSSecurityEngineResult.TAG_SIGNATURE_CONFIRMATION);

            byte[] sigVal = sc.getSignatureValue();
            if (sigVal != null) {
                if (sigv == null || sigv.size() == 0) {
                    //If there are no store signature values
                    if(sigVal.length != 0) {
                        //If there's no value in the case where there are no
                        //stored SV it is valid. Therefore if there IS a value 
                        //in the sig confirmation element
                        throw new WSSecurityException("WSHandler: Check Signature confirmation: got a SC element, but no stored SV");
                    }
                } else {
                    //If we have stored signature values
                    boolean found = false;
                    for (int ii = 0; ii < sigv.size(); ii++) {
                        byte[] storedValue = (byte[]) sigv.get(i);
                        if (Arrays.equals(sigVal, storedValue)) {
                            found = true;
                            sigv.remove(ii);
                            break;
                        }
                    }
                    if (!found) {
                        throw new WSSecurityException(
                        "WSHandler: Check Signature confirmation: got SC element, but no matching SV");
                    } 
                }
            }
        }

        /*
         * This indicates this is the last handler: the vector holding the
         * stored Signature values must be empty, otherwise we have an error
         */
        if (!reqData.isNoSerialization()) {
            log.debug("Check Signature confirmation - last handler");
            if (sigv != null && !sigv.isEmpty()) {
                throw new WSSecurityException("WSHandler: Check Signature confirmation: stored SV vector not empty");
            }
        }
    }
    /**
     * Hook to allow subclasses to load their Signature Crypto however they see
     * fit.
     */
    public Crypto loadSignatureCrypto(RequestData reqData) 
        throws WSSecurityException {
        Crypto crypto = null;
        /*
         * Get crypto property file for signature. If none specified throw
         * fault, otherwise get a crypto instance.
         */
        String sigPropFile = getString(WSHandlerConstants.SIG_PROP_FILE,
                reqData.getMsgContext());
        if (sigPropFile != null) {
            crypto = (Crypto) cryptos.get(sigPropFile);
            if (crypto == null) {
                crypto = CryptoFactory.getInstance(sigPropFile, this
                        .getClassLoader(reqData.getMsgContext()));
                cryptos.put(sigPropFile, crypto);
            }
        } else if (getString(WSHandlerConstants.SIG_PROP_REF_ID, reqData
                .getMsgContext()) != null) {
            /*
             * If the property file is missing then 
             * look for the Properties object 
             */
            String refId = getString(WSHandlerConstants.SIG_PROP_REF_ID,
                    reqData.getMsgContext());
            if (refId != null) {
                Object propObj = getProperty(reqData.getMsgContext(), refId);
                if(propObj instanceof Properties) {
                    crypto = (Crypto) cryptos.get(refId);
                    if (crypto == null) {
                        crypto = CryptoFactory.getInstance((Properties)propObj);
                        cryptos.put(refId, crypto);
                    }
                } else {
                    throw new WSSecurityException(
                        "WSHandler: Signature: signaturePropRefId must hold a " 
                            + "java.util.Properties object"
                    );
                }
            }
        } else {
            throw new WSSecurityException(
                "WSHandler: Signature: no crypto properties"
            );
        }
        return crypto;
    }

    /**
     * Hook to allow subclasses to load their Encryption Crypto however they
     * see fit.
     */
    protected Crypto loadEncryptionCrypto(RequestData reqData) 
        throws WSSecurityException {
        Crypto crypto = null;
        /*
         * Get encryption crypto property file. If non specified take crypto
         * instance from signature, if that fails: throw fault
         */
        String encPropFile = getString(WSHandlerConstants.ENC_PROP_FILE,
                reqData.getMsgContext());
        if (encPropFile != null) {
            crypto = (Crypto) cryptos.get(encPropFile);
            if (crypto == null) {
                crypto = CryptoFactory.getInstance(encPropFile, this
                        .getClassLoader(reqData.getMsgContext()));
                cryptos.put(encPropFile, crypto);
            }
        } else if (getString(WSHandlerConstants.ENC_PROP_REF_ID, reqData
                .getMsgContext()) != null) {
            /*
             * If the property file is missing then 
             * look for the Properties object 
             */
            String refId = getString(WSHandlerConstants.ENC_PROP_REF_ID,
                    reqData.getMsgContext());
            if(refId != null) {
                Object propObj = getProperty(reqData.getMsgContext(), refId);
                if(propObj instanceof Properties) {
                    crypto = (Crypto) cryptos.get(refId);
                    if (crypto == null) {
                        crypto = CryptoFactory.getInstance((Properties)propObj);
                        cryptos.put(refId, crypto);
                    }
                } else {
                    throw new WSSecurityException(
                        "WSHandler: Encryption: encryptionPropRefId must hold a" 
                            + " java.util.Properties object"
                    );
                }
            }
        } else if ((crypto = reqData.getSigCrypto()) == null) {
            throw new WSSecurityException(
                "WSHandler: Encryption: no crypto property file"
            );
        }
        return crypto;
    }

    protected void decodeUTParameter(RequestData reqData) 
        throws WSSecurityException {
        Object mc = reqData.getMsgContext();

        String type = getString(WSHandlerConstants.PASSWORD_TYPE, mc);
        if (type != null) {
            if(WSConstants.PW_TEXT.equals(type)) {
                reqData.setPwType(WSConstants.PASSWORD_TEXT);
            } else if(WSConstants.PW_DIGEST.equals(type)) {
                reqData.setPwType(WSConstants.PASSWORD_DIGEST);
            } else if(WSConstants.PW_NONE.equals(type)) {
                // No password requested.
                reqData.setPwType(null);
            } else {
                throw new WSSecurityException("Unknown password type encoding: " + type);
            }
        }

        String add = getString(WSHandlerConstants.ADD_UT_ELEMENTS, mc);
        if (add != null) {
            reqData.setUtElements(StringUtil.split(add, ' '));
        }
    }

    protected void decodeSignatureParameter(RequestData reqData) 
        throws WSSecurityException {
        Object mc = reqData.getMsgContext();
        String keyId = getString(WSHandlerConstants.SIG_KEY_ID, mc);
        if (keyId != null) {
            Integer id = (Integer) WSHandlerConstants.keyIdentifier.get(keyId);
            if (id == null) {
                throw new WSSecurityException(
                    "WSHandler: Signature: unknown key identification"
                );
            }
            int tmp = id.intValue();
            if (!(tmp == WSConstants.ISSUER_SERIAL
                    || tmp == WSConstants.BST_DIRECT_REFERENCE
                    || tmp == WSConstants.X509_KEY_IDENTIFIER
                    || tmp == WSConstants.SKI_KEY_IDENTIFIER
                    || tmp == WSConstants.THUMBPRINT_IDENTIFIER)) {
                throw new WSSecurityException(
                    "WSHandler: Signature: illegal key identification"
                );
            }
            reqData.setSigKeyId(tmp);
        }
        String algo = getString(WSHandlerConstants.SIG_ALGO, mc);
        reqData.setSigAlgorithm(algo);

        String parts = getString(WSHandlerConstants.SIGNATURE_PARTS, mc);
        if (parts != null) {
            splitEncParts(parts, reqData.getSignatureParts(), reqData);
        }
    }

    protected void decodeEncryptionParameter(RequestData reqData) 
        throws WSSecurityException {
        Object mc = reqData.getMsgContext();
        String encUser = getString(WSHandlerConstants.ENCRYPTION_USER, mc);

        if (encUser != null) {
            reqData.setEncUser(encUser);
        } else {
            reqData.setEncUser(reqData.getUsername());
        }
        if (reqData.getEncUser() == null) {
            throw new WSSecurityException("WSHandler: Encryption: no username");
        }
        /*
         * String msgType = msgContext.getCurrentMessage().getMessageType(); if
         * (msgType != null && msgType.equals(Message.RESPONSE)) {
         * handleSpecialUser(encUser); }
         */
        handleSpecialUser(reqData);

        /*
         * If the following parameters are no used (they return null) then the
         * default values of WSS4J are used.
         */
        String encKeyId = getString(WSHandlerConstants.ENC_KEY_ID, mc);
        if (encKeyId != null) {
            Integer id = (Integer) WSHandlerConstants.keyIdentifier.get(encKeyId);
            if (id == null) {
                throw new WSSecurityException(
                    "WSHandler: Encryption: unknown key identification"
                );
            }
            int tmp = id.intValue();
            reqData.setEncKeyId(tmp);
            if (!(tmp == WSConstants.ISSUER_SERIAL
                    || tmp == WSConstants.X509_KEY_IDENTIFIER
                    || tmp == WSConstants.SKI_KEY_IDENTIFIER
                    || tmp == WSConstants.BST_DIRECT_REFERENCE
                    || tmp == WSConstants.EMBEDDED_KEYNAME
                    || tmp == WSConstants.THUMBPRINT_IDENTIFIER)) {
                throw new WSSecurityException(
                    "WSHandler: Encryption: illegal key identification"
                );
            }
        }
        String encSymAlgo = getString(WSHandlerConstants.ENC_SYM_ALGO, mc);
        reqData.setEncSymmAlgo(encSymAlgo);

        String encKeyTransport = 
            getString(WSHandlerConstants.ENC_KEY_TRANSPORT, mc);
        reqData.setEncKeyTransport(encKeyTransport);

        String encParts = getString(WSHandlerConstants.ENCRYPTION_PARTS, mc);
        if (encParts != null) {
            splitEncParts(encParts, reqData.getEncryptParts(), reqData);
        }
    }

    protected boolean decodeMustUnderstand(RequestData reqData) 
        throws WSSecurityException {
        String mu = 
            getString(WSHandlerConstants.MUST_UNDERSTAND, reqData.getMsgContext());

        if (mu == null) {return true;}

        if ("0".equals(mu) || "false".equals(mu)) {return false;} 
        if ("1".equals(mu) || "true".equals(mu)) {return true;}

        throw new WSSecurityException(
            "WSHandler: illegal mustUnderstand parameter"
        );
    }

    public int decodeTimeToLive(RequestData reqData) {
        String ttl = 
            getString(WSHandlerConstants.TTL_TIMESTAMP, reqData.getMsgContext());
        int ttl_i = 0;
        if (ttl != null) {
            try {
                ttl_i = Integer.parseInt(ttl);
            } catch (NumberFormatException e) {
                ttl_i = reqData.getTimeToLive();
            }
        }
        if (ttl_i <= 0) {
            ttl_i = reqData.getTimeToLive();
        }
        return ttl_i;
    }

    protected boolean decodeEnableSignatureConfirmation(RequestData reqData) throws WSSecurityException {

        String value = getString(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION,
                reqData.getMsgContext());

        if (value == null) {return true;}

        if ("0".equals(value) || "false".equals(value)) {return false;} 
        if ("1".equals(value) || "true".equals(value)) {return true;}

        throw new WSSecurityException(
            "WSHandler: illegal enableSignatureConfirmation parameter"
        );
    }

    protected boolean decodeTimestampPrecision(RequestData reqData) 
        throws WSSecurityException {
        String value = getString(WSHandlerConstants.TIMESTAMP_PRECISION,
                reqData.getMsgContext());

        if (value == null) {return true;}

        if ("0".equals(value) || "false".equals(value)) {return false;} 
        if ("1".equals(value) || "true".equals(value)) {return true;}

        throw new WSSecurityException(
            "WSHandler: illegal precisionInMilliSeconds parameter"
        );
    }

    protected boolean decodeCustomPasswordTypes(RequestData reqData) 
        throws WSSecurityException {
        String value = getString(
                WSHandlerConstants.HANDLE_CUSTOM_PASSWORD_TYPES,
                reqData.getMsgContext()
        );

        if (value == null) {return false;}

        if ("0".equals(value) || "false".equals(value)) {return false;} 
        if ("1".equals(value) || "true".equals(value)) {return true;}

        throw new WSSecurityException(
            "WSHandler: illegal handleCustomPasswordTypes parameter"
        );
    }

    protected boolean decodeTimestampStrict(RequestData reqData) 
        throws WSSecurityException {
        String value = getString(WSHandlerConstants.TIMESTAMP_STRICT,
                reqData.getMsgContext());

        if (value == null) {return true;}

        if ("0".equals(value) || "false".equals(value)) {return false;} 
        if ("1".equals(value) || "true".equals(value)) {return true;}

        throw new WSSecurityException(
            "WSHandler: illegal timestampStrict parameter"
        );
    }

    /**
     * Get a password to construct a UsernameToken or sign a message.
     * <p/>
     * Try all possible sources to get a password.
     */
    public WSPasswordCallback getPassword(String username,
            int doAction,
            String clsProp,
            String refProp,
            RequestData reqData
    ) throws WSSecurityException {
        WSPasswordCallback pwCb = null;
        CallbackHandler cbHandler = null;
        String err = "provided null or empty password";
        Object mc = reqData.getMsgContext();
        String callback = getString(clsProp, mc);
        if (callback != null) { // we have a password callback class
            pwCb = readPwViaCallbackClass(callback, username, doAction, reqData);
            // Null passwords are not always a problem: if the callback was called to provide a username instead.
        } else if ((cbHandler = (CallbackHandler) getProperty(mc, refProp)) != null) {
            pwCb = performCallback(cbHandler, username, doAction);
        } else {
            //
            // If a callback isn't configured then try to get the password
            // from the message context
            //
            String password = getPassword(mc);
            if (password == null) {
                throw new WSSecurityException("WSHandler: application " + err);
            }
            pwCb = constructPasswordCallback(username, doAction);
            pwCb.setPassword(password);
        }
        return pwCb;
    }

    private WSPasswordCallback readPwViaCallbackClass(String callback,
            String username,
            int doAction,
            RequestData requestData
    ) throws WSSecurityException {

        Class cbClass = null;
        CallbackHandler cbHandler = null;
        try {
            cbClass = Loader.loadClass(getClassLoader(requestData
                    .getMsgContext()), callback);
        } catch (ClassNotFoundException e) {
            throw new WSSecurityException("WSHandler: cannot load password callback class: "
                    + callback,
                    e);
        }
        try {
            cbHandler = (CallbackHandler) cbClass.newInstance();
        } catch (Exception e) {
            throw new WSSecurityException("WSHandler: cannot create instance of password callback: "
                    + callback,
                    e);
        }
        return (performCallback(cbHandler, username, doAction));
    }

    /**
     * Perform a callback to get a password.
     * <p/>
     * The called back function gets an indication why to provide a password:
     * to produce a UsernameToken, Signature, or a password (key) for a given
     * name.
     */
    private WSPasswordCallback performCallback(CallbackHandler cbHandler,
            String username,
            int doAction
    ) throws WSSecurityException {

        WSPasswordCallback pwCb = constructPasswordCallback(username, doAction);
        Callback[] callbacks = new Callback[1];
        callbacks[0] = pwCb;
        /*
         * Call back the application to get the password
         */
        try {
            cbHandler.handle(callbacks);
        } catch (Exception e) {
            throw new WSSecurityException("WSHandler: password callback failed", e);
        }
        return pwCb;
    }

    private WSPasswordCallback constructPasswordCallback(
            String username,
            int doAction
    ) throws WSSecurityException {

        int reason = WSPasswordCallback.UNKNOWN;

        switch (doAction) {
        case WSConstants.UT:
        case WSConstants.UT_SIGN:
            reason = WSPasswordCallback.USERNAME_TOKEN;
            break;
        case WSConstants.SIGN:
            reason = WSPasswordCallback.SIGNATURE;
            break;
        case WSConstants.ENCR:
            reason = WSPasswordCallback.KEY_NAME;
            break;
        }
        return new WSPasswordCallback(username, reason);
    }

    private void splitEncParts(String tmpS, Vector parts, RequestData reqData)
        throws WSSecurityException {
        WSEncryptionPart encPart = null;
        String[] rawParts = StringUtil.split(tmpS, ';');

        for (int i = 0; i < rawParts.length; i++) {
            String[] partDef = StringUtil.split(rawParts[i], '}');

            if (partDef.length == 1) {
                if (doDebug) {
                    log.debug("single partDef: '" + partDef[0] + "'");
                }
                encPart =
                    new WSEncryptionPart(partDef[0].trim(),
                            reqData.getSoapConstants().getEnvelopeURI(),
                            "Content");
            } else if (partDef.length == 3) {
                String mode = partDef[0].trim();
                if (mode.length() <= 1) {
                    mode = "Content";
                } else {
                    mode = mode.substring(1);
                }
                String nmSpace = partDef[1].trim();
                if (nmSpace.length() <= 1) {
                    nmSpace = reqData.getSoapConstants().getEnvelopeURI();
                } else {
                    nmSpace = nmSpace.substring(1);
                    if (nmSpace.equals(WSConstants.NULL_NS)) {
                        nmSpace = null;
                    }
                }
                String element = partDef[2].trim();
                if (doDebug) {
                    log.debug("partDefs: '"
                            + mode
                            + "' ,'"
                            + nmSpace
                            + "' ,'"
                            + element
                            + "'");
                }
                encPart = new WSEncryptionPart(element, nmSpace, mode);
            } else {
                throw new WSSecurityException("WSHandler: wrong part definition: " + tmpS);
            }
            parts.add(encPart);
        }
    }

    private void handleSpecialUser(RequestData reqData) {
        if (!WSHandlerConstants.USE_REQ_SIG_CERT.equals(reqData.getEncUser())) {
            return;
        }
        Vector results = 
            (Vector) getProperty(reqData.getMsgContext(), WSHandlerConstants.RECV_RESULTS);
        if (results == null) {
            return;
        }
        /*
         * Scan the results for a matching actor. Use results only if the
         * receiving Actor and the sending Actor match.
         */
        for (int i = 0; i < results.size(); i++) {
            WSHandlerResult rResult =
                (WSHandlerResult) results.get(i);
            String hActor = rResult.getActor();
            if (!WSSecurityUtil.isActorEqual(reqData.getActor(), hActor)) {
                continue;
            }
            Vector wsSecEngineResults = rResult.getResults();
            /*
             * Scan the results for the first Signature action. Use the
             * certificate of this Signature to set the certificate for the
             * encryption action :-).
             */
            for (int j = 0; j < wsSecEngineResults.size(); j++) {
                WSSecurityEngineResult wser =
                    (WSSecurityEngineResult) wsSecEngineResults.get(j);
                int wserAction = 
                    ((java.lang.Integer)wser.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
                if (wserAction == WSConstants.SIGN) {
                    X509Certificate cert = 
                        (X509Certificate)wser.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
                    reqData.setEncCert(cert);
                    return;
                }
            }
        }
    }

    /**
     * Hook to allow subclasses to load their Decryption Crypto however they 
     * see fit.
     */
    protected Crypto loadDecryptionCrypto(RequestData reqData) 
        throws WSSecurityException {

        Crypto crypto = null;
        String decPropFile = getString(WSHandlerConstants.DEC_PROP_FILE,
                reqData.getMsgContext());
        if (decPropFile != null) {
            crypto = (Crypto) cryptos.get(decPropFile);
            if (crypto == null) {
                crypto = CryptoFactory.getInstance(decPropFile, this
                        .getClassLoader(reqData.getMsgContext()));
                cryptos.put(decPropFile, crypto);
            }
        } else if (getString(WSHandlerConstants.DEC_PROP_REF_ID, reqData
                .getMsgContext()) != null) {
            /*
             * If the property file is missing then 
             * look for the Properties object 
             */
            String refId = getString(WSHandlerConstants.DEC_PROP_REF_ID,
                    reqData.getMsgContext());
            if(refId != null) {
                Object propObj = getProperty(reqData.getMsgContext(), refId);
                if(propObj instanceof Properties) {
                    crypto = (Crypto) cryptos.get(refId);
                    if (crypto == null) {
                        crypto = CryptoFactory.getInstance((Properties)propObj);
                        cryptos.put(refId, crypto);
                    }
                } else {
                    throw new WSSecurityException(
                        "WSHandler: Decrytion: decryptionPropRefId must hold a" 
                            + " java.util.Properties object"
                    );
                }
            }
        } else if ((crypto = reqData.getSigCrypto()) == null) {
            throw new WSSecurityException(
                "WSHandler: Encryption: no crypto property file"
            );
        }
        return crypto;
    }

    protected void decodeSignatureParameter2(RequestData reqData) 
        throws WSSecurityException {
        reqData.setSigCrypto(loadSignatureCrypto(reqData));
        /* There are currently no other signature parameters that need 
         * to be handled here, but we call the load crypto hook rather 
         * than just changing the visibility
         * of this method to maintain parity with WSDoAllSender.
         */
    }

    /*
     * Set and check the decryption specific parameters, if necessary
     * take over signature crypto instance.
     */
    protected void decodeDecryptionParameter(RequestData reqData) 
        throws WSSecurityException {
        reqData.setDecCrypto(loadDecryptionCrypto(reqData));
        /* There are currently no other decryption parameters that need 
         * to be handled here, but we call the load crypto hook rather 
         * than just changing the visibility
         * of this method to maintain parity with WSDoAllSender.
         */
    }

    /**
     * Get the password callback class and get an instance
     * <p/>
     */
    protected CallbackHandler getPasswordCB(RequestData reqData) 
        throws WSSecurityException {

        Object mc = reqData.getMsgContext();
        CallbackHandler cbHandler = null;
        String callback = getString(WSHandlerConstants.PW_CALLBACK_CLASS, mc);
        if (callback != null) {
            Class cbClass = null;
            try {
                cbClass = Loader.loadClass(getClassLoader(reqData
                        .getMsgContext()), callback);
            } catch (ClassNotFoundException e) {
                throw new WSSecurityException(
                        "WSHandler: cannot load password callback class: "
                        + callback, e);
            }
            try {
                cbHandler = (CallbackHandler) cbClass.newInstance();
            } catch (java.lang.Exception e) {
                throw new WSSecurityException(
                        "WSHandler: cannot create instance of password callback: "
                        + callback, e);
            }
        } else {
            cbHandler = (CallbackHandler) getProperty(mc, 
                    WSHandlerConstants.PW_CALLBACK_REF);
            if (cbHandler == null) {
                throw new WSSecurityException(
                        "WSHandler: no reference in callback property");
            }
        }
        return cbHandler;
    }

    /**
     * Evaluate whether a given certificate should be trusted.
     * Hook to allow subclasses to implement custom validation methods however they see fit.
     * <p/>
     * Policy used in this implementation:
     * 1. Search the keystore for the transmitted certificate
     * 2. Search the keystore for a connection to the transmitted certificate
     * (that is, search for certificate(s) of the issuer of the transmitted certificate
     * 3. Verify the trust path for those certificates found because the search for the issuer might be fooled by a phony DN (String!)
     *
     * @param cert the certificate that should be validated against the keystore
     * @return true if the certificate is trusted, false if not (AxisFault is thrown for exceptions during CertPathValidation)
     * @throws WSSecurityException
     */
    protected boolean verifyTrust(X509Certificate cert, RequestData reqData) 
        throws WSSecurityException {

        // If no certificate was transmitted, do not trust the signature
        if (cert == null) {
            return false;
        }

        String[] aliases = null;
        String alias = null;
        X509Certificate[] certs;

        String subjectString = cert.getSubjectDN().getName();
        String issuerString = cert.getIssuerDN().getName();
        BigInteger issuerSerial = cert.getSerialNumber();

        if (doDebug) {
            log.debug("WSHandler: Transmitted certificate has subject " + subjectString);
            log.debug("WSHandler: Transmitted certificate has issuer " + issuerString + " (serial " + issuerSerial + ")");
        }

        // FIRST step
        // Search the keystore for the transmitted certificate

        // Search the keystore for the alias of the transmitted certificate
        try {
            alias = reqData.getSigCrypto().getAliasForX509Cert(issuerString, issuerSerial);
        } catch (WSSecurityException ex) {
            throw new WSSecurityException("WSHandler: Could not get alias for certificate with " + subjectString, ex);
        }

        if (alias != null) {
            // Retrieve the certificate for the alias from the keystore
            try {
                certs = reqData.getSigCrypto().getCertificates(alias);
            } catch (WSSecurityException ex) {
                throw new WSSecurityException("WSHandler: Could not get certificates for alias " + alias, ex);
            }

            // If certificates have been found, the certificates must be compared
            // to ensure against phony DNs (compare encoded form including signature)
            if (certs != null && certs.length > 0 && cert.equals(certs[0])) {
                if (doDebug) {
                    log.debug("Direct trust for certificate with " + subjectString);
                }
                return true;
            }
        } else {
            if (doDebug) {
                log.debug("No alias found for subject from issuer with " + issuerString + " (serial " + issuerSerial + ")");
            }
        }

        // SECOND step
        // Search for the issuer of the transmitted certificate in the keystore

        // Search the keystore for the alias of the transmitted certificates issuer
        try {
            aliases = reqData.getSigCrypto().getAliasesForDN(issuerString);
        } catch (WSSecurityException ex) {
            throw new WSSecurityException("WSHandler: Could not get alias for certificate with " + issuerString, ex);
        }

        // If the alias has not been found, the issuer is not in the keystore
        // As a direct result, do not trust the transmitted certificate
        if (aliases == null || aliases.length < 1) {
            if (doDebug) {
                log.debug("No aliases found in keystore for issuer " + issuerString + " of certificate for " + subjectString);
            }
            return false;
        }

        // THIRD step
        // Check the certificate trust path for every alias of the issuer found in the keystore
        for (int i = 0; i < aliases.length; i++) {
            alias = aliases[i];

            if (doDebug) {
                log.debug("Preparing to validate certificate path with alias " + alias + " for issuer " + issuerString);
            }

            // Retrieve the certificate(s) for the alias from the keystore
            try {
                certs = reqData.getSigCrypto().getCertificates(alias);
            } catch (WSSecurityException ex) {
                throw new WSSecurityException("WSHandler: Could not get certificates for alias " + alias, ex);
            }

            // If no certificates have been found, there has to be an error:
            // The keystore can find an alias but no certificate(s)
            if (certs == null || certs.length < 1) {
                throw new WSSecurityException("WSHandler: Could not get certificates for alias " + alias);
            }

            // Form a certificate chain from the transmitted certificate
            // and the certificate(s) of the issuer from the keystore
            // First, create new array
            X509Certificate[] x509certs = new X509Certificate[certs.length + 1];
            // Then add the first certificate ...
            x509certs[0] = cert;
            // ... and the other certificates
            for (int j = 0; j < certs.length; j++) {
                x509certs[j + 1] = certs[j];
            }
            certs = x509certs;

            // Use the validation method from the crypto to check whether the subjects certificate was really signed by the issuer stated in the certificate
            try {
                if (reqData.getSigCrypto().validateCertPath(certs)) {
                    if (doDebug) {
                        log.debug("WSHandler: Certificate path has been verified for certificate with subject " + subjectString);
                    }
                    return true;
                }
            } catch (WSSecurityException ex) {
                throw new WSSecurityException("WSHandler: Certificate path verification failed for certificate with subject " + subjectString, ex);
            }
        }

        log.debug("WSHandler: Certificate path could not be verified for certificate with subject " + subjectString);
        return false;
    }

    /**
     * Evaluate whether a timestamp is considered valid on receiverside. Hook to
     * allow subclasses to implement custom validation methods however they see
     * fit.
     * 
     * Policy used in this implementation:
     * 
     * 1. The receiver can set its own time to live (besides from that set on
     * sender side)
     * 
     * 2. If the message was created before (now-ttl) the message is rejected
     * 
     * @param timestamp
     *            the timestamp that is validated
     * @param timeToLive
     *            the limit on receiverside, the timestamp is validated against
     * @return true if the timestamp is before (now-timeToLive), false otherwise
     * @throws WSSecurityException
     */
    protected boolean verifyTimestamp(Timestamp timestamp, int timeToLive) throws WSSecurityException {

        // Calculate the time that is allowed for the message to travel
        Calendar validCreation = Calendar.getInstance();
        long currentTime = validCreation.getTime().getTime();
        currentTime -= timeToLive * 1000;
        validCreation.setTime(new Date(currentTime));

        if (doDebug) {
            log.debug("Preparing to verify the timestamp");
            DateFormat zulu = new XmlSchemaDateFormat();
            log.debug("Validation of Timestamp: Current time is "
                    + zulu.format(Calendar.getInstance().getTime()));
            log.debug("Validation of Timestamp: Valid creation is "
                    + zulu.format(validCreation.getTime()));
            if (timestamp.getCreated() != null) {
                log.debug("Validation of Timestamp: Timestamp created is "
                        + zulu.format(timestamp.getCreated().getTime()));
            }
        }
        // Validate the time it took the message to travel
        // if (timestamp.getCreated().before(validCreation) ||
        // !timestamp.getCreated().equals(validCreation)) {
        Calendar cre = timestamp.getCreated();
        if (cre != null && !cre.after(validCreation)) {
            if (doDebug) {
                log.debug("Validation of Timestamp: The message was created too long ago");
            }
            return false;
        }

        if (doDebug) {
            log.debug("Validation of Timestamp: Everything is ok");
        }
        return true;
    }

    /**
     * Looks up key first via {@link #getOption(String)} and if not found
     * there, via {@link #getProperty(Object, String)}
     *
     * @param key the key to search for. May not be null.
     * @param mc the message context to search. 
     * @return the value found.
     * @throws IllegalArgumentException if <code>key</code> is null.
     */
    public String getString(String key, Object mc) { 
        if (key == null) {
            throw new IllegalArgumentException("Key cannot be null");
        }
        String s = getStringOption(key);
        if (s != null) {
            return s;
        }
        if (mc == null) {
            throw new IllegalArgumentException("Message context cannot be null");
        }
        return (String) getProperty(mc, key);
    }


    /**
     * Returns the option on <code>name</code>.
     *
     * @param key the non-null key of the option.
     * @return the option on <code>key</code> if <code>key</code>
     *  exists and is of type java.lang.String; otherwise null.
     */
    public String getStringOption(String key) {
        Object o = getOption(key);
        if (o instanceof String){
            return (String) o;
        } else {
            return null;
        }
    }

//  /**
//  * Returns the classloader to be used for loading the callback class
//  * 
//  * @return class loader
//  */
//  public ClassLoader getClassLoader() {
//  try {
//  return Loader.getTCL();
//  } catch (Throwable t) {
//  return null;
//  }
//  }

    /**
     * Returns the classloader to be used for loading the callback class
     * @param msgCtx The MessageContext 
     * @return class loader
     */
    public ClassLoader getClassLoader(Object msgCtx) {
        try {
            return Loader.getTCL();
        } catch (Throwable t) {
            return null;
        }
    }

    public abstract Object getOption(String key);
    public abstract Object getProperty(Object msgContext, String key);

    public abstract void setProperty(Object msgContext, String key, 
            Object value);


    public abstract String getPassword(Object msgContext);

    public abstract void setPassword(Object msgContext, String password);
}
