8242060: Add revocation checking to jarsigner

Reviewed-by: mullan, weijun
This commit is contained in:
Hai-May Chao 2020-05-07 10:48:06 +08:00
parent 0ef6d1dff5
commit 76507eef63
7 changed files with 185 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,6 +33,7 @@ import javax.security.auth.x500.X500Principal;
import java.util.*;
import sun.security.util.Debug;
import sun.security.util.Event;
import sun.security.validator.Validator;
import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.*;
@ -246,6 +247,8 @@ public class DistributionPointFetcher {
if (debug != null) {
debug.println("Trying to fetch CRL from DP " + uri);
}
Event.report("event.crl.check", uri.toString());
CertStore ucs = null;
try {
ucs = URICertStore.getInstance(new URICertStoreParameters(uri));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -45,6 +45,7 @@ import java.util.Map;
import sun.security.action.GetIntegerAction;
import sun.security.util.Debug;
import sun.security.util.Event;
import sun.security.validator.Validator;
import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension;
@ -232,6 +233,8 @@ public final class OCSP {
if (debug != null) {
debug.println("connecting to OCSP service at: " + url);
}
Event.report("event.ocsp.check", url.toString());
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setConnectTimeout(CONNECT_TIMEOUT);
con.setReadTimeout(CONNECT_TIMEOUT);

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.security.util;
/**
* This class implements an event model with services for reporter and listener.
* Reporter uses report() method to generate an event.
* Listener uses setReportListener() to register for listening to an event,
* and uses clearReportListener() to unregister a listening session.
* Listener should implement the event handling of the Reporter interface.
*/
public final class Event {
private Event() {}
public interface Reporter {
public void handle(String type, Object... args);
}
private static Reporter reporter;
public static void setReportListener(Reporter re) {
reporter = re;
}
public static void clearReportListener() {
reporter = null;
}
public static void report(String type, Object... args) {
Reporter currentReporter = reporter;
if (currentReporter != null) {
currentReporter.handle(type, args);
}
}
}

View File

@ -158,6 +158,7 @@ public class Main {
boolean signManifest = true; // "sign" the whole manifest
boolean externalSF = true; // leave the .SF out of the PKCS7 block
boolean strict = false; // treat warnings as error
boolean revocationCheck = false; // Revocation check flag
// read zip entry raw bytes
private String altSignerClass = null;
@ -293,6 +294,7 @@ public class Main {
Arrays.fill(storepass, ' ');
storepass = null;
}
Event.clearReportListener();
}
if (strict) {
@ -484,6 +486,8 @@ public class Main {
// -help: legacy.
collator.compare(flags, "-help") == 0) {
fullusage();
} else if (collator.compare(flags, "-revCheck") == 0) {
revocationCheck = true;
} else {
System.err.println(
rb.getString("Illegal.option.") + flags);
@ -626,6 +630,9 @@ public class Main {
System.out.println(rb.getString
(".certs.display.certificates.when.verbose.and.verifying"));
System.out.println();
System.out.println(rb.getString
(".certs.revocation.check"));
System.out.println();
System.out.println(rb.getString
(".tsa.url.location.of.the.Timestamping.Authority"));
System.out.println();
@ -2053,7 +2060,13 @@ public class Main {
.map(c -> new TrustAnchor(c, null))
.collect(Collectors.toSet()),
null);
pkixParameters.setRevocationEnabled(false);
if (revocationCheck) {
Security.setProperty("ocsp.enable", "true");
System.setProperty("com.sun.security.enableCRLDP", "true");
Event.setReportListener((t, o) -> System.out.println(String.format(rb.getString(t), o)));
}
pkixParameters.setRevocationEnabled(revocationCheck);
} catch (InvalidAlgorithmParameterException ex) {
// Only if tas is empty
}

View File

@ -83,6 +83,8 @@ public class Resources extends java.util.ListResourceBundle {
" suboptions can be all, grouped or summary"},
{".certs.display.certificates.when.verbose.and.verifying",
"[-certs] display certificates when verbose and verifying"},
{".certs.revocation.check",
"[-revCheck] Enable certificate revocation check"},
{".tsa.url.location.of.the.Timestamping.Authority",
"[-tsa <url>] location of the Timestamping Authority"},
{".tsacert.alias.public.key.certificate.for.Timestamping.Authority",
@ -310,6 +312,8 @@ public class Resources extends java.util.ListResourceBundle {
{"Cannot.find.environment.variable.",
"Cannot find environment variable: "},
{"Cannot.find.file.", "Cannot find file: "},
{"event.ocsp.check", "Contacting OCSP server at %s ..."},
{"event.crl.check", "Downloading CRL from %s ..."},
};
/**

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8242060
* @summary Add a test to enable revocation check in jarsigner
* @library /test/lib
*/
import jdk.test.lib.SecurityTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.util.JarUtils;
import java.nio.file.Path;
public class EnableRevocation {
static OutputAnalyzer kt(String cmd, String ks) throws Exception {
return SecurityTools.keytool("-storepass changeit " + cmd +
" -keystore " + ks);
}
static void gencert(String owner, String cmd) throws Exception {
kt("-certreq -alias " + owner + " -file tmp.req", "ks");
kt("-gencert -infile tmp.req -outfile tmp.cert " + cmd, "ks");
kt("-importcert -alias " + owner + " -file tmp.cert", "ks");
}
public static void main(String[] args) throws Exception {
kt("-genkeypair -keyalg rsa -alias ca -dname CN=CA -ext bc:c", "ks");
kt("-genkeypair -keyalg rsa -alias ca1 -dname CN=CA1", "ks");
kt("-genkeypair -keyalg rsa -alias e1 -dname CN=E1", "ks");
gencert("ca1", "-alias ca -ext san=dns:ca1 -ext bc:c " +
"-ext crldp=URI:http://localhost:7000/crl.pem " +
"-ext aia=ocsp:URI:http://localhost:7200");
gencert("e1", "-alias ca1 -ext san=dns:e1 " +
"-ext crldp=URI:http://localhost:7000/crl.pem " +
"-ext aia=ocsp:URI:http://localhost:7100");
JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("ks"));
//Signing with -revCheck option
SecurityTools.jarsigner("-keystore ks -storepass changeit " +
"-signedjar signeda.jar " +
"-sigalg SHA256withRSA " +
" a.jar e1 -revCheck")
.shouldContain("Contacting OCSP server at")
.shouldContain("Downloading CRL from")
.shouldHaveExitValue(0);
kt("-exportcert -alias ca -rfc -file cacert", "ks");
kt("-importcert -noprompt -file cacert", "caks");
// Verifying with -revCheck option
SecurityTools.jarsigner("-verify -certs signeda.jar " +
"-keystore caks -storepass changeit -verbose -debug -revCheck")
.shouldContain("Contacting OCSP server at")
.shouldContain("Downloading CRL from")
.shouldHaveExitValue(0);
// Verifying with -revCheck and -strict options
SecurityTools.jarsigner("-verify -certs signeda.jar " +
"-keystore caks -storepass changeit " +
"-strict -verbose -debug -revCheck")
.shouldContain("Contacting OCSP server at")
.shouldContain("Downloading CRL from")
.shouldHaveExitValue(4);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -74,6 +74,9 @@ public class Usages {
static Pattern RB_GETSTRING = Pattern.compile(
"(?m)rb[ \\n]*\\.getString[ \\n]*\\([ \\n]*\"(.*?)\"\\)");
static Pattern EVENT_OCSP_CRL = Pattern.compile(
"Event\\.report\\(\"(.*?)\",");
// Command and Option enums in keytool
static Pattern KT_ENUM = Pattern.compile("\\n +[A-Z]+\\(.*\"(.*)\"");
@ -116,6 +119,10 @@ public class Usages {
new sun.security.tools.jarsigner.Resources(), List.of(
new Pair("jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java",
List.of(RB_GETSTRING)),
new Pair("java.base/share/classes/sun/security/provider/certpath/OCSP.java",
List.of(EVENT_OCSP_CRL)),
new Pair("java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java",
List.of(EVENT_OCSP_CRL)),
new Pair("java.base/share/classes/sun/security/tools/KeyStoreUtil.java",
List.of(RB_GETSTRING))),
new sun.security.util.Resources(), List.of(