home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / Security.java < prev    next >
Text File  |  1998-01-23  |  16KB  |  548 lines

  1. /*
  2.  * @(#)Security.java    1.54 97/02/06
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22.  
  23. package java.security;
  24.  
  25. import java.util.*;
  26. import java.io.*;
  27. /**
  28.  * <p>This class centralizes all security properties and common security
  29.  * methods. One of its primary uses is to manage providers.
  30.  *
  31.  * @version 1.54 97/02/06
  32.  * @author Benjamin Renaud */
  33. public final class Security {
  34.  
  35.     /* Are we debugging? -- for developers */
  36.     static boolean debug = false;
  37.  
  38.     /* Are we displaying errors? -- for users */
  39.     static boolean error = true;
  40.  
  41.     /* The java.security properties */
  42.     private static Properties props; 
  43.  
  44.     /* Where we cache provider properties */
  45.     private static Properties propCache;
  46.  
  47.     /* A vector of providers, in order of priority */
  48.     private static Vector providers;
  49.  
  50.     static {
  51.     initialize();
  52.     }
  53.     
  54.     private static void initialize() {
  55.     props = new Properties();
  56.     propCache = new Properties();
  57.     providers = new Vector();
  58.  
  59.     File propFile = securityPropFile("java.security");
  60.     if (!propFile.exists()) {
  61.         System.err.println("security properties not found. using defaults.");
  62.         initializeStatic();
  63.     } else {
  64.         try {
  65.         FileInputStream fis = new FileInputStream(propFile);
  66.         InputStream is = new BufferedInputStream(fis);
  67.         props.load(is);
  68.         is.close();
  69.         } catch (IOException e) {
  70.         error("could not load security properties file from " + propFile +
  71.               ". using defaults.");
  72.         initializeStatic();
  73.         }
  74.     }
  75.     loadProviders();
  76.     }
  77.  
  78.     /* 
  79.      * Initialize to default values, if <java.home>/lib/java.security
  80.      * is not found.
  81.      */
  82.     private static void initializeStatic() {
  83.     props.put("security.provider.1", "sun.security.provider.Sun");
  84.     props.put("system.scope","sun.security.provider.IdentityDatabase");
  85.     }
  86.  
  87.     /**
  88.      * Don't let anyone instantiate this. 
  89.      */
  90.     private Security() {
  91.     }
  92.  
  93.     /**
  94.      * Loops through provider declarations, which are expected to be
  95.      * of the form:
  96.      *
  97.      * security.provider.1=sun.security.provider.Sun
  98.      * security.provider.2=sun.security.jsafe.Jsafe
  99.      * etc.
  100.      *
  101.      * The order determines the default search order when looking for 
  102.      * an algorithm.
  103.      */
  104.     private static void loadProviders() {
  105.  
  106.     int i = 1;
  107.  
  108.     while(true) {
  109.  
  110.         String name = props.getProperty("security.provider." + i++);
  111.         if (name == null) {
  112.         break;
  113.  
  114.         } else {
  115.         Provider prov = Provider.loadProvider(name);
  116.         if (prov != null) {
  117.             /* This must manipulate the datastructure
  118.                directly, because going through addProviders
  119.                causes a security check to happen, which
  120.                sometimes will cause the security
  121.                initialization to fail with bad
  122.                consequences. */
  123.             providers.addElement(prov);
  124.         }
  125.         }
  126.     }
  127.     }
  128.  
  129.     static File securityPropFile(String filename) {
  130.     // maybe check for a system property which will specify where to
  131.     // look. Someday.
  132.     String sep = File.separator;
  133.     return new File(System.getProperty("java.home") + sep + "lib" + sep + 
  134.             "security" + sep + filename);
  135.     }
  136.  
  137.     /**
  138.      * Looks up providers, and returns the property mapping the key,
  139.      * if any. The order in which the providers are looked up is the
  140.      * provider-preference order, as specificed in the security
  141.      * properties file.
  142.      */
  143.     static String getProviderProperty(String key) {
  144.     
  145.     String prop = propCache.getProperty(key);
  146.     if (prop != null) {
  147.         return prop;
  148.     }
  149.  
  150.     for (int i = 0; i < providers.size(); i++) {
  151.         Provider prov = (Provider)providers.elementAt(i);
  152.         
  153.         prop = prov.getProperty(key);
  154.         if (prop != null) {
  155.         propCache.put(key, prop);
  156.         return prop;
  157.         }
  158.     }
  159.     return prop;
  160.     }
  161.  
  162.     /**
  163.      * We always map names to standard names
  164.      */
  165.     static String getStandardName(String alias, String engineType) {
  166.     return getProviderProperty("Alg.Alias." + engineType + "." + alias);
  167.     }
  168.  
  169.     /** 
  170.      * Gets a specified property for an algorithm. The algorithm name
  171.      * should be a standard name. See Appendix A in the <a href=
  172.      * "../guide/security/CryptoSpec.html#AppA">
  173.      * Java Cryptography Architecture API Specification & Reference </a> 
  174.      * for information about standard algorithm names.
  175.      * One possible use is by specialized algorithm parsers, which may map 
  176.      * classes to algorithms which they understand (much like Key parsers 
  177.      * do).
  178.      *
  179.      * @param algName the algorithm name.
  180.      *
  181.      * @param propName the name of the property to get.
  182.      * 
  183.      * @return the value of the specified property.  
  184.      */
  185.     public static String getAlgorithmProperty(String algName,
  186.                           String propName) {
  187.     return getProviderProperty("Alg." + propName + "." + algName);
  188.     }
  189.  
  190.     /** 
  191.      * Given an algorithm name, returns the name of PublicKey class
  192.      * capable of handling keys for that algorithm. The algorithm name
  193.      * should be a standard name. See Appendix A in the <a href=
  194.      * "../guide/security/CryptoSpec.html#AppA">
  195.      * Java Cryptography Architecture API Specification & Reference </a> 
  196.      * for information about standard algorithm names.
  197.      *
  198.      * @param algName the standard algorithm name for which to get
  199.      * a public key class name.
  200.      */
  201.     static String getPublicKeyClassName(String algName, String format) {
  202.  
  203.     String stdName = getStandardName(algName, "Key");
  204.  
  205.     if (stdName == null) {
  206.         stdName = algName;
  207.     }
  208.  
  209.     String formatAndAlg = "PublicKey." + format + "." + stdName;
  210.     return getProviderProperty(formatAndAlg);
  211.     }
  212.  
  213.  
  214.     /** Given an algorithm name, returns the name of PrivateKey class
  215.      * capable of handling keys for that algorithm. The algorithm name
  216.      * should be a standard name. See Appendix A in the <a href=
  217.      * "../guide/security/CryptoSpec.html#AppA">
  218.      * Java Cryptography Architecture API Specification & Reference </a> 
  219.      * for information about standard algorithm names.
  220.      */
  221.     static String getPrivateKeyClassName(String algName, String format) {
  222.  
  223.     String stdName = getStandardName(algName, "Key");
  224.  
  225.     if (stdName == null) {
  226.         stdName = algName;
  227.     }
  228.  
  229.     return getProviderProperty("PrivateKey." + format + "." + stdName);
  230.     }
  231.  
  232.     static String getEngineClassName(String algName,
  233.                      String engineType)
  234.     throws NoSuchAlgorithmException {
  235.     /* First get the standard name */
  236.     String stdName = getStandardName(algName, engineType);
  237.     
  238.     if (stdName == null) {
  239.         stdName = algName;
  240.     }
  241.  
  242.     Class impl = null;
  243.  
  244.     Enumeration enum = providers.elements();
  245.  
  246.     String classname = getProviderProperty(engineType + "." + stdName);
  247.  
  248.     if (classname != null) {
  249.         return classname;
  250.     }
  251.  
  252.     throw new NoSuchAlgorithmException("algorithm " + algName + 
  253.                        " not available.");
  254.     }
  255.  
  256.     /** Given an algorithm name, returns the name of Signature class
  257.      * capable of handling keys for that algorithm. The algorithm name
  258.      * should be a standard name. See Appendix A in the <a href=
  259.      * "../guide/security/CryptoSpec.html#AppA">
  260.      * Java Cryptography Architecture API Specification & Reference </a> 
  261.      * for information about standard algorithm names.
  262.      */
  263.     private static String getEngineClassName(String algName, String provider, 
  264.                          String engineType) 
  265.     throws NoSuchAlgorithmException, NoSuchProviderException {
  266.  
  267.     if (provider == null) {
  268.         return getEngineClassName(algName, engineType);
  269.     }
  270.  
  271.     /* First get the standard name */
  272.     String stdName = getStandardName(algName, engineType);
  273.     
  274.     if (stdName == null) {
  275.         stdName = algName;
  276.     }
  277.  
  278.     Provider prov = getProvider(provider);
  279.     if (prov == null) {
  280.         throw new NoSuchProviderException("no such provider: " +
  281.                         provider);
  282.     }
  283.     
  284.     String className = prov.getProperty(engineType + "." + stdName);
  285.     if (className == null) {
  286.         throw new NoSuchAlgorithmException("no such algorithm: " +
  287.                              algName + 
  288.                              " for provider " +
  289.                          provider);
  290.     }
  291.     return className;
  292.     }
  293.  
  294.     /**
  295.      * Adds a new provider, at a specified position. The position is
  296.      * the preference order in which providers are searched for
  297.      * requested algorithms. Note that it is not guaranteed that this
  298.      * preference will be respected. The position is 1-based, that is,
  299.      * 1 is most preferred, followed by 2, and so on. Sometimes it
  300.      * will be legal to add a provider, but only in the last position,
  301.      * in which case the <code>position</code> argument will be ignored. 
  302.      * 
  303.      * <p>A provider cannot be added if it is already installed.
  304.      *
  305.      * @param provider the provider to be added.
  306.      *
  307.      * @param position the preference position that the caller would
  308.      * like for this provider.
  309.      *
  310.      * @return the actual preference position in which the provider was 
  311.      * added, or -1 if the provider was not added because it is
  312.      * already installed.
  313.      *
  314.      * @see #getProvider
  315.      * @see #removeProvider 
  316.      */
  317.     public static int insertProviderAt(Provider provider, int position) {
  318.  
  319.     check();
  320.  
  321.     /* First check if the provider is already installed */
  322.     Provider already = getProvider(provider.getName());
  323.     if (already != null) {
  324.         return -1;
  325.     }    
  326.         
  327.     /* Internally, position is position - 1 */
  328.     position--;
  329.  
  330.     if (position < 0) {
  331.         position = 0;
  332.     }
  333.     
  334.     int size = providers.size();
  335.     if (position > size) {
  336.         position = size;
  337.     }
  338.  
  339.     providers.insertElementAt(provider, position);
  340.  
  341.     /* clear the prop caches */
  342.     propCache = new Properties();
  343.     
  344.     return position;
  345.     }
  346.  
  347.     /**
  348.      * Adds a provider to the next position available.
  349.      *
  350.      * @param provider the provider to be added.
  351.      *
  352.      * @return the preference position in which the provider was 
  353.      * added, or -1 if the provider was not added because it is
  354.      * already installed.
  355.      * 
  356.      * @see #getProvider
  357.      * @see #removeProvider
  358.      */
  359.     public static int addProvider(Provider provider) {
  360.     
  361.     return insertProviderAt(provider, providers.size() + 1);
  362.     }
  363.  
  364.     /**
  365.      * Removes the provider with the specified name.  This method
  366.      * returns silently if the provider is not installed.
  367.      *
  368.      * @param name the name of the provider to remove.
  369.      *
  370.      * @see #getProvider
  371.      * @see #addProvider
  372.      */
  373.     public static void removeProvider(String name) {
  374.  
  375.     check();
  376.     
  377.     Provider provider = getProvider(name);
  378.  
  379.     if (provider != null) {
  380.         providers.removeElement(provider);
  381.     }
  382.     }
  383.  
  384.     
  385.     /**
  386.      * Returns all providers currently installed.
  387.      * 
  388.      * @return an array of all providers currently installed.
  389.      */
  390.     public static Provider[] getProviders() {
  391.     check();
  392.     Provider[] result = new Provider[providers.size()];
  393.     providers.copyInto(result);
  394.     return result;
  395.     }
  396.  
  397.     /**
  398.      * Returns the provider installed with the specified name, if
  399.      * any. Returns null if no provider with the speicified name is
  400.      * installed.
  401.      * 
  402.      * @param name the name of the provider to get.
  403.      * 
  404.      * @return the provider of the specified name.
  405.      *
  406.      * @see #removeProvider
  407.      * @see #addProvider
  408.      */
  409.     public static Provider getProvider(String name) {
  410.     check();
  411.     Enumeration enum = providers.elements();
  412.     while (enum.hasMoreElements()) {
  413.         Provider prov = (Provider)enum.nextElement();
  414.         if (prov.getName().equals(name)) {
  415.         return prov;
  416.         }
  417.     }
  418.     return null;
  419.     }
  420.  
  421.     private static boolean checkSuperclass(Class subclass, Class superclass) {
  422.     while(!subclass.equals(superclass)) {
  423.         subclass = subclass.getSuperclass();
  424.         if (subclass == null) {
  425.         return false;
  426.         }
  427.     }
  428.     return true;
  429.     }
  430.  
  431.     /*
  432.      * Return an object configured to implemented type. Provider can
  433.      * be null, in which case all providers will be searched in order
  434.      * of preference.
  435.      */
  436.     static Object getImpl(String algorithm, String type, String provider)
  437.     throws NoSuchAlgorithmException, NoSuchProviderException {    
  438.  
  439.     String className = getEngineClassName(algorithm, provider, type);
  440.  
  441.     try {
  442.         Class typeClass = Class.forName("java.security." + type);
  443.         Class cl = Class.forName(className);
  444.  
  445.         if (checkSuperclass(cl, typeClass)) {
  446.         return cl.newInstance();
  447.         } else {
  448.         throw new NoSuchAlgorithmException("class configured for " + 
  449.                            type + ": " + className + 
  450.                            " not a " + type);
  451.         }
  452.     } catch (ClassNotFoundException e) {
  453.         throw new NoSuchAlgorithmException("class configured for " + 
  454.                            type + "(provider: " + 
  455.                            provider + ")" + 
  456.                            "cannot be found.\n" + 
  457.                            e.getMessage());
  458.     } catch (InstantiationException e) {
  459.         throw new NoSuchAlgorithmException("class " + className + 
  460.                            " configured for " + type +
  461.                            "(provider: " + provider + 
  462.                            ") cannot be instantiated.\n" + 
  463.                            e.getMessage());
  464.     } catch (IllegalAccessException e) {
  465.         throw new NoSuchAlgorithmException("class " + className + 
  466.                            " configured for " + type +
  467.                            "(provider: " + provider +
  468.                            ") cannot be accessed.\n" + 
  469.                            e.getMessage());
  470.     }
  471.     }
  472.  
  473.     /**
  474.      * Gets a security property.
  475.      *
  476.      * @param key the key of the property being retrieved.
  477.      *
  478.      * @return the valeu of the security property corresponding to key.
  479.      */
  480.     public static String getProperty(String key) {
  481.     check();
  482.     return props.getProperty(key);
  483.     }
  484.  
  485.     /**
  486.      * Sets a security property.
  487.      *
  488.      * @param key the name of the property to be set.
  489.      *
  490.      * @param datum the value of the property to be set.
  491.      */
  492.     public static void setProperty(String key, String datum) {
  493.     check();
  494.     props.put(key, datum);
  495.     }
  496.  
  497.     private static void check() {
  498.     
  499.     SecurityManager security = System.getSecurityManager();
  500.     if (security != null) {
  501.         security.checkSecurityAccess("java");
  502.     }
  503.     }
  504.     
  505.     /**
  506.      * Print an error message that may be significant to a user.
  507.      */
  508.     static void error(String msg) {
  509.     if (debug) {
  510.         System.err.println(msg);
  511.     }
  512.     }
  513.  
  514.     /**
  515.      * Print an error message that may be significant to a user.
  516.      */
  517.     static void error(String msg, Throwable t) {
  518.     error(msg);
  519.     if (debug) {
  520.         t.printStackTrace();
  521.     }
  522.     }
  523.     
  524.     /**
  525.      * Print an debugging message that may be significant to a developer.
  526.      */
  527.     static void debug(String msg) {
  528.     if (debug) {
  529.         System.err.println(msg);
  530.     }
  531.     }
  532.  
  533.     /**
  534.      * Print an debugging message that may be significant to a developer.
  535.      */
  536.     static void debug(String msg, Throwable t) {
  537.     if (debug) {
  538.         t.printStackTrace();
  539.         System.err.println(msg);
  540.     }
  541.     }
  542.  
  543.     
  544.     
  545. }
  546.     
  547.  
  548.