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

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

/*
* 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 org.apache.axis.components.logger.LogFactory;
import org.apache.commons.logging.Log;
import org.apache.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSDocInfo;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.sandbox.security.conversation.message.info.DerivedKeyInfo;
import org.apache.ws.sandbox.security.conversation.message.token.DerivedKeyToken;
import org.apache.ws.security.message.EnvelopeIdResolver;
import org.apache.ws.security.message.WSEncryptBody;
import org.apache.ws.security.message.token.Reference;
import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.security.transform.STRTransform;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.xml.security.c14n.Canonicalizer;
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.apache.xml.security.transforms.TransformationException;
import org.apache.xml.security.transforms.Transforms;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.callback.Callback;
import java.util.Vector;

/**
* This class helps handlers to carry on conversation.
* <p/>
* It performes functionalities
* 1) Adding derived Keys
* 2) Signing using derived keys
* 3) Encrypting using derive keys
* <p/>
* Actually the class is the collection of methods that are useful
* for carrying out conversation.
*
* @author Dimuthu Leelarathne. (muthulee@yahoo.com)
*/
public class ConversationManager {

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

    private int generation = 0;
    protected String canonAlgo = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;

    /**
      * Adds Derived key tokens to the header of the SOAP message, given the
      * following parameters.
      * @param doc
      * @param uuid
      * @param dkcbHandler
      * @param stRef2Base -SecurityTOkenReference to the token, from which the derived
      *                    key is derived from
      * @return
      * @throws ConversationException
      */
     public DerivedKeyInfo createDerivedKeyToken(Document doc,
                                             String uuid,
                                             DerivedKeyCallbackHandler dkcbHandler,SecurityTokenReference stRef2Base, int keyLen )
            throws ConversationException {
        String genID = ConversationUtil.genericID();
       
        /*
         * This metod is 4-step procedure.
         */
        
        // step 1 : Creating wsse:Reference to DerivedKeyToken
        Reference ref = new Reference(doc);
        ref.setURI("#" + genID);
        ref.setValueType(ConversationConstants.TOKEN_TYPE_DERIVED_KEY_TOKEN);
        SecurityTokenReference stRef = new SecurityTokenReference(doc);
        stRef.setReference(ref);

        WSSecurityUtil.setNamespace(stRef.getElement(),
                WSConstants.WSSE_NS,
                WSConstants.WSSE_PREFIX);

        // step 2 :Create the DerriveToken
        DerivedKeyToken dtoken = new DerivedKeyToken(doc);
    if(stRef2Base != null){
      dtoken.setSecuityTokenReference(doc, stRef2Base);
    }
        dtoken.setLabel(doc, "WS-SecureConversationWS-SecureConversation");
        dtoken.setNonce(doc, ConversationUtil.generateNonce(128));
        dtoken.setID(genID);
    //System.out.println("Fix me here ....");
   
    if(keyLen!=-1){
       dtoken.setLength(doc,keyLen);
    }
       
        //step 3 :add the derived key token infomation into the dkcbHandler
        DerivedKeyInfo dkInfo = null;
        try {
            dkInfo = new DerivedKeyInfo(dtoken);
            dkInfo.setSecTokRef2DkToken(stRef);
            dkcbHandler.addDerivedKey(uuid, dkInfo);
        } catch (WSSecurityException e) {
            e.printStackTrace();
            throw new ConversationException("ConversationManager:: Cannot add Derived key token to the envelope");
        }

              
    return dkInfo;

    }
   
   
    public void addDkToken(Document doc, DerivedKeyInfo info){
        DerivedKeyTokenAdder adder = new DerivedKeyTokenAdder();
        adder.build(doc, info.getDkTok());
    }     

    /**
     * Manages derived key encryption.
     *
     * @param encUser
     * @param actor
     * @param mu
     * @param doc
     * @param secRef - SecurityTokenReference pointing to the derived Key
     * @param dkcbHandler
     * @throws ConversationException
     */
    public void performDK_ENCR(String encUser,
                               String actor,
                               boolean mu,
                               Document doc,
                               SecurityTokenReference secRef,
                               DerivedKeyCallbackHandler dkcbHandler, Vector parts,
                               String symAlgo)
            throws ConversationException {
        WSEncryptBody wsEncrypt = new WSEncryptBody(actor, mu);

        /*
         * Here we want to add a wsse:SecurityTokenReference element into <KeyInfo>.
         * Rest is as same as EMBEDDED_KEYNAME , i.e. we want to encrypt the message
         * using a symmetric key and the result would be an <EncryptedData> element.
         * Steps are
         * step 1: Adding SecurityTokenReference pointing to DkToken
         * step 2: Adding the key into wsEncrypt
         * step 3: Setting the user.
         */
        wsEncrypt.setKeyIdentifierType(WSConstants.EMBED_SECURITY_TOKEN_REF);
   
        /*
         * step 1: Adding SecurityTokenReference pointing to DkToken.
         */
        wsEncrypt.setSecurityTokenReference(secRef);

        /*
         * step 2: Generating the key, and setting it in the the wsEncrypt
         */
        WSPasswordCallback pwCb =
                new WSPasswordCallback(encUser, WSPasswordCallback.UNKNOWN);
        Callback[] callbacks = new Callback[1];
        callbacks[0] = (Callback) pwCb;

        try {
            dkcbHandler.handle(callbacks);
        } catch (java.lang.Exception e) {
            e.printStackTrace();
            throw new ConversationException("ConversationManager :: PasswordCallback failed");
        }

        wsEncrypt.setKey(pwCb.getKey());
        /*
         * step 3: set the user.
         */
        wsEncrypt.setUserInfo(encUser);
       
        /*
         * step 4 : Setting encryption parts
         */
         wsEncrypt.setParts(parts)
       
         wsEncrypt.setSymmetricEncAlgorithm(symAlgo);
        
        try {
            wsEncrypt.build(doc, null);
        } catch (WSSecurityException e) {
          e.printStackTrace();
            throw new ConversationException("ConversationManager :: Encryption: error during message processing");
        }

    }

    /**
     * Manages derived key signature.
     *
     * @param doc
     * @param dkcbHandler
     * @param uuid
     * @param dkSigInfo
     * @throws ConversationException
     */
    public void performDK_Sign(Document doc,
                               DerivedKeyCallbackHandler dkcbHandler,
                               String uuid,
                               DerivedKeyInfo dkSigInfo, Vector parts)
            throws ConversationException {
        //            Signing....
        //        HMAC_SignVerify sign = new HMAC_SignVerify();
        String sigAlgo = XMLSignature.ALGO_ID_MAC_HMAC_SHA1;

        String sigUser =
                ConversationUtil.generateIdentifier(uuid, dkSigInfo.getId());
        System.out.println("Signature user is ::"+sigUser);
        WSPasswordCallback pwCb =
                new WSPasswordCallback(sigUser, WSPasswordCallback.UNKNOWN);
        Callback[] callbacks = new Callback[1];
        callbacks[0] = (Callback) pwCb;

        try {
            dkcbHandler.handle(callbacks);
        } catch (java.lang.Exception e) {
            throw new ConversationException("ConversationManager :: Password callback failed");
        }
        try {
            Reference ref = dkSigInfo.getSecTokRef2DkToken().getReference();
            this.build(doc, ref, pwCb.getKey(), parts);
        } catch (WSSecurityException e1) {
            e1.printStackTrace();
            throw new ConversationException("ConversationManager :: Error performing signature.");
        }

    }

    /**
     * The method is coded such that it can be plugged into WSSignEnvelope.
     * Performs HMAC_SHA1 signature.
     * needed.
     *
     * @param doc
     * @param ref
     * @param sk
     * @param parts
     * @return
     * @throws WSSecurityException
     */
    public Document build(Document doc, Reference ref, byte[] sk, Vector parts)
            throws WSSecurityException {
        boolean doDebug = log.isDebugEnabled();

        if (doDebug) {
            log.debug("Beginning signing...");
        }

        if (ref == null) {
            throw new WSSecurityException(WSSecurityException.FAILURE,
                    "invalidData",
                    new Object[]{"For symmeric key signatures - Reference object must be provided"});
        }

        if (sk == null) {
            throw new WSSecurityException(WSSecurityException.FAILURE,
                    "invalidData",
                    new Object[]{"For symmeric key signatures - Reference object must be provided"});
        }
        String sigAlgo = XMLSignature.ALGO_ID_MAC_HMAC_SHA1;
        log.debug("Key is "+new String(sk));

        SecretKey sharedKey = new SecretKeySpec(sk, sigAlgo);

        //TODO :: Check for the characteristics (eg: legnth of the key) of the key if it applies.

        /*
         * Gather some info about the document to process and store it for
         * retrival
         */
        WSDocInfo wsDocInfo = new WSDocInfo(doc.hashCode());
        Element envelope = doc.getDocumentElement();
        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
        Element securityHeader =
                WSSecurityUtil.findWsseSecurityHeaderBlock(doc,
                        doc.getDocumentElement(),
                        true);

        XMLSignature sig = null;
        try {
            sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
        } catch (XMLSecurityException e) {
            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
                    "noXMLSig");
        }

        KeyInfo info = sig.getKeyInfo();
        String keyInfoUri = "KeyId-" + info.hashCode();
        info.setId(keyInfoUri);

        SecurityTokenReference secRef = new SecurityTokenReference(doc);
        String strUri = "STRId-" + secRef.hashCode();
        secRef.setID(strUri);

        if (parts == null) {
            parts = new Vector();
            WSEncryptionPart encP =
                    new WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),
                            soapConstants.getEnvelopeURI(),
                            "Content");
            parts.add(encP);
        }

        /*
         * The below "for" loop (which perform transforms) is
         * copied from
         *        build(Document doc, Crypto crypto) method in
         *            org.apache.ws.security.message.WSEncryptBody.java                 
         */

        Transforms transforms = null;

        for (int part = 0; part < parts.size(); part++) {
            WSEncryptionPart encPart = (WSEncryptionPart) parts.get(part);
            String elemName = encPart.getName();
            String nmSpace = encPart.getNamespace();

            /*
             * Set up the elements to sign. There are two resevered element
             * names: "Token" and "STRTransform" "Token": Setup the Signature
             * to either sign the information that points to the security token
             * or the token itself. If its a direct reference sign the token,
             * otherwise sign the KeyInfo Element. "STRTransform": Setup the
             * ds:Reference to use STR Transform
             *
             */
            try {
                if (elemName.equals("Token")) {
                    transforms = new Transforms(doc);
                    transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
                    sig.addDocument("#" + keyInfoUri, transforms);
                } else if (elemName.equals("STRTransform")) { // STRTransform
                    Element ctx = createSTRParameter(doc);
                    transforms = new Transforms(doc);
                    transforms.addTransform(STRTransform.implementedTransformURI,
                            ctx);
                    sig.addDocument("#" + strUri, transforms);
                } else {
                    Element body =
                            (Element) WSSecurityUtil.findElement(envelope,
                                    elemName,
                                    nmSpace);
                    if (body == null) {
                        throw new WSSecurityException(WSSecurityException.FAILURE,
                                "noEncElement",
                                new Object[]{nmSpace + ", " + elemName});
                    }
                    transforms = new Transforms(doc);
                    transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
                    sig.addDocument("#" + setWsuId(body), transforms);
                }
            } catch (TransformationException e1) {
                throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
                        "noXMLSig",
                        null,
                        e1);
            } catch (XMLSignatureException e1) {
                throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
                        "noXMLSig",
                        null,
                        e1);
            }
        }

        sig.addResourceResolver(EnvelopeIdResolver.getInstance());

        /*
         * Prepending order
         * -Append the signature element.
         * -Apped the KeyInfo element
         */
        WSSecurityUtil.appendChildElement(doc,
                securityHeader,
                sig.getElement());

        /*
         * Put the "Reference object" into secRef in KeyInfo
         */
        secRef.setReference(ref);

        info.addUnknownElement(secRef.getElement());

        try {
            sig.sign(sharedKey);
        } catch (XMLSignatureException e1) {
            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
                    null,
                    null,
                    e1);
        }

        if (doDebug) {
            log.debug("Signing complete.");
        }
        return (doc);

    }

    /*
     * Extracted from org.apache.ws.security.message.WSSignEnvelope.java
     */
    private Element createSTRParameter(Document doc) {
        Element transformParam =
                doc.createElementNS(WSConstants.WSSE_NS,
                        WSConstants.WSSE_PREFIX + ":TransformationParameters");

        WSSecurityUtil.setNamespace(transformParam,
                WSConstants.WSSE_NS,
                WSConstants.WSSE_PREFIX);

        Element canonElem =
                doc.createElementNS(WSConstants.SIG_NS,
                        WSConstants.SIG_PREFIX + ":CanonicalizationMethod");

        WSSecurityUtil.setNamespace(canonElem,
                WSConstants.SIG_NS,
                WSConstants.SIG_PREFIX);

        canonElem.setAttributeNS(null,
                "Algorithm",
                Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
        transformParam.appendChild(canonElem);
        return transformParam;
    }

    /*
         * Extracted from org.apache.ws.security.message.WSSignEnvelope.java
         */

    protected String setWsuId(Element bodyElement) {
        String prefix =
                WSSecurityUtil.setNamespace(bodyElement,
                        WSConstants.WSU_NS,
                        WSConstants.WSU_PREFIX);
        String id = bodyElement.getAttributeNS(WSConstants.WSU_NS, "Id");
        if ((id == null) || (id.length() == 0)) {
            id = "id-" + Integer.toString(bodyElement.hashCode());
            bodyElement.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
        }
        return id;
    }

    /**
     * @param i
     */
    public void setGenerationInfo(int i) {
        generation = i;
    }

}
TOP

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

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.