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;