You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2015/12/21 16:10:18 UTC
cxf git commit: Default to default identifier if no keyInfo is
available
Repository: cxf
Updated Branches:
refs/heads/master eeaf5a5fa -> 165d769c6
Default to default identifier if no keyInfo is available
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/165d769c
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/165d769c
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/165d769c
Branch: refs/heads/master
Commit: 165d769c681163393cf68201f7d83f0f3119d319
Parents: eeaf5a5
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Dec 21 15:05:18 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Dec 21 15:05:18 2015 +0000
----------------------------------------------------------------------
.../saml/sso/SAMLProtocolResponseValidator.java | 132 ++++++++++---------
1 file changed, 72 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/165d769c/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
index d085a6e..4c084f8 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
@@ -70,27 +70,27 @@ import org.opensaml.xmlsec.signature.support.SignatureValidator;
/**
* Validate a SAML (1.1 or 2.0) Protocol Response. It validates the Response against the specs,
- * the signature of the Response (if it exists), and any internal Assertion stored in the Response
+ * the signature of the Response (if it exists), and any internal Assertion stored in the Response
* - including any signature. It validates the status code of the Response as well.
*/
public class SAMLProtocolResponseValidator {
-
- public static final String SAML2_STATUSCODE_SUCCESS =
+
+ public static final String SAML2_STATUSCODE_SUCCESS =
"urn:oasis:names:tc:SAML:2.0:status:Success";
public static final String SAML1_STATUSCODE_SUCCESS = "Success";
-
+
private static final Logger LOG = LogUtils.getL7dLogger(SAMLProtocolResponseValidator.class);
-
+
private Validator assertionValidator = new SamlAssertionValidator();
private Validator signatureValidator = new SignatureTrustValidator();
private boolean keyInfoMustBeAvailable = true;
-
+
/**
- * The time in seconds in the future within which the NotBefore time of an incoming
+ * The time in seconds in the future within which the NotBefore time of an incoming
* Assertion is valid. The default is 60 seconds.
*/
private int futureTTL = 60;
-
+
/**
* Validate a SAML 2 Protocol Response
* @param samlResponse
@@ -116,7 +116,7 @@ public class SAMLProtocolResponseValidator {
);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
if (samlResponse.getIssueInstant() != null) {
DateTime currentTime = new DateTime();
currentTime = currentTime.plusSeconds(futureTTL);
@@ -125,7 +125,7 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
if (SAMLVersion.VERSION_20 != samlResponse.getVersion()) {
LOG.fine(
"SAML Version of " + samlResponse.getVersion()
@@ -133,16 +133,16 @@ public class SAMLProtocolResponseValidator {
);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
validateResponseSignature(samlResponse, sigCrypto, callbackHandler);
Document doc = samlResponse.getDOM().getOwnerDocument();
// Decrypt any encrypted Assertions and add them to the Response (note that this will break any
// signature on the Response)
for (org.opensaml.saml.saml2.core.EncryptedAssertion assertion : samlResponse.getEncryptedAssertions()) {
-
+
Element decAssertion = decryptAssertion(assertion, sigCrypto, callbackHandler);
-
+
SamlAssertionWrapper wrapper = new SamlAssertionWrapper(decAssertion);
samlResponse.getAssertions().add(wrapper.getSaml2());
}
@@ -153,7 +153,7 @@ public class SAMLProtocolResponseValidator {
validateAssertion(wrapper, sigCrypto, callbackHandler, doc);
}
}
-
+
/**
* Validate a SAML 1.1 Protocol Response
* @param samlResponse
@@ -190,7 +190,7 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
if (SAMLVersion.VERSION_11 != samlResponse.getVersion()) {
LOG.fine(
"SAML Version of " + samlResponse.getVersion()
@@ -198,7 +198,7 @@ public class SAMLProtocolResponseValidator {
);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
validateResponseSignature(samlResponse, sigCrypto, callbackHandler);
// Validate Assertions
@@ -209,7 +209,7 @@ public class SAMLProtocolResponseValidator {
);
}
}
-
+
/**
* Validate the Response signature (if it exists)
*/
@@ -221,13 +221,13 @@ public class SAMLProtocolResponseValidator {
if (!samlResponse.isSigned()) {
return;
}
-
+
validateResponseSignature(
samlResponse.getSignature(), samlResponse.getDOM().getOwnerDocument(),
sigCrypto, callbackHandler
);
}
-
+
/**
* Validate the Response signature (if it exists)
*/
@@ -239,18 +239,18 @@ public class SAMLProtocolResponseValidator {
if (!samlResponse.isSigned()) {
return;
}
-
+
validateResponseSignature(
samlResponse.getSignature(), samlResponse.getDOM().getOwnerDocument(),
sigCrypto, callbackHandler
);
}
-
+
/**
* Validate the response signature
*/
private void validateResponseSignature(
- Signature signature,
+ Signature signature,
Document doc,
Crypto sigCrypto,
CallbackHandler callbackHandler
@@ -260,13 +260,13 @@ public class SAMLProtocolResponseValidator {
WSSConfig wssConfig = WSSConfig.getNewInstance();
requestData.setWssConfig(wssConfig);
requestData.setCallbackHandler(callbackHandler);
-
+
SAMLKeyInfo samlKeyInfo = null;
-
+
KeyInfo keyInfo = signature.getKeyInfo();
if (keyInfo != null) {
try {
- samlKeyInfo =
+ samlKeyInfo =
SAMLUtil.getCredentialFromKeyInfo(
keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(requestData, new WSDocInfo(doc)), sigCrypto
);
@@ -281,7 +281,7 @@ public class SAMLProtocolResponseValidator {
LOG.fine("No KeyInfo supplied in the SAMLResponse signature");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
// Validate Signature against profiles
validateSignatureAgainstProfiles(signature, samlKeyInfo);
@@ -297,10 +297,10 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
protected SAMLKeyInfo createKeyInfoFromDefaultAlias(Crypto sigCrypto) throws WSSecurityException {
try {
- X509Certificate[] certs = RSSecurityUtils.getCertificates(sigCrypto,
+ X509Certificate[] certs = RSSecurityUtils.getCertificates(sigCrypto,
sigCrypto.getDefaultX509Identifier());
SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(new X509Certificate[]{certs[0]});
samlKeyInfo.setPublicKey(certs[0].getPublicKey());
@@ -310,12 +310,12 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, ex);
}
}
-
+
/**
* Validate a signature against the profiles
*/
private void validateSignatureAgainstProfiles(
- Signature signature,
+ Signature signature,
SAMLKeyInfo samlKeyInfo
) throws WSSecurityException {
// Validate Signature against profiles
@@ -343,7 +343,7 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
/**
* Validate an internal Assertion
*/
@@ -355,27 +355,27 @@ public class SAMLProtocolResponseValidator {
) throws WSSecurityException {
Credential credential = new Credential();
credential.setSamlAssertion(assertion);
-
+
RequestData requestData = new RequestData();
requestData.setSigVerCrypto(sigCrypto);
WSSConfig wssConfig = WSSConfig.getNewInstance();
requestData.setWssConfig(wssConfig);
requestData.setCallbackHandler(callbackHandler);
-
+
if (assertion.isSigned()) {
if (assertion.getSaml1() != null) {
assertion.getSaml1().getDOM().setIdAttributeNS(null, "AssertionID", true);
} else {
assertion.getSaml2().getDOM().setIdAttributeNS(null, "ID", true);
}
-
+
// Verify the signature
try {
Signature sig = assertion.getSignature();
WSDocInfo docInfo = new WSDocInfo(sig.getDOM().getOwnerDocument());
-
+
SAMLKeyInfo samlKeyInfo = null;
-
+
KeyInfo keyInfo = sig.getKeyInfo();
if (keyInfo != null) {
samlKeyInfo = SAMLUtil.getCredentialFromKeyInfo(
@@ -389,12 +389,12 @@ public class SAMLProtocolResponseValidator {
LOG.fine("No KeyInfo supplied in the SAMLResponse assertion signature");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
assertion.verifySignature(samlKeyInfo);
-
+
assertion.parseSubject(
new WSSSAMLKeyInfoProcessor(requestData, new WSDocInfo(doc)),
- requestData.getSigVerCrypto(),
+ requestData.getSigVerCrypto(),
requestData.getCallbackHandler()
);
} catch (WSSecurityException e) {
@@ -402,7 +402,7 @@ public class SAMLProtocolResponseValidator {
throw e;
}
}
-
+
// Validate the Assertion & verify trust in the signature
try {
assertionValidator.validate(credential, requestData);
@@ -411,13 +411,13 @@ public class SAMLProtocolResponseValidator {
throw ex;
}
}
-
+
private Element decryptAssertion(
org.opensaml.saml.saml2.core.EncryptedAssertion assertion, Crypto sigCrypto, CallbackHandler callbackHandler
) throws WSSecurityException {
EncryptedData encryptedData = assertion.getEncryptedData();
Element encryptedDataDOM = encryptedData.getDOM();
-
+
Element encKeyElement = getNode(assertion.getDOM(), WSS4JConstants.ENC_NS, "EncryptedKey", 0);
if (encKeyElement == null) {
encKeyElement = getNode(encryptedDataDOM, WSS4JConstants.ENC_NS, "EncryptedKey", 0);
@@ -426,17 +426,17 @@ public class SAMLProtocolResponseValidator {
LOG.log(Level.FINE, "EncryptedKey element is not available");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
X509Certificate cert = loadCertificate(sigCrypto, encKeyElement);
if (cert == null) {
LOG.fine("X509Certificate cannot be retrieved from EncryptedKey element");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
// now start decrypting
String keyEncAlgo = getEncodingMethodAlgorithm(encKeyElement);
String digestAlgo = getDigestMethodAlgorithm(encKeyElement);
-
+
Element cipherValue = getNode(encKeyElement, WSS4JConstants.ENC_NS, "CipherValue", 0);
if (cipherValue == null) {
LOG.fine("CipherValue element is not available");
@@ -447,7 +447,7 @@ public class SAMLProtocolResponseValidator {
LOG.fine("A CallbackHandler must be configured to decrypt encrypted Assertions");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
PrivateKey key = null;
try {
key = sigCrypto.getPrivateKey(cert, callbackHandler);
@@ -455,7 +455,7 @@ public class SAMLProtocolResponseValidator {
LOG.log(Level.FINE, "Encrypted key can not be decrypted", ex);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
- Cipher cipher =
+ Cipher cipher =
EncryptionUtils.initCipherWithKey(keyEncAlgo, digestAlgo, Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = null;
try {
@@ -468,9 +468,9 @@ public class SAMLProtocolResponseValidator {
LOG.log(Level.FINE, "Encrypted key can not be decrypted", ex);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
String symKeyAlgo = getEncodingMethodAlgorithm(encryptedDataDOM);
-
+
byte[] decryptedPayload = null;
try {
decryptedPayload = decryptPayload(encryptedDataDOM, decryptedBytes, symKeyAlgo);
@@ -478,7 +478,7 @@ public class SAMLProtocolResponseValidator {
LOG.log(Level.FINE, "Payload can not be decrypted", ex);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
Document payloadDoc = null;
try {
payloadDoc = StaxUtils.read(new InputStreamReader(new ByteArrayInputStream(decryptedPayload),
@@ -489,18 +489,18 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
private Element getNode(Element parent, String ns, String name, int index) {
NodeList list = parent.getElementsByTagNameNS(ns, name);
if (list != null && list.getLength() >= index + 1) {
return (Element)list.item(index);
- }
+ }
return null;
}
private X509Certificate loadCertificate(Crypto crypto, Element encKeyElement) throws WSSecurityException {
- Element certNode =
+ Element certNode =
getNode(encKeyElement, Constants.SignatureSpecNS, "X509Certificate", 0);
if (certNode != null) {
try {
@@ -510,7 +510,7 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
certNode = getNode(encKeyElement, Constants.SignatureSpecNS, "X509IssuerSerial", 0);
if (certNode != null) {
try {
@@ -521,9 +521,21 @@ public class SAMLProtocolResponseValidator {
}
}
+ if (crypto.getDefaultX509Identifier() != null) {
+ try {
+ X509Certificate[] certs =
+ RSSecurityUtils.getCertificates(crypto, crypto.getDefaultX509Identifier());
+ if (certs.length > 0) {
+ return certs[0];
+ }
+ } catch (Exception ex) {
+ LOG.log(Level.FINE, "X509Certificate can not be created", ex);
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+ }
+ }
return null;
}
-
+
private String getEncodingMethodAlgorithm(Element parent) throws WSSecurityException {
Element encMethod = getNode(parent, WSS4JConstants.ENC_NS, "EncryptionMethod", 0);
if (encMethod == null) {
@@ -532,7 +544,7 @@ public class SAMLProtocolResponseValidator {
}
return encMethod.getAttribute("Algorithm");
}
-
+
private String getDigestMethodAlgorithm(Element parent) {
Element encMethod = getNode(parent, WSS4JConstants.ENC_NS, "EncryptionMethod", 0);
if (encMethod != null) {
@@ -543,14 +555,14 @@ public class SAMLProtocolResponseValidator {
}
return null;
}
-
-
+
+
private byte[] decryptPayload(
Element root, byte[] secretKeyBytes, String symEncAlgo
) throws WSSecurityException {
SecretKey key = KeyUtils.prepareSecretKey(symEncAlgo, secretKeyBytes);
try {
- XMLCipher xmlCipher =
+ XMLCipher xmlCipher =
EncryptionUtils.initXMLCipher(symEncAlgo, XMLCipher.DECRYPT_MODE, key);
return xmlCipher.decryptToByteArray(root);
} catch (XMLEncryptionException ex) {
@@ -569,5 +581,5 @@ public class SAMLProtocolResponseValidator {
public void setFutureTTL(int futureTTL) {
this.futureTTL = futureTTL;
}
-
+
}