提交 1e0e3cde 编写于 作者: W weijun

8024302: Clarify jar verifications

8023338: Update jarsigner to encourage timestamping
Reviewed-by: mullan, ahgross
上级 6accbed2
...@@ -158,8 +158,13 @@ public class Main { ...@@ -158,8 +158,13 @@ public class Main {
private String altSignerClasspath = null; private String altSignerClasspath = null;
private ZipFile zipFile = null; private ZipFile zipFile = null;
private boolean hasExpiredCert = false; // Informational warnings
private boolean hasExpiringCert = false; private boolean hasExpiringCert = false;
private boolean noTimestamp = false;
private Date expireDate = new Date(0L); // used in noTimestamp warning
// Severe warnings
private boolean hasExpiredCert = false;
private boolean notYetValidCert = false; private boolean notYetValidCert = false;
private boolean chainNotValidated = false; private boolean chainNotValidated = false;
private boolean notSignedByAlias = false; private boolean notSignedByAlias = false;
...@@ -258,9 +263,6 @@ public class Main { ...@@ -258,9 +263,6 @@ public class Main {
if (strict) { if (strict) {
int exitCode = 0; int exitCode = 0;
if (hasExpiringCert) {
exitCode |= 2;
}
if (chainNotValidated || hasExpiredCert || notYetValidCert) { if (chainNotValidated || hasExpiredCert || notYetValidCert) {
exitCode |= 4; exitCode |= 4;
} }
...@@ -754,14 +756,25 @@ public class Main { ...@@ -754,14 +756,25 @@ public class Main {
System.out.println(rb.getString( System.out.println(rb.getString(
"jar.is.unsigned.signatures.missing.or.not.parsable.")); "jar.is.unsigned.signatures.missing.or.not.parsable."));
} else { } else {
System.out.println(rb.getString("jar.verified.")); boolean warningAppeared = false;
if (hasUnsignedEntry || hasExpiredCert || hasExpiringCert || boolean errorAppeared = false;
badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
notYetValidCert || chainNotValidated || notYetValidCert || chainNotValidated || hasExpiredCert ||
aliasNotInStore || notSignedByAlias) { hasUnsignedEntry ||
aliasNotInStore || notSignedByAlias) {
if (strict) {
System.out.println(rb.getString("jar.verified.with.signer.errors."));
System.out.println();
System.out.println(rb.getString("Error."));
errorAppeared = true;
} else {
System.out.println(rb.getString("jar.verified."));
System.out.println();
System.out.println(rb.getString("Warning."));
warningAppeared = true;
}
System.out.println();
System.out.println(rb.getString("Warning."));
if (badKeyUsage) { if (badKeyUsage) {
System.out.println( System.out.println(
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
...@@ -785,10 +798,6 @@ public class Main { ...@@ -785,10 +798,6 @@ public class Main {
System.out.println(rb.getString( System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.has.expired.")); "This.jar.contains.entries.whose.signer.certificate.has.expired."));
} }
if (hasExpiringCert) {
System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
}
if (notYetValidCert) { if (notYetValidCert) {
System.out.println(rb.getString( System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.")); "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
...@@ -807,10 +816,29 @@ public class Main { ...@@ -807,10 +816,29 @@ public class Main {
if (aliasNotInStore) { if (aliasNotInStore) {
System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.")); System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
} }
} else {
System.out.println(rb.getString("jar.verified."));
}
if (hasExpiringCert || noTimestamp) {
if (!warningAppeared) {
System.out.println();
System.out.println(rb.getString("Warning."));
warningAppeared = true;
}
if (hasExpiringCert) {
System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
}
if (noTimestamp) {
System.out.println(
String.format(rb.getString("no.timestamp.verifying"), expireDate));
}
}
if (warningAppeared || errorAppeared) {
if (! (verbose != null && showcerts)) { if (! (verbose != null && showcerts)) {
System.out.println(); System.out.println();
System.out.println(rb.getString( System.out.println(rb.getString(
"Re.run.with.the.verbose.and.certs.options.for.more.details.")); "Re.run.with.the.verbose.and.certs.options.for.more.details."));
} }
} }
} }
...@@ -870,6 +898,9 @@ public class Main { ...@@ -870,6 +898,9 @@ public class Main {
try { try {
boolean printValidity = true; boolean printValidity = true;
if (timestamp == null) { if (timestamp == null) {
if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
expireDate = notAfter;
}
x509Cert.checkValidity(); x509Cert.checkValidity();
// test if cert will expire within six months // test if cert will expire within six months
if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) { if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
...@@ -1233,6 +1264,10 @@ public class Main { ...@@ -1233,6 +1264,10 @@ public class Main {
tsaCert = getTsaCert(tsaAlias); tsaCert = getTsaCert(tsaAlias);
} }
if (tsaUrl == null && tsaCert == null) {
noTimestamp = true;
}
SignatureFile.Block block = null; SignatureFile.Block block = null;
try { try {
...@@ -1380,12 +1415,20 @@ public class Main { ...@@ -1380,12 +1415,20 @@ public class Main {
} }
} }
if (hasExpiredCert || hasExpiringCert || notYetValidCert boolean warningAppeared = false;
|| badKeyUsage || badExtendedKeyUsage if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
|| badNetscapeCertType || chainNotValidated) { notYetValidCert || chainNotValidated || hasExpiredCert) {
System.out.println(); if (strict) {
System.out.println(rb.getString("jar.signed.with.signer.errors."));
System.out.println();
System.out.println(rb.getString("Error."));
} else {
System.out.println(rb.getString("jar.signed."));
System.out.println();
System.out.println(rb.getString("Warning."));
warningAppeared = true;
}
System.out.println(rb.getString("Warning."));
if (badKeyUsage) { if (badKeyUsage) {
System.out.println( System.out.println(
rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
...@@ -1404,9 +1447,6 @@ public class Main { ...@@ -1404,9 +1447,6 @@ public class Main {
if (hasExpiredCert) { if (hasExpiredCert) {
System.out.println( System.out.println(
rb.getString("The.signer.certificate.has.expired.")); rb.getString("The.signer.certificate.has.expired."));
} else if (hasExpiringCert) {
System.out.println(
rb.getString("The.signer.certificate.will.expire.within.six.months."));
} else if (notYetValidCert) { } else if (notYetValidCert) {
System.out.println( System.out.println(
rb.getString("The.signer.certificate.is.not.yet.valid.")); rb.getString("The.signer.certificate.is.not.yet.valid."));
...@@ -1416,6 +1456,24 @@ public class Main { ...@@ -1416,6 +1456,24 @@ public class Main {
System.out.println( System.out.println(
rb.getString("The.signer.s.certificate.chain.is.not.validated.")); rb.getString("The.signer.s.certificate.chain.is.not.validated."));
} }
} else {
System.out.println(rb.getString("jar.signed."));
}
if (hasExpiringCert || noTimestamp) {
if (!warningAppeared) {
System.out.println();
System.out.println(rb.getString("Warning."));
}
if (hasExpiringCert) {
System.out.println(
rb.getString("The.signer.certificate.will.expire.within.six.months."));
}
if (noTimestamp) {
System.out.println(
String.format(rb.getString("no.timestamp.signing"), expireDate));
}
} }
// no IOException thrown in the above try clause, so disable // no IOException thrown in the above try clause, so disable
...@@ -1502,6 +1560,7 @@ public class Main { ...@@ -1502,6 +1560,7 @@ public class Main {
timestamp = ts.getTimestamp(); timestamp = ts.getTimestamp();
} else { } else {
timestamp = null; timestamp = null;
noTimestamp = true;
} }
// display the certificate(s). The first one is end-entity cert and // display the certificate(s). The first one is end-entity cert and
// its KeyUsage should be checked. // its KeyUsage should be checked.
......
...@@ -135,7 +135,10 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -135,7 +135,10 @@ public class Resources extends java.util.ListResourceBundle {
{".Unsigned.entries.", "(Unsigned entries)"}, {".Unsigned.entries.", "(Unsigned entries)"},
{"jar.is.unsigned.signatures.missing.or.not.parsable.", {"jar.is.unsigned.signatures.missing.or.not.parsable.",
"jar is unsigned. (signatures missing or not parsable)"}, "jar is unsigned. (signatures missing or not parsable)"},
{"jar.signed.", "jar signed."},
{"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
{"jar.verified.", "jar verified."}, {"jar.verified.", "jar verified."},
{"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
{"jarsigner.", "jarsigner: "}, {"jarsigner.", "jarsigner: "},
{"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
"signature filename must consist of the following characters: A-Z, 0-9, _ or -"}, "signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
...@@ -193,6 +196,7 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -193,6 +196,7 @@ public class Resources extends java.util.ListResourceBundle {
"using an alternative signing mechanism"}, "using an alternative signing mechanism"},
{"entry.was.signed.on", "entry was signed on {0}"}, {"entry.was.signed.on", "entry was signed on {0}"},
{"Warning.", "Warning: "}, {"Warning.", "Warning: "},
{"Error.", "Error: "},
{"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
"This jar contains unsigned entries which have not been integrity-checked. "}, "This jar contains unsigned entries which have not been integrity-checked. "},
{"This.jar.contains.entries.whose.signer.certificate.has.expired.", {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
...@@ -229,6 +233,10 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -229,6 +233,10 @@ public class Resources extends java.util.ListResourceBundle {
"The signer's certificate chain is not validated."}, "The signer's certificate chain is not validated."},
{"This.jar.contains.entries.whose.certificate.chain.is.not.validated.", {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
"This jar contains entries whose certificate chain is not validated."}, "This jar contains entries whose certificate chain is not validated."},
{"no.timestamp.signing",
"No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
{"no.timestamp.verifying",
"This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
{"Unknown.password.type.", "Unknown password type: "}, {"Unknown.password.type.", "Unknown password type: "},
{"Cannot.find.environment.variable.", {"Cannot.find.environment.variable.",
"Cannot find environment variable: "}, "Cannot find environment variable: "},
......
...@@ -239,13 +239,13 @@ public class TimestampCheck { ...@@ -239,13 +239,13 @@ public class TimestampCheck {
" -J-Djava.security.egd=file:/dev/./urandom" + " -J-Djava.security.egd=file:/dev/./urandom" +
" -debug -keystore " + TSKS + " -storepass changeit" + " -debug -keystore " + TSKS + " -storepass changeit" +
" -tsa http://localhost:" + port + "/%d" + " -tsa http://localhost:" + port + "/%d" +
" -signedjar new.jar " + JAR + " old"; " -signedjar new_%d.jar " + JAR + " old";
} else { } else {
cmd = System.getProperty("java.home") + "/bin/jarsigner" + cmd = System.getProperty("java.home") + "/bin/jarsigner" +
" -J-Djava.security.egd=file:/dev/./urandom" + " -J-Djava.security.egd=file:/dev/./urandom" +
" -debug -keystore " + TSKS + " -storepass changeit" + " -debug -keystore " + TSKS + " -storepass changeit" +
" -tsa http://localhost:" + port + "/%d" + " -tsa http://localhost:" + port + "/%d" +
" -signedjar new.jar " + JAR + " old"; " -signedjar new_%d.jar " + JAR + " old";
} }
try { try {
...@@ -280,7 +280,7 @@ public class TimestampCheck { ...@@ -280,7 +280,7 @@ public class TimestampCheck {
static void jarsigner(String cmd, int path, boolean expected) static void jarsigner(String cmd, int path, boolean expected)
throws Exception { throws Exception {
System.err.println("Test " + path); System.err.println("Test " + path);
Process p = Runtime.getRuntime().exec(String.format(cmd, path)); Process p = Runtime.getRuntime().exec(String.format(cmd, path, path));
BufferedReader reader = new BufferedReader( BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getErrorStream())); new InputStreamReader(p.getErrorStream()));
while (true) { while (true) {
...@@ -288,9 +288,25 @@ public class TimestampCheck { ...@@ -288,9 +288,25 @@ public class TimestampCheck {
if (s == null) break; if (s == null) break;
System.err.println(s); System.err.println(s);
} }
// Will not see noTimestamp warning
boolean seeWarning = false;
reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while (true) {
String s = reader.readLine();
if (s == null) break;
System.err.println(s);
if (s.indexOf("Warning:") >= 0) {
seeWarning = true;
}
}
int result = p.waitFor(); int result = p.waitFor();
if (expected && result != 0 || !expected && result == 0) { if (expected && result != 0 || !expected && result == 0) {
throw new Exception("Failed"); throw new Exception("Failed");
} }
if (seeWarning) {
throw new Exception("See warning");
}
} }
} }
...@@ -139,7 +139,6 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l` ...@@ -139,7 +139,6 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l`
# 16 and 32 already covered in the first part # 16 and 32 already covered in the first part
# ========================================================== # ==========================================================
$KT -genkeypair -alias expiring -dname CN=expiring -startdate -1m
$KT -genkeypair -alias expired -dname CN=expired -startdate -10m $KT -genkeypair -alias expired -dname CN=expired -startdate -10m
$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m $KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m
$KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365 $KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365
...@@ -154,9 +153,6 @@ $KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \ ...@@ -154,9 +153,6 @@ $KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \
$KT -importcert -alias badchain $KT -importcert -alias badchain
$KT -delete -alias ca $KT -delete -alias ca
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expiring
[ $? = 2 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired $JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
# #
# @test # @test
# @bug 6543842 6543440 6939248 8009636 # @bug 6543842 6543440 6939248 8009636 8024302
# @summary checking response of timestamp # @summary checking response of timestamp
# #
# @run shell/timeout=600 ts.sh # @run shell/timeout=600 ts.sh
...@@ -53,7 +53,7 @@ fi ...@@ -53,7 +53,7 @@ fi
JAR="${TESTJAVA}${FS}bin${FS}jar" JAR="${TESTJAVA}${FS}bin${FS}jar"
JAVA="${TESTJAVA}${FS}bin${FS}java" JAVA="${TESTJAVA}${FS}bin${FS}java"
JAVAC="${TESTJAVA}${FS}bin${FS}javac" JAVAC="${TESTJAVA}${FS}bin${FS}javac"
KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit" KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -validity 200"
rm tsks rm tsks
echo Nothing > A echo Nothing > A
......
#
# Copyright (c) 2013, 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 8024302
# @summary Clarify jar verifications
#
if [ "${TESTJAVA}" = "" ] ; then
JAVAC_CMD=`which javac`
TESTJAVA=`dirname $JAVAC_CMD`/..
fi
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
Windows_* )
FS="\\"
;;
* )
FS="/"
;;
esac
KS=warnings.jks
JFILE=warnings.jar
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \
-keystore $KS"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit"
rm $KS 2> /dev/null
export LANG=C
echo 12345 > file
ERR=""
# Normal signer expiring on 2100-01-01
$KT -alias s1 -dname CN=s1 -genkey -startdate 2000/01/01 -validity 36525 || ERR="$ERR keytool s1,"
# Cert expiring soon, informational warning
$KT -alias s2 -dname CN=s2 -genkey -validity 100 || ERR="$ERR keytool s2,"
# Cert expired, severe warning
$KT -alias s3 -dname CN=s3 -genkey -startdate -200d -validity 100 || ERR="$ERR keytool s3,"
# noTimestamp is informatiional warning and includes a date
$JAR cvf $JFILE file
$JARSIGNER $JFILE s1 > output1 || ERR="$ERR jarsigner s1,"
$JARSIGNER -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict,"
$JARSIGNER -verify $JFILE s1 >> output1 || ERR="$ERR jarsigner s1,"
$JARSIGNER -verify -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict,"
cat output1 | grep Warning || ERR="$ERR s1 warning,"
cat output1 | grep Error && ERR="$ERR s1 error,"
cat output1 | grep timestamp | grep 2100-01-01 || ERR="$ERR s1 timestamp,"
cat output1 | grep "with signer errors" && ERR="$ERR s1 err,"
# hasExpiringCert is informatiional warning
$JAR cvf $JFILE file
$JARSIGNER $JFILE s2 > output2 || ERR="$ERR jarsigner s2,"
$JARSIGNER -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict,"
$JARSIGNER -verify $JFILE s2 >> output2 || ERR="$ERR jarsigner s2,"
$JARSIGNER -verify -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict,"
cat output2 | grep Warning || ERR="$ERR s2 warning,"
cat output2 | grep Error && ERR="$ERR s2 error,"
cat output2 | grep timestamp || ERR="$ERR s2 timestamp,"
cat output2 | grep "will expire" || ERR="$ERR s2 expiring,"
cat output2 | grep "with signer errors" && ERR="$ERR s2 err,"
# hasExpiredCert is severe warning
$JAR cvf $JFILE file
$JARSIGNER $JFILE s3 > output3 || ERR="$ERR jarsigner s3,"
$JARSIGNER -strict $JFILE s3 > output3s && ERR="$ERR jarsigner s3 strict,"
$JARSIGNER -verify $JFILE s3 >> output3 || ERR="$ERR jarsigner s3,"
$JARSIGNER -verify -strict $JFILE s3 >> output3s && ERR="$ERR jarsigner s3 strict,"
# warning without -strict
cat output3 | grep Warning || ERR="$ERR s3 warning,"
cat output3 | grep Error && ERR="$ERR s3 error,"
cat output3 | grep "with signer errors" && ERR="$ERR s3 err,"
# error with -strict
cat output3s | grep Warning || ERR="$ERR s3s warning,"
cat output3s | grep Error || ERR="$ERR s3s error,"
cat output3s | grep "with signer errors" || ERR="$ERR s3 err,"
if [ "$ERR" = "" ]; then
exit 0
else
echo "ERR is $ERR"
exit 1
fi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册