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