1 /*
2  * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package javax.crypto;
27 
28 import java.io.*;
29 import java.net.*;
30 import java.security.*;
31 import java.util.jar.*;
32 
33 /**
34  * This class verifies JAR files (and any supporting JAR files), and
35  * determines whether they may be used in this implementation.
36  *
37  * The JCE in OpenJDK has an open cryptographic interface, meaning it
38  * does not restrict which providers can be used.  Compliance with
39  * United States export controls and with local law governing the
40  * import/export of products incorporating the JCE in the OpenJDK is
41  * the responsibility of the licensee.
42  *
43  * @since 1.7
44  */
45 final class JarVerifier {
46 
47     // The URL for the JAR file we want to verify.
48     private URL jarURL;
49     private boolean savePerms;
50     private CryptoPermissions appPerms = null;
51 
52     /**
53      * Creates a JarVerifier object to verify the given URL.
54      *
55      * @param jarURL the JAR file to be verified.
56      * @param savePerms if true, save the permissions allowed by the
57      *          exemption mechanism
58      */
JarVerifier(URL jarURL, boolean savePerms)59     JarVerifier(URL jarURL, boolean savePerms) {
60         this.jarURL = jarURL;
61         this.savePerms = savePerms;
62     }
63 
64     /**
65      * Verify the JAR file is signed by an entity which has a certificate
66      * issued by a trusted CA.
67      *
68      * In OpenJDK, we just need to examine the "cryptoperms" file to see
69      * if any permissions were bundled together with this jar file.
70      */
verify()71     void verify() throws JarException, IOException {
72 
73         // Short-circuit.  If we weren't asked to save any, we're done.
74         if (!savePerms) {
75             return;
76         }
77 
78         // If the protocol of jarURL isn't "jar", we should
79         // construct a JAR URL so we can open a JarURLConnection
80         // for verifying this provider.
81         final URL url = jarURL.getProtocol().equalsIgnoreCase("jar")?
82                         jarURL : new URL("jar:" + jarURL.toString() + "!/");
83 
84         JarFile jf = null;
85         try {
86 
87             // Get a link to the Jarfile to search.
88             try {
89                 jf = AccessController.doPrivileged(
90                          new PrivilegedExceptionAction<JarFile>() {
91                              public JarFile run() throws Exception {
92                                  JarURLConnection conn =
93                                      (JarURLConnection) url.openConnection();
94                                  // You could do some caching here as
95                                  // an optimization.
96                                  conn.setUseCaches(false);
97                                  return conn.getJarFile();
98                              }
99                          });
100             } catch (java.security.PrivilegedActionException pae) {
101                 throw new SecurityException("Cannot load " + url.toString(), pae);
102             }
103 
104             if (jf != null) {
105                 JarEntry je = jf.getJarEntry("cryptoPerms");
106                 if (je == null) {
107                     throw new JarException(
108                         "Can not find cryptoPerms");
109                 }
110                 try {
111                     appPerms = new CryptoPermissions();
112                     appPerms.load(jf.getInputStream(je));
113                 } catch (Exception ex) {
114                     JarException jex =
115                         new JarException("Cannot load/parse" +
116                             jarURL.toString());
117                     jex.initCause(ex);
118                     throw jex;
119                 }
120             }
121         } finally {
122             // Only call close() when caching is not enabled.
123             // Otherwise, exceptions will be thrown for all
124             // subsequent accesses of this cached jar.
125             if (jf != null) {
126                 jf.close();
127             }
128         }
129     }
130 
131     /**
132      * Verify that the provided certs include the
133      * framework signing certificate.
134      *
135      * @param certs the list of certs to be checked.
136      * @throws Exception if the list of certs did not contain
137      *          the framework signing certificate
138      */
verifyPolicySigned(java.security.cert.Certificate[] certs)139     static void verifyPolicySigned(java.security.cert.Certificate[] certs)
140             throws Exception {
141     }
142 
143     /**
144      * Returns the permissions which are bundled with the JAR file,
145      * aka the "cryptoperms" file.
146      *
147      * NOTE: if this JarVerifier instance is constructed with "savePerms"
148      * equal to false, then this method would always return null.
149      */
getPermissions()150     CryptoPermissions getPermissions() {
151         return appPerms;
152     }
153 }
154