src/share/classes/sun/security/tools/jarsigner/Main.java
Print this page
*** 51,60 ****
--- 51,63 ----
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.util.Map.Entry;
+ import sun.security.pkcs.PKCS7;
+ import sun.security.pkcs.SignerInfo;
+ import sun.security.timestamp.TimestampToken;
import sun.security.tools.KeyStoreUtil;
import sun.security.tools.PathList;
import sun.security.x509.*;
import sun.security.util.*;
import java.util.Base64;
*** 95,104 ****
--- 98,116 ----
private static final String NONE = "NONE";
private static final String P11KEYSTORE = "PKCS11";
private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
+ private static final DisabledAlgorithmConstraints DISABLED_CHECK =
+ new DisabledAlgorithmConstraints(
+ DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
+
+ private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections
+ .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
+ private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
+ .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
+
// Attention:
// This is the entry that get launched by the security tool jarsigner.
public static void main(String args[]) throws Exception {
Main js = new Main();
js.run(args);
*** 170,179 ****
--- 182,193 ----
private boolean hasUnsignedEntry = false;
private boolean badKeyUsage = false;
private boolean badExtendedKeyUsage = false;
private boolean badNetscapeCertType = false;
+ private boolean seeWeak = false;
+
CertificateFactory certificateFactory;
CertPathValidator validator;
PKIXParameters pkixParameters;
public void run(String args[]) {
*** 575,584 ****
--- 589,602 ----
void verifyJar(String jarName)
throws Exception
{
boolean anySigned = false; // if there exists entry inside jar signed
JarFile jf = null;
+ Map<String,String> digestMap = new HashMap<>();
+ Map<String,PKCS7> sigMap = new HashMap<>();
+ Map<String,String> sigNameMap = new HashMap<>();
+ Map<String,String> unparsableSignatures = new HashMap<>();
try {
jf = new JarFile(jarName, true);
Vector<JarEntry> entriesVec = new Vector<>();
byte[] buffer = new byte[8192];
*** 585,605 ****
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
entriesVec.addElement(je);
! InputStream is = null;
try {
! is = jf.getInputStream(je);
! int n;
! while ((n = is.read(buffer, 0, buffer.length)) != -1) {
// we just read. this will throw a SecurityException
// if a signature/digest check fails.
}
- } finally {
- if (is != null) {
- is.close();
}
}
}
Manifest man = jf.getManifest();
--- 603,650 ----
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
entriesVec.addElement(je);
! try (InputStream is = jf.getInputStream(je)) {
! String name = je.getName();
! if (signatureRelated(name)
! && SignatureFileVerifier.isBlockOrSF(name)) {
! String alias = name.substring(name.lastIndexOf('/') + 1,
! name.lastIndexOf('.'));
try {
! if (name.endsWith(".SF")) {
! Manifest sf = new Manifest(is);
! boolean found = false;
! for (Object obj : sf.getMainAttributes().keySet()) {
! String key = obj.toString();
! if (key.endsWith("-Digest-Manifest")) {
! digestMap.put(alias,
! key.substring(0, key.length() - 16));
! found = true;
! break;
! }
! }
! if (!found) {
! unparsableSignatures.putIfAbsent(alias,
! String.format(
! rb.getString("history.unparsable"),
! name));
! }
! } else {
! sigNameMap.put(alias, name);
! sigMap.put(alias, new PKCS7(is));
! }
! } catch (IOException ioe) {
! unparsableSignatures.putIfAbsent(alias, String.format(
! rb.getString("history.unparsable"), name));
! }
! } else {
! while (is.read(buffer, 0, buffer.length) != -1) {
// we just read. this will throw a SecurityException
// if a signature/digest check fails.
}
}
}
}
Manifest man = jf.getManifest();
*** 754,770 ****
".i.at.least.one.certificate.was.found.in.identity.scope"));
if (ckaliases.size() > 0) {
System.out.println(rb.getString(
".X.not.signed.by.specified.alias.es."));
}
- System.out.println();
}
! if (man == null)
System.out.println(rb.getString("no.manifest."));
if (!anySigned) {
! if (hasSignature) {
System.out.println(rb.getString("jar.treated.unsigned"));
} else {
System.out.println(rb.getString("jar.is.unsigned"));
}
} else {
--- 799,908 ----
".i.at.least.one.certificate.was.found.in.identity.scope"));
if (ckaliases.size() > 0) {
System.out.println(rb.getString(
".X.not.signed.by.specified.alias.es."));
}
}
! if (man == null) {
! System.out.println();
System.out.println(rb.getString("no.manifest."));
+ }
+ // Even if the verbose option is not specified, all out strings
+ // must be generated so seeWeak can be updated.
+ if (!digestMap.isEmpty()
+ || !sigMap.isEmpty()
+ || !unparsableSignatures.isEmpty()) {
+ if (verbose != null) {
+ System.out.println();
+ }
+ for (String s : sigMap.keySet()) {
+ if (!digestMap.containsKey(s)) {
+ unparsableSignatures.putIfAbsent(s, String.format(
+ rb.getString("history.nosf"), s));
+ }
+ }
+ for (String s : digestMap.keySet()) {
+ PKCS7 p7 = sigMap.get(s);
+ if (p7 != null) {
+ String history;
+ try {
+ SignerInfo si = p7.getSignerInfos()[0];
+ X509Certificate signer = si.getCertificate(p7);
+ String digestAlg = digestMap.get(s);
+ String sigAlg = AlgorithmId.makeSigAlg(
+ si.getDigestAlgorithmId().getName(),
+ si.getDigestEncryptionAlgorithmId().getName());
+ PublicKey key = signer.getPublicKey();
+ PKCS7 tsToken = si.getTsToken();
+ if (tsToken != null) {
+ SignerInfo tsSi = tsToken.getSignerInfos()[0];
+ X509Certificate tsSigner = tsSi.getCertificate(tsToken);
+ byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
+ TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
+ PublicKey tsKey = tsSigner.getPublicKey();
+ String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName();
+ String tsSigAlg = AlgorithmId.makeSigAlg(
+ tsSi.getDigestAlgorithmId().getName(),
+ tsSi.getDigestEncryptionAlgorithmId().getName());
+ Calendar c = Calendar.getInstance(
+ TimeZone.getTimeZone("UTC"),
+ Locale.getDefault(Locale.Category.FORMAT));
+ c.setTime(tsTokenInfo.getDate());
+ history = String.format(
+ rb.getString("history.with.ts"),
+ signer.getSubjectX500Principal(),
+ withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(sigAlg, SIG_PRIMITIVE_SET),
+ withWeak(key),
+ c,
+ tsSigner.getSubjectX500Principal(),
+ withWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(tsSigAlg, SIG_PRIMITIVE_SET),
+ withWeak(tsKey));
+ } else {
+ history = String.format(
+ rb.getString("history.without.ts"),
+ signer.getSubjectX500Principal(),
+ withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(sigAlg, SIG_PRIMITIVE_SET),
+ withWeak(key));
+ }
+ } catch (Exception e) {
+ // The only usage of sigNameMap, remember the name
+ // of the block file if it's invalid.
+ history = String.format(
+ rb.getString("history.unparsable"),
+ sigNameMap.get(s));
+ }
+ if (verbose != null) {
+ System.out.println(history);
+ }
+ } else {
+ unparsableSignatures.putIfAbsent(s, String.format(
+ rb.getString("history.nobk"), s));
+ }
+ }
+ if (verbose != null) {
+ for (String s : unparsableSignatures.keySet()) {
+ System.out.println(unparsableSignatures.get(s));
+ }
+ }
+ }
+ System.out.println();
+
if (!anySigned) {
! if (seeWeak) {
! if (verbose != null) {
! System.out.println(rb.getString("jar.treated.unsigned.see.weak.verbose"));
! System.out.println("\n " +
! DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS +
! "=" + Security.getProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS));
! } else {
! System.out.println(rb.getString("jar.treated.unsigned.see.weak"));
! }
! } else if (hasSignature) {
System.out.println(rb.getString("jar.treated.unsigned"));
} else {
System.out.println(rb.getString("jar.is.unsigned"));
}
} else {
*** 867,876 ****
--- 1005,1034 ----
}
System.exit(1);
}
+ private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
+ if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
+ return alg;
+ } else {
+ seeWeak = true;
+ return String.format(rb.getString("with.weak"), alg);
+ }
+ }
+
+ private String withWeak(PublicKey key) {
+ if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
+ return String.format(
+ rb.getString("key.bit"), KeyUtil.getKeySize(key));
+ } else {
+ seeWeak = true;
+ return String.format(
+ rb.getString("key.bit.weak"), KeyUtil.getKeySize(key));
+ }
+ }
+
private static MessageFormat validityTimeForm = null;
private static MessageFormat notYetTimeForm = null;
private static MessageFormat expiredTimeForm = null;
private static MessageFormat expiringTimeForm = null;