提交 86ea65ab 编写于 作者: S Stephen Connolly

Make it possible for sub-classes to have a sub-class specific trust anchor chain

上级 4cb7414e
......@@ -218,7 +218,16 @@ public class UpdateSite {
* Verifies the signature in the update center data file.
*/
private FormValidation verifySignature(JSONObject o) throws IOException {
return new JSONSignatureValidator("update site '"+id+"'").verifySignature(o);
return getJsonSignatureValidator().verifySignature(o);
}
/**
* Let sub-classes of UpdateSite provide their own signature validator.
* @return the signature validator.
*/
@Nonnull
protected JSONSignatureValidator getJsonSignatureValidator() {
return new JSONSignatureValidator("update site '"+id+"'");
}
/**
......
......@@ -72,69 +72,7 @@ public class JSONSignatureValidator {
certs.add(c);
}
// 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<TrustAnchor>(); // CertificateUtil.getDefaultRootCAs();
Jenkins j = Jenkins.getInstance();
for (String cert : (Set<String>) 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
}
InputStream in = j.servletContext.getResourceAsStream(cert);
if (in == null) continue; // our test for paths ending in / should prevent this from happening
Certificate certificate;
try {
certificate = cf.generateCertificate(in);
} 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;
} finally {
in.close();
}
try {
anchors.add(new TrustAnchor((X509Certificate) certificate, null));
} 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
}
FileInputStream in = new FileInputStream(cert);
Certificate certificate;
try {
certificate = cf.generateCertificate(in);
} 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;
} finally {
in.close();
}
try {
anchors.add(new TrustAnchor((X509Certificate) certificate, null));
} 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);
}
}
}
CertificateUtil.validatePath(certs, anchors);
CertificateUtil.validatePath(certs, loadTrustAnchors(cf));
}
// this is for computing a digest to check sanity
......@@ -191,5 +129,71 @@ public class JSONSignatureValidator {
}
}
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<TrustAnchor>(); // CertificateUtil.getDefaultRootCAs();
Jenkins j = Jenkins.getInstance();
for (String cert : (Set<String>) 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
}
InputStream in = j.servletContext.getResourceAsStream(cert);
if (in == null) continue; // our test for paths ending in / should prevent this from happening
Certificate certificate;
try {
certificate = cf.generateCertificate(in);
} 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;
} finally {
in.close();
}
try {
anchors.add(new TrustAnchor((X509Certificate) certificate, null));
} 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
}
FileInputStream in = new FileInputStream(cert);
Certificate certificate;
try {
certificate = cf.generateCertificate(in);
} 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;
} finally {
in.close();
}
try {
anchors.add(new TrustAnchor((X509Certificate) certificate, null));
} 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;
}
private static final Logger LOGGER = Logger.getLogger(JSONSignatureValidator.class.getName());
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册