Skip to content

Commit 1a0e808

Browse files
committed
Adding more test to #139. Modify how multiple cert support works. Now getIdpx509certMulti only returns the cert registered as Multi following the description that had the method. Add multiCert support on LogoutRequest and LogoutResponse
1 parent d45f471 commit 1a0e808

File tree

11 files changed

+440
-18
lines changed

11 files changed

+440
-18
lines changed

core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,19 +281,30 @@ public boolean isValid(String requestId) {
281281

282282
validateSubjectConfirmation(responseInResponseTo);
283283

284-
if (settings.getWantAssertionsSigned() && !hasSignedAssertion) {
285-
throw new ValidationError("The Assertion of the Response is not signed and the SP requires it", ValidationError.NO_SIGNED_ASSERTION);
286-
}
284+
if (settings.getWantAssertionsSigned() && !hasSignedAssertion) {
285+
throw new ValidationError("The Assertion of the Response is not signed and the SP requires it", ValidationError.NO_SIGNED_ASSERTION);
286+
}
287287

288-
if (settings.getWantMessagesSigned() && !hasSignedResponse) {
289-
throw new ValidationError("The Message of the Response is not signed and the SP requires it", ValidationError.NO_SIGNED_MESSAGE);
290-
}
288+
if (settings.getWantMessagesSigned() && !hasSignedResponse) {
289+
throw new ValidationError("The Message of the Response is not signed and the SP requires it", ValidationError.NO_SIGNED_MESSAGE);
290+
}
291291
}
292292

293293
if (signedElements.isEmpty() || (!hasSignedAssertion && !hasSignedResponse)) {
294294
throw new ValidationError("No Signature found. SAML Response rejected", ValidationError.NO_SIGNATURE_FOUND);
295295
} else {
296-
List<X509Certificate> certList = settings.getIdpx509certMulti();
296+
X509Certificate cert = settings.getIdpx509cert();
297+
List<X509Certificate> certList = new ArrayList<X509Certificate>();
298+
List<X509Certificate> multipleCertList = settings.getIdpx509certMulti();
299+
300+
if (multipleCertList != null && multipleCertList.size() != 0) {
301+
certList = multipleCertList;
302+
}
303+
304+
if (cert != null && !certList.contains(cert)) {
305+
certList.add(0, cert);
306+
}
307+
297308
String fingerprint = settings.getIdpCertFingerprint();
298309
String alg = settings.getIdpCertFingerprintAlgorithm();
299310

core/src/main/java/com/onelogin/saml2/logout/LogoutRequest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,16 @@ public Boolean isValid() throws Exception {
363363
throw new SettingsException("In order to validate the sign on the Logout Request, the x509cert of the IdP is required", SettingsException.CERT_NOT_FOUND);
364364
}
365365

366+
List<X509Certificate> certList = settings.getIdpx509certMulti();
367+
if (certList != null) {
368+
if (!certList.contains(cert)) {
369+
certList.add(0, cert);
370+
}
371+
} else {
372+
certList = new ArrayList<X509Certificate>();
373+
certList.add(cert);
374+
}
375+
366376
String signAlg = request.getParameter("SigAlg");
367377
if (signAlg == null || signAlg.isEmpty()) {
368378
signAlg = Constants.RSA_SHA1;
@@ -377,7 +387,7 @@ public Boolean isValid() throws Exception {
377387

378388
signedQuery += "&SigAlg=" + request.getEncodedParameter("SigAlg", signAlg);
379389

380-
if (!Util.validateBinarySignature(signedQuery, Util.base64decoder(signature), cert, signAlg)) {
390+
if (!Util.validateBinarySignature(signedQuery, Util.base64decoder(signature), certList, signAlg)) {
381391
throw new ValidationError("Signature validation failed. Logout Request rejected", ValidationError.INVALID_SIGNATURE);
382392
}
383393
}

core/src/main/java/com/onelogin/saml2/logout/LogoutResponse.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import java.io.IOException;
44
import java.net.URL;
55
import java.security.cert.X509Certificate;
6+
import java.util.ArrayList;
67
import java.util.Calendar;
78
import java.util.HashMap;
9+
import java.util.List;
810
import java.util.Map;
911
import java.util.Objects;
1012

@@ -231,6 +233,17 @@ public Boolean isValid(String requestId) {
231233
throw new SettingsException("In order to validate the sign on the Logout Response, the x509cert of the IdP is required", SettingsException.CERT_NOT_FOUND);
232234
}
233235

236+
List<X509Certificate> certList = settings.getIdpx509certMulti();
237+
if (certList != null) {
238+
if (!certList.contains(cert)) {
239+
certList.add(0, cert);
240+
}
241+
} else {
242+
certList = new ArrayList<X509Certificate>();
243+
certList.add(cert);
244+
}
245+
246+
234247
String signAlg = request.getParameter("SigAlg");
235248
if (signAlg == null || signAlg.isEmpty()) {
236249
signAlg = Constants.RSA_SHA1;
@@ -245,7 +258,7 @@ public Boolean isValid(String requestId) {
245258

246259
signedQuery += "&SigAlg=" + request.getEncodedParameter("SigAlg", signAlg);
247260

248-
if (!Util.validateBinarySignature(signedQuery, Util.base64decoder(signature), cert, signAlg)) {
261+
if (!Util.validateBinarySignature(signedQuery, Util.base64decoder(signature), certList, signAlg)) {
249262
throw new ValidationError("Signature validation failed. Logout Response rejected", ValidationError.INVALID_SIGNATURE);
250263
}
251264
}

core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ private void loadIdpSetting() {
244244
X509Certificate idpX509cert = loadCertificateFromProp(IDP_X509CERT_PROPERTY_KEY);
245245
if (idpX509cert != null) {
246246
saml2Setting.setIdpx509cert(idpX509cert);
247-
idpX509certMulti.add(0, idpX509cert);
248247
}
249248

250249
String idpCertFingerprint = loadStringProperty(CERTFINGERPRINT_PROPERTY_KEY);

core/src/main/java/com/onelogin/saml2/util/Util.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,47 @@ public static Boolean validateBinarySignature(String signedQuery, byte[] signatu
12191219
return valid;
12201220
}
12211221

1222+
/**
1223+
* Validates signed binary data (Used to validate GET Signature).
1224+
*
1225+
* @param signedQuery
1226+
* The element we should validate
1227+
* @param signature
1228+
* The signature that will be validate
1229+
* @param certList
1230+
* The List of certificates
1231+
* @param signAlg
1232+
* Signature Algorithm
1233+
*
1234+
* @return the signed document in string format
1235+
*
1236+
* @throws NoSuchAlgorithmException
1237+
* @throws NoSuchProviderException
1238+
* @throws InvalidKeyException
1239+
* @throws SignatureException
1240+
*/
1241+
public static Boolean validateBinarySignature(String signedQuery, byte[] signature, List<X509Certificate> certList, String signAlg) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException {
1242+
Boolean valid = false;
1243+
1244+
org.apache.xml.security.Init.init();
1245+
String convertedSigAlg = signatureAlgConversion(signAlg);
1246+
Signature sig = Signature.getInstance(convertedSigAlg); //, provider);
1247+
1248+
for (X509Certificate cert : certList) {
1249+
try {
1250+
sig.initVerify(cert.getPublicKey());
1251+
sig.update(signedQuery.getBytes());
1252+
valid = sig.verify(signature);
1253+
if (valid) {
1254+
break;
1255+
}
1256+
} catch (Exception e) {
1257+
LOGGER.warn("Error executing validateSign: " + e.getMessage(), e);
1258+
}
1259+
}
1260+
return valid;
1261+
}
1262+
12221263
/**
12231264
* Generates a nameID.
12241265
*

0 commit comments

Comments
 (0)