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:28:20 UTC
[2/3] cxf git commit: Default to default identifier if no keyInfo is
available
Default to default identifier if no keyInfo is available
# Conflicts:
# rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/ceda2f55
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/ceda2f55
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/ceda2f55
Branch: refs/heads/3.0.x-fixes
Commit: ceda2f55a441ec39347ecc9b94c089c659dad710
Parents: e173659
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:23:23 2015 +0000
----------------------------------------------------------------------
.../saml/sso/SAMLProtocolResponseValidator.java | 159 +++++++++++++------
1 file changed, 107 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/ceda2f55/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 4e12de9..cea583a 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
@@ -68,27 +68,27 @@ import org.opensaml.xml.validation.ValidatorSuite;
/**
* 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
@@ -114,7 +114,7 @@ public class SAMLProtocolResponseValidator {
);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
-
+
if (samlResponse.getIssueInstant() != null) {
DateTime currentTime = new DateTime();
currentTime = currentTime.plusSeconds(futureTTL);
@@ -123,17 +123,34 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
+<<<<<<< HEAD
validateResponseAgainstSchemas(samlResponse);
+=======
+
+ if (SAMLVersion.VERSION_20 != samlResponse.getVersion()) {
+ LOG.fine(
+ "SAML Version of " + samlResponse.getVersion()
+ + "does not equal " + SAMLVersion.VERSION_20
+ );
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+ }
+
+>>>>>>> 078d14e... Default to default identifier if no keyInfo is available
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)
+<<<<<<< HEAD
for (org.opensaml.saml2.core.EncryptedAssertion assertion : samlResponse.getEncryptedAssertions()) {
+=======
+ for (org.opensaml.saml.saml2.core.EncryptedAssertion assertion : samlResponse.getEncryptedAssertions()) {
+
+>>>>>>> 078d14e... Default to default identifier if no keyInfo is available
Element decAssertion = decryptAssertion(assertion, sigCrypto, callbackHandler);
-
+
SamlAssertionWrapper wrapper = new SamlAssertionWrapper(decAssertion);
samlResponse.getAssertions().add(wrapper.getSaml2());
}
@@ -144,7 +161,7 @@ public class SAMLProtocolResponseValidator {
validateAssertion(wrapper, sigCrypto, callbackHandler, doc);
}
}
-
+
/**
* Validate a SAML 1.1 Protocol Response
* @param samlResponse
@@ -181,8 +198,20 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
+<<<<<<< HEAD
validateResponseAgainstSchemas(samlResponse);
+=======
+
+ if (SAMLVersion.VERSION_11 != samlResponse.getVersion()) {
+ LOG.fine(
+ "SAML Version of " + samlResponse.getVersion()
+ + "does not equal " + SAMLVersion.VERSION_11
+ );
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+ }
+
+>>>>>>> 078d14e... Default to default identifier if no keyInfo is available
validateResponseSignature(samlResponse, sigCrypto, callbackHandler);
// Validate Assertions
@@ -193,7 +222,7 @@ public class SAMLProtocolResponseValidator {
);
}
}
-
+
/**
* Validate the Response against the schemas
*/
@@ -239,13 +268,13 @@ public class SAMLProtocolResponseValidator {
if (!samlResponse.isSigned()) {
return;
}
-
+
validateResponseSignature(
samlResponse.getSignature(), samlResponse.getDOM().getOwnerDocument(),
sigCrypto, callbackHandler
);
}
-
+
/**
* Validate the Response signature (if it exists)
*/
@@ -257,18 +286,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
@@ -278,13 +307,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
);
@@ -299,7 +328,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);
@@ -315,10 +344,14 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
protected SAMLKeyInfo createKeyInfoFromDefaultAlias(Crypto sigCrypto) throws WSSecurityException {
try {
+<<<<<<< HEAD
X509Certificate[] certs = SecurityUtils.getCertificates(sigCrypto,
+=======
+ X509Certificate[] certs = RSSecurityUtils.getCertificates(sigCrypto,
+>>>>>>> 078d14e... Default to default identifier if no keyInfo is available
sigCrypto.getDefaultX509Identifier());
SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(new X509Certificate[]{certs[0]});
samlKeyInfo.setPublicKey(certs[0].getPublicKey());
@@ -328,12 +361,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
@@ -362,7 +395,7 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
/**
* Validate an internal Assertion
*/
@@ -374,27 +407,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(
@@ -408,12 +441,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) {
@@ -421,7 +454,7 @@ public class SAMLProtocolResponseValidator {
throw e;
}
}
-
+
// Validate the Assertion & verify trust in the signature
try {
assertionValidator.validate(credential, requestData);
@@ -430,13 +463,18 @@ public class SAMLProtocolResponseValidator {
throw ex;
}
}
-
+
private Element decryptAssertion(
org.opensaml.saml2.core.EncryptedAssertion assertion, Crypto sigCrypto, CallbackHandler callbackHandler
) throws WSSecurityException {
EncryptedData encryptedData = assertion.getEncryptedData();
Element encryptedDataDOM = encryptedData.getDOM();
+<<<<<<< HEAD
Element encKeyElement = getNode(assertion.getDOM(), WSConstants.ENC_NS, "EncryptedKey", 0);
+=======
+
+ Element encKeyElement = getNode(assertion.getDOM(), WSS4JConstants.ENC_NS, "EncryptedKey", 0);
+>>>>>>> 078d14e... Default to default identifier if no keyInfo is available
if (encKeyElement == null) {
encKeyElement = getNode(encryptedDataDOM, WSConstants.ENC_NS, "EncryptedKey", 0);
}
@@ -444,18 +482,23 @@ 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);
+<<<<<<< HEAD
Element cipherValue = getNode(encKeyElement, WSConstants.ENC_NS, "CipherValue", 0);
+=======
+
+ Element cipherValue = getNode(encKeyElement, WSS4JConstants.ENC_NS, "CipherValue", 0);
+>>>>>>> 078d14e... Default to default identifier if no keyInfo is available
if (cipherValue == null) {
LOG.fine("CipherValue element is not available");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
@@ -465,7 +508,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);
@@ -473,7 +516,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 {
@@ -486,9 +529,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);
@@ -496,7 +539,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),
@@ -507,18 +550,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 {
@@ -528,7 +571,7 @@ public class SAMLProtocolResponseValidator {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
}
-
+
certNode = getNode(encKeyElement, Constants.SignatureSpecNS, "X509IssuerSerial", 0);
if (certNode != null) {
try {
@@ -539,9 +582,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, WSConstants.ENC_NS, "EncryptionMethod", 0);
if (encMethod == null) {
@@ -550,7 +605,7 @@ public class SAMLProtocolResponseValidator {
}
return encMethod.getAttribute("Algorithm");
}
-
+
private String getDigestMethodAlgorithm(Element parent) {
Element encMethod = getNode(parent, WSConstants.ENC_NS, "EncryptionMethod", 0);
if (encMethod != null) {
@@ -561,14 +616,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) {
@@ -587,5 +642,5 @@ public class SAMLProtocolResponseValidator {
public void setFutureTTL(int futureTTL) {
this.futureTTL = futureTTL;
}
-
+
}