All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.xml.wss.saml.assertion.saml20.jaxb20.Assertion Maven / Gradle / Ivy

The newest version!
/*
 * $Id: Assertion.java,v 1.15 2008/03/10 23:32:33 jdg6688 Exp $
 */

/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (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/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
 */

package com.sun.xml.wss.saml.assertion.saml20.jaxb20;

import com.sun.xml.wss.core.SecurityTokenReference;
import com.sun.xml.wss.impl.dsig.WSSPolicyConsumerImpl;
import com.sun.xml.wss.saml.SAMLException;
import com.sun.xml.wss.saml.util.SAMLUtil;
import com.sun.xml.wss.saml.internal.saml20.jaxb20.AssertionType;
import com.sun.xml.wss.saml.internal.saml20.jaxb20.NameIDType;
import java.util.GregorianCalendar;
import javax.xml.bind.JAXBElement;

import javax.xml.datatype.DatatypeFactory;

import java.lang.reflect.Constructor;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;

import java.util.List;

import com.sun.xml.wss.logging.LogDomainConstants;
import com.sun.xml.wss.impl.XMLUtil;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.core.reference.X509SubjectKeyIdentifier;
import com.sun.xml.wss.impl.misc.Base64;
import com.sun.xml.wss.saml.util.SAML20JAXBUtil;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Map;

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

import javax.xml.bind.JAXBContext;
import java.util.Set;
import java.util.Iterator;
import java.util.logging.Logger;

import javax.xml.crypto.*;
import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.crypto.dsig.spec.*;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPException;

//import com.sun.xml.wss.saml.Assertion20;

/**
 * This object stands for Assertion element. An Assertion is a package
 * of information that supplies one or more Statement made by an
 * issuer. There are three kinds of assertions Au     [java] 
 * [java] 
 * [java] 
 * [java]     CN=SAML User,OU=SU,O=SAML
 * User,L=Los Angeles,ST=CA,C=US
 * [java]     
 * [java]         urn:oasis:names:tc:SAML:1.0:cm:sender-vouches
 * [java]     
 * [java] 
 * [java] 
 * [java]     ATTRIBUTE1
 * [java] 
 * thentication, Authorization
 * Decision and Attribute assertion.
 */
public class Assertion extends AssertionType implements com.sun.xml.wss.saml.Assertion {
    
    private Element signedAssertion = null;
    private NameIDType issuerValue = null;
    private java.math.BigInteger majorValue = null;
    private java.math.BigInteger minorValue = null;
    
    /**
     * XML Information Set REC
     * all namespace attributes (including those named xmlns, 
     * whose [prefix] property has no value) have a namespace URI of http://www.w3.org/2000/xmlns/
     */
    public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/".intern();

    public Assertion(AssertionType assertion) {
        this.setID(assertion.getID());
        this.setIssueInstant(assertion.getIssueInstant());
        this.setIssuer(assertion.getIssuer());
        this.setAdvice(assertion.getAdvice());
        this.setConditions(assertion.getConditions());
        this.setSubject(assertion.getSubject());
        this.setVersion(assertion.getVersion());
        this.setSignature(assertion.getSignature());
        this.setStatement(assertion.getStatementOrAuthnStatementOrAuthzDecisionStatement());
    }
    
    protected static final Logger log = Logger.getLogger(
            LogDomainConstants.WSS_API_DOMAIN,
            LogDomainConstants.WSS_API_DOMAIN_BUNDLE);
    
    public java.math.BigInteger getMajorVersion(){
        return this.majorValue;
    }
    
    public java.math.BigInteger getMinorVersion(){
        return this.minorValue;
    }
    
    public void setMajorVersion(java.math.BigInteger majorValue){
        this.majorValue = majorValue;
    }
    public void setMinorVersion(java.math.BigInteger minorValue){
        this.minorValue = minorValue;
    }
    
    public String getAssertionID(){
        return getID();
    }
    
    public String getSamlIssuer(){
        this.issuerValue = this.getIssuer();
        return issuerValue.getValue();
    }
    
    /**
     * sign the saml assertion (Enveloped Signature)
     * @param pubKey PublicKey to be used for Signature verification
     * @param privKey PrivateKey to be used for Signature calculation
     */
    
    public Element sign(PublicKey pubKey, PrivateKey privKey) throws SAMLException {
        
        //Check if the signature is already calculated
        if ( signedAssertion != null) {
            return signedAssertion;
        }
        
        //Calculate the enveloped signature
        try {
            
            XMLSignatureFactory fac = WSSPolicyConsumerImpl.getInstance().getSignatureFactory();
            return sign(fac.newDigestMethod(DigestMethod.SHA1,null),SignatureMethod.RSA_SHA1, pubKey,privKey);
            
        } catch (Exception ex) {
            // log here
            throw new SAMLException(ex);
        }
    }
    
    public Element sign(X509Certificate cert, PrivateKey privKey, boolean alwaysIncludeCert) throws SAMLException {
        //Check if the signature is already calculated
        if ( signedAssertion != null) {
            return signedAssertion;
        }
        
        //Calculate the enveloped signature
        try {
            
            XMLSignatureFactory fac = WSSPolicyConsumerImpl.getInstance().getSignatureFactory();
            return sign(fac.newDigestMethod(DigestMethod.SHA1,null),SignatureMethod.RSA_SHA1, cert,privKey, alwaysIncludeCert);
            
        } catch (Exception ex) {
            // log here
            throw new SAMLException(ex);
        }
    }
    
    public Element sign(X509Certificate cert, PrivateKey privKey) throws SAMLException {
        //Check if the signature is already calculated
        if ( signedAssertion != null) {
            return signedAssertion;
        }
        
        //Calculate the enveloped signature
        try {
            
            XMLSignatureFactory fac = WSSPolicyConsumerImpl.getInstance().getSignatureFactory();
            return sign(fac.newDigestMethod(DigestMethod.SHA1,null),SignatureMethod.RSA_SHA1, cert,privKey);
            
        } catch (Exception ex) {
            // log here
            throw new SAMLException(ex);
        }
    }
    
    /**
     * sign the saml assertion (Enveloped Signature)
     * @param digestMethod DigestMethod to be used
     * @param signatureMethod SignatureMethod to be used.
     * @param pubKey PublicKey to be used for Signature verification
     * @param privKey PrivateKey to be used for Signature calculation
     */
    
    public Element sign(DigestMethod digestMethod, String signatureMethod,PublicKey pubKey, PrivateKey privKey) throws SAMLException {
        
        //Check if the signature is already calculated
        if ( signedAssertion != null) {
            return signedAssertion;
            //return;
        }
        
        //Calculate the enveloped signature
        try {
            
            
            XMLSignatureFactory fac = WSSPolicyConsumerImpl.getInstance().getSignatureFactory();
            ArrayList transformList = new ArrayList();
            
            Transform tr1 = fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
            Transform tr2 = fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null);
            transformList.add(tr1);
            transformList.add(tr2);
            
            String uri = "#" + this.getID();
            Reference ref = fac.newReference(uri,digestMethod,transformList, null, null);
            
            // Create the SignedInfo
            SignedInfo si = fac.newSignedInfo
                    (fac.newCanonicalizationMethod
                    (CanonicalizationMethod.EXCLUSIVE,(C14NMethodParameterSpec) null),
                    fac.newSignatureMethod(signatureMethod, null),
                    Collections.singletonList(ref));
            
            // Create a KeyValue containing the DSA PublicKey that was generated
            KeyInfoFactory kif = fac.getKeyInfoFactory();
            KeyValue kv = kif.newKeyValue(pubKey);
            
            // Create a KeyInfo and add the KeyValue to it
            KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
            
            // Instantiate the document to be signed
            Document doc =  XMLUtil.newDocument();
            
            //Document document;
            
            //Element assertionElement = this.toElement(doc);
            Element assertionElement = this.toElement(doc);
            //try {
            //    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            //    DocumentBuilder builder = factory.newDocumentBuilder();
            //    document = builder.newDocument();
            //} catch (Exception ex) {
            //    throw new XWSSecurityException("Unable to create Document : " + ex.getMessage());
            //}
            
            //document.appendChild(assertionElement);
            //doc.appendChild(assertionElement);
            
            // Create a DOMSignContext and specify the DSA PrivateKey and
            // location of the resulting XMLSignature's parent element
            
            DOMSignContext dsc = new DOMSignContext(privKey, assertionElement);
            HashMap map = new HashMap();
            map.put(this.getID(),assertionElement);
            
            dsc.setURIDereferencer(new DSigResolver(map,assertionElement));
            XMLSignature signature = fac.newXMLSignature(si, ki);
            dsc.putNamespacePrefix("http://www.w3.org/2000/09/xmldsig#", "ds");
            
            // Marshal, generate (and sign) the enveloped signature
            signature.sign(dsc);
            
            signedAssertion = assertionElement;
            return assertionElement;
        } catch (Exception ex) {
            // log here
            throw new SAMLException(ex);
        }
        //return signedAssertion;
    }
    
    public Element sign(DigestMethod digestMethod, String signatureMethod, X509Certificate cert, PrivateKey privKey, boolean includeCert) throws SAMLException {
        //Check if the signature is already calculated
        if ( signedAssertion != null) {
            return signedAssertion;
            //return;
        }
        
        //Calculate the enveloped signature
        try {
            XMLSignatureFactory fac = WSSPolicyConsumerImpl.getInstance().getSignatureFactory();
            ArrayList transformList = new ArrayList();
            
            Transform tr1 = fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
            Transform tr2 = fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null);
            transformList.add(tr1);
            transformList.add(tr2);
            
            String uri = "#" + this.getID();
            Reference ref = fac.newReference(uri,digestMethod,transformList, null, null);
            
            // Create the SignedInfo
            SignedInfo si = fac.newSignedInfo
                    (fac.newCanonicalizationMethod
                    (CanonicalizationMethod.EXCLUSIVE,
                    (C14NMethodParameterSpec) null),
                    fac.newSignatureMethod(signatureMethod, null),
                    Collections.singletonList(ref));
            
            // Instantiate the document to be signed
            Document doc = MessageFactory.newInstance().createMessage().getSOAPPart();
            KeyInfoFactory kif = fac.getKeyInfoFactory();
            KeyInfo ki = null;
            if (!includeCert){
                byte[] skid = X509SubjectKeyIdentifier.getSubjectKeyIdentifier(cert);
                if (skid != null){
                    X509SubjectKeyIdentifier keyIdentifier = new X509SubjectKeyIdentifier(doc);
                    keyIdentifier.setCertificate(cert);
                    keyIdentifier.setReferenceValue(Base64.encode(skid));
                    SecurityTokenReference str = new SecurityTokenReference();
                    str.setReference(keyIdentifier);
                    DOMStructure domKeyInfo = new DOMStructure(str.getAsSoapElement());
                    ki = kif.newKeyInfo(Collections.singletonList(domKeyInfo));
                }
            }
            
            if (ki == null){
                  X509Data x509Data = kif.newX509Data(Collections.singletonList(cert));
                  ki = kif.newKeyInfo(Collections.singletonList(x509Data));
            }
           /* KeyIdentifier kid = new KeyIdentifierImpl(MessageConstants.X509SubjectKeyIdentifier_NS, MessageConstants.MessageConstants.BASE64_ENCODING_NS);
            kid.setValue(Base64.encode(X509SubjectKeyIdentifier.getSubjectKeyIdentifier(cert)));
            SecurityTokenReference str = new SecurityTokenReferenceImpl(kid);*/  
            Element assertionElement = this.toElement(doc);
            //try {
            //    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            //    DocumentBuilder builder = factory.newDocumentBuilder();
            //    document = builder.newDocument();
            //} catch (Exception ex) {
            //    throw new XWSSecurityException("Unable to create Document : " + ex.getMessage());
            //}
            //document.appendChild(assertionElement);
            //doc.appendChild(assertionElement);
            
            
            
            // Create a DOMSignContext and specify the DSA PrivateKey and
            // location of the resulting XMLSignature's parent element
            DOMSignContext dsc = new DOMSignContext(privKey, assertionElement);
            HashMap map = new HashMap();
            map.put(this.getID(),assertionElement);
            
            dsc.setURIDereferencer(new DSigResolver(map,assertionElement));
            XMLSignature signature = fac.newXMLSignature(si, ki);
            dsc.putNamespacePrefix("http://www.w3.org/2000/09/xmldsig#", "ds");
            
            // Marshal, generate (and sign) the enveloped signature
            signature.sign(dsc);
            
            signedAssertion = assertionElement;
            return assertionElement;
        } catch (XWSSecurityException ex) {
            throw new SAMLException(ex);
        } catch (MarshalException ex) {
            throw new SAMLException(ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new SAMLException(ex);
        } catch (SOAPException ex) {
            throw new SAMLException(ex);
        } catch (XMLSignatureException ex) {
            throw new SAMLException(ex);
        } catch (InvalidAlgorithmParameterException ex) {
            throw new SAMLException(ex);
        }
    }
    
    public Element sign(DigestMethod digestMethod, String signatureMethod, X509Certificate cert, PrivateKey privKey) throws SAMLException {
        return sign(digestMethod, signatureMethod, cert, privKey, false);
    }
    
    public Element toElement(Node doc) throws XWSSecurityException {
        if ( signedAssertion == null) {
            signedAssertion = SAMLUtil.toElement(doc, this);
            if (signedAssertion == null ){
                return signedAssertion;
            }
            if ( System.getProperty("com.sun.xml.wss.saml.binding.jaxb") == null) {
                signedAssertion.setAttributeNS(XMLNS_URI, "xmlns:xs", MessageConstants.XSD_NS);
            }
        }
        return signedAssertion;
    }
    
    public boolean isSigned() {
        return signature != null?true:false;
    }
    
    /**
     * This constructor is used to build Assertion object from a
     * block of existing XML that has already been built into a DOM.
     *
     * @param assertionElement A org.w3c.dom.Element representing
     *        DOM tree for Assertion object
     * @exception SAMLException if it could not process the Element properly,
     *            implying that there is an error in the sender or in the
     *            element definition.
     */
    public static Assertion fromElement(org.w3c.dom.Element element)
    throws SAMLException {
        try {
            JAXBContext jc = SAML20JAXBUtil.getJAXBContext();
            
            javax.xml.bind.Unmarshaller u = jc.createUnmarshaller();
            Object el = u.unmarshal(element);
            //return new Assertion((AssertionType)u.unmarshal(element));
            return new Assertion((AssertionType)((JAXBElement)el).getValue());
        } catch ( Exception ex) {
            // log here
            throw new SAMLException(ex);
        }
    }
    
    private void setStatement(List statement) {
        this.statementOrAuthnStatementOrAuthzDecisionStatement = statement;
    }
    
    public String getType() {
        return MessageConstants.SAML_v2_0_NS;
    }
    
    public Object getTokenValue() {
        //TODO: Implement this method
        return null;
    }
    
    /**
     * This constructor is used to populate the data members: the
     * assertionID, the issuer, time when assertion issued,
     * the conditions when creating a new assertion , Advice
     * applicable to this Assertion and a set of
     * Statement(s) in the assertion.
     *
     * @param assertionID AssertionID object contained within this
     *        Assertion if null its generated internally.
     * @param issuer The issuer of this assertion.
     * @param issueInstant Time instant of the issue. It has type
     *        dateTime which is built in to the W3C XML Schema
     *        Types specification. if null, current time is used.
     * @param conditions Conditions under which the this
     *        Assertion is valid.
     * @param advice Advice applicable for this
     *        Assertion.
     * @param statements List of Statement objects within this
     *         Assertion. It could be of type
     *         AuthenticationStatement,
     *         AuthorizationDecisionStatement and
     *         AttributeStatement. Each Assertion can have
     *         multiple type of statements in it.
     * @exception SAMLException if there is an error in processing input.
     */
    public Assertion(
            String assertionID, NameID issuer, GregorianCalendar issueInstant,
            Conditions conditions, Advice advice, Subject subject, List statements)
            throws SAMLException {
        if ( assertionID != null)
            setID(assertionID);
        
        if ( issuer != null)
            setIssuer(issuer);
        
        if ( issueInstant != null) {
            try {
                DatatypeFactory factory = DatatypeFactory.newInstance();
                setIssueInstant(factory.newXMLGregorianCalendar(issueInstant));
            } catch (Exception e) {
                //ignore
            }
        }
        
        if ( conditions != null)
            setConditions(conditions);
        
        if ( advice != null)
            setAdvice(advice);
        
        if ( statements != null)
            setStatement(statements);
        
        if ( subject != null)
            setSubject(subject);
        
        setVersion("2.0");
    }
    
    private static class DSigResolver implements URIDereferencer{
        //TODO : Convert DSigResolver to singleton class.
        Element elem = null;
        Map map = null;
        Class _nodeSetClass = null;
        String optNSClassName = "org.jcp.xml.dsig.internal.dom.DOMSubTreeData";
        Constructor _constructor = null;
        Boolean  _false = Boolean.valueOf(false);
        DSigResolver(Map map,Element elem){
            this.elem = elem;
            this.map = map;
            init();
        }
        
        void init(){
            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){
                
            }
        }
        public Data dereference(URIReference uriRef, XMLCryptoContext context) throws URIReferenceException {
            try{
                String uri = null;
                uri = uriRef.getURI();
                return dereferenceURI(uri,context);
            }catch(Exception ex){
                // log here
                throw new URIReferenceException(ex);
            }
        }
        Data dereferenceURI(String uri, XMLCryptoContext context) throws URIReferenceException{
            if(uri.charAt(0) == '#'){
                uri =  uri.substring(1,uri.length());
                Element el = elem.getOwnerDocument().getElementById(uri);
                if(el == null){
                    el = (Element)map.get(uri);
                }
                
                if(_constructor != null){
                    try{
                        return (Data)_constructor.newInstance(new Object[] {el,_false});
                    }catch(Exception ex){
                        // TODO: igonore this ?
                        ex.printStackTrace();
                    }
                }else{
                    final HashSet nodeSet = new HashSet();
                    toNodeSet(el,nodeSet);
                    return new NodeSetData(){
                        public Iterator iterator(){
                            return nodeSet.iterator();
                        }
                    };
                }
                
            }
            
            return null;
            //throw new URIReferenceException("Resource "+uri+" was not found");
        }
        
        void toNodeSet(final Node rootNode,final Set result){
            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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy