com.sun.xml.wss.saml.AssertionUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webservices-rt Show documentation
Show all versions of webservices-rt Show documentation
This module contains the Metro runtime code.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2018 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://oss.oracle.com/licenses/CDDL+GPL-1.1
* or 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 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.
*/
/*
* AssertionUtil.java
*
* Created on August 18, 2005, 6:40 PM
*
* To change this template, choose Tools | Options and locate the template under
* the Source Creation and Management node. Right-click the template and choose
* Open. You can then make changes to the template in the Source Editor.
*/
package com.sun.xml.wss.saml;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.content.X509Data;
import org.apache.xml.security.keys.content.KeyValue;
import org.apache.xml.security.utils.EncryptionConstants;
import org.apache.xml.security.encryption.EncryptedKey;
import org.apache.xml.security.encryption.XMLCipher;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.saml.internal.saml11.jaxb20.AssertionType;
import java.math.BigInteger;
import java.security.Key;
import java.security.cert.X509Certificate;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.bind.JAXBElement;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.xml.wss.SecurityEnvironment;
import com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl;
import com.sun.xml.wss.core.ReferenceElement;
import com.sun.xml.wss.core.SecurityTokenReference;
import com.sun.xml.wss.core.KeyInfoHeaderBlock;
import com.sun.xml.wss.core.reference.KeyIdentifier;
import com.sun.xml.wss.core.reference.X509IssuerSerial;
import com.sun.xml.wss.logging.LogDomainConstants;
import com.sun.xml.wss.impl.callback.*;
import com.sun.xml.wss.saml.util.SAMLJAXBUtil;
import com.sun.xml.wss.saml.util.SAML20JAXBUtil;
import javax.xml.bind.JAXBContext;
/**
*
* @author [email protected]
*/
public class AssertionUtil {
private static Logger log = Logger.getLogger(LogDomainConstants.WSS_API_DOMAIN, LogDomainConstants.WSS_API_DOMAIN_BUNDLE);
/** Creates a new instance of AssertionUtil */
private AssertionUtil(CallbackHandler callbackHandler) {
//do nothing
}
/**
* Retrive the key from HOK SAML Assertion
*
* @param assertion An org.w3c.dom.Element
representation of SAML Assertion
*
* @param callbackHandler A javax.security.auth.callback.CallbackHandler
object used to retrive the key
*
* @return java.security.Key
* @throws XWSSecurityException
*
*/
public static Key getSubjectConfirmationKey(Element assertion , CallbackHandler callbackHandler) throws XWSSecurityException {
NodeList nl1 = assertion.getElementsByTagName("SubjectConfirmation");
if ( nl1.getLength() == 0) {
throw new XWSSecurityException("SAML Assertion does not contain a key");
}
NodeList nl = ((Element)(nl1.item(0))).getElementsByTagNameNS(MessageConstants.DSIG_NS, "KeyInfo");
if ( nl.getLength() == 0) {
throw new XWSSecurityException("SAML Assertion does not contain a key");
}
try {
Element keyInfoElem = (Element)nl.item(0);
KeyInfo keyInfo = new KeyInfo(keyInfoElem, null);
if (keyInfo.containsKeyValue()) {
return keyInfo.itemKeyValue(0).getPublicKey();
} else if (keyInfo.containsX509Data()) {
return resolveX509Data(keyInfo.itemX509Data(0), callbackHandler);
} else if(keyInfo.length(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_ENCRYPTEDKEY) > 0){
return resolveEncryptedKey(keyInfo.itemEncryptedKey(0), callbackHandler);
}
else {
throw new XWSSecurityException("Unsupported Key Information");
}
} catch (Exception e) {
throw new XWSSecurityException(e);
}
}
public static Key resolveX509Data(X509Data x509Data, CallbackHandler callbackHandler) throws XWSSecurityException {
x509Data.getElement().normalize();
X509Certificate cert = null;
try {
if (x509Data.containsCertificate()) {
cert = (x509Data.itemCertificate(0)).getX509Certificate();
} else if (x509Data.containsSKI()) {
byte[] keyIdentifier = x509Data.itemSKI(0).getSKIBytes();
SignatureVerificationKeyCallback.X509CertificateRequest certRequest =
new SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest(keyIdentifier);
SignatureVerificationKeyCallback verifyKeyCallback = new SignatureVerificationKeyCallback(certRequest);
Callback[] callbacks = new Callback[] {verifyKeyCallback};
try {
callbackHandler.handle(callbacks);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
cert = certRequest.getX509Certificate();
if (cert == null) {
throw new XWSSecurityException("No Matching public key for " + Base64.encode(keyIdentifier) + " subject key identifier found");
}
} else if (x509Data.containsIssuerSerial()) {
String issuerName = x509Data.itemIssuerSerial(0).getIssuerName();
BigInteger serialNumber = x509Data.itemIssuerSerial(0).getSerialNumber();
SignatureVerificationKeyCallback.X509CertificateRequest certRequest =
new SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest(
issuerName,
serialNumber);
SignatureVerificationKeyCallback verifyKeyCallback =
new SignatureVerificationKeyCallback(certRequest);
Callback[] callbacks = new Callback[] {verifyKeyCallback};
try {
callbackHandler.handle(callbacks);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
cert = certRequest.getX509Certificate();
if (cert == null) {
throw new XWSSecurityException(
"No Matching public key for serial number " + serialNumber + " and issuer name " + issuerName + " found");
}
} else {
throw new XWSSecurityException(
"Unsupported child element of X509Data encountered");
}
return cert.getPublicKey();
} catch (Exception e) {
throw new XWSSecurityException(e);
}
}
public static Key resolveEncryptedKey(EncryptedKey encryptedKey, CallbackHandler callbackHandler) throws XWSSecurityException {
//Get the private key to decrypt the encrypted key
KeyInfo keyInfo = encryptedKey.getKeyInfo();
KeyInfoHeaderBlock keyInfoHb = new KeyInfoHeaderBlock(keyInfo);
Key kek = null;
try{
if (keyInfoHb.containsSecurityTokenReference()){
kek = processSecurityTokenReference(keyInfoHb, callbackHandler);
} else if (keyInfoHb.containsKeyValue()) {
SecurityEnvironment secEnv = new DefaultSecurityEnvironmentImpl(callbackHandler);
KeyValue keyValue = keyInfoHb.getKeyValue(0);
keyValue.getElement().normalize();
kek = secEnv.getPrivateKey(null, keyValue.getPublicKey(), false);
} else if (keyInfoHb.containsX509Data()) {
kek = processX509Data(keyInfoHb, callbackHandler);
}
else{
throw new XWSSecurityException("Unsupported Key Information");
}
// Decrypt the encrypted secret key and return
String algorithmURI = encryptedKey.getEncryptionMethod().getAlgorithm();
XMLCipher xmlCipher = XMLCipher.getInstance();
xmlCipher.init(XMLCipher.UNWRAP_MODE, null);
xmlCipher.setKEK(kek);
return xmlCipher.decryptKey(encryptedKey, algorithmURI);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
}
private static Key processSecurityTokenReference(KeyInfoHeaderBlock keyInfo, CallbackHandler callbackHandler)throws XWSSecurityException {
Key returnKey = null;
SecurityEnvironment secEnv = new DefaultSecurityEnvironmentImpl(callbackHandler);
SecurityTokenReference str = keyInfo.getSecurityTokenReference(0);
ReferenceElement refElement = str.getReference();
if (refElement instanceof KeyIdentifier) {
KeyIdentifier keyId = (KeyIdentifier)refElement;
byte[] decodedValue = keyId.getDecodedReferenceValue().getBytes();
if (MessageConstants.X509SubjectKeyIdentifier_NS.equals(keyId.getValueType()) ||
MessageConstants.X509v3SubjectKeyIdentifier_NS.equals(keyId.getValueType())) {
returnKey = secEnv.getPrivateKey(null, decodedValue);
} else if(MessageConstants.ThumbPrintIdentifier_NS.equals(keyId.getValueType())){
throw new XWSSecurityException("Unsupported KeyValueType :" + keyId.getValueType());
}
} /*else if(refElement instanceof DirectReference){
String uri = ((DirectReference) refElement).getURI();
}*/ else if (refElement instanceof X509IssuerSerial) {
BigInteger serialNumber = ((X509IssuerSerial) refElement).getSerialNumber();
String issuerName = ((X509IssuerSerial) refElement).getIssuerName();
returnKey = secEnv.getPrivateKey(null, serialNumber, issuerName);
}else {
log.log(
Level.SEVERE, "WSS0338.unsupported.reference.mechanism");
throw new XWSSecurityException(
"Key reference mechanism not supported");
}
return returnKey;
}
private static Key processX509Data(KeyInfoHeaderBlock keyInfo, CallbackHandler callbackHandler)throws XWSSecurityException {
SecurityEnvironment secEnv = new DefaultSecurityEnvironmentImpl(callbackHandler);
X509Data x509Data = keyInfo.getX509Data(0);
X509Certificate cert = null;
try {
if (x509Data.containsCertificate()) {
cert = (x509Data.itemCertificate(0)).getX509Certificate();
} else if (x509Data.containsSKI()) {
return secEnv.getPrivateKey(null, x509Data.itemSKI(0).getSKIBytes());
} else if (x509Data.containsIssuerSerial()) {
return secEnv.getPrivateKey(null,
x509Data.itemIssuerSerial(0).getSerialNumber(),
x509Data.itemIssuerSerial(0).getIssuerName());
} else {
log.log(Level.SEVERE, "WSS0339.unsupported.keyinfo");
throw new XWSSecurityException(
"Unsupported child element of X509Data encountered");
}
return secEnv.getPrivateKey(null, cert);
} catch (Exception e) {
log.log(Level.SEVERE, "WSS0602.illegal.x509.data", e.getMessage());
throw new XWSSecurityException(e);
}
}
public static Assertion fromElement(org.w3c.dom.Element element)
throws SAMLException {
try {
if (element.getAttributeNode("ID") != null){
JAXBContext jc = SAML20JAXBUtil.getJAXBContext();
javax.xml.bind.Unmarshaller u = jc.createUnmarshaller();
Object el = u.unmarshal(element);
return new com.sun.xml.wss.saml.assertion.saml20.jaxb20.Assertion((com.sun.xml.wss.saml.internal.saml20.jaxb20.AssertionType)((JAXBElement)el).getValue());
}else{
JAXBContext jc = SAMLJAXBUtil.getJAXBContext();
javax.xml.bind.Unmarshaller u = jc.createUnmarshaller();
Object el = u.unmarshal(element);
return new com.sun.xml.wss.saml.assertion.saml11.jaxb20.Assertion((AssertionType)((JAXBElement)el).getValue());
}
} catch ( Exception ex) {
// log here
throw new SAMLException(ex);
}
}
public static String getConfirmationMethod(Element assertion) {
NodeList nl = null;
if (assertion.getAttributeNode("ID") != null){
nl = assertion.getElementsByTagNameNS(MessageConstants.SAML_v2_0_NS, "SubjectConfirmation");
}else{
nl = assertion.getElementsByTagNameNS(MessageConstants.SAML_v1_0_NS, "ConfirmationMethod");
}
if ( nl.getLength() == 0)
return null;
Element confirmationMethod = (Element)nl.item(0);
try {
if (assertion.getAttributeNode("ID") != null){
return confirmationMethod.getAttribute("Method");
}else{
return confirmationMethod.getTextContent();
}
} catch (DOMException ex) {
//ignore
return null;
}
}
private static NodeList skipAdviceValidation(Element assertion, NodeList nodeList){
boolean keyPresent = false;
int returnNodeIndex = 0;
for (int i = 0; i < nodeList.getLength(); i++){
if(nodeList.item(i).getParentNode().getParentNode().getParentNode().getParentNode().getLocalName().equals("Advice")){
// skip this node
}else{
keyPresent = true;
returnNodeIndex = i;
break;
}
}
if(keyPresent){
return ((Element)nodeList.item(returnNodeIndex)).getElementsByTagNameNS(MessageConstants.DSIG_NS, "KeyInfo");
}else{
return null;
}
}
public static Element getSubjectConfirmationKeyInfo(Element assertion)
throws XWSSecurityException {
try {
NodeList nl = null;
NodeList nl1 = null;
if (assertion.getAttributeNode("ID") != null){
nl1 = assertion.getElementsByTagNameNS(MessageConstants.SAML_v2_0_NS, "SubjectConfirmationData");
}else{
nl1 = assertion.getElementsByTagNameNS(MessageConstants.SAML_v1_0_NS, "SubjectConfirmation");
}
if ( nl1.getLength() == 0) {
throw new XWSSecurityException("SAML Assertion does not contain a key");
}
nl = skipAdviceValidation(assertion, nl1);
if ( nl == null || nl.getLength() == 0) {
throw new XWSSecurityException("SAML Assertion does not contain a key");
}
//NodeList nl = assertion.getElementsByTagNameNS(MessageConstants.DSIG_NS, "KeyInfo");
if ( nl.getLength() != 0) {
Element keyInfo = (Element)nl.item(0);
if(keyInfo != null){
return keyInfo;
}
}
} catch (Exception e) {
throw new XWSSecurityException(e);
}
throw new XWSSecurityException(
"Unable to locate KeyInfo inside SubjectConfirmation of SAML Assertion");
}
}