in ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java [755:900]
protected void verifyTrust(
X509Certificate[] certs,
boolean enableRevocation,
Collection<Pattern> subjectCertConstraints
) throws WSSecurityException {
//
// FIRST step - Search the keystore for the transmitted certificate
//
if (certs.length == 1 && !enableRevocation) {
String issuerString = certs[0].getIssuerX500Principal().getName();
BigInteger issuerSerial = certs[0].getSerialNumber();
CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ISSUER_SERIAL);
cryptoType.setIssuerSerial(issuerString, issuerSerial);
X509Certificate[] foundCerts = getX509Certificates(cryptoType);
//
// If a certificate has been found, the certificates must be compared
// to ensure against phony DNs (compare encoded form including signature)
//
if (foundCerts != null && foundCerts.length > 0 && foundCerts[0] != null && foundCerts[0].equals(certs[0])) {
try {
certs[0].checkValidity();
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILED_CHECK, e, "invalidCert"
);
}
LOG.debug(
"Direct trust for certificate with {}", certs[0].getSubjectX500Principal().getName()
);
return;
}
}
//
// SECOND step - Search for the issuer cert (chain) of the transmitted certificate in the
// keystore or the truststore
//
List<Certificate[]> foundIssuingCertChains = null;
String issuerString = certs[0].getIssuerX500Principal().getName();
if (certs.length == 1) {
Object subject = convertSubjectToPrincipal(issuerString);
if (keystore != null) {
foundIssuingCertChains = getCertificates(subject, keystore, false);
}
//If we can't find the issuer in the keystore then look at the truststore
if ((foundIssuingCertChains == null || foundIssuingCertChains.isEmpty()) && truststore != null) {
foundIssuingCertChains = getCertificates(subject, truststore, true);
}
if (foundIssuingCertChains == null || foundIssuingCertChains.isEmpty()
|| foundIssuingCertChains.get(0).length < 1) {
String subjectString = certs[0].getSubjectX500Principal().getName();
LOG.debug(
"No certs found in keystore for issuer {} of certificate for {}",
issuerString, subjectString
);
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILURE, "certpath", new Object[] {"No trusted certs found"}
);
}
}
//
// THIRD step
// Check the certificate trust path for the issuer cert chain
//
LOG.debug(
"Preparing to validate certificate path for issuer {}", issuerString
);
try {
Set<TrustAnchor> set = new HashSet<>();
if (truststore != null) {
addTrustAnchors(set, truststore);
}
//
// Add certificates from the keystore - only if there is no TrustStore, apart from
// the case that the truststore is the JDK CA certs. This behaviour is preserved
// for backwards compatibility reasons
//
if (keystore != null && (truststore == null || loadCACerts)) {
addTrustAnchors(set, keystore);
}
// Verify the trust path using the above settings
String provider = getCryptoProvider();
CertPathValidator validator = null;
if (provider == null || provider.length() == 0) {
validator = CertPathValidator.getInstance("PKIX");
} else {
validator = CertPathValidator.getInstance("PKIX", provider);
}
PKIXParameters param = createPKIXParameters(set, enableRevocation);
// Generate cert path
if (foundIssuingCertChains != null && !foundIssuingCertChains.isEmpty()) {
java.security.cert.CertPathValidatorException validatorException = null;
// Try each potential issuing cert path for a match
for (Certificate[] foundCertChain : foundIssuingCertChains) {
X509Certificate[] x509certs = new X509Certificate[foundCertChain.length + 1];
x509certs[0] = certs[0];
System.arraycopy(foundCertChain, 0, x509certs, 1, foundCertChain.length);
List<X509Certificate> certList = Arrays.asList(x509certs);
CertPath path = getCertificateFactory().generateCertPath(certList);
try {
validator.validate(path, param);
// We have a valid cert path at this point so break
validatorException = null;
break;
} catch (java.security.cert.CertPathValidatorException e) {
validatorException = e;
}
}
if (validatorException != null) {
throw validatorException;
}
} else {
List<X509Certificate> certList = Arrays.asList(certs);
CertPath path = getCertificateFactory().generateCertPath(certList);
validator.validate(path, param);
}
} catch (NoSuchProviderException | NoSuchAlgorithmException
| CertificateException | InvalidAlgorithmParameterException
| java.security.cert.CertPathValidatorException
| KeyStoreException e) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILURE, e, "certpath"
);
}
// Finally check Cert Constraints
if (!matchesSubjectDnPattern(certs[0], subjectCertConstraints)) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
}