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