151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.util.jar;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.*;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.URL;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.*;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.*;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.cert.CertificateException;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.zip.ZipEntry;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.ManifestDigester;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.ManifestEntryVerifier;
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.SignatureFileVerifier;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.Debug;
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author      Roland Schemers
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass JarVerifier {
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Are we debugging ? */
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final Debug debug = Debug.getInstance("jar");
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* a table mapping names to code signers, for jar entries that have
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       had their actual hashes verified */
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Hashtable verifiedSigners;
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* a table mapping names to code signers, for jar entries that have
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       passed the .SF/.DSA/.EC -> MANIFEST check */
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Hashtable sigFileSigners;
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* a hash table to hold .SF bytes */
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Hashtable sigFileData;
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** "queue" of pending PKCS7 blocks that we couldn't parse
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  until we parsed the .SF file */
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ArrayList pendingBlocks;
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* cache of CodeSigner objects */
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ArrayList signerCache;
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Are we parsing a block? */
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean parsingBlockOrSF = false;
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Are we done parsing META-INF entries? */
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean parsingMeta = true;
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Are there are files to verify? */
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean anyToVerify = true;
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* The output stream to use when keeping track of files we are interested
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       in */
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ByteArrayOutputStream baos;
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** The ManifestDigester object */
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private volatile ManifestDigester manDig;
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** the bytes for the manDig object */
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    byte manifestRawBytes[] = null;
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** controls eager signature validation */
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    boolean eagerValidation;
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** makes code source singleton instances unique to us */
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object csdomain = new Object();
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** collect -DIGEST-MANIFEST values for blacklist */
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private List manifestDigests;
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public JarVerifier(byte rawBytes[]) {
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        manifestRawBytes = rawBytes;
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sigFileSigners = new Hashtable();
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        verifiedSigners = new Hashtable();
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sigFileData = new Hashtable(11);
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        pendingBlocks = new ArrayList();
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        baos = new ByteArrayOutputStream();
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        manifestDigests = new ArrayList();
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method scans to see which entry we're parsing and
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * keeps various state information depending on what type of
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * file is being parsed.
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void beginEntry(JarEntry je, ManifestEntryVerifier mev)
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (je == null)
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (debug != null) {
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            debug.println("beginEntry "+je.getName());
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String name = je.getName();
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Assumptions:
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * 1. The manifest should be the first entry in the META-INF directory.
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * 2. The .SF/.DSA/.EC files follow the manifest, before any normal entries
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * 3. Any of the following will throw a SecurityException:
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *    a. digest mismatch between a manifest section and
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *       the SF section.
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *    b. digest mismatch between the actual jar entry and the manifest
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (parsingMeta) {
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String uname = name.toUpperCase(Locale.ENGLISH);
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((uname.startsWith("META-INF/") ||
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 uname.startsWith("/META-INF/"))) {
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (je.isDirectory()) {
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    mev.setEntry(null, je);
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return;
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (SignatureFileVerifier.isBlockOrSF(uname)) {
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    /* We parse only DSA, RSA or EC PKCS7 blocks. */
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    parsingBlockOrSF = true;
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    baos.reset();
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    mev.setEntry(null, je);
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (parsingMeta) {
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            doneWithMeta();
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (je.isDirectory()) {
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            mev.setEntry(null, je);
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // be liberal in what you accept. If the name starts with ./, remove
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // it as we internally canonicalize it with out the ./.
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name.startsWith("./"))
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            name = name.substring(2);
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // be liberal in what you accept. If the name starts with /, remove
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // it as we internally canonicalize it with out the /.
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name.startsWith("/"))
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            name = name.substring(1);
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // only set the jev object for entries that have a signature
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (sigFileSigners.get(name) != null) {
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            mev.setEntry(name, je);
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // don't compute the digest for this entry
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mev.setEntry(null, je);
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return;
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * update a single byte.
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void update(int b, ManifestEntryVerifier mev)
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (b != -1) {
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (parsingBlockOrSF) {
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                baos.write(b);
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                mev.update((byte)b);
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            processEntry(mev);
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * update an array of bytes.
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void update(int n, byte[] b, int off, int len,
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       ManifestEntryVerifier mev)
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n != -1) {
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (parsingBlockOrSF) {
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                baos.write(b, off, n);
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                mev.update(b, off, n);
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            processEntry(mev);
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * called when we reach the end of entry in one of the read() methods.
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void processEntry(ManifestEntryVerifier mev)
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!parsingBlockOrSF) {
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            JarEntry je = mev.getEntry();
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((je != null) && (je.signers == null)) {
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                je.signers = mev.verify(verifiedSigners, sigFileSigners);
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                je.certs = mapSignersToCertArray(je.signers);
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                parsingBlockOrSF = false;
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (debug != null) {
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    debug.println("processEntry: processing block");
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String uname = mev.getEntry().getName()
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                             .toUpperCase(Locale.ENGLISH);
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (uname.endsWith(".SF")) {
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String key = uname.substring(0, uname.length()-3);
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    byte bytes[] = baos.toByteArray();
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // add to sigFileData in case future blocks need it
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    sigFileData.put(key, bytes);
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // check pending blocks, we can now process
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // anyone waiting for this .SF file
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Iterator it = pendingBlocks.iterator();
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    while (it.hasNext()) {
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        SignatureFileVerifier sfv =
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            (SignatureFileVerifier) it.next();
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (sfv.needSignatureFile(key)) {
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (debug != null) {
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                debug.println(
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 "processEntry: processing pending block");
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            sfv.setSignatureFile(bytes);
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            sfv.process(sigFileSigners, manifestDigests);
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return;
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // now we are parsing a signature block file
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String key = uname.substring(0, uname.lastIndexOf("."));
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (signerCache == null)
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    signerCache = new ArrayList();
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (manDig == null) {
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    synchronized(manifestRawBytes) {
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (manDig == null) {
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            manDig = new ManifestDigester(manifestRawBytes);
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            manifestRawBytes = null;
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                SignatureFileVerifier sfv =
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                  new SignatureFileVerifier(signerCache,
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                            manDig, uname, baos.toByteArray());
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (sfv.needSignatureFileBytes()) {
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // see if we have already parsed an external .SF file
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    byte[] bytes = (byte[]) sigFileData.get(key);
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (bytes == null) {
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // put this block on queue for later processing
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // since we don't have the .SF bytes yet
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // (uname, block);
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (debug != null) {
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            debug.println("adding pending block");
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pendingBlocks.add(sfv);
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return;
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sfv.setSignatureFile(bytes);
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sfv.process(sigFileSigners, manifestDigests);
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IOException ioe) {
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // e.g. sun.security.pkcs.ParsingException
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (debug != null) debug.println("processEntry caught: "+ioe);
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // ignore and treat as unsigned
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (SignatureException se) {
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (debug != null) debug.println("processEntry caught: "+se);
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // ignore and treat as unsigned
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (NoSuchAlgorithmException nsae) {
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (debug != null) debug.println("processEntry caught: "+nsae);
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // ignore and treat as unsigned
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (CertificateException ce) {
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (debug != null) debug.println("processEntry caught: "+ce);
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // ignore and treat as unsigned
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return an array of java.security.cert.Certificate objects for
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the given file in the jar.
3289e78cee3f3edf84254174717f475605d712aad1cNarayan Kamath     * @deprecated Deprecated.
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
3309e78cee3f3edf84254174717f475605d712aad1cNarayan Kamath    @Deprecated // Android-changed added "Deprecated."
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public java.security.cert.Certificate[] getCerts(String name)
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return mapSignersToCertArray(getCodeSigners(name));
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public java.security.cert.Certificate[] getCerts(JarFile jar, JarEntry entry)
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return mapSignersToCertArray(getCodeSigners(jar, entry));
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * return an array of CodeSigner objects for
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the given file in the jar. this array is not cloned.
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public CodeSigner[] getCodeSigners(String name)
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (CodeSigner[])verifiedSigners.get(name);
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public CodeSigner[] getCodeSigners(JarFile jar, JarEntry entry)
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String name = entry.getName();
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (eagerValidation && sigFileSigners.get(name) != null) {
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Force a read of the entry data to generate the
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * verification hash.
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                InputStream s = jar.getInputStream(entry);
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                byte[] buffer = new byte[1024];
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int n = buffer.length;
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (n != -1) {
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    n = s.read(buffer, 0, buffer.length);
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                s.close();
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IOException e) {
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getCodeSigners(name);
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Convert an array of signers into an array of concatenated certificate
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * arrays.
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static java.security.cert.Certificate[] mapSignersToCertArray(
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CodeSigner[] signers) {
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (signers != null) {
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ArrayList certChains = new ArrayList();
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < signers.length; i++) {
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                certChains.addAll(
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    signers[i].getSignerCertPath().getCertificates());
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Convert into a Certificate[]
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (java.security.cert.Certificate[])
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                certChains.toArray(
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    new java.security.cert.Certificate[certChains.size()]);
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return null;
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * returns true if there no files to verify.
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * should only be called after all the META-INF entries
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * have been processed.
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    boolean nothingToVerify()
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (anyToVerify == false);
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * called to let us know we have processed all the
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * META-INF entries, and if we re-read one of them, don't
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * re-process it. Also gets rid of any data structures
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * we needed when parsing META-INF entries.
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void doneWithMeta()
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        parsingMeta = false;
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        anyToVerify = !sigFileSigners.isEmpty();
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        baos = null;
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sigFileData = null;
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        pendingBlocks = null;
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        signerCache = null;
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        manDig = null;
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // MANIFEST.MF is always treated as signed and verified,
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // move its signers from sigFileSigners to verifiedSigners.
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (sigFileSigners.containsKey(JarFile.MANIFEST_NAME)) {
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            verifiedSigners.put(JarFile.MANIFEST_NAME,
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    sigFileSigners.remove(JarFile.MANIFEST_NAME));
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static class VerifierStream extends java.io.InputStream {
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private InputStream is;
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private JarVerifier jv;
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private ManifestEntryVerifier mev;
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private long numLeft;
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        VerifierStream(Manifest man,
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       JarEntry je,
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       InputStream is,
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       JarVerifier jv) throws IOException
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
4406dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            // Android changed : Added to make sure inputs are not null. This allows to
4416dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            // use is == null to detect closed verifier streams.
4426dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            if (is == null) {
4436dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath                throw new NullPointerException("is == null");
4446dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            }
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.is = is;
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.jv = jv;
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.mev = new ManifestEntryVerifier(man);
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.jv.beginEntry(je, mev);
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.numLeft = je.getSize();
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (this.numLeft == 0)
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.jv.update(-1, this.mev);
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int read() throws IOException
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
4566dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            // Android added.
4576dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            if (is == null) {
4586dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath                throw new IOException("stream closed");
4596dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            }
4606dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (numLeft > 0) {
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int b = is.read();
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                jv.update(b, mev);
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                numLeft--;
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (numLeft == 0)
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    jv.update(-1, mev);
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return b;
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int read(byte b[], int off, int len) throws IOException {
4746dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            // Android added.
4756dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            if (is == null) {
4766dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath                throw new IOException("stream closed");
4776dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            }
4786dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((numLeft > 0) && (numLeft < len)) {
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                len = (int)numLeft;
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (numLeft > 0) {
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int n = is.read(b, off, len);
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                jv.update(n, b, off, len, mev);
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                numLeft -= n;
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (numLeft == 0)
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    jv.update(-1, b, off, len, mev);
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return n;
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void close()
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws IOException
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (is != null)
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                is.close();
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            is = null;
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            mev = null;
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            jv = null;
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int available() throws IOException {
5066dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            // Android added.
5076dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            if (is == null) {
5086dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath                throw new IOException("stream closed");
5096dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath            }
5106dddb4c2136efba05ffc06f34e6bfed51c9f8ea1Narayan Kamath
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return is.available();
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Extended JavaUtilJarAccess CodeSource API Support
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Map urlToCodeSourceMap = new HashMap();
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Map signerToCodeSource = new HashMap();
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private URL lastURL;
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Map lastURLMap;
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Create a unique mapping from codeSigner cache entries to CodeSource.
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * In theory, multiple URLs origins could map to a single locally cached
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and shared JAR file although in practice there will be a single URL in use.
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private synchronized CodeSource mapSignersToCodeSource(URL url, CodeSigner[] signers) {
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Map map;
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (url == lastURL) {
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            map = lastURLMap;
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            map = (Map) urlToCodeSourceMap.get(url);
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (map == null) {
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                map = new HashMap();
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                urlToCodeSourceMap.put(url, map);
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastURLMap = map;
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastURL = url;
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CodeSource cs = (CodeSource) map.get(signers);
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cs == null) {
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cs = new VerifierCodeSource(csdomain, url, signers);
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signerToCodeSource.put(signers, cs);
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cs;
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private CodeSource[] mapSignersToCodeSources(URL url, List signers, boolean unsigned) {
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List sources = new ArrayList();
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < signers.size(); i++) {
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sources.add(mapSignersToCodeSource(url, (CodeSigner[]) signers.get(i)));
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (unsigned) {
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sources.add(mapSignersToCodeSource(url, null));
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (CodeSource[]) sources.toArray(new CodeSource[sources.size()]);
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private CodeSigner[] emptySigner = new CodeSigner[0];
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Match CodeSource to a CodeSigner[] in the signer cache.
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private CodeSigner[] findMatchingSigners(CodeSource cs) {
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cs instanceof VerifierCodeSource) {
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            VerifierCodeSource vcs = (VerifierCodeSource) cs;
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (vcs.isSameDomain(csdomain)) {
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return ((VerifierCodeSource) cs).getPrivateSigners();
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * In practice signers should always be optimized above
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * but this handles a CodeSource of any type, just in case.
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CodeSource[] sources = mapSignersToCodeSources(cs.getLocation(), getJarCodeSigners(), true);
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List sourceList = new ArrayList();
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < sources.length; i++) {
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sourceList.add(sources[i]);
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int j = sourceList.indexOf(cs);
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (j != -1) {
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CodeSigner[] match;
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            match = ((VerifierCodeSource) sourceList.get(j)).getPrivateSigners();
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (match == null) {
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                match = emptySigner;
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return match;
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return null;
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Instances of this class hold uncopied references to internal
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * signing data that can be compared by object reference identity.
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static class VerifierCodeSource extends CodeSource {
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        URL vlocation;
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CodeSigner[] vsigners;
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        java.security.cert.Certificate[] vcerts;
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object csdomain;
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        VerifierCodeSource(Object csdomain, URL location, CodeSigner[] signers) {
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super(location, signers);
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.csdomain = csdomain;
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            vlocation = location;
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            vsigners = signers; // from signerCache
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        VerifierCodeSource(Object csdomain, URL location, java.security.cert.Certificate[] certs) {
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super(location, certs);
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.csdomain = csdomain;
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            vlocation = location;
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            vcerts = certs; // from signerCache
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * All VerifierCodeSource instances are constructed based on
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * singleton signerCache or signerCacheCert entries for each unique signer.
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * No CodeSigner<->Certificate[] conversion is required.
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * We use these assumptions to optimize equality comparisons.
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean equals(Object obj) {
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (obj == this) {
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return true;
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (obj instanceof VerifierCodeSource) {
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                VerifierCodeSource that = (VerifierCodeSource) obj;
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /*
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * Only compare against other per-signer singletons constructed
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * on behalf of the same JarFile instance. Otherwise, compare
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * things the slower way.
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 */
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (isSameDomain(that.csdomain)) {
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (that.vsigners != this.vsigners
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            || that.vcerts != this.vcerts) {
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return false;
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (that.vlocation != null) {
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return that.vlocation.equals(this.vlocation);
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else if (this.vlocation != null) {
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return this.vlocation.equals(that.vlocation);
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else { // both null
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return true;
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return super.equals(obj);
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isSameDomain(Object csdomain) {
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return this.csdomain == csdomain;
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private CodeSigner[] getPrivateSigners() {
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return vsigners;
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private java.security.cert.Certificate[] getPrivateCertificates() {
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return vcerts;
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Map signerMap;
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private synchronized Map signerMap() {
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (signerMap == null) {
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Snapshot signer state so it doesn't change on us. We care
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * only about the asserted signatures. Verification of
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * signature validity happens via the JarEntry apis.
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signerMap = new HashMap(verifiedSigners.size() + sigFileSigners.size());
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signerMap.putAll(verifiedSigners);
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signerMap.putAll(sigFileSigners);
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return signerMap;
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized Enumeration<String> entryNames(JarFile jar, final CodeSource[] cs) {
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Map map = signerMap();
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Iterator itor = map.entrySet().iterator();
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean matchUnsigned = false;
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Grab a single copy of the CodeSigner arrays. Check
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * to see if we can optimize CodeSigner equality test.
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List req = new ArrayList(cs.length);
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < cs.length; i++) {
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CodeSigner[] match = findMatchingSigners(cs[i]);
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (match != null) {
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (match.length > 0) {
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    req.add(match);
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    matchUnsigned = true;
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final List signersReq = req;
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Enumeration enum2 = (matchUnsigned) ? unsignedEntryNames(jar) : emptyEnumeration;
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new Enumeration<String>() {
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String name;
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public boolean hasMoreElements() {
71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (name != null) {
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (itor.hasNext()) {
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Map.Entry e = (Map.Entry) itor.next();
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (signersReq.contains((CodeSigner[]) e.getValue())) {
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        name = (String) e.getKey();
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return true;
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (enum2.hasMoreElements()) {
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    name = (String) enum2.nextElement();
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public String nextElement() {
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (hasMoreElements()) {
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String value = name;
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    name = null;
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return value;
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NoSuchElementException();
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        };
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Like entries() but screens out internal JAR mechanism entries
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and includes signed entries with no ZIP data.
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Enumeration<JarEntry> entries2(final JarFile jar, Enumeration e) {
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Map map = new HashMap();
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        map.putAll(signerMap());
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Enumeration enum_ = e;
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new Enumeration<JarEntry>() {
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Enumeration signers = null;
75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            JarEntry entry;
75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public boolean hasMoreElements() {
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (entry != null) {
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (enum_.hasMoreElements()) {
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ZipEntry ze = (ZipEntry) enum_.nextElement();
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (JarVerifier.isSigningRelated(ze.getName())) {
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        continue;
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    entry = jar.newEntry(ze);
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (signers == null) {
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    signers = Collections.enumeration(map.keySet());
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (signers.hasMoreElements()) {
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String name = (String) signers.nextElement();
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    entry = jar.newEntry(new ZipEntry(name));
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Any map entries left?
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public JarEntry nextElement() {
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (hasMoreElements()) {
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    JarEntry je = entry;
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    map.remove(je.getName());
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    entry = null;
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return je;
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NoSuchElementException();
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        };
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Enumeration emptyEnumeration = new Enumeration<String>() {
79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean hasMoreElements() {
79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public String nextElement() {
79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NoSuchElementException();
79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    };
79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // true if file is part of the signature mechanism itself
80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static boolean isSigningRelated(String name) {
80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        name = name.toUpperCase(Locale.ENGLISH);
80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!name.startsWith("META-INF/")) {
80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        name = name.substring(9);
80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name.indexOf('/') != -1) {
80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name.endsWith(".DSA")
81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                || name.endsWith(".RSA")
81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                || name.endsWith(".SF")
81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                || name.endsWith(".EC")
81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                || name.startsWith("SIG-")
81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                || name.equals("MANIFEST.MF")) {
81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Enumeration<String> unsignedEntryNames(JarFile jar) {
82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Map map = signerMap();
82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final Enumeration entries = jar.entries();
82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new Enumeration<String>() {
82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String name;
82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Grab entries from ZIP directory but screen out
83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * metadata.
83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public boolean hasMoreElements() {
83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (name != null) {
83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (entries.hasMoreElements()) {
83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String value;
83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ZipEntry e = (ZipEntry) entries.nextElement();
83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    value = e.getName();
84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (e.isDirectory() || isSigningRelated(value)) {
84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        continue;
84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (map.get(value) == null) {
84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        name = value;
84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return true;
84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public String nextElement() {
85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (hasMoreElements()) {
85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String value = name;
85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    name = null;
85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return value;
85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NoSuchElementException();
85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        };
86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private List jarCodeSigners;
86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private synchronized List getJarCodeSigners() {
86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CodeSigner[] signers;
86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (jarCodeSigners == null) {
86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            HashSet set = new HashSet();
86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.addAll(signerMap().values());
86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            jarCodeSigners = new ArrayList();
86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            jarCodeSigners.addAll(set);
87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return jarCodeSigners;
87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized CodeSource[] getCodeSources(JarFile jar, URL url) {
87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean hasUnsigned = unsignedEntryNames(jar).hasMoreElements();
87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return mapSignersToCodeSources(url, getJarCodeSigners(), hasUnsigned);
87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public CodeSource getCodeSource(URL url, String name) {
88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CodeSigner[] signers;
88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        signers = (CodeSigner[]) signerMap().get(name);
88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return mapSignersToCodeSource(url, signers);
88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public CodeSource getCodeSource(URL url, JarFile jar, JarEntry je) {
88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CodeSigner[] signers;
88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return mapSignersToCodeSource(url, getCodeSigners(jar, je));
89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void setEagerValidation(boolean eager) {
89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        eagerValidation = eager;
89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized List getManifestDigests() {
89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return Collections.unmodifiableList(manifestDigests);
89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static CodeSource getUnsignedCS(URL url) {
90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new VerifierCodeSource(null, url, (java.security.cert.Certificate[]) null);
90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
905