1 /* 2 * Copyright (c) 1999, 2007, 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.security; 29 import java.net; 30 import java.util; 31 import java.util.jar; 32 33 /** 34 * The JCE security manager. 35 * 36 * <p>The JCE security manager is responsible for determining the maximum 37 * allowable cryptographic strength for a given applet/application, for a given 38 * algorithm, by consulting the configured jurisdiction policy files and 39 * the cryptographic permissions bundled with the applet/application. 40 * 41 * <p>Note that this security manager is never installed, only instantiated. 42 * 43 * @author Jan Luehe 44 * 45 * @since 1.4 46 */ 47 48 final class JceSecurityManager extends SecurityManager { 49 50 private static final CryptoPermissions defaultPolicy; 51 private static final CryptoPermissions exemptPolicy; 52 private static final CryptoAllPermission allPerm; 53 private static final Vector TrustedCallersCache = new Vector(2); 54 private static final Map exemptCache = new HashMap(); 55 56 // singleton instance 57 static final JceSecurityManager INSTANCE; 58 59 static { 60 defaultPolicy = JceSecurity.getDefaultPolicy(); 61 exemptPolicy = JceSecurity.getExemptPolicy(); 62 allPerm = CryptoAllPermission.INSTANCE; 63 INSTANCE = (JceSecurityManager) 64 AccessController.doPrivileged(new PrivilegedAction() { 65 public Object run() { 66 return new JceSecurityManager(); 67 } 68 }); 69 } 70 71 private JceSecurityManager() { 72 // empty 73 } 74 75 /** 76 * Returns the maximum allowable crypto strength for the given 77 * applet/application, for the given algorithm. 78 */ 79 CryptoPermission getCryptoPermission(String alg) { 80 // Need to convert to uppercase since the crypto perm 81 // lookup is case sensitive. 82 alg = alg.toUpperCase(Locale.ENGLISH); 83 84 // If CryptoAllPermission is granted by default, we return that. 85 // Otherwise, this will be the permission we return if anything goes 86 // wrong. 87 CryptoPermission defaultPerm = getDefaultPermission(alg); 88 if (defaultPerm == CryptoAllPermission.INSTANCE) { 89 return defaultPerm; 90 } 91 92 // Determine the codebase of the caller of the JCE API. 93 // This is the codebase of the first class which is not in 94 // javax.crypto.* packages. 95 // NOTE: javax.crypto.* package maybe subject to package 96 // insertion, so need to check its classloader as well. 97 Class[] context = getClassContext(); 98 URL callerCodeBase = null; 99 int i; 100 for (i=0; i<context.length; i++) { 101 Class cls = context[i]; 102 callerCodeBase = JceSecurity.getCodeBase(cls); 103 if (callerCodeBase != null) { 104 break; 105 } else { 106 if (cls.getName().startsWith("javax.crypto.")) { 107 // skip jce classes since they aren't the callers 108 continue; 109 } 110 // use default permission when the caller is system classes 111 return defaultPerm; 112 } 113 } 114 115 if (i == context.length) { 116 return defaultPerm; 117 } 118 119 CryptoPermissions appPerms; 120 synchronized (this.getClass()) { 121 if (exemptCache.containsKey(callerCodeBase)) { 122 appPerms = (CryptoPermissions)exemptCache.get(callerCodeBase); 123 } else { 124 appPerms = getAppPermissions(callerCodeBase); 125 exemptCache.put(callerCodeBase, appPerms); 126 } 127 } 128 129 if (appPerms == null) { 130 return defaultPerm; 131 } 132 133 // If the app was granted the special CryptoAllPermission, return that. 134 if (appPerms.implies(allPerm)) { 135 return allPerm; 136 } 137 138 // Check if the crypto permissions granted to the app contain a 139 // crypto permission for the requested algorithm that does not require 140 // any exemption mechanism to be enforced. 141 // Return that permission, if present. 142 PermissionCollection appPc = appPerms.getPermissionCollection(alg); 143 if (appPc == null) { 144 return defaultPerm; 145 } 146 Enumeration enum_ = appPc.elements(); 147 while (enum_.hasMoreElements()) { 148 CryptoPermission cp = (CryptoPermission)enum_.nextElement(); 149 if (cp.getExemptionMechanism() == null) { 150 return cp; 151 } 152 } 153 154 // Check if the jurisdiction file for exempt applications contains 155 // any entries for the requested algorithm. 156 // If not, return the default permission. 157 PermissionCollection exemptPc = 158 exemptPolicy.getPermissionCollection(alg); 159 if (exemptPc == null) { 160 return defaultPerm; 161 } 162 163 // In the jurisdiction file for exempt applications, go through the 164 // list of CryptoPermission entries for the requested algorithm, and 165 // stop at the first entry: 166 // - that is implied by the collection of crypto permissions granted 167 // to the app, and 168 // - whose exemption mechanism is available from one of the 169 // registered CSPs 170 enum_ = exemptPc.elements(); 171 while (enum_.hasMoreElements()) { 172 CryptoPermission cp = (CryptoPermission)enum_.nextElement(); 173 try { 174 ExemptionMechanism.getInstance(cp.getExemptionMechanism()); 175 if (cp.getAlgorithm().equals( 176 CryptoPermission.ALG_NAME_WILDCARD)) { 177 CryptoPermission newCp; 178 if (cp.getCheckParam()) { 179 newCp = new CryptoPermission( 180 alg, cp.getMaxKeySize(), 181 cp.getAlgorithmParameterSpec(), 182 cp.getExemptionMechanism()); 183 } else { 184 newCp = new CryptoPermission( 185 alg, cp.getMaxKeySize(), 186 cp.getExemptionMechanism()); 187 } 188 if (appPerms.implies(newCp)) { 189 return newCp; 190 } 191 } 192 193 if (appPerms.implies(cp)) { 194 return cp; 195 } 196 } catch (Exception e) { 197 continue; 198 } 199 } 200 return defaultPerm; 201 } 202 203 private static CryptoPermissions getAppPermissions(URL callerCodeBase) { 204 // Check if app is exempt, and retrieve the permissions bundled with it 205 try { 206 return JceSecurity.verifyExemptJar(callerCodeBase); 207 } catch (Exception e) { 208 // Jar verification fails 209 return null; 210 } 211 212 } 213 214 /** 215 * Returns the default permission for the given algorithm. 216 */ 217 private CryptoPermission getDefaultPermission(String alg) { 218 Enumeration enum_ = 219 defaultPolicy.getPermissionCollection(alg).elements(); 220 return (CryptoPermission)enum_.nextElement(); 221 } 222 223 // See bug 4341369 & 4334690 for more info. 224 boolean isCallerTrusted() { 225 // Get the caller and its codebase. 226 Class[] context = getClassContext(); 227 URL callerCodeBase = null; 228 int i; 229 for (i=0; i<context.length; i++) { 230 callerCodeBase = JceSecurity.getCodeBase(context[i]); 231 if (callerCodeBase != null) { 232 break; 233 } 234 } 235 // The caller is in the JCE framework. 236 if (i == context.length) { 237 return true; 238 } 239 //The caller has been verified. 240 if (TrustedCallersCache.contains(context[i])) { 241 return true; 242 } 243 // Check whether the caller is a trusted provider. 244 try { 245 JceSecurity.verifyProviderJar(callerCodeBase); 246 } catch (Exception e2) { 247 return false; 248 } 249 TrustedCallersCache.addElement(context[i]); 250 return true; 251 } 252 }