-
Notifications
You must be signed in to change notification settings - Fork 401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
See #294 Support Alg Deprecated rejection. #295
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -282,7 +282,7 @@ onelogin.saml2.idp.x509cert = | |
# let the toolkit know which Algorithm was used. Possible values: sha1, sha256, sha384 or sha512 | ||
# 'sha1' is the default value. | ||
# onelogin.saml2.idp.certfingerprint = | ||
# onelogin.saml2.idp.certfingerprint_algorithm = sha1 | ||
# onelogin.saml2.idp.certfingerprint_algorithm = sha256 | ||
|
||
# Security settings | ||
# | ||
|
@@ -342,7 +342,18 @@ onelogin.saml2.security.want_xml_validation = true | |
# 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' | ||
# 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384' | ||
# 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512' | ||
onelogin.saml2.security.signature_algorithm = http://www.w3.org/2000/09/xmldsig#rsa-sha1 | ||
onelogin.saml2.security.signature_algorithm = http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 | ||
|
||
# Algorithm that the toolkit will use on digest process. Options: | ||
# 'http://www.w3.org/2000/09/xmldsig#sha1' | ||
# 'http://www.w3.org/2001/04/xmlenc#sha256' | ||
# 'http://www.w3.org/2001/04/xmldsig-more#sha384' | ||
# 'http://www.w3.org/2001/04/xmlenc#sha512' | ||
onelogin.saml2.security.digest_algorithm = http://www.w3.org/2001/04/xmlenc#sha256 | ||
|
||
|
||
# Reject Signatures with deprecated algorithms (sha1) | ||
onelogin.saml2.security.reject_deprecated_alg = true | ||
|
||
# Organization | ||
onelogin.saml2.organization.name = SP Java | ||
|
@@ -362,6 +373,7 @@ onelogin.saml2.contacts.support.email_address = [email protected] | |
# onelogin.saml2.unique_id_prefix = _ | ||
``` | ||
|
||
|
||
##### KeyStores | ||
|
||
The Auth constructor supports the ability to read SP public cert/private key from a KeyStore. A KeyStoreSettings object must be provided with the KeyStore, the Alias and the KeyEntry password. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -456,6 +456,17 @@ public Boolean isValid() throws Exception { | |
if (signAlg == null || signAlg.isEmpty()) { | ||
signAlg = Constants.RSA_SHA1; | ||
} | ||
|
||
if (signAlg.equals(Constants.RSA_SHA1)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok |
||
Boolean rejectDeprecatedAlg = settings.getRejectDeprecatedAlg(); | ||
if (rejectDeprecatedAlg) { | ||
LOGGER.error("A deprecated algorithm (RSA_SHA1) found in the Signature element, rejecting it"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it can be confusing that there are 2 kinds of rejections, the other being: if (!isAlgorithmWhitelisted(sigMethodAlg)){
throw new Exception(sigMethodAlg + " is not a valid supported algorithm");
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Supported by the toolkit vs Acceptable |
||
return false; | ||
} else { | ||
LOGGER.info("RSA_SHA1 alg found in a Signature element, consider request a more robust alg"); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe hide/share the common logic inside an utility method: if (Util.mustRejectDeprecatedSignatureAlgo(signAlg, settings.getRejectDeprecatedAlg())
return false; private static final Set<String> DEPRECATED_ALGOS = new HashSet<>(Arrays.asList(
Constants.RSA_SHA1, Constants.DSA_SHA1));
public boolean mustRejectDeprecatedSignatureAlgo(String signAlg, boolean rejectDeprecatedAlg) {
if (DEPRECATED_ALGOS.contains(signAlg) {
boolean rejectDeprecatedAlg = settings.getRejectDeprecatedAlg();
if (rejectDeprecatedAlg) {
LOGGER.error("A deprecated algorithm (xxx_SHA1) found in the Signature element, rejecting it");
return true; // must reject
} else {
LOGGER.info("xxx_SHA1 alg found in a Signature element, consider request a more robust alg");
return false; // can continue
}
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good |
||
|
||
String relayState = request.getEncodedParameter("RelayState"); | ||
|
||
String signedQuery = "SAMLRequest=" + request.getEncodedParameter("SAMLRequest"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -923,13 +923,30 @@ public static boolean validateSign(final Document doc, final X509Certificate cer | |
*/ | ||
public static boolean validateSign(final Document doc, final List<X509Certificate> certList, final String fingerprint, | ||
final String alg, final String xpath) { | ||
return validateSign(doc, certList, fingerprint,alg, xpath, false); | ||
} | ||
|
||
/** | ||
* Validate the signature pointed to by the xpath | ||
* | ||
* @param doc The document we should validate | ||
* @param certList The public certificates | ||
* @param fingerprint The fingerprint of the public certificate | ||
* @param alg The signature algorithm method | ||
* @param xpath the xpath of the ds:Signture node to validate | ||
* @param rejectDeprecatedAlg Flag to invalidate or not Signatures with deprecated alg | ||
* | ||
* @return True if the signature exists and is valid, false otherwise. | ||
*/ | ||
public static boolean validateSign(final Document doc, final List<X509Certificate> certList, final String fingerprint, | ||
final String alg, final String xpath, final Boolean rejectDeprecatedAlg) { | ||
try { | ||
final NodeList signatures = query(doc, xpath); | ||
|
||
if (signatures.getLength() == 1) { | ||
final Node signNode = signatures.item(0); | ||
|
||
Map<String,Object> signatureData = getSignatureData(signNode, alg); | ||
Map<String,Object> signatureData = getSignatureData(signNode, alg, rejectDeprecatedAlg); | ||
if (signatureData.isEmpty()) { | ||
return false; | ||
} | ||
|
@@ -984,6 +1001,26 @@ public static boolean validateSign(final Document doc, final List<X509Certificat | |
* @return True if the sign is valid, false otherwise. | ||
*/ | ||
public static Boolean validateMetadataSign(Document doc, X509Certificate cert, String fingerprint, String alg) { | ||
return validateMetadataSign(doc, cert, fingerprint, alg, false); | ||
} | ||
|
||
/** | ||
* Validate signature (Metadata). | ||
* | ||
* @param doc | ||
* The document we should validate | ||
* @param cert | ||
* The public certificate | ||
* @param fingerprint | ||
* The fingerprint of the public certificate | ||
* @param alg | ||
* The signature algorithm method | ||
* @param rejectDeprecatedAlg | ||
* Flag to invalidate or not Signatures with deprecated alg | ||
* | ||
* @return True if the sign is valid, false otherwise. | ||
*/ | ||
public static Boolean validateMetadataSign(Document doc, X509Certificate cert, String fingerprint, String alg, Boolean rejectDeprecatedAlg) { | ||
NodeList signNodesToValidate; | ||
try { | ||
signNodesToValidate = query(doc, "/md:EntitiesDescriptor/ds:Signature"); | ||
|
@@ -999,7 +1036,7 @@ public static Boolean validateMetadataSign(Document doc, X509Certificate cert, S | |
if (signNodesToValidate.getLength() > 0) { | ||
for (int i = 0; i < signNodesToValidate.getLength(); i++) { | ||
Node signNode = signNodesToValidate.item(i); | ||
if (!validateSignNode(signNode, cert, fingerprint, alg)) { | ||
if (!validateSignNode(signNode, cert, fingerprint, alg, rejectDeprecatedAlg)) { | ||
return false; | ||
} | ||
} | ||
|
@@ -1026,6 +1063,26 @@ public static Boolean validateMetadataSign(Document doc, X509Certificate cert, S | |
* @return True if the sign is valid, false otherwise. | ||
*/ | ||
private static Map<String,Object> getSignatureData(Node signNode, String alg) { | ||
return getSignatureData(signNode, alg, false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a bit risky to have an implicit rejectDeprecatedAlg=false no? (the safer flag There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't set it true, I need to maintain backward compatibility. But notice that in the settings file I added the rejection of deprecated alg as default. |
||
} | ||
|
||
/** | ||
* Validate signature (Metadata). | ||
* | ||
* @param doc | ||
* The document we should validate | ||
* @param cert | ||
* The public certificate | ||
* @param fingerprint | ||
* The fingerprint of the public certificate | ||
* @param alg | ||
* The signature algorithm method | ||
* @param rejectDeprecatedAlg | ||
* Flag to invalidate or not Signatures with deprecated alg | ||
* | ||
* @return True if the sign is valid, false otherwise. | ||
*/ | ||
private static Map<String,Object> getSignatureData(Node signNode, String alg, Boolean rejectDeprecatedAlg) { | ||
Map<String,Object> signatureData = new HashMap<>(); | ||
try { | ||
Element sigElement = (Element) signNode; | ||
|
@@ -1036,6 +1093,15 @@ private static Map<String,Object> getSignatureData(Node signNode, String alg) { | |
throw new Exception(sigMethodAlg + " is not a valid supported algorithm"); | ||
} | ||
|
||
if (sigMethodAlg.equals(Constants.RSA_SHA1)) { | ||
if (rejectDeprecatedAlg) { | ||
LOGGER.error("A deprecated algorithm (RSA_SHA1) found in the Signature element, rejecting it"); | ||
return signatureData; | ||
} else { | ||
LOGGER.info("RSA_SHA1 alg found in a Signature element, consider request a more robust alg"); | ||
} | ||
} | ||
|
||
signatureData.put("signature", signature); | ||
|
||
String extractedFingerprint = null; | ||
|
@@ -1073,7 +1139,29 @@ private static Map<String,Object> getSignatureData(Node signNode, String alg) { | |
* @throws Exception | ||
*/ | ||
public static Boolean validateSignNode(Node signNode, X509Certificate cert, String fingerprint, String alg) { | ||
Map<String,Object> signatureData = getSignatureData(signNode, alg); | ||
return validateSignNode(signNode, cert, fingerprint, alg, false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see other comment about forced flag |
||
} | ||
|
||
/** | ||
* Validate signature of the Node. | ||
* | ||
* @param signNode | ||
* The document we should validate | ||
* @param cert | ||
* The public certificate | ||
* @param fingerprint | ||
* The fingerprint of the public certificate | ||
* @param alg | ||
* The signature algorithm method | ||
* @param rejectDeprecatedAlg | ||
* Flag to invalidate or not Signatures with deprecated alg | ||
* | ||
* @return True if the sign is valid, false otherwise. | ||
* | ||
* @throws Exception | ||
*/ | ||
public static Boolean validateSignNode(Node signNode, X509Certificate cert, String fingerprint, String alg, Boolean rejectDeprecatedAlg) { | ||
Map<String,Object> signatureData = getSignatureData(signNode, alg, rejectDeprecatedAlg); | ||
if (signatureData.isEmpty()) { | ||
return false; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect an unboxed, non-nullable (primitive) bool here