Package org.apache.ws.sandbox.security.conversation

Source Code of org.apache.ws.sandbox.security.conversation.ConversationEngine

/*
* 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.sandbox.security.conversation;

import java.util.HashMap;
import java.util.Vector;

import javax.crypto.SecretKey;
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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.sandbox.axis.security.conversation.ConvHandlerConstants;
import org.apache.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSDocInfo;
import org.apache.ws.security.WSDocInfoStore;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.processor.EncryptedKeyProcessor;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.sandbox.security.conversation.message.info.DerivedKeyInfo;
import org.apache.ws.sandbox.security.conversation.message.info.SecurityContextInfo;
import org.apache.ws.sandbox.security.conversation.message.token.DerivedKeyToken;
import org.apache.ws.sandbox.security.conversation.message.token.SecurityContextToken;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.message.EnvelopeIdResolver;
import org.apache.ws.security.message.token.Reference;
import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.sandbox.security.trust.TrustConstants;
import org.apache.ws.sandbox.security.trust.TrustEngine;
import org.apache.ws.sandbox.security.trust.WSTrustException;
import org.apache.ws.sandbox.security.trust.message.token.RequestSecurityTokenResponse;
import org.apache.ws.sandbox.security.trust.message.token.RequestedProofToken;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.ws.security.util.Loader;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.encryption.XMLEncryptionException;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

/**
* Conversation Engine follows the basic structure of SecurityEngine<link>
*
* @author Dimuthu (muthulee@yahoo.com)
*/
public class ConversationEngine {
    private static Log log =
        LogFactory.getLog(ConversationEngine.class.getName());
    private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");

    private boolean doDebug = false;

    /**
     * <code>wsc:DerivedKeyToken</code> as defined in WS Secure Conversation specification.
     */
    protected static final QName DERIVEDKEY_TOKEN =
        new QName(
            ConversationConstants.WSC_NS,
            ConversationConstants.DERIVED_KEY_TOKEN_LN);

    /**
     * <code>wsc:SecurityContextToken</code> as defined in WS Secure Conversation specification.
     */
    protected static final QName SCT_TOKEN =
        new QName(
            ConversationConstants.WSC_NS,
            ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);
    /**
     * Refer WS secure Conversation specification
     */
    protected static final QName REQUESTED_SECURITY_TOKEN_RESPONSE =
        new QName(
            TrustConstants.WST_NS,
            TrustConstants.REQUEST_SECURITY_TOKEN_RESPONSE_LN);
    /**
     * <code>ds:Signature</code> as defined by XML Signature specification.
     */
    protected static final QName SIGNATURE =
        new QName(WSConstants.SIG_NS, WSConstants.SIG_LN);
    /**
     * <code>xenc:ReferenceList</code> as defined by XML Encryption specification,
     */
    protected static final QName REFERENCE_LIST =
        new QName(WSConstants.ENC_NS, WSConstants.REF_LIST_LN);

    protected static final QName SCT = SecurityContextToken.TOKEN;

    protected HashMap configurator = new HashMap();

    protected String trustPropFile = null;

    protected boolean verifyTrust = false;

    protected WSSConfig wssConfig = WSSConfig.getDefaultWSConfig();

    static {
        org.apache.xml.security.Init.init();
    }

    public ConversationEngine(HashMap config) {

        this.configurator = config;
        //TODO :: Move this out of here.
        Boolean bool = null;
        if ((bool =
            (Boolean) configurator.get(ConvHandlerConstants.VERIFY_TRUST))
            == null) {

        } else {
            this.verifyTrust = bool.booleanValue();
            if (verifyTrust) {
                this.trustPropFile =
                    (String) configurator.get(
                        ConvHandlerConstants.TRUST_ENGINE_PROP);
            }
        }
    }

    /**
     * This method is extracted from org.apache.ws.security.SecurityEngine
     *
     * @param doc
     * @param actor
     * @param cb
     * @return
     * @throws ConversationException
     */

    public Vector processSecConvHeader(
        Document doc,
        String actor,
        DerivedKeyCallbackHandler dkcb,
        String callback)
        throws ConversationException {

        doDebug = log.isDebugEnabled();
        if (doDebug) {
            log.debug("enter processSecurityHeader()");
        }

        if (actor == null) {
            actor = "";
        }
        NodeList list =
            doc.getElementsByTagNameNS(
                WSConstants.WSSE_NS,
                WSConstants.WSSE_LN);
        int len = list.getLength();
        if (len == 0) { // No Security headers found
            return null;
        }
        if (doDebug) {
            log.debug("Found WS-Security header(s): " + len);
        }
        Element elem = null;
        Attr attr = null;
        String headerActor = null;
        SOAPConstants sc =
            WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
        Vector convResult = new Vector();

        for (int i = 0; i < len; i++) {
            elem = (Element) list.item(i);
            attr =
                elem.getAttributeNodeNS(
                    sc.getEnvelopeURI(),
                    sc.getRoleAttributeQName().getLocalPart());
            if (attr != null) {
                headerActor = attr.getValue();
            }
            if ((headerActor == null)
                || (headerActor.length() == 0)
                || headerActor.equalsIgnoreCase(actor)
                || headerActor.equals(sc.getNextRoleURI())) {
                if (doDebug) {
                    log.debug(
                        "Processing WS-Security header for '"
                            + actor
                            + "' actor.");
                }

                try {
                    convResult = processConvHeader(elem, doc, dkcb, callback);
                } catch (WSSecurityException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ConversationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }
        return convResult;
    }

    /**
     * @param doc
     * @param dkcbHandler
     * @throws ConversationException
     */

    protected Vector processConvHeader(
        Element securityHeader,
        Document doc,
        DerivedKeyCallbackHandler dkcbHandler,
        String callback)
        throws ConversationException, WSSecurityException {

        long t0 = 0, t1 = 0, t2 = 0;
        if (tlog.isDebugEnabled()) {
            t0 = System.currentTimeMillis();
        }

        NodeList list = securityHeader.getChildNodes();
        int len = list.getLength();
        Node elem;
        String localName = null;
        String namespace = null;

        if (tlog.isDebugEnabled()) {
            t1 = System.currentTimeMillis();
        }

        Vector returnResults = new Vector();

        for (int i = 0; i < len; i++) {
            elem = list.item(i);
            if (elem.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            QName el = new QName(elem.getNamespaceURI(), elem.getLocalName());

            if (el.equals(REQUESTED_SECURITY_TOKEN_RESPONSE)) {
                if (doDebug) {
                    log.debug("Found RequestedSecurityTokenResponse element");
                }

                returnResults.add(
                    this.handleRequestedSecurityTokenResponse(
                        (Element) elem,
                        dkcbHandler,
                        callback));

            } else if (el.equals(SIGNATURE)) {
                if (doDebug) {
                    log.debug("Found Signature element");
                }

                ConvEngineResult convResult =
                    this.VerifySignature((Element) elem, dkcbHandler);
                returnResults.add(convResult);
            } else if (el.equals(REFERENCE_LIST)) {
                if (doDebug) {
                    log.debug("Found Reference List element");

                }
                Vector tmpVec =
                    handleReferenceList((Element) elem, dkcbHandler);
                for (int j = 0; j < tmpVec.size(); j++) {
                    returnResults.add(tmpVec.get(j));
                }
            } else if (el.equals(SCT)) {
                SecurityContextToken sct =
                    new SecurityContextToken((Element) elem);
                String uuid = sct.getIdentifier();
                ConvEngineResult convResult =
                    new ConvEngineResult(ConvEngineResult.SCT);
                convResult.setUuid(uuid);
                returnResults.add(convResult);
            }

        }
        return returnResults;
    }

    public ConvEngineResult handleRequestedSecurityTokenResponse(
        Element eleSTRes,
        DerivedKeyCallbackHandler dkcbHandler,
        String callback)
        throws ConversationException {
        String uuid = null;
        RequestSecurityTokenResponse stRes = null;

        try {
            if (verifyTrust) {
                TrustEngine trstEngine = new TrustEngine(this.trustPropFile);
               
                // TODO :: Verify trust......
                System.out.println("...........Verifying trust.........");

            }

            //Now trust is verified.

            stRes = new RequestSecurityTokenResponse(eleSTRes, true);
            SecurityContextToken SCT =
                stRes.getRequestedSecurityToken().getSct();
            uuid = SCT.getIdentifier();
            RequestedProofToken proofToken = stRes.getRequestedProofToken();
            //TODO:: romove the hard coded decryption

            proofToken.doDecryption(callback, this.loadDecryptionCrypto());

            SecurityContextInfo scInfo = null;
            scInfo = new SecurityContextInfo(SCT, proofToken, 1);

            dkcbHandler.addSecurtiyContext(uuid, scInfo);
                dkcbHandler.setDerivedKeyLength(
                    uuid,
                    ((Long) configurator.get(ConvHandlerConstants.KEY_LEGNTH))
                        .longValue());

            log.debug(" Done SecurityToekenResponse Handled");
            ConvEngineResult res =
                new ConvEngineResult(ConvEngineResult.SECURITY_TOKEN_RESPONSE);
            res.setUuid(uuid);
            return res;

        } catch (WSTrustException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new ConversationException("");
        } catch (WSSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new ConversationException("");
        }
    }

    private ConvEngineResult VerifySignature(
        Element elem,
        DerivedKeyCallbackHandler dkcbHandler)
        throws ConversationException {
        ConvEngineResult convResult = null;
        XMLSignature sig = null;
//      System.out.println("******** at VerifySignature");
//    ByteArrayOutputStream os = new ByteArrayOutputStream();
//    XMLUtils.outputDOM(elem, os, true);
//    String osStr = os.toString();
//    System.out.println(osStr);
        try {
            sig = new XMLSignature(elem, null);
        } catch (XMLSignatureException e2) {
            throw new ConversationException("noXMLSig");
        } catch (XMLSecurityException e2) {
            throw new ConversationException("noXMLSig");
        }
        String sigMethodURI = sig.getSignedInfo().getSignatureMethodURI();
        //verifying the sinature
        if (sigMethodURI.equals(XMLSignature.ALGO_ID_MAC_HMAC_SHA1)) {

            try {
                //sign.verifiyXMLHMac_SHA1_Signarue(sig, dkcbHandler);
                convResult =
                    this.verifiyXMLHMac_SHA1_Signarue(sig, dkcbHandler);
            } catch (WSSecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        } else {
            throw new ConversationException("Failed");
        }
        return convResult;
    }

    /**
     * This method is extracted from WSSecurityEngine.
     * <p/>
     * Dereferences and decodes encrypted data elements.
     */
    private Vector handleReferenceList(
        Element elem,
        DerivedKeyCallbackHandler dkcbHandler)
        throws WSSecurityException {
        Vector results = new Vector();
        Document doc = elem.getOwnerDocument();
        Node tmpE = null;
        for (tmpE = elem.getFirstChild();
            tmpE != null;
            tmpE = tmpE.getNextSibling()) {
            if (tmpE.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            if (!tmpE.getNamespaceURI().equals(WSConstants.ENC_NS)) {
                continue;
            }
            if (tmpE.getLocalName().equals("DataReference")) {
                String dataRefURI = ((Element) tmpE).getAttribute("URI");
                ConvEngineResult convRes =
                    decryptDataRef(doc, dataRefURI, dkcbHandler);
                results.add((Object) convRes);
            } else if (tmpE.getLocalName().equals("KeyReference")) {
                String keyRefURI = ((Element) tmpE).getAttribute("URI");
            }
        }
        return results;
    }

    private ConvEngineResult decryptDataRef(
        Document doc,
        String dataRefURI,
        DerivedKeyCallbackHandler dkcbHandler)
        throws WSSecurityException {

        log.debug("ConversationEngine :: Found data refernce: " + dataRefURI);

        ConvEngineResult convResult = null;
        /*
         * Look up the encrypted data. First try wsu:Id="someURI". If no such Id then
         * try the generic lookup to find Id="someURI"
         */
        Element encBodyData = null;
        if ((encBodyData =
            WSSecurityUtil.getElementByWsuId(
                doc,
                dataRefURI))
            == null) {
            encBodyData = WSSecurityUtil.getElementByGenId(doc, dataRefURI);
        }
        if (encBodyData == null) {
            throw new WSSecurityException(
                WSSecurityException.INVALID_SECURITY,
                "dataRef",
                new Object[] { dataRefURI });
        }

        Element tmpE = null;
        log.debug(
            "ConversationEngine :: Going to figure out the key to decrypt");
        byte[] decryptedBytes = null;

        /*
         * Decryption is performed in 3 major steps
         */

        //Step 1 : Get the key from SecurityTokenReference.

        log.debug(
            "ConversationEngine:: Going to look for SecurityTokenReference");

        if ((tmpE =
            (Element) WSSecurityUtil.findElement(
                (Node) encBodyData,
                "SecurityTokenReference",
                WSConstants.WSSE_NS))
            != null) {
            SecurityTokenReference secRef =
                new SecurityTokenReference(
                    tmpE);

            try {
                convResult =
                    this.handleSecurityTokenReference(secRef, dkcbHandler);
                decryptedBytes = convResult.getKeyAssociated();
            } catch (ConversationException e2) {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            }

        } else {
            //TODO:: Provide more info
            throw new WSSecurityException(WSSecurityException.FAILURE);
        }

        // Step 2 :: Now figure out the encryption algorithm
        String symEncAlgo = getEncAlgo(encBodyData);
        SecretKey symmetricKey =
            WSSecurityUtil.prepareSecretKey(symEncAlgo, decryptedBytes);


        // Step 3 :: initialize Cipher ....
        XMLCipher xmlCipher = null;
        try {
            xmlCipher = XMLCipher.getInstance(symEncAlgo);
            xmlCipher.init(XMLCipher.DECRYPT_MODE, symmetricKey);
        } catch (XMLEncryptionException e1) {
            throw new WSSecurityException(
                WSSecurityException.UNSUPPORTED_ALGORITHM,
                null,
                null,
                e1);
        }



    WSSecurityEngine eng = new WSSecurityEngine();
        boolean content = this.isContent(encBodyData);//Whether content encryption or element encryption

        if (content) {
            encBodyData = (Element) encBodyData.getParentNode();
        }else{
          System.out.println("Not content:-)");
        }

        try {
            xmlCipher.doFinal(doc, encBodyData, content);
        } catch (Exception e) {
            throw new WSSecurityException(
                WSSecurityException.FAILED_ENC_DEC,
                null,
                null,
                e);
        }
        return convResult;
    }

    public ConvEngineResult handleSecurityTokenReference(
        SecurityTokenReference secRef2DkToken,
        DerivedKeyCallbackHandler dkcbHandler)
        throws ConversationException {

        if (secRef2DkToken.containsReference()) {
            Reference ref = null;
            try {
                ref = secRef2DkToken.getReference();
            } catch (WSSecurityException e1) {
                e1.printStackTrace();
                throw new ConversationException(e1.getMessage());
            }

            String valueType = ref.getValueType();
            //  System.out.println("ref.getURI()" + ref.getURI());

            //If the reference type is a derived key token
            if (valueType.equals(ConversationConstants.TOKEN_TYPE_DERIVED_KEY_TOKEN)) {
              //Get hold of the DerivedKeyToken 'Element'
                Element ele =
                    WSSecurityUtil.getElementByWsuId(
                        secRef2DkToken.getElement().getOwnerDocument(),
                        ref.getURI());
                if (ele == null) {
                    throw new ConversationException("Cannot find  referenced Derived Key");
                }
                String uuid = null;
                DerivedKeyToken dkToken = null;
                try {
                    dkToken = new DerivedKeyToken(ele)//Cover the 'Element' into 'DerivedKeyToken' object
                    if (dkToken.getSecuityTokenReference() == null) {
                        //if dkToken doesn't have a STR find a SecurityContextToken in the SOAP Envelope
                        SecurityContextToken secContextTk =
                            ConversationUtil.getSCT(dkToken);
                        uuid = secContextTk.getIdentifier();
                        log.debug(
                            "ConversationEngine :: The uuid is found " + uuid);
                        DerivedKeyInfo dkInfo = new DerivedKeyInfo(dkToken);
                        dkcbHandler.addDerivedKey(uuid, dkInfo);
                    } else { ///i.e. dkToken has a STR
                        SecurityTokenReference str2Base =
                            dkToken.getSecuityTokenReference();
                        if (str2Base.containsReference()) {
                            Reference ref2Base = str2Base.getReference();

                            if (ref2Base
                                .getValueType()
                                .equals("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID")) {
                                /* ok now I have a SAML token. What should I do ?
                                 * -Decrypt the secret.
                                 * -create tempUUID
                                 * -add the scTInfo into dkcbHandler
                                 * -add the derived key token to dkcbHandler.
                                 */
                               uuid = ref2Base.getURI();
                            if(dkcbHandler.getSession(uuid)==null){
                        byte[] key = handleSAML(ref2Base.getElement().getOwnerDocument(), uuid);
                   System.out.println("I am here :-)");
                   SecurityContextInfo sctInfo = new SecurityContextInfo(
                                     uuid,
                                     key,
                                     1);
                   dkcbHandler.addSecurtiyContext(
                                     uuid,
                                     sctInfo);
                 }
                  DerivedKeyInfo dkInfo = new DerivedKeyInfo(dkToken);
                  dkcbHandler.addDerivedKey(uuid, dkInfo);
                            }



                            //TODO :: Add other tokens else if
                        } else if(str2Base.containsKeyIdentifier()){
                          Element elem = str2Base.getFirstElement();
                          //.getKeyIdentifier()System.out.println("KeyIdentifier :: He ehee ........");
              String value = elem.getAttribute("ValueType");
              if("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID".equals(value)){
                uuid = ((Text)elem.getChildNodes().item(0)).getNodeValue();
                if(dkcbHandler.getSession(uuid)==null){
                     byte[] key = handleSAML(elem.getOwnerDocument(), uuid);
                     System.out.println("UUID of SAML is"+uuid);
                     SecurityContextInfo sctInfo = new SecurityContextInfo(
                                                     uuid,
                                                     key,
                                                     1);
                     dkcbHandler.addSecurtiyContext(uuid,sctInfo);
                }
                DerivedKeyInfo dkInfo = new DerivedKeyInfo(dkToken);
                dkcbHandler.addDerivedKey(uuid, dkInfo);
              }

                        }else{
                            throw new ConversationException("Cannot handle this type of security token reference: " + dkToken.getSecuityTokenReference().getReference().getValueType());
                        }
                    } //////end :if dkToken has a STR
                    //TODO :: Ask ruchith to throw correct exception
                } catch (WSSecurityException e2) {
                    e2.printStackTrace();
                } catch (ConversationException e2) {
                    e2.printStackTrace();
                }

                String identifier =
                    ConversationUtil.generateIdentifier(uuid, dkToken.getID());
                WSPasswordCallback pwCb =
                    new WSPasswordCallback(
                        identifier,
                        WSPasswordCallback.UNKNOWN);
                Callback[] callbacks = new Callback[1];
                callbacks[0] = pwCb;
                try {
                    dkcbHandler.handle(callbacks);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                byte[] arr = pwCb.getKey();
                ConvEngineResult res =
                    new ConvEngineResult(ConvEngineResult.ENCRYPT_DERIVED_KEY);
                res.setKeyAssociated(arr);
                return res;
            } else {
                throw new ConversationException("ConversationEngine :: SecurityTokenRerence doesn't contain DerivedKeys");
            }
        } else {
            throw new ConversationException("ConversationEngine ::SecurityTokenRerence doesn't contain refernce");
        }

    }

    /**
     * @param sig - XML Signature obeject containing the XMLSignature element.
     * @param cb  - Callback handler to get the symmetric key.
     * @return
     */
    private ConvEngineResult verifiyXMLHMac_SHA1_Signarue(
        XMLSignature sig,
        DerivedKeyCallbackHandler dkcbHandler)
        throws WSSecurityException {

        log.debug("Verifying HMAC-SHA1 Signature......");

        String userName = null;
        long t0 = 0, t1 = 0, t2 = 0;
        if (tlog.isDebugEnabled()) {
            t0 = System.currentTimeMillis();
        }
        ConvEngineResult convResult = null;
        if (sig == null) {
            throw new WSSecurityException(
                WSSecurityException.INVALID_SECURITY_TOKEN,
                "XMLSignature object is null");
        } /* Following lines of code - upto WSDocInfoStore.lookup(docHash) is copied
                                  * from the verifyXMLSignature() method.
                                  *
                                  */

        sig.addResourceResolver(
            EnvelopeIdResolver.getInstance());
        KeyInfo info = sig.getKeyInfo();
        if (info == null) {
            throw new WSSecurityException(
                WSSecurityException.INVALID_SECURITY,
                "unsupportedKeyInfo");
        }
        Node node =
            WSSecurityUtil.getDirectChild(
                info.getElement(),
                SecurityTokenReference.SECURITY_TOKEN_REFERENCE,
                WSConstants.WSSE_NS);
        if (node == null) {
            throw new WSSecurityException(
                WSSecurityException.INVALID_SECURITY,
                "unsupportedKeyInfo");
        }
        SecurityTokenReference secRef =
            new SecurityTokenReference(
                (Element) node);
        Document docSig = sig.getDocument();
        int docHash = docSig.hashCode();
        if (doDebug) {
            log.debug("XML Verify doc: " + docHash);
        } /*
                                  * Her we get some information about the document that is being processed,
                                  * in partucular the crypto implementation, and already detected BST that
                                  * may be used later during dereferencing.
                                  */
        WSDocInfo wsDocInfo = WSDocInfoStore.lookup(docHash);
        if (secRef.containsReference()) {
            Element token =
                secRef.getTokenElement(sig.getDocument(), wsDocInfo);
            /* check token type: We support Derivedkey tokens now.
             * We will support security context tokens.
             */
            QName el = new QName(token.getNamespaceURI(), token.getLocalName());
            if (el.equals(DERIVEDKEY_TOKEN)) {
                DerivedKeyToken dkToken = new DerivedKeyToken(token);
                DerivedKeyInfo dkInfo = null;

        String uuid = null;

                try {
          if (dkToken.getSecuityTokenReference() == null) {
            //if dkToken doesn't have a STR
            SecurityContextToken secContextTk =
              ConversationUtil.getSCT(dkToken);
            uuid = secContextTk.getIdentifier();
            log.debug(
              "ConversationEngine :: The uuid is found " + uuid);
            dkInfo = new DerivedKeyInfo(dkToken);
            dkcbHandler.addDerivedKey(uuid, dkInfo);
          } else { ///i.e. dkToken has a STR
            SecurityTokenReference str2Base =
              dkToken.getSecuityTokenReference();
            if (str2Base.containsReference()) {
              Reference ref2Base = str2Base.getReference();
                          //TODO:: Find where can I find the constants.
              if (ref2Base
                .getValueType()
                .equals("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID")) {
                /* ok now I have a SAML token. What should I do ?
                 * -Decrypt the secret.
                 * -create tempUUID
                 * -add the scTInfo into dkcbHandler
                 * -add the derived key token to dkcbHandler.
                 */
                uuid = ref2Base.getURI();
                if(dkcbHandler.getSession(uuid)==null){
                  byte[] key = handleSAML(docSig, uuid);
                  System.out.println("I am here :-)");
                  SecurityContextInfo sctInfo =
                  new SecurityContextInfo(
                    uuid,
                    key,
                    1);
                  dkcbHandler.addSecurtiyContext(
                    uuid,
                  sctInfo);
                }
                  dkInfo = new DerivedKeyInfo(dkToken);
                  dkcbHandler.addDerivedKey(uuid, dkInfo);
                }
            } else if(str2Base.containsKeyIdentifier()){
                          Element elem = str2Base.getFirstElement();
                          //.getKeyIdentifier()System.out.println("KeyIdentifier :: He ehee ........");
                          String value = elem.getAttribute("ValueType");
                if("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID".equals(value)){
                  uuid = ((Text)elem.getChildNodes().item(0)).getNodeValue();
                  if(dkcbHandler.getSession(uuid)==null){
                     byte[] key = handleSAML(elem.getOwnerDocument(), uuid);
                     System.out.println("UUID of SAML is"+uuid);
                     SecurityContextInfo sctInfo = new SecurityContextInfo(uuid,key,1);
                     dkcbHandler.addSecurtiyContext(uuid,sctInfo);
                  }
                dkInfo = new DerivedKeyInfo(dkToken);
                dkcbHandler.addDerivedKey(uuid, dkInfo);
                }

            } else {
              throw new ConversationException("Don't know how to process here");
            }

          }
                //String uuid = "aNewUuid";
                String dkId = dkToken.getID();
                userName = ConversationUtil.generateIdentifier(uuid, dkId);
                convResult =
                    new ConvEngineResult(ConvEngineResult.SIGN_DERIVED_KEY);
                    dkcbHandler.addDerivedKey(uuid, dkInfo);
                    log.debug(
                        "ConversationEngine: added for signature varification. uuil:"
                            + uuid
                            + " id:"
                            + dkId);
                } catch (ConversationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                //TODO :: Ask ruchith to throw correct exception
        } catch (WSSecurityException e2) {
          // TODO Auto-generated catch block
          e2.printStackTrace();
        }


            } else if (el.equals(SCT_TOKEN)) {
                throw new WSSecurityException(
                    WSSecurityException.INVALID_SECURITY,
                    "SCT is not Yet supported",
                    new Object[] { el.toString()});
            } else {
                throw new WSSecurityException(
                    WSSecurityException.INVALID_SECURITY,
                    "unsupportedToken",
                    new Object[] { el.toString()});
            }

            if (tlog.isDebugEnabled()) {
                t1 = System.currentTimeMillis();
            }

            try {
                // get the key from the callback handler
                WSPasswordCallback callbacks[] =
                    {
                         new WSPasswordCallback(
                            userName,
                            WSPasswordCallback.UNKNOWN)};
                try {
                    dkcbHandler.handle(callbacks);
                } catch (UnsupportedCallbackException e) {
                    e.printStackTrace();
                    throw new WSSecurityException(
                        WSSecurityException.FAILED_SIGNATURE,
                        "password call back failed",
                        new Object[] { e.toString()});
                } // get the key and check whether it is null
                byte[] keyBytes = callbacks[0].getKey();
                if (keyBytes == null) {
                    throw new WSSecurityException(
                        WSSecurityException.INVALID_SECURITY,
                        "password call bac in DerivedKeyTokenHandler failed");
                }

                convResult.setKeyAssociated(keyBytes);
                //System.out.println(new String(keyBytes));
                SecretKey symetricKey =
                    new SecretKeySpec(
                        keyBytes,
                        XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
                if (sig.checkSignatureValue(symetricKey)) {
                    if (tlog.isDebugEnabled()) {
                        t2 = System.currentTimeMillis();
                        tlog.debug(
                            "Verify: total= "
                                + (t2 - t0)
                                + ", Find-the token refernced by wsse:Reference= "
                                + (t1 - t0)
                                + ", password call back & verify= "
                                + (t2 - t1));
                    }

                } else {
                    throw new WSSecurityException(
                        WSSecurityException.FAILED_CHECK);
                }
            } catch (XMLSignatureException e1) {
                throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
            }

        }

        return convResult;
    }

    /**
     * Extracted from WSSecurityEngine.
     *
     * @param encBodyData
     * @return
     * @throws WSSecurityException
     */
    private String getEncAlgo(Node encBodyData) throws WSSecurityException {
        Element tmpE =
            (Element) WSSecurityUtil.findElement(
                encBodyData,
                "EncryptionMethod",
                WSConstants.ENC_NS);
        String symEncAlgo = null;
        if (tmpE != null) {
            symEncAlgo = tmpE.getAttribute("Algorithm");
        }
        if (symEncAlgo == null) {
            throw new WSSecurityException(
                WSSecurityException.UNSUPPORTED_ALGORITHM,
                "noEncAlgo");
        }
        if (doDebug) {
            log.debug("Sym Enc Algo: " + symEncAlgo);
        }
        return symEncAlgo;
    } //TODO :: Remove this. Temporary method.


  private Crypto loadDecryptionCrypto() {
      Crypto crypto = null;
      String encPropFile = (String)configurator.get(WSHandlerConstants.DEC_PROP_FILE);
      crypto = CryptoFactory.getInstance(encPropFile);
      return crypto;
    }

    /**
     * This method will be scrapped after the re-architecture.
     * Not so elegant work-around.
     *
     */
    private byte[] handleSAML(Document doc, String assertionId) throws ConversationException{

      try {
            Crypto crypto = this.loadDecryptionCrypto();
            //get the security header block
            //get the saml assertion

            Element ele=WSSecurityUtil.findWsseSecurityHeaderBlock(doc, doc.getDocumentElement(), false);
            Element samEle =(Element)WSSecurityUtil.getDirectChild(ele, "Assertion", "urn:oasis:names:tc:SAML:1.0:assertion" );
//            SAMLAssertion assertion = new SAMLAssertion(samEle);
//
//            Iterator itr = assertion.getStatements();
//
//             SAMLAuthenticationStatement auth = (SAMLAuthenticationStatement)itr.next();
//             Element eleEnc = auth.getSubject().getConfirmationData();
//

      Element eleEnc = (Element)samEle.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#","EncryptedKey").item(0);
            String cb = (String)this.configurator.get(WSHandlerConstants.PW_CALLBACK_CLASS);

            CallbackHandler cbHandler = null;
      if (cb != null) {
        Class cbClass = null;
          try {
            cbClass = Loader.loadClass(cb);
                 cbHandler = (CallbackHandler) cbClass.newInstance();

          } catch (ClassNotFoundException e) {
            throw new ConversationException("Cannot find passwordcallback");
          } catch (InstantiationException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
            } catch (IllegalAccessException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
          }

      }else{
        throw new ConversationException("Cannot find passwordcallback");
      }

            EncryptedKeyProcessor processor = new EncryptedKeyProcessor();
            processor.handleEncryptedKey(eleEnc, cbHandler, crypto);
            byte[] key = processor.getDecryptedBytes();

            return key;

      }catch (WSSecurityException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
      throw new ConversationException("Cannot find passwordcallback");
    }

    }
   /**
    *
    * Taken from WSSecurityEngine
    *
    * @param encBodyData
    * @return
    */
    private boolean isContent(Node encBodyData) {
        /*
         * Depending on the encrypted data type (Content or Element) the encBodyData either
         * holds the element whose contents where encrypted, e.g. soapenv:Body, or the
         * xenc:EncryptedData element (in case of Element encryption). In either case we need
         * to get the xenc:EncryptedData element. So get it. The findElement method returns
         * immediatly if its already the correct element.
         * Then we can get the Type attribute.
         */

        Element tmpE = (Element) WSSecurityUtil.findElement(encBodyData,
                "EncryptedData", WSConstants.ENC_NS);
        String typeStr = null;
        boolean content = true;
        if (tmpE != null) {
            typeStr = tmpE.getAttribute("Type");
        }
        if (typeStr != null) {
            content = typeStr.equals(WSConstants.ENC_NS + "Content") ? true : false;
        }
        return content;
    }

}
TOP

Related Classes of org.apache.ws.sandbox.security.conversation.ConversationEngine

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.