in core/src/main/java/jenkins/util/JSONSignatureValidator.java [245:319]
protected Set<TrustAnchor> loadTrustAnchors(CertificateFactory cf) throws IOException {
// if we trust default root CAs, we end up trusting anyone who has a valid certificate,
// which isn't useful at all
Set<TrustAnchor> anchors = new HashSet<>(); // CertificateUtil.getDefaultRootCAs();
Jenkins j = Jenkins.get();
for (String cert : j.servletContext.getResourcePaths("/WEB-INF/update-center-rootCAs")) {
if (cert.endsWith("/") || cert.endsWith(".txt")) {
continue; // skip directories also any text files that are meant to be documentation
}
Certificate certificate;
try (InputStream in = j.servletContext.getResourceAsStream(cert)) {
if (in == null) continue; // our test for paths ending in / should prevent this from happening
certificate = cf.generateCertificate(in);
if (certificate instanceof X509Certificate) {
X509Certificate c = (X509Certificate) certificate;
LOGGER.log(Level.FINE, "Add CA certificate found in webapp resources:\n\tsubjectDN: {0}\n\tissuer: {1}\n\tnotBefore: {2}\n\tnotAfter: {3}",
new Object[] { c.getSubjectDN(), c.getIssuerDN(), c.getNotBefore(), c.getNotAfter() });
}
LOGGER.log(Level.FINEST, () -> "CA certificate from webapp resource " + cert + ": " + certificate);
} catch (CertificateException e) {
LOGGER.log(Level.WARNING, String.format("Webapp resources in /WEB-INF/update-center-rootCAs are "
+ "expected to be either certificates or .txt files documenting the "
+ "certificates, but %s did not parse as a certificate. Skipping this "
+ "resource for now.",
cert), e);
continue;
}
try {
TrustAnchor certificateAuthority = new TrustAnchor((X509Certificate) certificate, null);
anchors.add(certificateAuthority);
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING,
String.format("The name constraints in the certificate resource %s could not be "
+ "decoded. Skipping this resource for now.",
cert), e);
}
}
File[] cas = new File(j.root, "update-center-rootCAs").listFiles();
if (cas!=null) {
for (File cert : cas) {
if (cert.isDirectory() || cert.getName().endsWith(".txt")) {
continue; // skip directories also any text files that are meant to be documentation
}
Certificate certificate;
try (InputStream in = Files.newInputStream(cert.toPath())) {
certificate = cf.generateCertificate(in);
if (certificate instanceof X509Certificate) {
X509Certificate c = (X509Certificate) certificate;
LOGGER.log(Level.FINE, "Add CA certificate found in Jenkins home:\n\tsubjectDN: {0}\n\tissuer: {1}\n\tnotBefore: {2}\n\tnotAfter: {3}",
new Object[] { c.getSubjectDN(), c.getIssuerDN(), c.getNotBefore(), c.getNotAfter() });
}
LOGGER.log(Level.FINEST, () -> "CA certificate from Jenkins home " + cert + ": " + certificate);
} catch (InvalidPathException e) {
throw new IOException(e);
} catch (CertificateException e) {
LOGGER.log(Level.WARNING, String.format("Files in %s are expected to be either "
+ "certificates or .txt files documenting the certificates, "
+ "but %s did not parse as a certificate. Skipping this file for now.",
cert.getParentFile().getAbsolutePath(),
cert.getAbsolutePath()), e);
continue;
}
try {
TrustAnchor certificateAuthority = new TrustAnchor((X509Certificate) certificate, null);
anchors.add(certificateAuthority);
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING,
String.format("The name constraints in the certificate file %s could not be "
+ "decoded. Skipping this file for now.",
cert.getAbsolutePath()), e);
}
}
}
return anchors;
}