Home » openjdk-7 » javax » crypto » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2009, 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.util;
   29   import java.util.jar;
   30   import java.io;
   31   import java.net.URL;
   32   import java.security;
   33   
   34   import java.security.Provider.Service;
   35   
   36   import sun.security.jca;
   37   import sun.security.jca.GetInstance.Instance;
   38   
   39   /**
   40    * This class instantiates implementations of JCE engine classes from
   41    * providers registered with the java.security.Security object.
   42    *
   43    * @author Jan Luehe
   44    * @author Sharon Liu
   45    * @since 1.4
   46    */
   47   
   48   final class JceSecurity {
   49   
   50       static final SecureRandom RANDOM = new SecureRandom();
   51   
   52       // The defaultPolicy and exemptPolicy will be set up
   53       // in the static initializer.
   54       private static CryptoPermissions defaultPolicy = null;
   55       private static CryptoPermissions exemptPolicy = null;
   56   
   57       // Map<Provider,?> of the providers we already have verified
   58       // value == PROVIDER_VERIFIED is successfully verified
   59       // value is failure cause Exception in error case
   60       private final static Map verificationResults = new IdentityHashMap();
   61   
   62       // Map<Provider,?> of the providers currently being verified
   63       private final static Map verifyingProviders = new IdentityHashMap();
   64   
   65       // Set the default value. May be changed in the static initializer.
   66       private static boolean isRestricted = true;
   67   
   68       /*
   69        * Don't let anyone instantiate this.
   70        */
   71       private JceSecurity() {
   72       }
   73   
   74       static {
   75           try {
   76               AccessController.doPrivileged(new PrivilegedExceptionAction() {
   77                   public Object run() throws Exception {
   78                       setupJurisdictionPolicies();
   79                       return null;
   80                   }
   81               });
   82   
   83               isRestricted = defaultPolicy.implies(
   84                   CryptoAllPermission.INSTANCE) ? false : true;
   85           } catch (Exception e) {
   86               SecurityException se =
   87                   new SecurityException(
   88                       "Can not initialize cryptographic mechanism");
   89               se.initCause(e);
   90               throw se;
   91           }
   92       }
   93   
   94       static Instance getInstance(String type, Class clazz, String algorithm,
   95               String provider) throws NoSuchAlgorithmException,
   96               NoSuchProviderException {
   97           Service s = GetInstance.getService(type, algorithm, provider);
   98           Exception ve = getVerificationResult(s.getProvider());
   99           if (ve != null) {
  100               String msg = "JCE cannot authenticate the provider " + provider;
  101               throw (NoSuchProviderException)
  102                                   new NoSuchProviderException(msg).initCause(ve);
  103           }
  104           return GetInstance.getInstance(s, clazz);
  105       }
  106   
  107       static Instance getInstance(String type, Class clazz, String algorithm,
  108               Provider provider) throws NoSuchAlgorithmException {
  109           Service s = GetInstance.getService(type, algorithm, provider);
  110           Exception ve = JceSecurity.getVerificationResult(provider);
  111           if (ve != null) {
  112               String msg = "JCE cannot authenticate the provider "
  113                   + provider.getName();
  114               throw new SecurityException(msg, ve);
  115           }
  116           return GetInstance.getInstance(s, clazz);
  117       }
  118   
  119       static Instance getInstance(String type, Class clazz, String algorithm)
  120               throws NoSuchAlgorithmException {
  121           List services = GetInstance.getServices(type, algorithm);
  122           NoSuchAlgorithmException failure = null;
  123           for (Iterator t = services.iterator(); t.hasNext(); ) {
  124               Service s = (Service)t.next();
  125               if (canUseProvider(s.getProvider()) == false) {
  126                   // allow only signed providers
  127                   continue;
  128               }
  129               try {
  130                   Instance instance = GetInstance.getInstance(s, clazz);
  131                   return instance;
  132               } catch (NoSuchAlgorithmException e) {
  133                   failure = e;
  134               }
  135           }
  136           throw new NoSuchAlgorithmException("Algorithm " + algorithm
  137                   + " not available", failure);
  138       }
  139   
  140       /**
  141        * Verify if the JAR at URL codeBase is a signed exempt application
  142        * JAR file and returns the permissions bundled with the JAR.
  143        *
  144        * @throws Exception on error
  145        */
  146       static CryptoPermissions verifyExemptJar(URL codeBase) throws Exception {
  147           JarVerifier jv = new JarVerifier(codeBase, true);
  148           jv.verify();
  149           return jv.getPermissions();
  150       }
  151   
  152       /**
  153        * Verify if the JAR at URL codeBase is a signed provider JAR file.
  154        *
  155        * @throws Exception on error
  156        */
  157       static void verifyProviderJar(URL codeBase) throws Exception {
  158           // Verify the provider JAR file and all
  159           // supporting JAR files if there are any.
  160           JarVerifier jv = new JarVerifier(codeBase, false);
  161           jv.verify();
  162       }
  163   
  164       private final static Object PROVIDER_VERIFIED = Boolean.TRUE;
  165   
  166       /*
  167        * Verify that the provider JAR files are signed properly, which
  168        * means the signer's certificate can be traced back to a
  169        * JCE trusted CA.
  170        * Return null if ok, failure Exception if verification failed.
  171        */
  172       static synchronized Exception getVerificationResult(Provider p) {
  173           Object o = verificationResults.get(p);
  174           if (o == PROVIDER_VERIFIED) {
  175               return null;
  176           } else if (o != null) {
  177               return (Exception)o;
  178           }
  179           if (verifyingProviders.get(p) != null) {
  180               // this method is static synchronized, must be recursion
  181               // return failure now but do not save the result
  182               return new NoSuchProviderException("Recursion during verification");
  183           }
  184           try {
  185               verifyingProviders.put(p, Boolean.FALSE);
  186               URL providerURL = getCodeBase(p.getClass());
  187               verifyProviderJar(providerURL);
  188               // Verified ok, cache result
  189               verificationResults.put(p, PROVIDER_VERIFIED);
  190               return null;
  191           } catch (Exception e) {
  192               verificationResults.put(p, e);
  193               return e;
  194           } finally {
  195               verifyingProviders.remove(p);
  196           }
  197       }
  198   
  199       // return whether this provider is properly signed and can be used by JCE
  200       static boolean canUseProvider(Provider p) {
  201           return getVerificationResult(p) == null;
  202       }
  203   
  204       // dummy object to represent null
  205       private static final URL NULL_URL;
  206   
  207       static {
  208           try {
  209               NULL_URL = new URL("http://null.sun.com/");
  210           } catch (Exception e) {
  211               throw new RuntimeException(e);
  212           }
  213       }
  214   
  215       // reference to a Map we use as a cache for codebases
  216       private static final Map codeBaseCacheRef = new WeakHashMap();
  217   
  218       /*
  219        * Retuns the CodeBase for the given class.
  220        */
  221       static URL getCodeBase(final Class clazz) {
  222           URL url = (URL)codeBaseCacheRef.get(clazz);
  223           if (url == null) {
  224               url = (URL)AccessController.doPrivileged(new PrivilegedAction() {
  225                   public Object run() {
  226                       ProtectionDomain pd = clazz.getProtectionDomain();
  227                       if (pd != null) {
  228                           CodeSource cs = pd.getCodeSource();
  229                           if (cs != null) {
  230                               return cs.getLocation();
  231                           }
  232                       }
  233                       return NULL_URL;
  234                   }
  235               });
  236               codeBaseCacheRef.put(clazz, url);
  237           }
  238           return (url == NULL_URL) ? null : url;
  239       }
  240   
  241       private static void setupJurisdictionPolicies() throws Exception {
  242           String javaHomeDir = System.getProperty("java.home");
  243           String sep = File.separator;
  244           String pathToPolicyJar = javaHomeDir + sep + "lib" + sep +
  245               "security" + sep;
  246   
  247           File exportJar = new File(pathToPolicyJar, "US_export_policy.jar");
  248           File importJar = new File(pathToPolicyJar, "local_policy.jar");
  249           URL jceCipherURL = ClassLoader.getSystemResource
  250                   ("javax/crypto/Cipher.class");
  251   
  252           if ((jceCipherURL == null) ||
  253                   !exportJar.exists() || !importJar.exists()) {
  254               throw new SecurityException
  255                                   ("Cannot locate policy or framework files!");
  256           }
  257   
  258           // Read jurisdiction policies.
  259           CryptoPermissions defaultExport = new CryptoPermissions();
  260           CryptoPermissions exemptExport = new CryptoPermissions();
  261           loadPolicies(exportJar, defaultExport, exemptExport);
  262   
  263           CryptoPermissions defaultImport = new CryptoPermissions();
  264           CryptoPermissions exemptImport = new CryptoPermissions();
  265           loadPolicies(importJar, defaultImport, exemptImport);
  266   
  267           // Merge the export and import policies for default applications.
  268           if (defaultExport.isEmpty() || defaultImport.isEmpty()) {
  269               throw new SecurityException("Missing mandatory jurisdiction " +
  270                                           "policy files");
  271           }
  272           defaultPolicy = defaultExport.getMinimum(defaultImport);
  273   
  274           // Merge the export and import policies for exempt applications.
  275           if (exemptExport.isEmpty())  {
  276               exemptPolicy = exemptImport.isEmpty() ? null : exemptImport;
  277           } else {
  278               exemptPolicy = exemptExport.getMinimum(exemptImport);
  279           }
  280       }
  281   
  282       /**
  283        * Load the policies from the specified file. Also checks that the
  284        * policies are correctly signed.
  285        */
  286       private static void loadPolicies(File jarPathName,
  287                                        CryptoPermissions defaultPolicy,
  288                                        CryptoPermissions exemptPolicy)
  289           throws Exception {
  290   
  291           JarFile jf = new JarFile(jarPathName);
  292   
  293           Enumeration entries = jf.entries();
  294           while (entries.hasMoreElements()) {
  295               JarEntry je = (JarEntry)entries.nextElement();
  296               InputStream is = null;
  297               try {
  298                   if (je.getName().startsWith("default_")) {
  299                       is = jf.getInputStream(je);
  300                       defaultPolicy.load(is);
  301                   } else if (je.getName().startsWith("exempt_")) {
  302                       is = jf.getInputStream(je);
  303                       exemptPolicy.load(is);
  304                   } else {
  305                       continue;
  306                   }
  307               } finally {
  308                   if (is != null) {
  309                       is.close();
  310                   }
  311               }
  312   
  313               // Enforce the signer restraint, i.e. signer of JCE framework
  314               // jar should also be the signer of the two jurisdiction policy
  315               // jar files.
  316               JarVerifier.verifyPolicySigned(je.getCertificates());
  317           }
  318           // Close and nullify the JarFile reference to help GC.
  319           jf.close();
  320           jf = null;
  321       }
  322   
  323       static CryptoPermissions getDefaultPolicy() {
  324           return defaultPolicy;
  325       }
  326   
  327       static CryptoPermissions getExemptPolicy() {
  328           return exemptPolicy;
  329       }
  330   
  331       static boolean isRestricted() {
  332           return isRestricted;
  333       }
  334   }

Home » openjdk-7 » javax » crypto » [javadoc | source]