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

org.apache.ws.security.saml.SAMLUtil Maven / Gradle / Ivy

Go to download

The Apache WSS4J project provides a Java implementation of the primary security standards for Web Services, namely the OASIS Web Services Security (WS-Security) specifications from the OASIS Web Services Security TC.

There is a newer version: 1.6.19
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.security.saml;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.processor.EncryptedKeyProcessor;
import org.apache.ws.security.util.Base64;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.content.X509Data;
import org.apache.xml.security.keys.content.x509.XMLX509Certificate;
import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial;
import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLAttributeStatement;
import org.opensaml.SAMLAuthenticationStatement;
import org.opensaml.SAMLException;
import org.opensaml.SAMLObject;
import org.opensaml.SAMLStatement;
import org.opensaml.SAMLSubject;
import org.opensaml.SAMLSubjectStatement;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;

import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.Iterator;

/**
 * Utility methods for SAML stuff
 */
public class SAMLUtil {
    private static Log log = LogFactory.getLog(SAMLUtil.class.getName());

    
    
    /**
     * Extract certificates or the key available in the SAMLAssertion
     * @param elem
     * @return the SAML Key Info
     * @throws WSSecurityException
     */
    public static SAMLKeyInfo getSAMLKeyInfo(Element elem, Crypto crypto,
            CallbackHandler cb) throws WSSecurityException {
        SAMLAssertion assertion;
        try {
            assertion = new SAMLAssertion(elem);
            return getSAMLKeyInfo(assertion, crypto, cb);
        } catch (SAMLException e) {
            throw new WSSecurityException(WSSecurityException.FAILURE,
                    "invalidSAMLToken", new Object[]{"for Signature (cannot parse)"}, e);
        }

    }
    
    public static SAMLKeyInfo getSAMLKeyInfo(SAMLAssertion assertion, Crypto crypto,
            CallbackHandler cb) throws WSSecurityException {
        
        //First ask the cb whether it can provide the secret
        WSPasswordCallback pwcb = new WSPasswordCallback(assertion.getId(), WSPasswordCallback.CUSTOM_TOKEN);
        if (cb != null) {
            try {
                cb.handle(new Callback[]{pwcb});
            } catch (Exception e1) {
                throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
                        new Object[] { assertion.getId() }, e1);
            }
        }
        
        byte[] key = pwcb.getKey();
        
        if (key != null) {
            return new SAMLKeyInfo(assertion, key);
        } else {
            Iterator statements = assertion.getStatements();
            while (statements.hasNext()) {
                SAMLStatement stmt = (SAMLStatement) statements.next();
                if (stmt instanceof SAMLAttributeStatement) {
                    SAMLAttributeStatement attrStmt = (SAMLAttributeStatement) stmt;
                    SAMLSubject samlSubject = attrStmt.getSubject();
                    Element kiElem = samlSubject.getKeyInfo();
                    
                    NodeList children = kiElem.getChildNodes();
                    int len = children.getLength();
                    
                    for (int i = 0; i < len; i++) {
                        Node child = children.item(i);
                        if (child.getNodeType() != Node.ELEMENT_NODE) {
                            continue;
                        }
                        QName el = new QName(child.getNamespaceURI(), child.getLocalName());
                        if (el.equals(WSSecurityEngine.ENCRYPTED_KEY)) {
                            
                            EncryptedKeyProcessor proc = new EncryptedKeyProcessor();
                            proc.handleEncryptedKey((Element)child, cb, crypto, null);
                            
                            return new SAMLKeyInfo(assertion, proc.getDecryptedBytes());
                        } else if (el.equals(new QName(WSConstants.WST_NS, "BinarySecret"))) {
                            Text txt = (Text)child.getFirstChild();
                            return new SAMLKeyInfo(assertion, Base64.decode(txt.getData()));
                        }
                    }

                } else if (stmt instanceof SAMLAuthenticationStatement) {
                    SAMLAuthenticationStatement authStmt = (SAMLAuthenticationStatement)stmt;
                    SAMLSubject samlSubj = authStmt.getSubject(); 
                    if (samlSubj == null) {
                        throw new WSSecurityException(WSSecurityException.FAILURE,
                                "invalidSAMLToken", new Object[]{"for Signature (no Subject)"});
                    }

                    Element e = samlSubj.getKeyInfo();
                    X509Certificate[] certs = null;
                    try {
                        KeyInfo ki = new KeyInfo(e, null);

                        if (ki.containsX509Data()) {
                            X509Data data = ki.itemX509Data(0);
                            if (data != null && data.containsCertificate()) {
                                XMLX509Certificate certElem = data.itemCertificate(0);
                                if (certElem != null) {
                                    X509Certificate cert = certElem.getX509Certificate();
                                    certs = new X509Certificate[1];
                                    certs[0] = cert;
                                    return new SAMLKeyInfo(assertion, certs);
                                }
                            } else if (data != null && data.containsIssuerSerial()) {
                                XMLX509IssuerSerial issuerSerial = data.itemIssuerSerial(0);
                                String alias = 
                                    crypto.getAliasForX509Cert(
                                        issuerSerial.getIssuerName(), issuerSerial.getSerialNumber()
                                    );
                                certs = crypto.getCertificates(alias);
                                return new SAMLKeyInfo(assertion, certs);
                            }
                        } else if (ki.containsKeyValue()) {
                            PublicKey pk = ki.getPublicKey();
                            return new SAMLKeyInfo(assertion, pk);
                        }
                    } catch (XMLSecurityException e3) {
                        throw new WSSecurityException(WSSecurityException.FAILURE,
                                "invalidSAMLsecurity",
                                new Object[]{"cannot get certificate (key holder)"}, e3);
                    }
                    
                } else {
                    throw new WSSecurityException(WSSecurityException.FAILURE,
                            "invalidSAMLsecurity",
                            new Object[]{"cannot get certificate or key "});
                }
            }
            
            throw new WSSecurityException(WSSecurityException.FAILURE,
                    "invalidSAMLsecurity",
                    new Object[]{"cannot get certificate or key "});
                        
        }

    }
    
    /**
     * Extracts the certificate(s) from the SAML token reference.
     * 

* * @param elem The element containing the SAML token. * @return an array of X509 certificates * @throws org.apache.ws.security.WSSecurityException */ public static X509Certificate[] getCertificatesFromSAML(Element elem) throws WSSecurityException { /* * Get some information about the SAML token content. This controls how * to deal with the whole stuff. First get the Authentication statement * (includes Subject), then get the _first_ confirmation method only. */ SAMLAssertion assertion; try { assertion = new SAMLAssertion(elem); } catch (SAMLException e) { throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLToken", new Object[]{"for Signature (cannot parse)"}, e); } SAMLSubjectStatement samlSubjS = null; Iterator it = assertion.getStatements(); while (it.hasNext()) { SAMLObject so = (SAMLObject) it.next(); if (so instanceof SAMLSubjectStatement) { samlSubjS = (SAMLSubjectStatement) so; break; } } SAMLSubject samlSubj = null; if (samlSubjS != null) { samlSubj = samlSubjS.getSubject(); } if (samlSubj == null) { throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLToken", new Object[]{"for Signature (no Subject)"}); } // String confirmMethod = null; // it = samlSubj.getConfirmationMethods(); // if (it.hasNext()) { // confirmMethod = (String) it.next(); // } // boolean senderVouches = false; // if (SAMLSubject.CONF_SENDER_VOUCHES.equals(confirmMethod)) { // senderVouches = true; // } Element e = samlSubj.getKeyInfo(); X509Certificate[] certs = null; try { KeyInfo ki = new KeyInfo(e, null); if (ki.containsX509Data()) { X509Data data = ki.itemX509Data(0); XMLX509Certificate certElem = null; if (data != null && data.containsCertificate()) { certElem = data.itemCertificate(0); } if (certElem != null) { X509Certificate cert = certElem.getX509Certificate(); certs = new X509Certificate[1]; certs[0] = cert; } } // TODO: get alias name for cert, check against username set by caller } catch (XMLSecurityException e3) { throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLsecurity", new Object[]{"cannot get certificate (key holder)"}, e3); } return certs; } public static String getAssertionId(Element envelope, String elemName, String nmSpace) throws WSSecurityException { String id; // Make the AssertionID the wsu:Id and the signature reference the same SAMLAssertion assertion; Element assertionElement = (Element) WSSecurityUtil .findElement(envelope, elemName, nmSpace); try { assertion = new SAMLAssertion(assertionElement); id = assertion.getId(); } catch (Exception e1) { log.error(e1); throw new WSSecurityException( WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e1); } return id; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy