2445 lines · 92.7 KB · Java
RawDownload
        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