for (CodeSigner signer: signers) { int result = inKeyStoreForOneSigner(signer); output |= result; } if (ckaliases.size() > 0 && (output & SIGNED_BY_ALIAS) == 0) { output |= NOT_ALIAS; } return output; } void signJar(String jarName, String alias, String[] args) throws Exception { boolean aliasUsed = false; X509Certificate tsaCert = null; if (sigfile == null) { sigfile = alias; aliasUsed = true; } if (sigfile.length() > 8) { sigfile = sigfile.substring(0, 8).toUpperCase(Locale.ENGLISH); } else { sigfile = sigfile.toUpperCase(Locale.ENGLISH); } StringBuilder tmpSigFile = new StringBuilder(sigfile.length()); for (int j = 0; j < sigfile.length(); j++) { char c = sigfile.charAt(j); if (! ((c>= 'A' && c<= 'Z') || (c>= '0' && c<= '9') || (c == '-') || (c == '_'))) { if (aliasUsed) { // convert illegal characters from the alias to be _'s c = '_'; } else { throw new RuntimeException(rb.getString ("signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.")); } } tmpSigFile.append(c); } sigfile = tmpSigFile.toString(); String tmpJarName; if (signedjar == null) tmpJarName = jarName+".sig"; else tmpJarName = signedjar; File jarFile = new File(jarName); File signedJarFile = new File(tmpJarName); // Open the jar (zip) file try { zipFile = new ZipFile(jarName); } catch (IOException ioe) { error(rb.getString("unable.to.open.jar.file.")+jarName, ioe); } FileOutputStream fos = null; try { fos = new FileOutputStream(signedJarFile); } catch (IOException ioe) { error(rb.getString("unable.to.create.")+tmpJarName, ioe); } PrintStream ps = new PrintStream(fos); ZipOutputStream zos = new ZipOutputStream(ps); /* First guess at what they might be - we don't xclude RSA ones. */ String sfFilename = (META_INF + sigfile + ".SF").toUpperCase(Locale.ENGLISH); String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase(Locale.ENGLISH); Manifest manifest = new Manifest(); Map<String,Attributes> mfEntries = manifest.getEntries(); // The Attributes of manifest before updating Attributes oldAttr = null; boolean mfModified = false; boolean mfCreated = false; byte[] mfRawBytes = null; try { MessageDigest digests[] = { MessageDigest.getInstance(digestalg) }; // Check if manifest exists ZipEntry mfFile; if ((mfFile = getManifestFile(zipFile)) != null) { // Manifest exists. Read its raw bytes. mfRawBytes = getBytes(zipFile, mfFile); manifest.read(new ByteArrayInputStream(mfRawBytes)); oldAttr = (Attributes)(manifest.getMainAttributes().clone()); } else { // Create new manifest Attributes mattr = manifest.getMainAttributes(); mattr.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0"); String javaVendor = System.getProperty("java.vendor"); String jdkVersion = System.getProperty("java.version"); mattr.putValue("Created-By", jdkVersion + " (" +javaVendor + ")"); mfFile = new ZipEntry(JarFile.MANIFEST_NAME); mfCreated = true; } /* * For each entry in jar * (except for signature-related META-INF entries), * do the following: * * - if entry is not contained in manifest, add it to manifest; * - if entry is contained in manifest, calculate its hash and * compare it with the one in the manifest; if they are * different, replace the hash in the manifest with the newly * generated one. (This may invalidate existing signatures!) */ BASE64Encoder encoder = new JarBASE64Encoder(); Vector<ZipEntry> mfFiles = new Vector<>(); boolean wasSigned = false; for (Enumeration<? extends ZipEntry> enum_=zipFile.entries(); enum_.hasMoreElements();) { ZipEntry ze = enum_.nextElement(); if (ze.getName().startsWith(META_INF)) { // Store META-INF files in vector, so they can be written // out first mfFiles.addElement(ze); if (SignatureFileVerifier.isBlockOrSF( ze.getName().toUpperCase(Locale.ENGLISH))) { wasSigned = true; } if (signatureRelated(ze.getName())) { // ignore signature-related and manifest files continue; } } if (manifest.getAttributes(ze.getName()) != null) { // jar entry is contained in manifest, check and // possibly update its digest attributes if (updateDigests(ze, zipFile, digests, encoder, manifest) == true) { mfModified = true; } } else if (!ze.isDirectory()) { // Add entry to manifest Attributes attrs = getDigestAttributes(ze, zipFile, digests, encoder); mfEntries.put(ze.getName(), attrs); mfModified = true; } } // Recalculate the manifest raw bytes if necessary if (mfModified) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); manifest.write(baos); if (wasSigned) { byte[] newBytes = baos.toByteArray(); if (mfRawBytes != null && oldAttr.equals(manifest.getMainAttributes())) { /* * Note: * * The Attributes object is based on HashMap and can handle * continuation columns. Therefore, even if the contents are * not changed (in a Map view), the bytes that it write() * may be different from the original bytes that it read() * from. Since the signature on the main attributes is based * on raw bytes, we must retain the exact bytes. */ int newPos = findHeaderEnd(newBytes); int oldPos = findHeaderEnd(mfRawBytes); if (newPos == oldPos) { System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos); } else { // cat oldHead newTail > newBytes byte[] lastBytes = new byte[oldPos + newBytes.length - newPos]; System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos); System.arraycopy(newBytes, newPos, lastBytes, oldPos, newBytes.length - newPos); newBytes = lastBytes; } } mfRawBytes = newBytes; } else { mfRawBytes = baos.toByteArray(); } } // Write out the manifest if (mfModified) { // manifest file has new length mfFile = new ZipEntry(JarFile.MANIFEST_NAME); } if (verbose != null) { if (mfCreated) { System.out.println(rb.getString(".adding.") + mfFile.getName()); } else if (mfModified) { System.out.println(rb.getString(".updating.") + mfFile.getName()); } } zos.putNextEntry(mfFile); zos.write(mfRawBytes); // Calculate SignatureFile (".SF") and SignatureBlockFile ManifestDigester manDig = new ManifestDigester(mfRawBytes); SignatureFile sf = new SignatureFile(digests, manifest, manDig, sigfile, signManifest); if (tsaAlias != null) { tsaCert = getTsaCert(tsaAlias); } SignatureFile.Block block = null; try { block = sf.generateBlock(privateKey, sigalg, certChain, externalSF, tsaUrl, tsaCert, signingMechanism, args, zipFile); } catch (SocketTimeoutException e) { // Provide a helpful message when TSA is beyond a firewall error(rb.getString("unable.to.sign.jar.") + rb.getString("no.response.from.the.Timestamping.Authority.") + "\n -J-Dhttp.proxyHost=<hostname>" + "\n -J-Dhttp.proxyPort=<portnumber>\n" + rb.getString("or") + "\n -J-Dhttps.proxyHost=<hostname> " + "\n -J-Dhttps.proxyPort=<portnumber> ", e); } sfFilename = sf.getMetaName(); bkFilename = block.getMetaName(); ZipEntry sfFile = new ZipEntry(sfFilename); ZipEntry bkFile = new ZipEntry(bkFilename); long time = System.currentTimeMillis(); sfFile.setTime(time); bkFile.setTime(time); // signature file zos.putNextEntry(sfFile); sf.write(zos); if (verbose != null) { if (zipFile.getEntry(sfFilename) != null) { System.out.println(rb.getString(".updating.") + sfFilename); } else { System.out.println(rb.getString(".adding.") + sfFilename); } } if (verbose != null) { if (tsaUrl != null || tsaCert != null) { System.out.println( rb.getString("requesting.a.signature.timestamp")); } if (tsaUrl != null) { System.out.println(rb.getString("TSA.location.") + tsaUrl); } if (tsaCert != null) { String certUrl = TimestampedSigner.getTimestampingUrl(tsaCert); if (certUrl != null) { System.out.println(rb.getString("TSA.location.") + certUrl); } System.out.println(rb.getString("TSA.certificate.") + printCert("", tsaCert, false, 0, false)); } if (signingMechanism != null) { System.out.println( rb.getString("using.an.alternative.signing.mechanism")); } } // signature block file zos.putNextEntry(bkFile); block.write(zos); if (verbose != null) { if (zipFile.getEntry(bkFilename) != null) { System.out.println(rb.getString(".updating.") + bkFilename); } else { System.out.println(rb.getString(".adding.") + bkFilename); } } // Write out all other META-INF files that we stored in the // vector for (int i=0; i<mfFiles.size(); i++) { ZipEntry ze = mfFiles.elementAt(i); if (!ze.getName().equalsIgnoreCase(JarFile.MANIFEST_NAME) && !ze.getName().equalsIgnoreCase(sfFilename) && !ze.getName().equalsIgnoreCase(bkFilename)) { writeEntry(zipFile, zos, ze); } } // Write out all other files for (Enumeration<? extends ZipEntry> enum_=zipFile.entries(); enum_.hasMoreElements();) { ZipEntry ze = enum_.nextElement(); if (!ze.getName().startsWith(META_INF)) { if (verbose != null) { if (manifest.getAttributes(ze.getName()) != null) System.out.println(rb.getString(".signing.") + ze.getName()); else System.out.println(rb.getString(".adding.") + ze.getName()); } writeEntry(zipFile, zos, ze); } } } catch(IOException ioe) { error(rb.getString("unable.to.sign.jar.")+ioe, ioe); } finally { // close the resouces if (zipFile != null) { zipFile.close(); zipFile = null; } if (zos != null) { zos.close(); } } // no IOException thrown in the follow try clause, so disable // the try clause. // try { if (signedjar == null) { // attempt an atomic rename. If that fails, // rename the original jar file, then the signed // one, then delete the original. if (!signedJarFile.renameTo(jarFile)) { File origJar = new File(jarName+".orig"); if (jarFile.renameTo(origJar)) { if (signedJarFile.renameTo(jarFile)) { origJar.delete(); } else { MessageFormat form = new MessageFormat(rb.getString ("attempt.to.rename.signedJarFile.to.jarFile.failed")); Object[] source = {signedJarFile, jarFile}; error(form.format(source)); } } else { MessageFormat form = new MessageFormat(rb.getString ("attempt.to.rename.jarFile.to.origJar.failed")); Object[] source = {jarFile, origJar}; error(form.format(source)); } } } if (hasExpiredCert || hasExpiringCert || notYetValidCert || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || chainNotValidated) { System.out.println(); System.out.println(rb.getString("Warning.")); if (badKeyUsage) { System.out.println( rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); } if (badExtendedKeyUsage) { System.out.println( rb.getString("The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.")); } if (badNetscapeCertType) { System.out.println( rb.getString("The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.")); } if (hasExpiredCert) { System.out.println( 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) { System.out.println( rb.getString("The.signer.certificate.is.not.yet.valid.")); } if (chainNotValidated) { System.out.println( rb.getString("The.signer.s.certificate.chain.is.not.validated.")); } } // no IOException thrown in the above try clause, so disable // the catch clause. // } catch(IOException ioe) { // error(rb.getString("unable.to.sign.jar.")+ioe, ioe); // } } /** * Find the length of header inside bs. The header is a multiple (>=0) * lines of attributes plus an empty line. The empty line is included * in the header. */ private int findHeaderEnd(byte[] bs) { // Initial state true to deal with empty header boolean newline = true; // just met a newline int len = bs.length; for (int i=0; i<len; i++) { switch (bs[i]) { case '\r': if (i < len - 1 && bs[i+1] == '\n') i++; // fallthrough case '\n': if (newline) return i+1; //+1 to get length newline = true; break; default: newline = false; } } // If header end is not found, it means the MANIFEST.MF has only // the main attributes section and it does not end with 2 newlines. // Returns the whole length so that it can be completely replaced. return len; } /** * signature-related files include: * . META-INF/MANIFEST.MF * . META-INF/SIG-* * . META-INF/*.SF * . META-INF/*.DSA * . META-INF/*.RSA * . META-INF/*.EC */ private boolean signatureRelated(String name) { String ucName = name.toUpperCase(Locale.ENGLISH); if (ucName.equals(JarFile.MANIFEST_NAME) || ucName.equals(META_INF) || (ucName.startsWith(SIG_PREFIX) && ucName.indexOf("/") == ucName.lastIndexOf("/"))) { return true; } if (ucName.startsWith(META_INF) && SignatureFileVerifier.isBlockOrSF(ucName)) { // .SF/.DSA/.RSA/.EC files in META-INF subdirs // are not considered signature-related return (ucName.indexOf("/") == ucName.lastIndexOf("/")); } return false; } Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>(); /** * Returns a string of singer info, with a newline at the end */ private String signerInfo(CodeSigner signer, String tab, long now) { if (cacheForSignerInfo.containsKey(signer)) { return cacheForSignerInfo.get(signer); } StringBuffer s = new StringBuffer(); List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates(); // display the signature timestamp, if present Timestamp timestamp = signer.getTimestamp(); if (timestamp != null) { s.append(printTimestamp(tab, timestamp)); s.append('\n'); } // display the certificate(s). The first one is end-enity cert and // its KeyUsage should be checked. boolean first = true; for (Certificate c : certs) { s.append(printCert(tab, c, true, now, first));Lines 1001–1500 of 2445. Previous lines Load more
for (CodeSigner signer: signers) { int result = inKeyStoreForOneSigner(signer); output |= result; } if (ckaliases.size() > 0 && (output & SIGNED_BY_ALIAS) == 0) { output |= NOT_ALIAS; } return output; } void signJar(String jarName, String alias, String[] args) throws Exception { boolean aliasUsed = false; X509Certificate tsaCert = null; if (sigfile == null) { sigfile = alias; aliasUsed = true; } if (sigfile.length() > 8) { sigfile = sigfile.substring(0, 8).toUpperCase(Locale.ENGLISH); } else { sigfile = sigfile.toUpperCase(Locale.ENGLISH); } StringBuilder tmpSigFile = new StringBuilder(sigfile.length()); for (int j = 0; j < sigfile.length(); j++) { char c = sigfile.charAt(j); if (! ((c>= 'A' && c<= 'Z') || (c>= '0' && c<= '9') || (c == '-') || (c == '_'))) { if (aliasUsed) { // convert illegal characters from the alias to be _'s c = '_'; } else { throw new RuntimeException(rb.getString ("signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.")); } } tmpSigFile.append(c); } sigfile = tmpSigFile.toString(); String tmpJarName; if (signedjar == null) tmpJarName = jarName+".sig"; else tmpJarName = signedjar; File jarFile = new File(jarName); File signedJarFile = new File(tmpJarName); // Open the jar (zip) file try { zipFile = new ZipFile(jarName); } catch (IOException ioe) { error(rb.getString("unable.to.open.jar.file.")+jarName, ioe); } FileOutputStream fos = null; try { fos = new FileOutputStream(signedJarFile); } catch (IOException ioe) { error(rb.getString("unable.to.create.")+tmpJarName, ioe); } PrintStream ps = new PrintStream(fos); ZipOutputStream zos = new ZipOutputStream(ps); /* First guess at what they might be - we don't xclude RSA ones. */ String sfFilename = (META_INF + sigfile + ".SF").toUpperCase(Locale.ENGLISH); String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase(Locale.ENGLISH); Manifest manifest = new Manifest(); Map<String,Attributes> mfEntries = manifest.getEntries(); // The Attributes of manifest before updating Attributes oldAttr = null; boolean mfModified = false; boolean mfCreated = false; byte[] mfRawBytes = null; try { MessageDigest digests[] = { MessageDigest.getInstance(digestalg) }; // Check if manifest exists ZipEntry mfFile; if ((mfFile = getManifestFile(zipFile)) != null) { // Manifest exists. Read its raw bytes. mfRawBytes = getBytes(zipFile, mfFile); manifest.read(new ByteArrayInputStream(mfRawBytes)); oldAttr = (Attributes)(manifest.getMainAttributes().clone()); } else { // Create new manifest Attributes mattr = manifest.getMainAttributes(); mattr.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0"); String javaVendor = System.getProperty("java.vendor"); String jdkVersion = System.getProperty("java.version"); mattr.putValue("Created-By", jdkVersion + " (" +javaVendor + ")"); mfFile = new ZipEntry(JarFile.MANIFEST_NAME); mfCreated = true; } /* * For each entry in jar * (except for signature-related META-INF entries), * do the following: * * - if entry is not contained in manifest, add it to manifest; * - if entry is contained in manifest, calculate its hash and * compare it with the one in the manifest; if they are * different, replace the hash in the manifest with the newly * generated one. (This may invalidate existing signatures!) */ BASE64Encoder encoder = new JarBASE64Encoder(); Vector<ZipEntry> mfFiles = new Vector<>(); boolean wasSigned = false; for (Enumeration<? extends ZipEntry> enum_=zipFile.entries(); enum_.hasMoreElements();) { ZipEntry ze = enum_.nextElement(); if (ze.getName().startsWith(META_INF)) { // Store META-INF files in vector, so they can be written // out first mfFiles.addElement(ze); if (SignatureFileVerifier.isBlockOrSF( ze.getName().toUpperCase(Locale.ENGLISH))) { wasSigned = true; } if (signatureRelated(ze.getName())) { // ignore signature-related and manifest files continue; } } if (manifest.getAttributes(ze.getName()) != null) { // jar entry is contained in manifest, check and // possibly update its digest attributes if (updateDigests(ze, zipFile, digests, encoder, manifest) == true) { mfModified = true; } } else if (!ze.isDirectory()) { // Add entry to manifest Attributes attrs = getDigestAttributes(ze, zipFile, digests, encoder); mfEntries.put(ze.getName(), attrs); mfModified = true; } } // Recalculate the manifest raw bytes if necessary if (mfModified) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); manifest.write(baos); if (wasSigned) { byte[] newBytes = baos.toByteArray(); if (mfRawBytes != null && oldAttr.equals(manifest.getMainAttributes())) { /* * Note: * * The Attributes object is based on HashMap and can handle * continuation columns. Therefore, even if the contents are * not changed (in a Map view), the bytes that it write() * may be different from the original bytes that it read() * from. Since the signature on the main attributes is based * on raw bytes, we must retain the exact bytes. */ int newPos = findHeaderEnd(newBytes); int oldPos = findHeaderEnd(mfRawBytes); if (newPos == oldPos) { System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos); } else { // cat oldHead newTail > newBytes byte[] lastBytes = new byte[oldPos + newBytes.length - newPos]; System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos); System.arraycopy(newBytes, newPos, lastBytes, oldPos, newBytes.length - newPos); newBytes = lastBytes; } } mfRawBytes = newBytes; } else { mfRawBytes = baos.toByteArray(); } } // Write out the manifest if (mfModified) { // manifest file has new length mfFile = new ZipEntry(JarFile.MANIFEST_NAME); } if (verbose != null) { if (mfCreated) { System.out.println(rb.getString(".adding.") + mfFile.getName()); } else if (mfModified) { System.out.println(rb.getString(".updating.") + mfFile.getName()); } } zos.putNextEntry(mfFile); zos.write(mfRawBytes); // Calculate SignatureFile (".SF") and SignatureBlockFile ManifestDigester manDig = new ManifestDigester(mfRawBytes); SignatureFile sf = new SignatureFile(digests, manifest, manDig, sigfile, signManifest); if (tsaAlias != null) { tsaCert = getTsaCert(tsaAlias); } SignatureFile.Block block = null; try { block = sf.generateBlock(privateKey, sigalg, certChain, externalSF, tsaUrl, tsaCert, signingMechanism, args, zipFile); } catch (SocketTimeoutException e) { // Provide a helpful message when TSA is beyond a firewall error(rb.getString("unable.to.sign.jar.") + rb.getString("no.response.from.the.Timestamping.Authority.") + "\n -J-Dhttp.proxyHost=<hostname>" + "\n -J-Dhttp.proxyPort=<portnumber>\n" + rb.getString("or") + "\n -J-Dhttps.proxyHost=<hostname> " + "\n -J-Dhttps.proxyPort=<portnumber> ", e); } sfFilename = sf.getMetaName(); bkFilename = block.getMetaName(); ZipEntry sfFile = new ZipEntry(sfFilename); ZipEntry bkFile = new ZipEntry(bkFilename); long time = System.currentTimeMillis(); sfFile.setTime(time); bkFile.setTime(time); // signature file zos.putNextEntry(sfFile); sf.write(zos); if (verbose != null) { if (zipFile.getEntry(sfFilename) != null) { System.out.println(rb.getString(".updating.") + sfFilename); } else { System.out.println(rb.getString(".adding.") + sfFilename); } } if (verbose != null) { if (tsaUrl != null || tsaCert != null) { System.out.println( rb.getString("requesting.a.signature.timestamp")); } if (tsaUrl != null) { System.out.println(rb.getString("TSA.location.") + tsaUrl); } if (tsaCert != null) { String certUrl = TimestampedSigner.getTimestampingUrl(tsaCert); if (certUrl != null) { System.out.println(rb.getString("TSA.location.") + certUrl); } System.out.println(rb.getString("TSA.certificate.") + printCert("", tsaCert, false, 0, false)); } if (signingMechanism != null) { System.out.println( rb.getString("using.an.alternative.signing.mechanism")); } } // signature block file zos.putNextEntry(bkFile); block.write(zos); if (verbose != null) { if (zipFile.getEntry(bkFilename) != null) { System.out.println(rb.getString(".updating.") + bkFilename); } else { System.out.println(rb.getString(".adding.") + bkFilename); } } // Write out all other META-INF files that we stored in the // vector for (int i=0; i<mfFiles.size(); i++) { ZipEntry ze = mfFiles.elementAt(i); if (!ze.getName().equalsIgnoreCase(JarFile.MANIFEST_NAME) && !ze.getName().equalsIgnoreCase(sfFilename) && !ze.getName().equalsIgnoreCase(bkFilename)) { writeEntry(zipFile, zos, ze); } } // Write out all other files for (Enumeration<? extends ZipEntry> enum_=zipFile.entries(); enum_.hasMoreElements();) { ZipEntry ze = enum_.nextElement(); if (!ze.getName().startsWith(META_INF)) { if (verbose != null) { if (manifest.getAttributes(ze.getName()) != null) System.out.println(rb.getString(".signing.") + ze.getName()); else System.out.println(rb.getString(".adding.") + ze.getName()); } writeEntry(zipFile, zos, ze); } } } catch(IOException ioe) { error(rb.getString("unable.to.sign.jar.")+ioe, ioe); } finally { // close the resouces if (zipFile != null) { zipFile.close(); zipFile = null; } if (zos != null) { zos.close(); } } // no IOException thrown in the follow try clause, so disable // the try clause. // try { if (signedjar == null) { // attempt an atomic rename. If that fails, // rename the original jar file, then the signed // one, then delete the original. if (!signedJarFile.renameTo(jarFile)) { File origJar = new File(jarName+".orig"); if (jarFile.renameTo(origJar)) { if (signedJarFile.renameTo(jarFile)) { origJar.delete(); } else { MessageFormat form = new MessageFormat(rb.getString ("attempt.to.rename.signedJarFile.to.jarFile.failed")); Object[] source = {signedJarFile, jarFile}; error(form.format(source)); } } else { MessageFormat form = new MessageFormat(rb.getString ("attempt.to.rename.jarFile.to.origJar.failed")); Object[] source = {jarFile, origJar}; error(form.format(source)); } } } if (hasExpiredCert || hasExpiringCert || notYetValidCert || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || chainNotValidated) { System.out.println(); System.out.println(rb.getString("Warning.")); if (badKeyUsage) { System.out.println( rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); } if (badExtendedKeyUsage) { System.out.println( rb.getString("The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.")); } if (badNetscapeCertType) { System.out.println( rb.getString("The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.")); } if (hasExpiredCert) { System.out.println( 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) { System.out.println( rb.getString("The.signer.certificate.is.not.yet.valid.")); } if (chainNotValidated) { System.out.println( rb.getString("The.signer.s.certificate.chain.is.not.validated.")); } } // no IOException thrown in the above try clause, so disable // the catch clause. // } catch(IOException ioe) { // error(rb.getString("unable.to.sign.jar.")+ioe, ioe); // } } /** * Find the length of header inside bs. The header is a multiple (>=0) * lines of attributes plus an empty line. The empty line is included * in the header. */ private int findHeaderEnd(byte[] bs) { // Initial state true to deal with empty header boolean newline = true; // just met a newline int len = bs.length; for (int i=0; i<len; i++) { switch (bs[i]) { case '\r': if (i < len - 1 && bs[i+1] == '\n') i++; // fallthrough case '\n': if (newline) return i+1; //+1 to get length newline = true; break; default: newline = false; } } // If header end is not found, it means the MANIFEST.MF has only // the main attributes section and it does not end with 2 newlines. // Returns the whole length so that it can be completely replaced. return len; } /** * signature-related files include: * . META-INF/MANIFEST.MF * . META-INF/SIG-* * . META-INF/*.SF * . META-INF/*.DSA * . META-INF/*.RSA * . META-INF/*.EC */ private boolean signatureRelated(String name) { String ucName = name.toUpperCase(Locale.ENGLISH); if (ucName.equals(JarFile.MANIFEST_NAME) || ucName.equals(META_INF) || (ucName.startsWith(SIG_PREFIX) && ucName.indexOf("/") == ucName.lastIndexOf("/"))) { return true; } if (ucName.startsWith(META_INF) && SignatureFileVerifier.isBlockOrSF(ucName)) { // .SF/.DSA/.RSA/.EC files in META-INF subdirs // are not considered signature-related return (ucName.indexOf("/") == ucName.lastIndexOf("/")); } return false; } Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>(); /** * Returns a string of singer info, with a newline at the end */ private String signerInfo(CodeSigner signer, String tab, long now) { if (cacheForSignerInfo.containsKey(signer)) { return cacheForSignerInfo.get(signer); } StringBuffer s = new StringBuffer(); List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates(); // display the signature timestamp, if present Timestamp timestamp = signer.getTimestamp(); if (timestamp != null) { s.append(printTimestamp(tab, timestamp)); s.append('\n'); } // display the certificate(s). The first one is end-enity cert and // its KeyUsage should be checked. boolean first = true; for (Certificate c : certs) { s.append(printCert(tab, c, true, now, first));