Пример #1
1
  /**
   * Load the policies from the specified file. Also checks that the policies are correctly signed.
   */
  private static void loadPolicies(
      File jarPathName, CryptoPermissions defaultPolicy, CryptoPermissions exemptPolicy)
      throws Exception {

    JarFile jf = new JarFile(jarPathName);

    Enumeration<JarEntry> entries = jf.entries();
    while (entries.hasMoreElements()) {
      JarEntry je = entries.nextElement();
      InputStream is = null;
      try {
        if (je.getName().startsWith("default_")) {
          is = jf.getInputStream(je);
          defaultPolicy.load(is);
        } else if (je.getName().startsWith("exempt_")) {
          is = jf.getInputStream(je);
          exemptPolicy.load(is);
        } else {
          continue;
        }
      } finally {
        if (is != null) {
          is.close();
        }
      }

      // Enforce the signer restraint, i.e. signer of JCE framework
      // jar should also be the signer of the two jurisdiction policy
      // jar files.
      JarVerifier.verifyPolicySigned(je.getCertificates());
    }
    // Close and nullify the JarFile reference to help GC.
    jf.close();
    jf = null;
  }
 private Certificate[] getCertificates(final File container, final String entry)
     throws IOException {
   if (container.isDirectory()) {
     return null;
   }
   final JarFile jarFile = this.jarFiles.get(container);
   if (jarFile == null) {
     return null;
   }
   final JarEntry ent = jarFile.getJarEntry(entry);
   return (Certificate[]) ((ent == null) ? null : ent.getCertificates());
 }
Пример #3
0
 VerifierStream(Manifest man, JarEntry je, InputStream is, JarVerifier jv) throws IOException {
   this.is = is;
   this.jv = jv;
   this.mev = new ManifestEntryVerifier(man);
   this.jv.beginEntry(je, mev);
   this.numLeft = je.getSize();
   if (this.numLeft == 0) this.jv.update(-1, this.mev);
 }
Пример #4
0
  public String verify(JarFile jar, String... algorithms) throws IOException {
    if (algorithms == null || algorithms.length == 0) algorithms = new String[] {"MD5", "SHA"};
    else if (algorithms.length == 1 && algorithms[0].equals("-")) return null;

    try {
      Manifest m = jar.getManifest();
      if (m.getEntries().isEmpty()) return "No name sections";

      for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
        JarEntry je = e.nextElement();
        if (MANIFEST_ENTRY.matcher(je.getName()).matches()) continue;

        Attributes nameSection = m.getAttributes(je.getName());
        if (nameSection == null) return "No name section for " + je.getName();

        for (String algorithm : algorithms) {
          try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            String expected = nameSection.getValue(algorithm + "-Digest");
            if (expected != null) {
              byte digest[] = Base64.decodeBase64(expected);
              copy(jar.getInputStream(je), md);
              if (!Arrays.equals(digest, md.digest()))
                return "Invalid digest for "
                    + je.getName()
                    + ", "
                    + expected
                    + " != "
                    + Base64.encodeBase64(md.digest());
            } else reporter.error("could not find digest for " + algorithm + "-Digest");
          } catch (NoSuchAlgorithmException nsae) {
            return "Missing digest algorithm " + algorithm;
          }
        }
      }
    } catch (Exception e) {
      return "Failed to verify due to exception: " + e.getMessage();
    }
    return null;
  }
Пример #5
0
 public CodeSigner[] getCodeSigners(JarFile jar, JarEntry entry) {
   String name = entry.getName();
   if (eagerValidation && sigFileSigners.get(name) != null) {
     /*
      * Force a read of the entry data to generate the
      * verification hash.
      */
     try {
       InputStream s = jar.getInputStream(entry);
       byte[] buffer = new byte[1024];
       int n = buffer.length;
       while (n != -1) {
         n = s.read(buffer, 0, buffer.length);
       }
       s.close();
     } catch (IOException e) {
     }
   }
   return getCodeSigners(name);
 }
Пример #6
0
  /** called when we reach the end of entry in one of the read() methods. */
  private void processEntry(ManifestEntryVerifier mev) throws IOException {
    if (!parsingBlockOrSF) {
      JarEntry je = mev.getEntry();
      if ((je != null) && (je.signers == null)) {
        je.signers = mev.verify(verifiedSigners, sigFileSigners);
        je.certs = mapSignersToCertArray(je.signers);
      }
    } else {

      try {
        parsingBlockOrSF = false;

        if (debug != null) {
          debug.println("processEntry: processing block");
        }

        String uname = mev.getEntry().getName().toUpperCase(Locale.ENGLISH);

        if (uname.endsWith(".SF")) {
          String key = uname.substring(0, uname.length() - 3);
          byte bytes[] = baos.toByteArray();
          // add to sigFileData in case future blocks need it
          sigFileData.put(key, bytes);
          // check pending blocks, we can now process
          // anyone waiting for this .SF file
          Iterator it = pendingBlocks.iterator();
          while (it.hasNext()) {
            SignatureFileVerifier sfv = (SignatureFileVerifier) it.next();
            if (sfv.needSignatureFile(key)) {
              if (debug != null) {
                debug.println("processEntry: processing pending block");
              }

              sfv.setSignatureFile(bytes);
              sfv.process(sigFileSigners, manifestDigests);
            }
          }
          return;
        }

        // now we are parsing a signature block file

        String key = uname.substring(0, uname.lastIndexOf("."));

        if (signerCache == null) signerCache = new ArrayList();

        if (manDig == null) {
          synchronized (manifestRawBytes) {
            if (manDig == null) {
              manDig = new ManifestDigester(manifestRawBytes);
              manifestRawBytes = null;
            }
          }
        }

        SignatureFileVerifier sfv =
            new SignatureFileVerifier(signerCache, manDig, uname, baos.toByteArray());

        if (sfv.needSignatureFileBytes()) {
          // see if we have already parsed an external .SF file
          byte[] bytes = (byte[]) sigFileData.get(key);

          if (bytes == null) {
            // put this block on queue for later processing
            // since we don't have the .SF bytes yet
            // (uname, block);
            if (debug != null) {
              debug.println("adding pending block");
            }
            pendingBlocks.add(sfv);
            return;
          } else {
            sfv.setSignatureFile(bytes);
          }
        }
        sfv.process(sigFileSigners, manifestDigests);

      } catch (IOException ioe) {
        // e.g. sun.security.pkcs.ParsingException
        if (debug != null) debug.println("processEntry caught: " + ioe);
        // ignore and treat as unsigned
      } catch (SignatureException se) {
        if (debug != null) debug.println("processEntry caught: " + se);
        // ignore and treat as unsigned
      } catch (NoSuchAlgorithmException nsae) {
        if (debug != null) debug.println("processEntry caught: " + nsae);
        // ignore and treat as unsigned
      } catch (CertificateException ce) {
        if (debug != null) debug.println("processEntry caught: " + ce);
        // ignore and treat as unsigned
      }
    }
  }
Пример #7
0
  /**
   * This method scans to see which entry we're parsing and keeps various state information
   * depending on what type of file is being parsed.
   */
  public void beginEntry(JarEntry je, ManifestEntryVerifier mev) throws IOException {
    if (je == null) return;

    if (debug != null) {
      debug.println("beginEntry " + je.getName());
    }

    String name = je.getName();

    /*
     * Assumptions:
     * 1. The manifest should be the first entry in the META-INF directory.
     * 2. The .SF/.DSA/.EC files follow the manifest, before any normal entries
     * 3. Any of the following will throw a SecurityException:
     *    a. digest mismatch between a manifest section and
     *       the SF section.
     *    b. digest mismatch between the actual jar entry and the manifest
     */

    if (parsingMeta) {
      String uname = name.toUpperCase(Locale.ENGLISH);
      if ((uname.startsWith("META-INF/") || uname.startsWith("/META-INF/"))) {

        if (je.isDirectory()) {
          mev.setEntry(null, je);
          return;
        }

        if (uname.equals(JarFile.MANIFEST_NAME) || uname.equals(JarIndex.INDEX_NAME)) {
          return;
        }

        if (SignatureFileVerifier.isBlockOrSF(uname)) {
          /* We parse only DSA, RSA or EC PKCS7 blocks. */
          parsingBlockOrSF = true;
          baos.reset();
          mev.setEntry(null, je);
          return;
        }

        // If a META-INF entry is not MF or block or SF, they should
        // be normal entries. According to 2 above, no more block or
        // SF will appear. Let's doneWithMeta.
      }
    }

    if (parsingMeta) {
      doneWithMeta();
    }

    if (je.isDirectory()) {
      mev.setEntry(null, je);
      return;
    }

    // be liberal in what you accept. If the name starts with ./, remove
    // it as we internally canonicalize it with out the ./.
    if (name.startsWith("./")) name = name.substring(2);

    // be liberal in what you accept. If the name starts with /, remove
    // it as we internally canonicalize it with out the /.
    if (name.startsWith("/")) name = name.substring(1);

    // only set the jev object for entries that have a signature
    // (either verified or not)
    if (sigFileSigners.get(name) != null || verifiedSigners.get(name) != null) {
      mev.setEntry(name, je);
      return;
    }

    // don't compute the digest for this entry
    mev.setEntry(null, je);

    return;
  }