Package org.apache.ws.axis.security

Source Code of org.apache.ws.axis.security.WSDoAllSender$RequestData

/*
* Copyright  2003-2004 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.axis.security;

import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.SOAPPart;
import org.apache.axis.handlers.BasicHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.saml.SAMLIssuer;
import org.apache.ws.security.saml.SAMLIssuerFactory;
import org.apache.ws.axis.security.util.AxisUtil;
import org.apache.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.handler.WSHandlerResult;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.message.WSAddTimestamp;
import org.apache.ws.security.message.WSEncryptBody;
import org.apache.ws.security.message.WSSAddSAMLToken;
import org.apache.ws.security.message.WSSAddUsernameToken;
import org.apache.ws.security.message.WSSignEnvelope;
import org.apache.ws.security.util.StringUtil;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.utils.XMLUtils;
import org.opensaml.SAMLAssertion;
import org.w3c.dom.Document;

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

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.cert.X509Certificate;
import java.util.Hashtable;
import java.util.Vector;

/**
* @author Werner Dittmann (werner@apache.org)
*/
public class WSDoAllSender extends BasicHandler {

    static Log log = LogFactory.getLog(WSDoAllSender.class.getName());

    static final WSSecurityEngine secEngine = WSSecurityEngine.getInstance();

    private static boolean doDebug = true;

    private static Hashtable cryptos = new Hashtable(5);
   
    /**
     * This nested private class hold per request data.
     *
     * @author wdi
     */
    protected class RequestData {
        MessageContext msgContext = null;

        boolean noSerialization = false;

        SOAPConstants soapConstants = null;

        String actor = null;

        String username = null;

        String pwType = null;

        String[] utElements = null;

        Crypto sigCrypto = null;

        int sigKeyId = 0;

        String sigAlgorithm = null;

        Vector signatureParts = new Vector();

        Crypto encCrypto = null;

        int encKeyId = 0;

        String encSymmAlgo = null;

        String encKeyTransport = null;

        String encUser = null;

        Vector encryptParts = new Vector();

        X509Certificate encCert = null;

        int timeToLive = 300;   // Timestamp: time in seconds between creation
                // and expiery
        void clear() {
          soapConstants = null;
          actor = username = pwType = sigAlgorithm = encSymmAlgo = encKeyTransport = encUser = null;
          sigCrypto = encCrypto = null;
          signatureParts.clear();
          encryptParts.clear();
          signatureParts = encryptParts = null;
          encCert = null;
          utElements = null;
        }
    }

    /**
     * Initialize data fields from previous use in case of cached object. Axis
     * may cache the handler object, thus we need to intiailize (reset) some
     * data fields. In particular remove old elements from the vectors. The
     * other fields are initialized implictly using the lookup of the WSDD
     * parameter (getOption()) and properties.
     */
    private RequestData initialize() {
      RequestData reqData = new RequestData();
      return reqData;
    }

    /**
     * Axis calls invoke to handle a message. <p/>
     *
     * @param mc message context.
     * @throws AxisFault
     */
    public void invoke(MessageContext mc) throws AxisFault {

    doDebug = log.isDebugEnabled();
    if (doDebug) {
      log.debug("WSDoAllSender: enter invoke() with msg type: "
          + mc.getCurrentMessage().getMessageType());
    }

    RequestData reqData = initialize();

    reqData.noSerialization = false;
    reqData.msgContext = mc;
    /*
     * The overall try, just to have a finally at the end to perform some
     * housekeeping.
     */
    try {
      /*
       * Get the action first.
       */
      Vector actions = new Vector();
      String action = null;
      if ((action = (String) getOption(WSHandlerConstants.ACTION)) == null) {
        action = (String) reqData.msgContext
            .getProperty(WSHandlerConstants.ACTION);
      }
      if (action == null) {
        throw new AxisFault("WSDoAllSender: No action defined");
      }
      int doAction = AxisUtil.decodeAction(action, actions);
      if (doAction == WSConstants.NO_SECURITY) {
        return;
      }

      boolean mu = decodeMustUnderstand(reqData);

            secEngine.setPrecisionInMilliSeconds(decodeTimestampPrecision(reqData));

      if ((reqData.actor = (String) getOption(WSHandlerConstants.ACTOR)) == null) {
        reqData.actor = (String) reqData.msgContext
            .getProperty(WSHandlerConstants.ACTOR);
      }
      /*
       * For every action we need a username, so get this now. The
       * username defined in the deployment descriptor takes precedence.
       */
      reqData.username = (String) getOption(WSHandlerConstants.USER);
      if (reqData.username == null || reqData.username.equals("")) {
                String username = (String) reqData.msgContext.getProperty(WSHandlerConstants.USER);
                if (username != null) {
                    reqData.username = username;
                } else {
                    reqData.username = reqData.msgContext.getUsername();
                    reqData.msgContext.setUsername(null);
                }
      }
      /*
       * Now we perform some set-up for UsernameToken and Signature
       * functions. No need to do it for encryption only. Check if
       * username is available and then get a passowrd.
       */
      if ((doAction & (WSConstants.SIGN | WSConstants.UT | WSConstants.UT_SIGN)) != 0) {
        /*
         * We need a username - if none throw an AxisFault. For
         * encryption there is a specific parameter to get a username.
         */
        if (reqData.username == null || reqData.username.equals("")) {
          throw new AxisFault(
              "WSDoAllSender: Empty username for specified action");
        }
      }
      if (doDebug) {
        log.debug("Action: " + doAction);
        log.debug("Actor: " + reqData.actor + ", mu: " + mu);
      }
      /*
       * Now get the SOAP part from the request message and convert it
       * into a Document.
       *
       * This forces Axis to serialize the SOAP request into FORM_STRING.
       * This string is converted into a document.
       *
       * During the FORM_STRING serialization Axis performs multi-ref of
       * complex data types (if requested), generates and inserts
       * references for attachements and so on. The resulting Document
       * MUST be the complete and final SOAP request as Axis would send it
       * over the wire. Therefore this must shall be the last (or only)
       * handler in a chain.
       *
       * Now we can perform our security operations on this request.
       */
      Document doc = null;
      Message message = reqData.msgContext.getCurrentMessage();

      /*
       * If the message context property conatins a document then this is
       * a chained handler.
       */
      SOAPPart sPart = (org.apache.axis.SOAPPart) message.getSOAPPart();
      if ((doc = (Document) reqData.msgContext
          .getProperty(WSHandlerConstants.SND_SECURITY)) == null) {
        try {
          doc = ((org.apache.axis.message.SOAPEnvelope) sPart
              .getEnvelope()).getAsDocument();
        } catch (Exception e) {
          throw new AxisFault(
              "WSDoAllSender: cannot get SOAP envlope from message"
                  + e);
        }
      }
      reqData.soapConstants = 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.sigCrypto = 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.encCrypto = loadEncryptionCrypto(reqData);
        decodeEncryptionParameter(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);
        }

        String password = null;
        switch (actionToDo) {
        case WSConstants.UT:
          performUTAction(actionToDo, mu, doc, reqData);
          break;

        case WSConstants.ENCR:
          performENCRAction(mu, actionToDo, doc, reqData);
          break;

        case WSConstants.SIGN:
          performSIGNAction(actionToDo, mu, doc, reqData);
          break;

        case WSConstants.ST_SIGNED:
          performST_SIGNAction(actionToDo, mu, doc, reqData);
          break;

        case WSConstants.ST_UNSIGNED:
          performSTAction(actionToDo, mu, doc, reqData);
          break;

        case WSConstants.TS:
          performTSAction(actionToDo, mu, doc, reqData);
          break;

        case WSConstants.UT_SIGN:
          performUT_SIGNAction(actionToDo, mu, doc, reqData);
          break;

        case WSConstants.NO_SERIALIZE:
          reqData.noSerialization = true;
          break;
        }
      }

      /*
       * If required convert the resulting document into a message first.
       * The outputDOM() method performs the necessary c14n call. After
       * that we extract it as a string for further processing.
       *
       * Set the resulting byte array as the new SOAP message.
       *
       * If noSerialization is false, this handler shall be the last (or
       * only) one in a handler chain. If noSerialization is true, just
       * set the processed Document in the transfer property. The next
       * Axis WSS4J handler takes it and performs additional security
       * processing steps.
       * 
       */
      if (reqData.noSerialization) {
        reqData.msgContext.setProperty(WSHandlerConstants.SND_SECURITY,
            doc);
      } else {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        XMLUtils.outputDOM(doc, os, true);
        sPart.setCurrentMessage(os.toByteArray(), SOAPPart.FORM_BYTES);
        if (doDebug) {
          String osStr = null;
          try {
            osStr = os.toString("UTF-8");
          } catch (UnsupportedEncodingException e) {
            osStr = os.toString();
          }
          log.debug("Send request:");
          log.debug(osStr);
        }
        reqData.msgContext.setProperty(WSHandlerConstants.SND_SECURITY,
            null);
      }
      if (doDebug) {
        log.debug("WSDoAllSender: exit invoke()");
      }
    } finally {
      reqData.clear();
      reqData = null;
    }
  }

    private void performSIGNAction(int actionToDo, boolean mu, Document doc, RequestData reqData)
            throws AxisFault {
        String password;
        password =
                getPassword(reqData.username,
                        actionToDo,
                        WSHandlerConstants.PW_CALLBACK_CLASS,
                        WSHandlerConstants.PW_CALLBACK_REF, reqData)
                .getPassword();

        WSSignEnvelope wsSign = new WSSignEnvelope(reqData.actor, mu);
        if (reqData.sigKeyId != 0) {
            wsSign.setKeyIdentifierType(reqData.sigKeyId);
        }
        if (reqData.sigAlgorithm != null) {
            wsSign.setSignatureAlgorithm(reqData.sigAlgorithm);
        }

        wsSign.setUserInfo(reqData.username, password);
        if (reqData.signatureParts.size() > 0) {
            wsSign.setParts(reqData.signatureParts);
        }

        try {
            wsSign.build(doc, reqData.sigCrypto);
        } catch (WSSecurityException e) {
            throw new AxisFault("WSDoAllSender: Signature: error during message procesing" + e);
        }
    }

    private void performENCRAction(boolean mu, int actionToDo, Document doc, RequestData reqData)
            throws AxisFault {
        WSEncryptBody wsEncrypt = new WSEncryptBody(reqData.actor, mu);
        if (reqData.encKeyId != 0) {
            wsEncrypt.setKeyIdentifierType(reqData.encKeyId);
        }
        if (reqData.encKeyId == WSConstants.EMBEDDED_KEYNAME) {
            String encKeyName = null;
            if ((encKeyName =
                    (String) getOption(WSHandlerConstants.ENC_KEY_NAME))
                    == null) {
                encKeyName =
                        (String) reqData.msgContext.getProperty(WSHandlerConstants.ENC_KEY_NAME);
            }
            wsEncrypt.setEmbeddedKeyName(encKeyName);
            byte[] embeddedKey =
                    getPassword(reqData.encUser,
                            actionToDo,
                            WSHandlerConstants.ENC_CALLBACK_CLASS,
                            WSHandlerConstants.ENC_CALLBACK_REF, reqData)
                    .getKey();
            wsEncrypt.setKey(embeddedKey);
        }
        if (reqData.encSymmAlgo != null) {
            wsEncrypt.setSymmetricEncAlgorithm(reqData.encSymmAlgo);
        }
        if (reqData.encKeyTransport != null) {
            wsEncrypt.setKeyEnc(reqData.encKeyTransport);
        }
        wsEncrypt.setUserInfo(reqData.encUser);
        wsEncrypt.setUseThisCert(reqData.encCert);
        if (reqData.encryptParts.size() > 0) {
            wsEncrypt.setParts(reqData.encryptParts);
        }
        try {
            wsEncrypt.build(doc, reqData.encCrypto);
        } catch (WSSecurityException e) {
            throw new AxisFault("WSDoAllSender: Encryption: error during message processing"
                    + e);
        }
    }

    private void performUTAction(int actionToDo, boolean mu, Document doc, RequestData reqData)
            throws AxisFault {
        String password;
        password =
                getPassword(reqData.username,
                        actionToDo,
                        WSHandlerConstants.PW_CALLBACK_CLASS,
                        WSHandlerConstants.PW_CALLBACK_REF, reqData)
                .getPassword();

        WSSAddUsernameToken builder = new WSSAddUsernameToken(reqData.actor, mu);
        builder.setPasswordType(reqData.pwType);
        // add the UsernameToken to the SOAP Enevelope
        builder.build(doc, reqData.username, password);

        if (reqData.utElements != null && reqData.utElements.length > 0) {
            for (int j = 0; j < reqData.utElements.length; j++) {
              reqData.utElements[j].trim();
                if (reqData.utElements[j].equals("Nonce")) {
                    builder.addNonce(doc);
                }
                if (reqData.utElements[j].equals("Created")) {
                    builder.addCreated(doc);
                }
                reqData.utElements[j] = null;
            }
        }
    }

    private void performUT_SIGNAction(int actionToDo, boolean mu, Document doc, RequestData reqData)
      throws AxisFault {
    String password;
    password = getPassword(reqData.username, actionToDo,
        WSHandlerConstants.PW_CALLBACK_CLASS,
        WSHandlerConstants.PW_CALLBACK_REF, reqData).getPassword();

    WSSAddUsernameToken builder = new WSSAddUsernameToken(reqData.actor, mu);
    builder.setPasswordType(WSConstants.PASSWORD_TEXT);
    builder.preSetUsernameToken(doc, reqData.username, password);
    builder.addCreated(doc);
    builder.addNonce(doc);

    WSSignEnvelope sign = new WSSignEnvelope(reqData.actor, mu);
        if (reqData.signatureParts.size() > 0) {
            sign.setParts(reqData.signatureParts);
        }
    sign.setUsernameToken(builder);
    sign.setKeyIdentifierType(WSConstants.UT_SIGNING);
    sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
    try {
      sign.build(doc, null);
    } catch (WSSecurityException e) {
      throw new AxisFault("WSDoAllSender: Error during Signatur with UsernameToken secret"
          + e);
    }
    builder.build(doc, null, null);
  }


    private void performSTAction(int actionToDo, boolean mu, Document doc, RequestData reqData)
            throws AxisFault {
        WSSAddSAMLToken builder = new WSSAddSAMLToken(reqData.actor, mu);
        SAMLIssuer saml = loadSamlIssuer(reqData);
        saml.setUsername(reqData.username);
        SAMLAssertion assertion = saml.newAssertion();

        // add the SAMLAssertion Token to the SOAP Enevelope
        builder.build(doc, assertion);
    }

    private void performST_SIGNAction(int actionToDo, boolean mu, Document doc, RequestData reqData)
            throws AxisFault {
        Crypto crypto = null;
        /*
         * it is possible and legal that we do not have a signature
         * crypto here - thus ignore the exception. This is usually
         * the case for the SAML option "sender vouches". In this case
         * no user crypto is required.
         */
        try {
          crypto = loadSignatureCrypto(reqData);
        } catch (AxisFault ex) {}
       
        SAMLIssuer saml = loadSamlIssuer(reqData);
        saml.setUsername(reqData.username);
        saml.setUserCrypto(crypto);
        saml.setInstanceDoc(doc);

        SAMLAssertion assertion = saml.newAssertion();
        if (assertion == null) {
            throw new AxisFault("WSDoAllSender: Signed SAML: no SAML token received");
        }
        String issuerKeyName = null;
        String issuerKeyPW = null;
        Crypto issuerCrypto = null;

        WSSignEnvelope wsSign = new WSSignEnvelope(reqData.actor, mu);
        String password = null;
        if (saml.isSenderVouches()) {
            issuerKeyName = saml.getIssuerKeyName();
            issuerKeyPW = saml.getIssuerKeyPassword();
            issuerCrypto = saml.getIssuerCrypto();
        } else {
            password =
                    getPassword(reqData.username,
                            actionToDo,
                            WSHandlerConstants.PW_CALLBACK_CLASS,
                            WSHandlerConstants.PW_CALLBACK_REF, reqData)
                    .getPassword();
            wsSign.setUserInfo(reqData.username, password);
        }
        if (reqData.sigKeyId != 0) {
            wsSign.setKeyIdentifierType(reqData.sigKeyId);
        }
        try {
            wsSign.build(doc,
                    crypto,
                    assertion,
                    issuerCrypto,
                    issuerKeyName,
                    issuerKeyPW);
        } catch (WSSecurityException e) {
            throw new AxisFault("WSDoAllSender: Signed SAML: error during message processing"
                    + e);
        }
    }

    private void performTSAction(int actionToDo, boolean mu, Document doc, RequestData reqData) throws AxisFault {
        String ttl = null;
        if ((ttl =
                (String) getOption(WSHandlerConstants.TTL_TIMESTAMP))
                == null) {
            ttl =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.TTL_TIMESTAMP);
        }
        int ttl_i = 0;
        if (ttl != null) {
            try {
                ttl_i = Integer.parseInt(ttl);
            } catch (NumberFormatException e) {
                ttl_i = reqData.timeToLive;
            }
        }
        if (ttl_i <= 0) {
            ttl_i = reqData.timeToLive;
        }
        WSAddTimestamp timeStampBuilder =
                new WSAddTimestamp(reqData.actor, mu);
        // add the Timestamp to the SOAP Enevelope
        timeStampBuilder.build(doc, ttl_i);
    }

    /**
     * Hook to allow subclasses to load their Signature Crypto however they see
     * fit.
     */
    protected Crypto loadSignatureCrypto(RequestData reqData) throws AxisFault {
        Crypto crypto = null;
        /*
         * Get crypto property file for signature. If none specified throw
         * fault, otherwise get a crypto instance.
         */
        String sigPropFile = null;
        if ((sigPropFile = (String) getOption(WSHandlerConstants.SIG_PROP_FILE))
                == null) {
            sigPropFile =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.SIG_PROP_FILE);
        }
        if (sigPropFile != null) {
            if ((crypto = (Crypto) cryptos.get(sigPropFile)) == null) {
                crypto = CryptoFactory.getInstance(sigPropFile);
                cryptos.put(sigPropFile, crypto);
            }
        } else {
            throw new AxisFault("WSDoAllSender: Signature: no crypto property file");
        }
        return crypto;
    }

    /**
     * Hook to allow subclasses to load their Encryption Crypto however they
     * see fit.
     */
    protected Crypto loadEncryptionCrypto(RequestData reqData) throws AxisFault {
        Crypto crypto = null;
        /*
         * Get encryption crypto property file. If non specified take crypto
         * instance from signature, if that fails: throw fault
         */
        String encPropFile = null;
        if ((encPropFile = (String) getOption(WSHandlerConstants.ENC_PROP_FILE))
                == null) {
            encPropFile =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.ENC_PROP_FILE);
        }
        if (encPropFile != null) {
            if ((crypto = (Crypto) cryptos.get(encPropFile)) == null) {
                crypto = CryptoFactory.getInstance(encPropFile);
                cryptos.put(encPropFile, crypto);
            }
        } else if ((crypto = reqData.sigCrypto) == null) {
            throw new AxisFault("WSDoAllSender: Encryption: no crypto property file");
        }
        return crypto;
    }

    protected SAMLIssuer loadSamlIssuer(RequestData reqData) {
        String samlPropFile = null;
       
        if ((samlPropFile =
            (String) getOption(WSHandlerConstants.SAML_PROP_FILE))
            == null) {
        samlPropFile =
                (String) reqData.msgContext.getProperty(WSHandlerConstants.SAML_PROP_FILE);
    }
        return SAMLIssuerFactory.getInstance(samlPropFile)
    }

    private void decodeUTParameter(RequestData reqData) throws AxisFault {
        if ((reqData.pwType = (String) getOption(WSHandlerConstants.PASSWORD_TYPE))
                == null) {
          reqData.pwType =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.PASSWORD_TYPE);
        }
        if (reqData.pwType != null) {
          reqData.pwType =
            reqData.pwType.equals(WSConstants.PW_TEXT)
                    ? WSConstants.PASSWORD_TEXT
                    : WSConstants.PASSWORD_DIGEST;
        }
        String tmpS = null;
        if ((tmpS = (String) getOption(WSHandlerConstants.ADD_UT_ELEMENTS))
                == null) {
            tmpS =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.ADD_UT_ELEMENTS);
        }
        if (tmpS != null) {
          reqData.utElements = StringUtil.split(tmpS, ' ');
        }
    }

    private void decodeSignatureParameter(RequestData reqData) throws AxisFault {
        String tmpS = null;
        if ((tmpS = (String) getOption(WSHandlerConstants.SIG_KEY_ID)) == null) {
            tmpS = (String) reqData.msgContext.getProperty(WSHandlerConstants.SIG_KEY_ID);
        }
        if (tmpS != null) {
            Integer I = (Integer) WSHandlerConstants.keyIdentifier.get(tmpS);
            if (I == null) {
                throw new AxisFault("WSDoAllSender: Signature: unknown key identification");
            }
            reqData.sigKeyId = I.intValue();
            if (!(reqData.sigKeyId == WSConstants.ISSUER_SERIAL
                    || reqData.sigKeyId == WSConstants.BST_DIRECT_REFERENCE
                    || reqData.sigKeyId == WSConstants.X509_KEY_IDENTIFIER
                    || reqData.sigKeyId == WSConstants.SKI_KEY_IDENTIFIER)) {
                throw new AxisFault("WSDoAllSender: Signature: illegal key identification");
            }
        }
        if ((reqData.sigAlgorithm = (String) getOption(WSHandlerConstants.SIG_ALGO))
                == null) {
            tmpS = (String) reqData.msgContext.getProperty(WSHandlerConstants.SIG_ALGO);
        }
        if ((tmpS = (String) getOption(WSHandlerConstants.SIGNATURE_PARTS))
                == null) {
            tmpS =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.SIGNATURE_PARTS);
        }
        if (tmpS != null) {
            splitEncParts(tmpS, reqData.signatureParts, reqData);
        }
    }

    private void decodeEncryptionParameter(RequestData reqData) throws AxisFault {
        if ((reqData.encUser = (String) getOption(WSHandlerConstants.ENCRYPTION_USER))
                == null) {
          reqData.encUser =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.ENCRYPTION_USER);
        }

        if (reqData.encUser == null && (reqData.encUser = reqData.username) == null) {
            throw new AxisFault("WSDoAllSender: 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 tmpS = null;
        if ((tmpS = (String) getOption(WSHandlerConstants.ENC_KEY_ID)) == null) {
            tmpS = (String) reqData.msgContext.getProperty(WSHandlerConstants.ENC_KEY_ID);
        }
        if (tmpS != null) {
            Integer I = (Integer) WSHandlerConstants.keyIdentifier.get(tmpS);
            if (I == null) {
                throw new AxisFault("WSDoAllSender: Encryption: unknown key identification");
            }
            reqData.encKeyId = I.intValue();
            if (!(reqData.encKeyId == WSConstants.ISSUER_SERIAL
                    || reqData.encKeyId == WSConstants.X509_KEY_IDENTIFIER
                    || reqData.encKeyId == WSConstants.SKI_KEY_IDENTIFIER
                    || reqData.encKeyId == WSConstants.BST_DIRECT_REFERENCE
                    || reqData.encKeyId == WSConstants.EMBEDDED_KEYNAME)) {
                throw new AxisFault("WSDoAllSender: Encryption: illegal key identification");
            }
        }
        if ((reqData.encSymmAlgo = (String) getOption(WSHandlerConstants.ENC_SYM_ALGO))
                == null) {
          reqData.encSymmAlgo =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.ENC_SYM_ALGO);
        }
        if ((reqData.encKeyTransport =
                (String) getOption(WSHandlerConstants.ENC_KEY_TRANSPORT))
                == null) {
          reqData.encKeyTransport =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.ENC_KEY_TRANSPORT);
        }
        if ((tmpS = (String) getOption(WSHandlerConstants.ENCRYPTION_PARTS))
                == null) {
            tmpS =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.ENCRYPTION_PARTS);
        }
        if (tmpS != null) {
            splitEncParts(tmpS, reqData.encryptParts, reqData);
        }
    }

    private boolean decodeMustUnderstand(RequestData reqData) throws AxisFault {
        boolean mu = true;
        String mustUnderstand = null;
        if ((mustUnderstand =
                (String) getOption(WSHandlerConstants.MUST_UNDERSTAND))
                == null) {
            mustUnderstand =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.MUST_UNDERSTAND);
        }
        if (mustUnderstand != null) {
            if (mustUnderstand.equals("0") || mustUnderstand.equals("false")) {
                mu = false;
            } else if (
                    mustUnderstand.equals("1") || mustUnderstand.equals("true")) {
                mu = true;
            } else {
                throw new AxisFault("WSDoAllSender: illegal mustUnderstand parameter");
            }
        }
        return mu;
    }

    private boolean decodeTimestampPrecision(RequestData reqData) throws AxisFault {
        boolean precisionInMilliSeconds = true;
        String value = null;
        if ((value =
                (String) getOption(WSHandlerConstants.TIMESTAMP_PRECISION))
                == null) {
            value =
                    (String) reqData.msgContext.getProperty(WSHandlerConstants.TIMESTAMP_PRECISION);
        }
        if (value != null) {
            if (value.equals("0") || value.equals("false")) {
                precisionInMilliSeconds = false;
            } else if (
                    value.equals("1") || value.equals("true")) {
                precisionInMilliSeconds = true;
            } else {
                throw new AxisFault("WSDoAllSender: illegal precisionInMilliSeconds parameter");
            }
        }
        return precisionInMilliSeconds;
    }

    /**
     * Get a password to construct a UsernameToken or sign a message.
     * <p/>
     * Try all possible sources to get a password.
     */
    private WSPasswordCallback getPassword(String username,
                                           int doAction,
                                           String clsProp,
                                           String refProp,
                       RequestData reqData)
            throws AxisFault {
        WSPasswordCallback pwCb = null;
        String password = null;
        String callback = null;
        CallbackHandler cbHandler = null;

        if ((callback = (String) getOption(clsProp)) == null) {
            callback = (String) reqData.msgContext.getProperty(clsProp);
        }
        if (callback != null) { // we have a password callback class
            pwCb = readPwViaCallbackClass(callback, username, doAction);
            if ((pwCb.getPassword() == null) && (pwCb.getKey() == null)) {
                throw new AxisFault("WSDoAllSender: password callback class provided null or empty password");
            }
        } else if (
                (cbHandler = (CallbackHandler) reqData.msgContext.getProperty(refProp))
                != null) {
            pwCb = performCallback(cbHandler, username, doAction);
            if ((pwCb.getPassword() == null) && (pwCb.getKey() == null)) {
                throw new AxisFault("WSDoAllSender: password callback provided null or empty password");
            }
        } else if ((password = reqData.msgContext.getPassword()) == null) {
            throw new AxisFault("WSDoAllSender: application provided null or empty password");
        } else {
          reqData.msgContext.setPassword(null);
            pwCb = new WSPasswordCallback("", WSPasswordCallback.UNKNOWN);
            pwCb.setPassword(password);
        }
        return pwCb;
    }

    private WSPasswordCallback readPwViaCallbackClass(String callback,
                                                      String username,
                                                      int doAction)
            throws AxisFault {

        Class cbClass = null;
        CallbackHandler cbHandler = null;
        try {
            cbClass = java.lang.Class.forName(callback);
        } catch (ClassNotFoundException e) {
            throw new AxisFault("WSDoAllSender: cannot load password callback class: "
                    + callback,
                    e);
        }
        try {
            cbHandler = (CallbackHandler) cbClass.newInstance();
        } catch (java.lang.Exception e) {
            throw new AxisFault("WSDoAllSender: 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 AxisFault {

        WSPasswordCallback pwCb = null;
        int reason = 0;

        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;
        }
        pwCb = new WSPasswordCallback(username, reason);
        Callback[] callbacks = new Callback[1];
        callbacks[0] = pwCb;
        /*
         * Call back the application to get the password
         */
        try {
            cbHandler.handle(callbacks);
        } catch (java.lang.Exception e) {
            throw new AxisFault("WSDoAllSender: password callback failed", e);
        }
        return pwCb;
    }

    private void splitEncParts(String tmpS, Vector parts, RequestData reqData)
            throws AxisFault {
        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.soapConstants.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.soapConstants.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 AxisFault("WSDoAllSender: wrong part definition: " + tmpS);
            }
            parts.add(encPart);
        }
    }

    private void handleSpecialUser(RequestData reqData) {
        if (!WSHandlerConstants.USE_REQ_SIG_CERT.equals(reqData.encUser)) {
            return;
        }
        Vector results = null;
        if ((results =
                (Vector) reqData.msgContext.getProperty(WSHandlerConstants.RECV_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.actor, 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);
                if (wser.getAction() == WSConstants.SIGN) {
                  reqData.encCert = wser.getCertificate();
                    return;
                }
            }
        }
    }
}
TOP

Related Classes of org.apache.ws.axis.security.WSDoAllSender$RequestData

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.