Package com.sun.xml.wss.impl.dsig

Source Code of com.sun.xml.wss.impl.dsig.DSigResolver

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2014 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.xml.wss.impl.dsig;


import com.sun.xml.wss.core.reference.X509ThumbPrintIdentifier;
import com.sun.xml.wss.impl.FilterProcessingContext;
import com.sun.xml.wss.core.reference.X509SubjectKeyIdentifier;
import com.sun.xml.wss.logging.LogDomainConstants;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.impl.SecurableSoapMessage;
import com.sun.xml.wss.impl.XMLUtil;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.impl.XWSSecurityRuntimeException;
import com.sun.xml.wss.core.ReferenceElement;
import com.sun.xml.wss.core.SecurityToken;
import com.sun.xml.wss.core.SecurityTokenReference;
import com.sun.xml.wss.core.X509SecurityToken;
import com.sun.xml.wss.core.reference.DirectReference;
import com.sun.xml.wss.core.reference.KeyIdentifier;
import com.sun.xml.wss.core.reference.X509IssuerSerial;
import com.sun.xml.wss.logging.impl.dsig.LogStringsMessages;
import com.sun.xml.wss.saml.AssertionUtil;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Logger;
import javax.xml.crypto.Data;
import javax.xml.crypto.NodeSetData;
import javax.xml.crypto.OctetStreamData;
import javax.xml.crypto.URIDereferencer;
import javax.xml.crypto.URIReference;
import javax.xml.crypto.URIReferenceException;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.dom.DOMURIReference;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPMessage;

import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import com.sun.xml.wss.saml.Assertion;
import com.sun.xml.wss.saml.util.SAMLUtil;
import java.util.logging.Level;


/**
* Implementation of JSR 105 URIDereference interface.
* @author <U><B>k.venugopal@sun.com</B></U>
*/
public class DSigResolver implements URIDereferencer{
   
    private static volatile DSigResolver resolver = null;
    private static Logger logger = Logger.getLogger (LogDomainConstants.IMPL_SIGNATURE_DOMAIN,
            LogDomainConstants.IMPL_SIGNATURE_DOMAIN_BUNDLE);
   
    private String optNSClassName = "org.apache.jcp.xml.dsig.internal.dom.DOMSubTreeData";
    private Class _nodeSetClass = null;
    private Constructor _constructor = null;
    private Boolean  _false = Boolean.valueOf(false);
   
    /** Creates a new instance of DSigResolver */
    @SuppressWarnings("unchecked")
    private DSigResolver () {
        try{
            _nodeSetClass = Class.forName (optNSClassName);
            _constructor = _nodeSetClass.getConstructor (new Class [] {org.w3c.dom.Node.class,boolean.class});
        }catch(LinkageError le){
            logger.log (Level.FINE,"Not able load JSR 105 RI specific NodeSetData class ",le);
        }catch(ClassNotFoundException cne){
            logger.log (Level.FINE,"Not able load JSR 105 RI specific NodeSetData class ",cne);
        }catch(NoSuchMethodException ne){
           
        }
    }
   
    /**
     *
     * @return URI Dereferencer instance.
     */
    public static URIDereferencer getInstance (){
        if(resolver == null){
            init ();
        }
        return resolver;
    }
   
    private static void init (){
        if(resolver == null){
            synchronized(DSigResolver.class){
                if(resolver == null){
                    resolver = new DSigResolver ();               
                }
            }
        }
    }
   
   
    /**
     * resolve the URI of type "cid:" , "attachmentRef:", "http:", "#xyz".
     * @param uriRef {@inheritDoc}
     * @param context{@inheritDoc}
     * @throws URIReferenceException {@inheritDoc}
     * @return {@inheritDoc}
     */
    public Data dereference (URIReference uriRef, XMLCryptoContext context) throws URIReferenceException {
        String uri = null;
       
        try{
            if(uriRef instanceof DOMURIReference ){
                DOMURIReference domRef = (DOMURIReference) uriRef;
                Node node = domRef.getHere ();
                if(node.getNodeType () == Node.ATTRIBUTE_NODE){
                    uri = uriRef.getURI ();
                    return dereferenceURI (uri,context);
                }else if(node.getNodeType () == Node.ELEMENT_NODE ){
                    if("SecurityTokenReference".equals (node.getLocalName ())){
                        return derefSecurityTokenReference (node,context);
                    }
                }
            }else {
                uri = uriRef.getURI ();
                if(MessageConstants.debug){
                    logger.log (Level.FINEST, "URI "+ uri);
                }
                return dereferenceURI (uri,context);
            }
        }catch(XWSSecurityException ex){
            if(logger.getLevel () == Level.FINEST){
                logger.log (Level.FINEST,"Error occurred while resolving"+uri,ex);
            }
            throw new URIReferenceException (ex.getMessage ());
        }
        return null;
    }
   
   
    Data dereferenceURI (String uri, XMLCryptoContext context) throws URIReferenceException, XWSSecurityException{
        FilterProcessingContext filterContext =(FilterProcessingContext) context.get (MessageConstants.WSS_PROCESSING_CONTEXT);
        SecurableSoapMessage secureMsg = filterContext.getSecurableSoapMessage ();
        if(uri == null || uri.equals ("")){
            SOAPMessage msg = filterContext.getSOAPMessage ();
            Document doc = msg.getSOAPPart ();
            if(_constructor == null){
                return convertToData ((Node)doc,true);
            }else{
                try{
                    return (Data)_constructor.newInstance (new Object[] {doc,_false});
                }catch(Exception ex){
                    //throw new XWSSecurityException(ex);
                }
                return convertToData ((Node)doc,true);
            }
        }else if(uri.charAt (0) == '#'){
            return dereferenceFragment (secureMsg.getIdFromFragmentRef (uri),context);
        }else if(uri.startsWith ("cid:") || uri.startsWith ("attachmentRef:")){
            return dereferenceAttachments (uri,context);
        }else if(uri.startsWith ("http")){
            //throw new UnsupportedOperationException("Not yet supported ");
            return dereferenceExternalResource (uri,context);
        }else {
            return dereferenceFragment (uri,context);
        }
        //throw new URIReferenceException("Resource "+uri+" was not found");
    }
   
    Data dereferenceExternalResource (final String uri,XMLCryptoContext context) throws URIReferenceException, XWSSecurityException {
       
        URIDereferencer resolver = WSSPolicyConsumerImpl.getInstance ().getDefaultResolver ();
        URIReference uriRef = null;
        FilterProcessingContext filterContext =(FilterProcessingContext) context.get (MessageConstants.WSS_PROCESSING_CONTEXT);
        SecurableSoapMessage secureMsg = filterContext.getSecurableSoapMessage ();
        final Attr uriAttr = secureMsg.getSOAPMessage ().getSOAPPart ().createAttribute ("uri");
        uriAttr.setNodeValue (uri);
        uriRef = new DOMURIReference (){
           
            public String getURI (){
                return uri;
            }
           
            public String getType (){
                return null;
            }
            public Node getHere (){
                return uriAttr;
            }
        };
        try{
            Data data = resolver.dereference (uriRef, context);
           
            if(MessageConstants.debug){
                if(data instanceof NodeSetData){
                    logger.log (Level.FINE,"Node set Data");
                }else if(data instanceof OctetStreamData){
                    logger.log (Level.FINE,"Octet Data");
                    try{
                        InputStream is = ((OctetStreamData)data).getOctetStream ();
                        int len = is.available ();
                        byte [] bb = new byte[len];
                        is.read (bb);
                        logger.log (Level.FINE,"Data: "+new String (bb));
                    }catch(Exception ex){
                        logger.log (Level.FINE,"ERROR",ex);
                    }
                }
            }
            return data;
        }catch(URIReferenceException ue){
            logger.log (Level.SEVERE,LogStringsMessages.WSS_1325_DSIG_EXTERNALTARGET(ue));
            throw ue;
        }
       
    }
   
   
    Data dereferenceAttachments (String uri, XMLCryptoContext context) throws URIReferenceException, XWSSecurityException {
        boolean sunAttachmentTransformProvider = true;
        FilterProcessingContext filterContext =(FilterProcessingContext)
        context.get (MessageConstants.WSS_PROCESSING_CONTEXT);
       
        SecurableSoapMessage secureMsg = filterContext.getSecurableSoapMessage ();
        AttachmentPart attachment = secureMsg.getAttachmentPart (uri);
        if(attachment == null){
            throw new URIReferenceException ("Attachment Resource with Identifier  "+uri+" was not found");
        }
        if(sunAttachmentTransformProvider){
            AttachmentData attachData = new AttachmentData ();
            attachData.setAttachmentPart (attachment);
            return attachData;
        }else{
            //Attachments need to be serialized and returned as OctectStreamData
            //attachment.getDataHandler();
            // new OctectStreamData();
            throw new UnsupportedOperationException ("Not yet supported ");
        }
        //        throw new URIReferenceException("Attachment Resource with Identifier  "+uri+" was not found");
    }
   
    Data dereferenceFragment (String uri, XMLCryptoContext context) throws URIReferenceException, XWSSecurityException {
        FilterProcessingContext filterContext =(FilterProcessingContext) context.get(MessageConstants.WSS_PROCESSING_CONTEXT);
        HashMap elementCache = filterContext.getElementCache ();
        if(elementCache.size () > 0){
            Object obj = elementCache.get (uri);
            if(obj != null ){
                if(_constructor == null){
                    return convertToData ((Element)obj,true);
                }else{
                    try{
                        return (Data)_constructor.newInstance (new Object[] {obj,_false});
                    }catch(Exception ex){
                        //throw new XWSSecurityException(ex);
                    }
                }
                return convertToData ((Element)obj,true);
            }
        }
        SecurableSoapMessage secureMsg = filterContext.getSecurableSoapMessage ();
        Element element = secureMsg.getElementById (uri);
        if(element == null){
            throw new URIReferenceException ("Resource with fragment Identifier  "+uri+" was not found");
            //log;
        }
        if(_constructor == null){
            return convertToData (element,true);
        }else{
            try{
                return (Data)_constructor.newInstance (new Object[] {element,_false});
            }catch(Exception ex){
                //throw new XWSSecurityException(ex);
            }
        }
        return convertToData (element,true);
    }
   
    Data convertToData (final Node node,boolean xpathNodeSet){
        final HashSet nodeSet = new HashSet ();
        if(xpathNodeSet){
            toNodeSet (node,nodeSet);
            return new NodeSetData (){
                public Iterator iterator (){
                    return nodeSet.iterator ();
                }
            };
        }else{
            return new NodeSetData (){
                public Iterator iterator (){
                    return Collections.singletonList (node).iterator ();
                   
                }
            };
        }
    }
    @SuppressWarnings("unchecked")
    void toNodeSet (final Node rootNode,final Set result){
        //handle EKSHA1 under DKT
        if (rootNode == null) return;
        switch (rootNode.getNodeType ()) {
            case Node.ELEMENT_NODE:
                result.add (rootNode);
                Element el=(Element)rootNode;
                if (el.hasAttributes ()) {
                    NamedNodeMap nl = ((Element)rootNode).getAttributes ();
                    for (int i=0;i<nl.getLength ();i++) {
                        result.add (nl.item (i));
                    }
                }
                //no return keep working
            case Node.DOCUMENT_NODE:
                for (Node r=rootNode.getFirstChild ();r!=null;r=r.getNextSibling ()){
                    if (r.getNodeType ()==Node.TEXT_NODE) {
                        result.add (r);
                        while ((r!=null) && (r.getNodeType ()==Node.TEXT_NODE)) {
                            r=r.getNextSibling ();
                        }
                        if (r==null)
                            return;
                    }
                    toNodeSet (r,result);
                }
                return;
            case Node.COMMENT_NODE:
                return;
            case Node.DOCUMENT_TYPE_NODE:
                return;
            default:
                result.add (rootNode);
        }
        return;
    }
    @SuppressWarnings("unchecked")
    private Data derefSecurityTokenReference (Node element, XMLCryptoContext context)
    throws XWSSecurityException,URIReferenceException {
        /**
         * Four Cases:
         *    (1). Direct Reference
         *    (2). KeyIdentifier
         *         * X509 SubjectKeyIdentifier
         *         * SAML Assertion ID
         *    (3). Embedded Reference
         *    (4). X509 Issuer Serial
         */
        SecurityToken secToken = null;
        FilterProcessingContext filterContext = (FilterProcessingContext)context.get (MessageConstants.WSS_PROCESSING_CONTEXT);
        SecurableSoapMessage secureMessage = filterContext.getSecurableSoapMessage ();
        Document soapDocument = secureMessage.getSOAPPart ();
        SOAPElement soapElem =  XMLUtil.convertToSoapElement (soapDocument, (Element) element);
        SecurityTokenReference tokenRef = new SecurityTokenReference (soapElem);
        ReferenceElement refElement =  tokenRef.getReference ();
        HashMap tokenCache = filterContext.getTokenCache ();
        Element tokenElement = null;
        Element newElement = null;
       
        if (refElement instanceof DirectReference) {
            // isXMLToken = true;
            /* Use the URI value to locate the BST */
            String uri = ((DirectReference) refElement).getURI ();
            String tokenId = uri.substring (1);
            secToken = (SecurityToken)tokenCache.get (tokenId);
            if(secToken == null){
                tokenElement = secureMessage.getElementById (tokenId);
                if(tokenElement == null){
                    throw new URIReferenceException ("Could not locate token with following ID"+tokenId);
                }
            
            } else {
                tokenElement = secToken.getAsSoapElement();
            }
            newElement = (Element)element.getOwnerDocument ().importNode (tokenElement, true);
           
        } else if (refElement instanceof KeyIdentifier) {
            String valueType = ((KeyIdentifier) refElement).getValueType ();
            String keyId = ((KeyIdentifier) refElement).getReferenceValue ();
            if (MessageConstants.X509SubjectKeyIdentifier_NS.
                    equals (valueType) ||
                    MessageConstants.X509v3SubjectKeyIdentifier_NS.
                    equals (valueType)) {
                /* Use the Subject Key Identifier to locate BST */
                //  isXMLToken = false;
                X509Certificate cert = null;
               
                Object token = tokenCache.get (keyId);
                if(token instanceof X509SubjectKeyIdentifier ){
                    if(token != null){
                        cert = ((X509SubjectKeyIdentifier)token).getCertificate ();
                    }
                }
               
                if(cert == null){
                    cert = filterContext.getSecurityEnvironment ().getCertificate (
                            filterContext.getExtraneousProperties (), XMLUtil.getDecodedBase64EncodedData (keyId));
                }
                secToken = new X509SecurityToken (soapDocument, cert);
                tokenElement = secToken.getAsSoapElement ();
                newElement = tokenElement;
                //(Element)element.getOwnerDocument().importNode(tokenElement, true);
                try {
                    // EncodingType should not be set -
                    // As specified by WSS spec
                    newElement.removeAttribute ("EncodingType");
                } catch (DOMException de) {
                    logger.log(Level.SEVERE,com.sun.xml.wss.logging.LogStringsMessages.WSS_0607_STR_TRANSFORM_EXCEPTION());
                    throw new XWSSecurityRuntimeException (de.getMessage (), de);
                }
            } else if (MessageConstants.ThumbPrintIdentifier_NS.equals (valueType)) {
                X509Certificate cert = null;
               
                Object token = tokenCache.get (keyId);
                if(token instanceof X509ThumbPrintIdentifier ){
                    if(token != null){
                        cert = ((X509ThumbPrintIdentifier)token).getCertificate ();
                    }
                }
               
                if(cert == null){
                    cert = filterContext.getSecurityEnvironment ().getCertificate (
                            filterContext.getExtraneousProperties (), XMLUtil.getDecodedBase64EncodedData (keyId), MessageConstants.THUMB_PRINT_TYPE);
                }
                secToken = new X509SecurityToken (soapDocument, cert);
                tokenElement = secToken.getAsSoapElement ();
                newElement = tokenElement;
                //(Element)element.getOwnerDocument().importNode(tokenElement, true);
                try {
                    // EncodingType should not be set -
                    // As specified by WSS spec
                    newElement.removeAttribute ("EncodingType");
                } catch (DOMException de) {
                    logger.log(Level.SEVERE,com.sun.xml.wss.logging.LogStringsMessages.WSS_0607_STR_TRANSFORM_EXCEPTION());
                    throw new XWSSecurityRuntimeException (de.getMessage (), de);
                }
            }else if(MessageConstants.EncryptedKeyIdentifier_NS.equals (valueType)){
                // do something here
                newElement = null;
            } else if (MessageConstants.WSSE_SAML_KEY_IDENTIFIER_VALUE_TYPE.equals (valueType) ||
                     MessageConstants.WSSE_SAML_v2_0_KEY_IDENTIFIER_VALUE_TYPE.equals (valueType)) {
               
                //TODO : should we first try locating from the cache
                if (tokenRef.getSamlAuthorityBinding () != null) {
                    tokenElement = filterContext.getSecurityEnvironment ().
                            locateSAMLAssertion (
                            filterContext.getExtraneousProperties(), tokenRef.getSamlAuthorityBinding (), keyId, secureMessage.getSOAPPart ());
                } else {
                    tokenElement = SAMLUtil.locateSamlAssertion (keyId,secureMessage.getSOAPPart ());
                }
                newElement = (Element)element.getOwnerDocument ().importNode (tokenElement, true);
               
                Assertion assertion = null;
                try {
                    assertion = AssertionUtil.fromElement(tokenElement);
                } catch (Exception e) {
                    throw new XWSSecurityException (e);
                }
                tokenCache.put (keyId, assertion);
               
            } else {
                try {
                    tokenElement = resolveSAMLToken (tokenRef, keyId, filterContext);
                } catch (Exception e) {
                    // ignore
                }
                if (tokenElement != null) {
                    newElement = (Element)element.getOwnerDocument ().importNode (tokenElement, true);
                } else {
                    //TODO : there can be a X509 KeyIdentifier without ValueType
                    //    log.log(Level.SEVERE, "WSS0334.unsupported.keyidentifier");
                    XWSSecurityException xwsse =
                            new XWSSecurityException (
                            "WSS_DSIG0008:unsupported KeyIdentifier Reference Type "
                            + valueType);
                    throw SecurableSoapMessage.newSOAPFaultException (
                            MessageConstants.WSSE_INVALID_SECURITY_TOKEN,
                            xwsse.getMessage (),
                            xwsse);
                }
            }
           
        } else if (refElement instanceof X509IssuerSerial) {
            //       isXMLToken = false;
            BigInteger serialNumber =
                    ((X509IssuerSerial) refElement).getSerialNumber ();
            String issuerName = ((X509IssuerSerial) refElement).getIssuerName ();
            X509Certificate cert =  null;
            Object token = tokenCache.get (issuerName+serialNumber);
            if(token instanceof X509IssuerSerial){
                cert = ((X509IssuerSerial)token).getCertificate ();
            }
           
            if(cert == null){
                cert = filterContext.getSecurityEnvironment ().getCertificate (
                        filterContext.getExtraneousProperties (),serialNumber, issuerName);
            }
            secToken = new X509SecurityToken (soapDocument, cert);
            tokenElement = secToken.getAsSoapElement ();
            newElement = tokenElement;
            //(Element)element.getOwnerDocument().importNode(tokenElement, true);
            try {
                // EncodingType should not be set - As specified by WSS spec
                newElement.removeAttribute ("EncodingType");
            } catch (DOMException de) {
                logger.log(Level.SEVERE,com.sun.xml.wss.logging.LogStringsMessages.WSS_0607_STR_TRANSFORM_EXCEPTION());
                throw new XWSSecurityException (de.getMessage (), de);
            }
        } else {
            logger.log(Level.SEVERE,com.sun.xml.wss.logging.LogStringsMessages.WSS_0608_DIAG_CAUSE_1());
            throw new XWSSecurityException (
                    "Cannot handle reference mechanism: " +
                    refElement.getTagName ());
        }
        Attr attr = newElement.getOwnerDocument ().createAttributeNS (MessageConstants.NAMESPACES_NS, "xmlns");
        attr.setValue ("");
        if (newElement != null) {
            newElement.setAttributeNodeNS (attr);
        }
        return convertToData (newElement,false);
    }
    @SuppressWarnings("unchecked")
    private static Element resolveSAMLToken (SecurityTokenReference tokenRef, String assertionId,
            FilterProcessingContext context)throws XWSSecurityException {
      
        Assertion ret = (Assertion)context.getTokenCache().get(assertionId);
        if (ret != null) {
            try {
                return SAMLUtil.toElement(context.getSecurableSoapMessage().getSOAPPart(), ret,null);
            } catch (Exception e) {
                throw new XWSSecurityException (e);
            }
        }
       
        Element tokenElement = null;
        if (tokenRef.getSamlAuthorityBinding () != null) {
            tokenElement = context.getSecurityEnvironment ().
                    locateSAMLAssertion (
                    context.getExtraneousProperties(),
                    tokenRef.getSamlAuthorityBinding (),
                    assertionId,
                    context.getSOAPMessage ().getSOAPPart ());
        } else {
            tokenElement = SAMLUtil.locateSamlAssertion (
                    assertionId, context.getSOAPMessage ().getSOAPPart ());
        }
       
        try {
            ret = AssertionUtil.fromElement(tokenElement);
        } catch (Exception e) {
            throw new XWSSecurityException (e);
        }
        context.getTokenCache ().put (assertionId, ret);
       
        return tokenElement;
    }
   
}
TOP

Related Classes of com.sun.xml.wss.impl.dsig.DSigResolver

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.