src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
changeset 48893 454518b338b0
parent 48760 25725c11c296
child 53398 dd1be616c95e
equal deleted inserted replaced
48892:034839ee4f4b 48893:454518b338b0
    28 import java.io.*;
    28 import java.io.*;
    29 import java.net.UnknownHostException;
    29 import java.net.UnknownHostException;
    30 import java.security.cert.CertPathValidatorException;
    30 import java.security.cert.CertPathValidatorException;
    31 import java.security.cert.PKIXBuilderParameters;
    31 import java.security.cert.PKIXBuilderParameters;
    32 import java.util.*;
    32 import java.util.*;
       
    33 import java.util.stream.Collectors;
    33 import java.util.zip.*;
    34 import java.util.zip.*;
    34 import java.util.jar.*;
    35 import java.util.jar.*;
    35 import java.net.URI;
    36 import java.net.URI;
    36 import java.text.Collator;
    37 import java.text.Collator;
    37 import java.text.MessageFormat;
    38 import java.text.MessageFormat;
    90 
    91 
    91     private static final String NONE = "NONE";
    92     private static final String NONE = "NONE";
    92     private static final String P11KEYSTORE = "PKCS11";
    93     private static final String P11KEYSTORE = "PKCS11";
    93 
    94 
    94     private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
    95     private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
       
    96     private static final long ONE_YEAR = 366*24*60*60*1000L;
    95 
    97 
    96     private static final DisabledAlgorithmConstraints DISABLED_CHECK =
    98     private static final DisabledAlgorithmConstraints DISABLED_CHECK =
    97             new DisabledAlgorithmConstraints(
    99             new DisabledAlgorithmConstraints(
    98                     DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
   100                     DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
    99 
   101 
   100     private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections
   102     private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections
   101             .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
   103             .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
   102     private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
   104     private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
   103             .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
   105             .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
       
   106 
       
   107     static final String VERSION = "1.0";
       
   108 
       
   109     static final int IN_KEYSTORE = 0x01;        // signer is in keystore
       
   110     static final int NOT_ALIAS = 0x04;          // alias list is NOT empty and
       
   111     // signer is not in alias list
       
   112     static final int SIGNED_BY_ALIAS = 0x08;    // signer is in alias list
   104 
   113 
   105     // Attention:
   114     // Attention:
   106     // This is the entry that get launched by the security tool jarsigner.
   115     // This is the entry that get launched by the security tool jarsigner.
   107     public static void main(String args[]) throws Exception {
   116     public static void main(String args[]) throws Exception {
   108         Main js = new Main();
   117         Main js = new Main();
   109         js.run(args);
   118         js.run(args);
   110     }
   119     }
   111 
       
   112     static final String VERSION = "1.0";
       
   113 
       
   114     static final int IN_KEYSTORE = 0x01;        // signer is in keystore
       
   115     static final int NOT_ALIAS = 0x04;          // alias list is NOT empty and
       
   116                                                 // signer is not in alias list
       
   117     static final int SIGNED_BY_ALIAS = 0x08;    // signer is in alias list
       
   118 
   120 
   119     X509Certificate[] certChain;    // signer's cert chain (when composing)
   121     X509Certificate[] certChain;    // signer's cert chain (when composing)
   120     PrivateKey privateKey;          // private key
   122     PrivateKey privateKey;          // private key
   121     KeyStore store;                 // the keystore specified by -keystore
   123     KeyStore store;                 // the keystore specified by -keystore
   122                                     // or the default keystore, never null
   124                                     // or the default keystore, never null
   158     private String altSignerClasspath = null;
   160     private String altSignerClasspath = null;
   159     private ZipFile zipFile = null;
   161     private ZipFile zipFile = null;
   160 
   162 
   161     // Informational warnings
   163     // Informational warnings
   162     private boolean hasExpiringCert = false;
   164     private boolean hasExpiringCert = false;
   163     private boolean noTimestamp = false;
   165     private boolean hasExpiringTsaCert = false;
   164     private Date expireDate = new Date(0L);     // used in noTimestamp warning
   166     private boolean noTimestamp = true;
       
   167 
       
   168     // Expiration date. The value could be null if signed by a trusted cert.
       
   169     private Date expireDate = null;
       
   170     private Date tsaExpireDate = null;
       
   171 
       
   172     // If there is a time stamp block inside the PKCS7 block file
       
   173     boolean hasTimestampBlock = false;
       
   174 
   165 
   175 
   166     // Severe warnings.
   176     // Severe warnings.
   167 
   177 
   168     // jarsigner used to check signer cert chain validity and key usages
   178     // jarsigner used to check signer cert chain validity and key usages
   169     // itself and set various warnings. Later CertPath validation is
   179     // itself and set various warnings. Later CertPath validation is
   172     // only tsaChainNotValidated is set, i.e. has no affect on hasExpiredCert,
   182     // only tsaChainNotValidated is set, i.e. has no affect on hasExpiredCert,
   173     // notYetValidCert, or any badXyzUsage.
   183     // notYetValidCert, or any badXyzUsage.
   174 
   184 
   175     private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
   185     private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
   176     private boolean hasExpiredCert = false;
   186     private boolean hasExpiredCert = false;
       
   187     private boolean hasExpiredTsaCert = false;
   177     private boolean notYetValidCert = false;
   188     private boolean notYetValidCert = false;
   178     private boolean chainNotValidated = false;
   189     private boolean chainNotValidated = false;
   179     private boolean tsaChainNotValidated = false;
   190     private boolean tsaChainNotValidated = false;
   180     private boolean notSignedByAlias = false;
   191     private boolean notSignedByAlias = false;
   181     private boolean aliasNotInStore = false;
   192     private boolean aliasNotInStore = false;
   189     private Throwable tsaChainNotValidatedReason = null;
   200     private Throwable tsaChainNotValidatedReason = null;
   190 
   201 
   191     private boolean seeWeak = false;
   202     private boolean seeWeak = false;
   192 
   203 
   193     PKIXBuilderParameters pkixParameters;
   204     PKIXBuilderParameters pkixParameters;
       
   205     Set<X509Certificate> trustedCerts = new HashSet<>();
   194 
   206 
   195     public void run(String args[]) {
   207     public void run(String args[]) {
   196         try {
   208         try {
   197             args = parseArgs(args);
   209             args = parseArgs(args);
   198 
   210 
   275             }
   287             }
   276         }
   288         }
   277 
   289 
   278         if (strict) {
   290         if (strict) {
   279             int exitCode = 0;
   291             int exitCode = 0;
   280             if (weakAlg != 0 || chainNotValidated
   292             if (weakAlg != 0 || chainNotValidated || hasExpiredCert
   281                     || hasExpiredCert || notYetValidCert || signerSelfSigned) {
   293                     || hasExpiredTsaCert || notYetValidCert || signerSelfSigned) {
   282                 exitCode |= 4;
   294                 exitCode |= 4;
   283             }
   295             }
   284             if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
   296             if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
   285                 exitCode |= 8;
   297                 exitCode |= 8;
   286             }
   298             }
   877                 System.out.println();
   889                 System.out.println();
   878                 System.out.println(rb.getString("no.manifest."));
   890                 System.out.println(rb.getString("no.manifest."));
   879             }
   891             }
   880 
   892 
   881             // If signer is a trusted cert or private entry in user's own
   893             // If signer is a trusted cert or private entry in user's own
   882             // keystore, it can be self-signed.
   894             // keystore, it can be self-signed. Please note aliasNotInStore
   883             if (!aliasNotInStore) {
   895             // is always false when ~/.keystore is used.
       
   896             if (!aliasNotInStore && keystore != null) {
   884                 signerSelfSigned = false;
   897                 signerSelfSigned = false;
   885             }
   898             }
   886 
       
   887             // If there is a time stamp block inside the PKCS7 block file
       
   888             boolean hasTimestampBlock = false;
       
   889 
   899 
   890             // Even if the verbose option is not specified, all out strings
   900             // Even if the verbose option is not specified, all out strings
   891             // must be generated so seeWeak can be updated.
   901             // must be generated so seeWeak can be updated.
   892             if (!digestMap.isEmpty()
   902             if (!digestMap.isEmpty()
   893                     || !sigMap.isEmpty()
   903                     || !sigMap.isEmpty()
   984                     System.out.println(rb.getString("jar.treated.unsigned"));
   994                     System.out.println(rb.getString("jar.treated.unsigned"));
   985                 } else {
   995                 } else {
   986                     System.out.println(rb.getString("jar.is.unsigned"));
   996                     System.out.println(rb.getString("jar.is.unsigned"));
   987                 }
   997                 }
   988             } else {
   998             } else {
   989                 boolean warningAppeared = false;
   999                 displayMessagesAndResult(false);
   990                 boolean errorAppeared = false;
       
   991                 if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
       
   992                         notYetValidCert || chainNotValidated || hasExpiredCert ||
       
   993                         hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
       
   994                         aliasNotInStore || notSignedByAlias || tsaChainNotValidated) {
       
   995 
       
   996                     if (strict) {
       
   997                         System.out.println(rb.getString("jar.verified.with.signer.errors."));
       
   998                         System.out.println();
       
   999                         System.out.println(rb.getString("Error."));
       
  1000                         errorAppeared = true;
       
  1001                     } else {
       
  1002                         System.out.println(rb.getString("jar.verified."));
       
  1003                         System.out.println();
       
  1004                         System.out.println(rb.getString("Warning."));
       
  1005                         warningAppeared = true;
       
  1006                     }
       
  1007 
       
  1008                     if (weakAlg != 0) {
       
  1009                         // In fact, jarsigner verification did not catch this
       
  1010                         // since it has not read the JarFile content itself.
       
  1011                         // Everything is done with JarFile API. The signing
       
  1012                         // history (digestMap etc) will show these info and
       
  1013                         // print out proper warnings.
       
  1014                     }
       
  1015 
       
  1016                     if (badKeyUsage) {
       
  1017                         System.out.println(
       
  1018                             rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
       
  1019                     }
       
  1020 
       
  1021                     if (badExtendedKeyUsage) {
       
  1022                         System.out.println(
       
  1023                             rb.getString("This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
       
  1024                     }
       
  1025 
       
  1026                     if (badNetscapeCertType) {
       
  1027                         System.out.println(
       
  1028                             rb.getString("This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
       
  1029                     }
       
  1030 
       
  1031                     if (hasUnsignedEntry) {
       
  1032                         System.out.println(rb.getString(
       
  1033                             "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
       
  1034                     }
       
  1035                     if (hasExpiredCert) {
       
  1036                         System.out.println(rb.getString(
       
  1037                             "This.jar.contains.entries.whose.signer.certificate.has.expired."));
       
  1038                     }
       
  1039                     if (notYetValidCert) {
       
  1040                         System.out.println(rb.getString(
       
  1041                             "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
       
  1042                     }
       
  1043 
       
  1044                     if (chainNotValidated) {
       
  1045                         System.out.println(String.format(
       
  1046                                 rb.getString("This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"),
       
  1047                                 chainNotValidatedReason.getLocalizedMessage()));
       
  1048                     }
       
  1049 
       
  1050                     if (tsaChainNotValidated) {
       
  1051                         System.out.println(String.format(
       
  1052                                 rb.getString("This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"),
       
  1053                                 tsaChainNotValidatedReason.getLocalizedMessage()));
       
  1054                     }
       
  1055 
       
  1056                     if (notSignedByAlias) {
       
  1057                         System.out.println(
       
  1058                                 rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
       
  1059                     }
       
  1060 
       
  1061                     if (aliasNotInStore) {
       
  1062                         System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
       
  1063                     }
       
  1064 
       
  1065                     if (signerSelfSigned) {
       
  1066                         System.out.println(rb.getString(
       
  1067                                 "This.jar.contains.entries.whose.signer.certificate.is.self.signed."));
       
  1068                     }
       
  1069                 } else {
       
  1070                     System.out.println(rb.getString("jar.verified."));
       
  1071                 }
       
  1072                 if (hasExpiringCert || noTimestamp) {
       
  1073                     if (!warningAppeared) {
       
  1074                         System.out.println();
       
  1075                         System.out.println(rb.getString("Warning."));
       
  1076                         warningAppeared = true;
       
  1077                     }
       
  1078                     if (hasExpiringCert) {
       
  1079                         System.out.println(rb.getString(
       
  1080                                 "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
       
  1081                     }
       
  1082                     if (noTimestamp) {
       
  1083                         if (hasTimestampBlock) {
       
  1084                             // JarSigner API has not seen the timestamp,
       
  1085                             // might have ignored it due to weak alg, etc.
       
  1086                             System.out.println(
       
  1087                                     String.format(rb.getString("bad.timestamp.verifying"), expireDate));
       
  1088                         } else {
       
  1089                             System.out.println(
       
  1090                                     String.format(rb.getString("no.timestamp.verifying"), expireDate));
       
  1091                         }
       
  1092                     }
       
  1093                 }
       
  1094                 if (warningAppeared || errorAppeared) {
       
  1095                     if (! (verbose != null && showcerts)) {
       
  1096                         System.out.println();
       
  1097                         System.out.println(rb.getString(
       
  1098                                 "Re.run.with.the.verbose.and.certs.options.for.more.details."));
       
  1099                     }
       
  1100                 }
       
  1101             }
  1000             }
  1102             return;
  1001             return;
  1103         } catch (Exception e) {
  1002         } catch (Exception e) {
  1104             System.out.println(rb.getString("jarsigner.") + e);
  1003             System.out.println(rb.getString("jarsigner.") + e);
  1105             if (debug) {
  1004             if (debug) {
  1110                 jf.close();
  1009                 jf.close();
  1111             }
  1010             }
  1112         }
  1011         }
  1113 
  1012 
  1114         System.exit(1);
  1013         System.exit(1);
       
  1014     }
       
  1015 
       
  1016     private void displayMessagesAndResult(boolean isSigning) {
       
  1017         String result;
       
  1018         List<String> errors = new ArrayList<>();
       
  1019         List<String> warnings = new ArrayList<>();
       
  1020         List<String> info = new ArrayList<>();
       
  1021 
       
  1022         boolean signerNotExpired = expireDate == null
       
  1023                 || expireDate.after(new Date());
       
  1024 
       
  1025         if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
       
  1026                 notYetValidCert || chainNotValidated || hasExpiredCert ||
       
  1027                 hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
       
  1028                 aliasNotInStore || notSignedByAlias ||
       
  1029                 tsaChainNotValidated ||
       
  1030                 (hasExpiredTsaCert && !signerNotExpired)) {
       
  1031 
       
  1032             if (strict) {
       
  1033                 result = rb.getString(isSigning
       
  1034                         ? "jar.signed.with.signer.errors."
       
  1035                         : "jar.verified.with.signer.errors.");
       
  1036             } else {
       
  1037                 result = rb.getString(isSigning
       
  1038                         ? "jar.signed."
       
  1039                         : "jar.verified.");
       
  1040             }
       
  1041 
       
  1042             if (badKeyUsage) {
       
  1043                 errors.add(rb.getString(isSigning
       
  1044                         ? "The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."
       
  1045                         : "This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
       
  1046             }
       
  1047 
       
  1048             if (badExtendedKeyUsage) {
       
  1049                 errors.add(rb.getString(isSigning
       
  1050                         ? "The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."
       
  1051                         : "This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
       
  1052             }
       
  1053 
       
  1054             if (badNetscapeCertType) {
       
  1055                 errors.add(rb.getString(isSigning
       
  1056                         ? "The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."
       
  1057                         : "This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
       
  1058             }
       
  1059 
       
  1060             // only in verifying
       
  1061             if (hasUnsignedEntry) {
       
  1062                 errors.add(rb.getString(
       
  1063                         "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
       
  1064             }
       
  1065             if (hasExpiredCert) {
       
  1066                 errors.add(rb.getString(isSigning
       
  1067                         ? "The.signer.certificate.has.expired."
       
  1068                         : "This.jar.contains.entries.whose.signer.certificate.has.expired."));
       
  1069             }
       
  1070             if (notYetValidCert) {
       
  1071                 errors.add(rb.getString(isSigning
       
  1072                         ? "The.signer.certificate.is.not.yet.valid."
       
  1073                         : "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
       
  1074             }
       
  1075 
       
  1076             if (chainNotValidated) {
       
  1077                 errors.add(String.format(rb.getString(isSigning
       
  1078                                 ? "The.signer.s.certificate.chain.is.invalid.reason.1"
       
  1079                                 : "This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"),
       
  1080                         chainNotValidatedReason.getLocalizedMessage()));
       
  1081             }
       
  1082 
       
  1083             if (hasExpiredTsaCert) {
       
  1084                 errors.add(rb.getString("The.timestamp.has.expired."));
       
  1085             }
       
  1086             if (tsaChainNotValidated) {
       
  1087                 errors.add(String.format(rb.getString(isSigning
       
  1088                                 ? "The.tsa.certificate.chain.is.invalid.reason.1"
       
  1089                                 : "This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"),
       
  1090                         tsaChainNotValidatedReason.getLocalizedMessage()));
       
  1091             }
       
  1092 
       
  1093             // only in verifying
       
  1094             if (notSignedByAlias) {
       
  1095                 errors.add(
       
  1096                         rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
       
  1097             }
       
  1098 
       
  1099             // only in verifying
       
  1100             if (aliasNotInStore) {
       
  1101                 errors.add(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
       
  1102             }
       
  1103 
       
  1104             if (signerSelfSigned) {
       
  1105                 errors.add(rb.getString(isSigning
       
  1106                         ? "The.signer.s.certificate.is.self.signed."
       
  1107                         : "This.jar.contains.entries.whose.signer.certificate.is.self.signed."));
       
  1108             }
       
  1109 
       
  1110             // weakAlg only detected in signing. The jar file is
       
  1111             // now simply treated unsigned in verifying.
       
  1112             if ((weakAlg & 1) == 1) {
       
  1113                 errors.add(String.format(
       
  1114                         rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
       
  1115                         digestalg, "-digestalg"));
       
  1116             }
       
  1117 
       
  1118             if ((weakAlg & 2) == 2) {
       
  1119                 errors.add(String.format(
       
  1120                         rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
       
  1121                         sigalg, "-sigalg"));
       
  1122             }
       
  1123             if ((weakAlg & 4) == 4) {
       
  1124                 errors.add(String.format(
       
  1125                         rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
       
  1126                         tSADigestAlg, "-tsadigestalg"));
       
  1127             }
       
  1128             if ((weakAlg & 8) == 8) {
       
  1129                 errors.add(String.format(
       
  1130                         rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."),
       
  1131                         privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
       
  1132             }
       
  1133         } else {
       
  1134             result = rb.getString(isSigning ? "jar.signed." : "jar.verified.");
       
  1135         }
       
  1136 
       
  1137         if (hasExpiredTsaCert) {
       
  1138             // No need to warn about expiring if already expired
       
  1139             hasExpiringTsaCert = false;
       
  1140         }
       
  1141 
       
  1142         if (hasExpiringCert ||
       
  1143                 (hasExpiringTsaCert  && expireDate != null) ||
       
  1144                 (noTimestamp && expireDate != null) ||
       
  1145                 (hasExpiredTsaCert && signerNotExpired)) {
       
  1146 
       
  1147             if (hasExpiredTsaCert && signerNotExpired) {
       
  1148                 if (expireDate != null) {
       
  1149                     warnings.add(String.format(
       
  1150                             rb.getString("The.timestamp.expired.1.but.usable.2"),
       
  1151                             tsaExpireDate,
       
  1152                             expireDate));
       
  1153                 }
       
  1154                 // Reset the flag so exit code is 0
       
  1155                 hasExpiredTsaCert = false;
       
  1156             }
       
  1157             if (hasExpiringCert) {
       
  1158                 warnings.add(rb.getString(isSigning
       
  1159                         ? "The.signer.certificate.will.expire.within.six.months."
       
  1160                         : "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
       
  1161             }
       
  1162             if (hasExpiringTsaCert && expireDate != null) {
       
  1163                 if (expireDate.after(tsaExpireDate)) {
       
  1164                     warnings.add(String.format(rb.getString(
       
  1165                             "The.timestamp.will.expire.within.one.year.on.1.but.2"), tsaExpireDate, expireDate));
       
  1166                 } else {
       
  1167                     warnings.add(String.format(rb.getString(
       
  1168                             "The.timestamp.will.expire.within.one.year.on.1"), tsaExpireDate));
       
  1169                 }
       
  1170             }
       
  1171             if (noTimestamp && expireDate != null) {
       
  1172                 if (hasTimestampBlock) {
       
  1173                     warnings.add(String.format(rb.getString(isSigning
       
  1174                             ? "invalid.timestamp.signing"
       
  1175                             : "bad.timestamp.verifying"), expireDate));
       
  1176                 } else {
       
  1177                     warnings.add(String.format(rb.getString(isSigning
       
  1178                             ? "no.timestamp.signing"
       
  1179                             : "no.timestamp.verifying"), expireDate));
       
  1180                 }
       
  1181             }
       
  1182         }
       
  1183 
       
  1184         System.out.println(result);
       
  1185         if (strict) {
       
  1186             if (!errors.isEmpty()) {
       
  1187                 System.out.println();
       
  1188                 System.out.println(rb.getString("Error."));
       
  1189                 errors.forEach(System.out::println);
       
  1190             }
       
  1191             if (!warnings.isEmpty()) {
       
  1192                 System.out.println();
       
  1193                 System.out.println(rb.getString("Warning."));
       
  1194                 warnings.forEach(System.out::println);
       
  1195             }
       
  1196         } else {
       
  1197             if (!errors.isEmpty() || !warnings.isEmpty()) {
       
  1198                 System.out.println();
       
  1199                 System.out.println(rb.getString("Warning."));
       
  1200                 errors.forEach(System.out::println);
       
  1201                 warnings.forEach(System.out::println);
       
  1202             }
       
  1203         }
       
  1204         if (!isSigning && (!errors.isEmpty() || !warnings.isEmpty())) {
       
  1205             if (! (verbose != null && showcerts)) {
       
  1206                 System.out.println();
       
  1207                 System.out.println(rb.getString(
       
  1208                         "Re.run.with.the.verbose.and.certs.options.for.more.details."));
       
  1209             }
       
  1210         }
       
  1211 
       
  1212         if (isSigning || verbose != null) {
       
  1213             // Always print out expireDate, unless expired or expiring.
       
  1214             if (!hasExpiringCert && !hasExpiredCert
       
  1215                     && expireDate != null && signerNotExpired) {
       
  1216                 info.add(String.format(rb.getString(
       
  1217                         "The.signer.certificate.will.expire.on.1."), expireDate));
       
  1218             }
       
  1219             if (!noTimestamp) {
       
  1220                 if (!hasExpiringTsaCert && !hasExpiredTsaCert && tsaExpireDate != null) {
       
  1221                     if (signerNotExpired) {
       
  1222                         info.add(String.format(rb.getString(
       
  1223                                 "The.timestamp.will.expire.on.1."), tsaExpireDate));
       
  1224                     } else {
       
  1225                         info.add(String.format(rb.getString(
       
  1226                                 "signer.cert.expired.1.but.timestamp.good.2."),
       
  1227                                 expireDate,
       
  1228                                 tsaExpireDate));
       
  1229                     }
       
  1230                 }
       
  1231             }
       
  1232         }
       
  1233 
       
  1234         if (!info.isEmpty()) {
       
  1235             System.out.println();
       
  1236             info.forEach(System.out::println);
       
  1237         }
  1115     }
  1238     }
  1116 
  1239 
  1117     private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
  1240     private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
  1118         if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
  1241         if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
  1119             return alg;
  1242             return alg;
  1150      * [<validity-period> | <expiry-warning>]
  1273      * [<validity-period> | <expiry-warning>]
  1151      * [<key-usage-warning>]
  1274      * [<key-usage-warning>]
  1152      *
  1275      *
  1153      * Note: no newline character at the end.
  1276      * Note: no newline character at the end.
  1154      *
  1277      *
  1155      * When isTsCert is true, this method sets global flags like hasExpiredCert,
  1278      * This method sets global flags like hasExpiringCert, hasExpiredCert,
  1156      * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType.
  1279      * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType,
       
  1280      * hasExpiringTsaCert, hasExpiredTsaCert.
  1157      *
  1281      *
  1158      * @param isTsCert true if c is in the TSA cert chain, false otherwise.
  1282      * @param isTsCert true if c is in the TSA cert chain, false otherwise.
  1159      * @param checkUsage true to check code signer keyUsage
  1283      * @param checkUsage true to check code signer keyUsage
  1160      */
  1284      */
  1161     String printCert(boolean isTsCert, String tab, Certificate c,
  1285     String printCert(boolean isTsCert, String tab, Certificate c,
  1180         }
  1304         }
  1181 
  1305 
  1182         if (x509Cert != null) {
  1306         if (x509Cert != null) {
  1183 
  1307 
  1184             certStr.append("\n").append(tab).append("[");
  1308             certStr.append("\n").append(tab).append("[");
  1185             Date notAfter = x509Cert.getNotAfter();
  1309 
  1186             try {
  1310             if (trustedCerts.contains(x509Cert)) {
  1187                 boolean printValidity = true;
  1311                 certStr.append(rb.getString("trusted.certificate"));
  1188                 if (timestamp == null) {
  1312             } else {
  1189                     if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
  1313                 Date notAfter = x509Cert.getNotAfter();
  1190                         expireDate = notAfter;
  1314                 try {
  1191                     }
  1315                     boolean printValidity = true;
  1192                     x509Cert.checkValidity();
  1316                     if (isTsCert) {
  1193                     // test if cert will expire within six months
  1317                         if (tsaExpireDate == null || tsaExpireDate.after(notAfter)) {
  1194                     if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
  1318                             tsaExpireDate = notAfter;
  1195                         if (!isTsCert) hasExpiringCert = true;
       
  1196                         if (expiringTimeForm == null) {
       
  1197                             expiringTimeForm = new MessageFormat(
       
  1198                                 rb.getString("certificate.will.expire.on"));
       
  1199                         }
  1319                         }
  1200                         Object[] source = { notAfter };
  1320                     } else {
  1201                         certStr.append(expiringTimeForm.format(source));
  1321                         if (expireDate == null || expireDate.after(notAfter)) {
  1202                         printValidity = false;
  1322                             expireDate = notAfter;
  1203                     }
  1323                         }
  1204                 } else {
  1324                     }
  1205                     x509Cert.checkValidity(timestamp);
  1325                     if (timestamp == null) {
  1206                 }
  1326                         x509Cert.checkValidity();
  1207                 if (printValidity) {
  1327                         // test if cert will expire within six months (or one year for tsa)
  1208                     if (validityTimeForm == null) {
  1328                         long age = isTsCert ? ONE_YEAR : SIX_MONTHS;
  1209                         validityTimeForm = new MessageFormat(
  1329                         if (notAfter.getTime() < System.currentTimeMillis() + age) {
  1210                             rb.getString("certificate.is.valid.from"));
  1330                             if (isTsCert) {
  1211                     }
  1331                                 hasExpiringTsaCert = true;
  1212                     Object[] source = { x509Cert.getNotBefore(), notAfter };
  1332                             } else {
  1213                     certStr.append(validityTimeForm.format(source));
  1333                                 hasExpiringCert = true;
  1214                 }
  1334                             }
  1215             } catch (CertificateExpiredException cee) {
  1335                             if (expiringTimeForm == null) {
  1216                 if (!isTsCert) hasExpiredCert = true;
  1336                                 expiringTimeForm = new MessageFormat(
  1217 
  1337                                         rb.getString("certificate.will.expire.on"));
  1218                 if (expiredTimeForm == null) {
  1338                             }
  1219                     expiredTimeForm = new MessageFormat(
  1339                             Object[] source = {notAfter};
  1220                         rb.getString("certificate.expired.on"));
  1340                             certStr.append(expiringTimeForm.format(source));
  1221                 }
  1341                             printValidity = false;
  1222                 Object[] source = { notAfter };
  1342                         }
  1223                 certStr.append(expiredTimeForm.format(source));
  1343                     } else {
  1224 
  1344                         x509Cert.checkValidity(timestamp);
  1225             } catch (CertificateNotYetValidException cnyve) {
  1345                     }
  1226                 if (!isTsCert) notYetValidCert = true;
  1346                     if (printValidity) {
  1227 
  1347                         if (validityTimeForm == null) {
  1228                 if (notYetTimeForm == null) {
  1348                             validityTimeForm = new MessageFormat(
  1229                     notYetTimeForm = new MessageFormat(
  1349                                     rb.getString("certificate.is.valid.from"));
  1230                         rb.getString("certificate.is.not.valid.until"));
  1350                         }
  1231                 }
  1351                         Object[] source = {x509Cert.getNotBefore(), notAfter};
  1232                 Object[] source = { x509Cert.getNotBefore() };
  1352                         certStr.append(validityTimeForm.format(source));
  1233                 certStr.append(notYetTimeForm.format(source));
  1353                     }
       
  1354                 } catch (CertificateExpiredException cee) {
       
  1355                     if (isTsCert) {
       
  1356                         hasExpiredTsaCert = true;
       
  1357                     } else {
       
  1358                         hasExpiredCert = true;
       
  1359                     }
       
  1360 
       
  1361                     if (expiredTimeForm == null) {
       
  1362                         expiredTimeForm = new MessageFormat(
       
  1363                                 rb.getString("certificate.expired.on"));
       
  1364                     }
       
  1365                     Object[] source = {notAfter};
       
  1366                     certStr.append(expiredTimeForm.format(source));
       
  1367 
       
  1368                 } catch (CertificateNotYetValidException cnyve) {
       
  1369                     if (!isTsCert) notYetValidCert = true;
       
  1370 
       
  1371                     if (notYetTimeForm == null) {
       
  1372                         notYetTimeForm = new MessageFormat(
       
  1373                                 rb.getString("certificate.is.not.valid.until"));
       
  1374                     }
       
  1375                     Object[] source = {x509Cert.getNotBefore()};
       
  1376                     certStr.append(notYetTimeForm.format(source));
       
  1377                 }
  1234             }
  1378             }
  1235             certStr.append("]");
  1379             certStr.append("]");
  1236 
  1380 
  1237             if (checkUsage) {
  1381             if (checkUsage) {
  1238                 boolean[] bad = new boolean[3];
  1382                 boolean[] bad = new boolean[3];
  1444             }
  1588             }
  1445 
  1589 
  1446             if (tSAPolicyID != null) {
  1590             if (tSAPolicyID != null) {
  1447                 builder.setProperty("tsaPolicyId", tSAPolicyID);
  1591                 builder.setProperty("tsaPolicyId", tSAPolicyID);
  1448             }
  1592             }
  1449         } else {
       
  1450             noTimestamp = true;
       
  1451         }
  1593         }
  1452 
  1594 
  1453         if (altSignerClass != null) {
  1595         if (altSignerClass != null) {
  1454             builder.setProperty("altSigner", altSignerClass);
  1596             builder.setProperty("altSigner", altSignerClass);
  1455             if (verbose != null) {
  1597             if (verbose != null) {
  1517         if (failedCause != null) {
  1659         if (failedCause != null) {
  1518             signedJarFile.delete();
  1660             signedJarFile.delete();
  1519             error(failedMessage, failedCause);
  1661             error(failedMessage, failedCause);
  1520         }
  1662         }
  1521 
  1663 
       
  1664         if (verbose != null) {
       
  1665             System.out.println();
       
  1666         }
       
  1667 
  1522         // The JarSigner API always accepts the timestamp received.
  1668         // The JarSigner API always accepts the timestamp received.
  1523         // We need to extract the certs from the signed jar to
  1669         // We need to extract the certs from the signed jar to
  1524         // validate it.
  1670         // validate it.
  1525         if (!noTimestamp) {
  1671         try (JarFile check = new JarFile(signedJarFile)) {
  1526             try (JarFile check = new JarFile(signedJarFile)) {
  1672             PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
  1527                 PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
  1673                     "META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
  1528                         "META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
  1674             Timestamp ts = null;
       
  1675             try {
  1529                 SignerInfo si = p7.getSignerInfos()[0];
  1676                 SignerInfo si = p7.getSignerInfos()[0];
  1530                 PKCS7 tsToken = si.getTsToken();
  1677                 if (si.getTsToken() != null) {
  1531                 SignerInfo tsSi = tsToken.getSignerInfos()[0];
  1678                     hasTimestampBlock = true;
  1532                 try {
  1679                 }
  1533                     validateCertChain(Validator.VAR_TSA_SERVER,
  1680                 ts = si.getTimestamp();
  1534                             tsSi.getCertificateChain(tsToken), null);
       
  1535                 } catch (Exception e) {
       
  1536                     tsaChainNotValidated = true;
       
  1537                     tsaChainNotValidatedReason = e;
       
  1538                 }
       
  1539             } catch (Exception e) {
  1681             } catch (Exception e) {
  1540                 if (debug) {
  1682                 tsaChainNotValidated = true;
  1541                     e.printStackTrace();
  1683                 tsaChainNotValidatedReason = e;
  1542                 }
  1684             }
  1543             }
  1685             // Spaces before the ">>> Signer" and other lines are different
  1544         }
  1686             String result = certsAndTSInfo("", "    ", Arrays.asList(certChain), ts);
  1545 
  1687             if (verbose != null) {
  1546         // no IOException thrown in the follow try clause, so disable
  1688                 System.out.println(result);
  1547         // the try clause.
  1689             }
  1548         // try {
  1690         } catch (Exception e) {
  1549             if (signedjar == null) {
  1691             if (debug) {
  1550                 // attempt an atomic rename. If that fails,
  1692                 e.printStackTrace();
  1551                 // rename the original jar file, then the signed
  1693             }
  1552                 // one, then delete the original.
  1694         }
  1553                 if (!signedJarFile.renameTo(jarFile)) {
  1695 
  1554                     File origJar = new File(jarName+".orig");
  1696         if (signedjar == null) {
  1555 
  1697             // attempt an atomic rename. If that fails,
  1556                     if (jarFile.renameTo(origJar)) {
  1698             // rename the original jar file, then the signed
  1557                         if (signedJarFile.renameTo(jarFile)) {
  1699             // one, then delete the original.
  1558                             origJar.delete();
  1700             if (!signedJarFile.renameTo(jarFile)) {
  1559                         } else {
  1701                 File origJar = new File(jarName+".orig");
  1560                             MessageFormat form = new MessageFormat(rb.getString
  1702 
  1561                         ("attempt.to.rename.signedJarFile.to.jarFile.failed"));
  1703                 if (jarFile.renameTo(origJar)) {
  1562                             Object[] source = {signedJarFile, jarFile};
  1704                     if (signedJarFile.renameTo(jarFile)) {
  1563                             error(form.format(source));
  1705                         origJar.delete();
  1564                         }
       
  1565                     } else {
  1706                     } else {
  1566                         MessageFormat form = new MessageFormat(rb.getString
  1707                         MessageFormat form = new MessageFormat(rb.getString
  1567                             ("attempt.to.rename.jarFile.to.origJar.failed"));
  1708                     ("attempt.to.rename.signedJarFile.to.jarFile.failed"));
  1568                         Object[] source = {jarFile, origJar};
  1709                         Object[] source = {signedJarFile, jarFile};
  1569                         error(form.format(source));
  1710                         error(form.format(source));
  1570                     }
  1711                     }
  1571                 }
       
  1572             }
       
  1573 
       
  1574             boolean warningAppeared = false;
       
  1575             if (weakAlg != 0 || badKeyUsage || badExtendedKeyUsage
       
  1576                     || badNetscapeCertType || notYetValidCert
       
  1577                     || chainNotValidated || tsaChainNotValidated
       
  1578                     || hasExpiredCert || signerSelfSigned) {
       
  1579                 if (strict) {
       
  1580                     System.out.println(rb.getString("jar.signed.with.signer.errors."));
       
  1581                     System.out.println();
       
  1582                     System.out.println(rb.getString("Error."));
       
  1583                 } else {
  1712                 } else {
  1584                     System.out.println(rb.getString("jar.signed."));
  1713                     MessageFormat form = new MessageFormat(rb.getString
  1585                     System.out.println();
  1714                         ("attempt.to.rename.jarFile.to.origJar.failed"));
  1586                     System.out.println(rb.getString("Warning."));
  1715                     Object[] source = {jarFile, origJar};
  1587                     warningAppeared = true;
  1716                     error(form.format(source));
  1588                 }
  1717                 }
  1589 
  1718             }
  1590                 if (badKeyUsage) {
  1719         }
  1591                     System.out.println(
  1720 
  1592                         rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
  1721         displayMessagesAndResult(true);
  1593                 }
       
  1594 
       
  1595                 if (badExtendedKeyUsage) {
       
  1596                     System.out.println(
       
  1597                         rb.getString("The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
       
  1598                 }
       
  1599 
       
  1600                 if (badNetscapeCertType) {
       
  1601                     System.out.println(
       
  1602                         rb.getString("The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
       
  1603                 }
       
  1604 
       
  1605                 if (hasExpiredCert) {
       
  1606                     System.out.println(
       
  1607                         rb.getString("The.signer.certificate.has.expired."));
       
  1608                 } else if (notYetValidCert) {
       
  1609                     System.out.println(
       
  1610                         rb.getString("The.signer.certificate.is.not.yet.valid."));
       
  1611                 }
       
  1612 
       
  1613                 if (chainNotValidated) {
       
  1614                     System.out.println(String.format(
       
  1615                             rb.getString("The.signer.s.certificate.chain.is.invalid.reason.1"),
       
  1616                             chainNotValidatedReason.getLocalizedMessage()));
       
  1617                 }
       
  1618 
       
  1619                 if (tsaChainNotValidated) {
       
  1620                     System.out.println(String.format(
       
  1621                             rb.getString("The.tsa.certificate.chain.is.invalid.reason.1"),
       
  1622                             tsaChainNotValidatedReason.getLocalizedMessage()));
       
  1623                 }
       
  1624 
       
  1625                 if (signerSelfSigned) {
       
  1626                     System.out.println(
       
  1627                             rb.getString("The.signer.s.certificate.is.self.signed."));
       
  1628                 }
       
  1629 
       
  1630                 if ((weakAlg & 1) == 1) {
       
  1631                     System.out.println(String.format(
       
  1632                             rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
       
  1633                             digestalg, "-digestalg"));
       
  1634                 }
       
  1635 
       
  1636                 if ((weakAlg & 2) == 2) {
       
  1637                     System.out.println(String.format(
       
  1638                             rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
       
  1639                             sigalg, "-sigalg"));
       
  1640                 }
       
  1641                 if ((weakAlg & 4) == 4) {
       
  1642                     System.out.println(String.format(
       
  1643                             rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
       
  1644                             tSADigestAlg, "-tsadigestalg"));
       
  1645                 }
       
  1646                 if ((weakAlg & 8) == 8) {
       
  1647                     System.out.println(String.format(
       
  1648                             rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."),
       
  1649                             privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
       
  1650                 }
       
  1651             } else {
       
  1652                 System.out.println(rb.getString("jar.signed."));
       
  1653             }
       
  1654             if (hasExpiringCert || noTimestamp) {
       
  1655                 if (!warningAppeared) {
       
  1656                     System.out.println();
       
  1657                     System.out.println(rb.getString("Warning."));
       
  1658                 }
       
  1659 
       
  1660                 if (hasExpiringCert) {
       
  1661                     System.out.println(
       
  1662                             rb.getString("The.signer.certificate.will.expire.within.six.months."));
       
  1663                 }
       
  1664 
       
  1665                 if (noTimestamp) {
       
  1666                     System.out.println(
       
  1667                             String.format(rb.getString("no.timestamp.signing"), expireDate));
       
  1668                 }
       
  1669             }
       
  1670 
       
  1671         // no IOException thrown in the above try clause, so disable
       
  1672         // the catch clause.
       
  1673         // } catch(IOException ioe) {
       
  1674         //     error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
       
  1675         // }
       
  1676     }
  1722     }
  1677 
  1723 
  1678     /**
  1724     /**
  1679      * signature-related files include:
  1725      * signature-related files include:
  1680      * . META-INF/MANIFEST.MF
  1726      * . META-INF/MANIFEST.MF
  1689     }
  1735     }
  1690 
  1736 
  1691     Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
  1737     Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
  1692 
  1738 
  1693     /**
  1739     /**
  1694      * Returns a string of singer info, with a newline at the end
  1740      * Returns a string of signer info, with a newline at the end.
       
  1741      * Called by verifyJar().
  1695      */
  1742      */
  1696     private String signerInfo(CodeSigner signer, String tab) throws Exception {
  1743     private String signerInfo(CodeSigner signer, String tab) throws Exception {
  1697         if (cacheForSignerInfo.containsKey(signer)) {
  1744         if (cacheForSignerInfo.containsKey(signer)) {
  1698             return cacheForSignerInfo.get(signer);
  1745             return cacheForSignerInfo.get(signer);
  1699         }
  1746         }
  1700         StringBuilder sb = new StringBuilder();
       
  1701         List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
  1747         List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
  1702         // display the signature timestamp, if present
  1748         // signing time is only displayed on verification
       
  1749         Timestamp ts = signer.getTimestamp();
       
  1750         String tsLine = "";
       
  1751         if (ts != null) {
       
  1752             tsLine = printTimestamp(tab, ts) + "\n";
       
  1753         }
       
  1754         // Spaces before the ">>> Signer" and other lines are the same.
       
  1755 
       
  1756         String result = certsAndTSInfo(tab, tab, certs, ts);
       
  1757         cacheForSignerInfo.put(signer, tsLine + result);
       
  1758         return result;
       
  1759     }
       
  1760 
       
  1761     /**
       
  1762      * Fills info on certs and timestamp into a StringBuilder, sets
       
  1763      * warning flags (through printCert) and validates cert chains.
       
  1764      *
       
  1765      * @param tab1 spaces before the ">>> Signer" line
       
  1766      * @param tab2 spaces before the other lines
       
  1767      * @param certs the signer cert
       
  1768      * @param ts the timestamp, can be null
       
  1769      * @return the info as a string
       
  1770      */
       
  1771     private String certsAndTSInfo(
       
  1772             String tab1,
       
  1773             String tab2,
       
  1774             List<? extends Certificate> certs, Timestamp ts)
       
  1775             throws Exception {
       
  1776 
  1703         Date timestamp;
  1777         Date timestamp;
  1704         Timestamp ts = signer.getTimestamp();
       
  1705         if (ts != null) {
  1778         if (ts != null) {
  1706             sb.append(printTimestamp(tab, ts));
       
  1707             sb.append('\n');
       
  1708             timestamp = ts.getTimestamp();
  1779             timestamp = ts.getTimestamp();
       
  1780             noTimestamp = false;
  1709         } else {
  1781         } else {
  1710             timestamp = null;
  1782             timestamp = null;
  1711             noTimestamp = true;
       
  1712         }
  1783         }
  1713         // display the certificate(sb). The first one is end-entity cert and
  1784         // display the certificate(sb). The first one is end-entity cert and
  1714         // its KeyUsage should be checked.
  1785         // its KeyUsage should be checked.
  1715         boolean first = true;
  1786         boolean first = true;
  1716         sb.append(tab).append(rb.getString("...Signer")).append('\n');
  1787         StringBuilder sb = new StringBuilder();
       
  1788         sb.append(tab1).append(rb.getString("...Signer")).append('\n');
  1717         for (Certificate c : certs) {
  1789         for (Certificate c : certs) {
  1718             sb.append(printCert(false, tab, c, timestamp, first));
  1790             sb.append(printCert(false, tab2, c, timestamp, first));
  1719             sb.append('\n');
  1791             sb.append('\n');
  1720             first = false;
  1792             first = false;
  1721         }
  1793         }
  1722         try {
  1794         try {
  1723             validateCertChain(Validator.VAR_CODE_SIGNING, certs, ts);
  1795             validateCertChain(Validator.VAR_CODE_SIGNING, certs, ts);
  1724         } catch (Exception e) {
  1796         } catch (Exception e) {
  1725             chainNotValidated = true;
  1797             chainNotValidated = true;
  1726             chainNotValidatedReason = e;
  1798             chainNotValidatedReason = e;
  1727             sb.append(tab).append(rb.getString(".Invalid.certificate.chain."))
  1799             sb.append(tab2).append(rb.getString(".Invalid.certificate.chain."))
  1728                     .append(e.getLocalizedMessage()).append("]\n");
  1800                     .append(e.getLocalizedMessage()).append("]\n");
  1729         }
  1801         }
  1730         if (ts != null) {
  1802         if (ts != null) {
  1731             sb.append(tab).append(rb.getString("...TSA")).append('\n');
  1803             sb.append(tab1).append(rb.getString("...TSA")).append('\n');
  1732             for (Certificate c : ts.getSignerCertPath().getCertificates()) {
  1804             for (Certificate c : ts.getSignerCertPath().getCertificates()) {
  1733                 sb.append(printCert(true, tab, c, timestamp, false));
  1805                 sb.append(printCert(true, tab2, c, null, false));
  1734                 sb.append('\n');
  1806                 sb.append('\n');
  1735             }
  1807             }
  1736             try {
  1808             try {
  1737                 validateCertChain(Validator.VAR_TSA_SERVER,
  1809                 validateCertChain(Validator.VAR_TSA_SERVER,
  1738                         ts.getSignerCertPath().getCertificates(), null);
  1810                         ts.getSignerCertPath().getCertificates(), null);
  1739             } catch (Exception e) {
  1811             } catch (Exception e) {
  1740                 tsaChainNotValidated = true;
  1812                 tsaChainNotValidated = true;
  1741                 tsaChainNotValidatedReason = e;
  1813                 tsaChainNotValidatedReason = e;
  1742                 sb.append(tab).append(rb.getString(".Invalid.TSA.certificate.chain."))
  1814                 sb.append(tab2).append(rb.getString(".Invalid.TSA.certificate.chain."))
  1743                         .append(e.getLocalizedMessage()).append("]\n");
  1815                         .append(e.getLocalizedMessage()).append("]\n");
  1744             }
  1816             }
  1745         }
  1817         }
  1746         if (certs.size() == 1
  1818         if (certs.size() == 1
  1747                 && KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
  1819                 && KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
  1748             signerSelfSigned = true;
  1820             signerSelfSigned = true;
  1749         }
  1821         }
  1750         String result = sb.toString();
  1822 
  1751         cacheForSignerInfo.put(signer, result);
  1823         return sb.toString();
  1752         return result;
       
  1753     }
  1824     }
  1754 
  1825 
  1755     void loadKeyStore(String keyStoreName, boolean prompt) {
  1826     void loadKeyStore(String keyStoreName, boolean prompt) {
  1756 
  1827 
  1757         if (!nullStream && keyStoreName == null) {
  1828         if (!nullStream && keyStoreName == null) {
  1758             keyStoreName = System.getProperty("user.home") + File.separator
  1829             keyStoreName = System.getProperty("user.home") + File.separator
  1759                 + ".keystore";
  1830                 + ".keystore";
  1760         }
  1831         }
  1761 
  1832 
  1762         try {
  1833         try {
  1763             Set<TrustAnchor> tas = new HashSet<>();
       
  1764             try {
  1834             try {
  1765                 KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
  1835                 KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
  1766                 if (caks != null) {
  1836                 if (caks != null) {
  1767                     Enumeration<String> aliases = caks.aliases();
  1837                     Enumeration<String> aliases = caks.aliases();
  1768                     while (aliases.hasMoreElements()) {
  1838                     while (aliases.hasMoreElements()) {
  1769                         String a = aliases.nextElement();
  1839                         String a = aliases.nextElement();
  1770                         try {
  1840                         try {
  1771                             tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
  1841                             trustedCerts.add((X509Certificate)caks.getCertificate(a));
  1772                         } catch (Exception e2) {
  1842                         } catch (Exception e2) {
  1773                             // ignore, when a SecretkeyEntry does not include a cert
  1843                             // ignore, when a SecretkeyEntry does not include a cert
  1774                         }
  1844                         }
  1775                     }
  1845                     }
  1776                 }
  1846                 }
  1825                         X509Certificate c = (X509Certificate)store.getCertificate(a);
  1895                         X509Certificate c = (X509Certificate)store.getCertificate(a);
  1826                         // Only add TrustedCertificateEntry and self-signed
  1896                         // Only add TrustedCertificateEntry and self-signed
  1827                         // PrivateKeyEntry
  1897                         // PrivateKeyEntry
  1828                         if (store.isCertificateEntry(a) ||
  1898                         if (store.isCertificateEntry(a) ||
  1829                                 c.getSubjectDN().equals(c.getIssuerDN())) {
  1899                                 c.getSubjectDN().equals(c.getIssuerDN())) {
  1830                             tas.add(new TrustAnchor(c, null));
  1900                             trustedCerts.add(c);
  1831                         }
  1901                         }
  1832                     } catch (Exception e2) {
  1902                     } catch (Exception e2) {
  1833                         // ignore, when a SecretkeyEntry does not include a cert
  1903                         // ignore, when a SecretkeyEntry does not include a cert
  1834                     }
  1904                     }
  1835                 }
  1905                 }
  1836             } finally {
  1906             } finally {
  1837                 try {
  1907                 try {
  1838                     pkixParameters = new PKIXBuilderParameters(tas, null);
  1908                     pkixParameters = new PKIXBuilderParameters(
       
  1909                             trustedCerts.stream()
       
  1910                                     .map(c -> new TrustAnchor(c, null))
       
  1911                                     .collect(Collectors.toSet()),
       
  1912                             null);
  1839                     pkixParameters.setRevocationEnabled(false);
  1913                     pkixParameters.setRevocationEnabled(false);
  1840                 } catch (InvalidAlgorithmParameterException ex) {
  1914                 } catch (InvalidAlgorithmParameterException ex) {
  1841                     // Only if tas is empty
  1915                     // Only if tas is empty
  1842                 }
  1916                 }
  1843             }
  1917             }
  1949         } catch (IOException e) {
  2023         } catch (IOException e) {
  1950             //
  2024             //
  1951         }
  2025         }
  1952     }
  2026     }
  1953 
  2027 
       
  2028     // Called by signJar().
  1954     void getAliasInfo(String alias) throws Exception {
  2029     void getAliasInfo(String alias) throws Exception {
  1955 
  2030 
  1956         Key key = null;
  2031         Key key = null;
  1957 
  2032 
  1958         try {
  2033         try {
  1991                 if (!(cs[i] instanceof X509Certificate)) {
  2066                 if (!(cs[i] instanceof X509Certificate)) {
  1992                     error(rb.getString
  2067                     error(rb.getString
  1993                         ("found.non.X.509.certificate.in.signer.s.chain"));
  2068                         ("found.non.X.509.certificate.in.signer.s.chain"));
  1994                 }
  2069                 }
  1995                 certChain[i] = (X509Certificate)cs[i];
  2070                 certChain[i] = (X509Certificate)cs[i];
  1996             }
       
  1997 
       
  1998             // We don't meant to print anything, the next call
       
  1999             // checks validity and keyUsage etc
       
  2000             printCert(false, "", certChain[0], null, true);
       
  2001 
       
  2002             try {
       
  2003                 validateCertChain(Validator.VAR_CODE_SIGNING,
       
  2004                         Arrays.asList(certChain), null);
       
  2005             } catch (Exception e) {
       
  2006                 chainNotValidated = true;
       
  2007                 chainNotValidatedReason = e;
       
  2008             }
       
  2009 
       
  2010             if (KeyStoreUtil.isSelfSigned(certChain[0])) {
       
  2011                 signerSelfSigned = true;
       
  2012             }
  2071             }
  2013 
  2072 
  2014             try {
  2073             try {
  2015                 if (!token && keypass == null)
  2074                 if (!token && keypass == null)
  2016                     key = store.getKey(alias, storepass);
  2075                     key = store.getKey(alias, storepass);
  2064      * Validates a cert chain.
  2123      * Validates a cert chain.
  2065      *
  2124      *
  2066      * @param parameter this might be a timestamp
  2125      * @param parameter this might be a timestamp
  2067      */
  2126      */
  2068     void validateCertChain(String variant, List<? extends Certificate> certs,
  2127     void validateCertChain(String variant, List<? extends Certificate> certs,
  2069                            Object parameter)
  2128                            Timestamp parameter)
  2070             throws Exception {
  2129             throws Exception {
  2071         try {
  2130         try {
  2072             Validator.getInstance(Validator.TYPE_PKIX,
  2131             Validator.getInstance(Validator.TYPE_PKIX,
  2073                     variant,
  2132                     variant,
  2074                     pkixParameters)
  2133                     pkixParameters)
  2078             if (debug) {
  2137             if (debug) {
  2079                 e.printStackTrace();
  2138                 e.printStackTrace();
  2080             }
  2139             }
  2081 
  2140 
  2082             // Exception might be dismissed if another warning flag
  2141             // Exception might be dismissed if another warning flag
  2083             // is already set by printCert. This is only done for
  2142             // is already set by printCert.
  2084             // code signing certs.
  2143 
       
  2144             if (variant.equals(Validator.VAR_TSA_SERVER) &&
       
  2145                     e instanceof ValidatorException) {
       
  2146                 // Throw cause if it's CertPathValidatorException,
       
  2147                 if (e.getCause() != null &&
       
  2148                         e.getCause() instanceof CertPathValidatorException) {
       
  2149                     e = (Exception) e.getCause();
       
  2150                     Throwable t = e.getCause();
       
  2151                     if ((t instanceof CertificateExpiredException &&
       
  2152                             hasExpiredTsaCert)) {
       
  2153                         // we already have hasExpiredTsaCert
       
  2154                         return;
       
  2155                     }
       
  2156                 }
       
  2157             }
  2085 
  2158 
  2086             if (variant.equals(Validator.VAR_CODE_SIGNING) &&
  2159             if (variant.equals(Validator.VAR_CODE_SIGNING) &&
  2087                     e instanceof ValidatorException) {
  2160                     e instanceof ValidatorException) {
  2088                 // Throw cause if it's CertPathValidatorException,
  2161                 // Throw cause if it's CertPathValidatorException,
  2089                 if (e.getCause() != null &&
  2162                 if (e.getCause() != null &&