jdk/src/share/classes/com/sun/security/auth/PolicyFile.java
changeset 19439 57876ed3c426
parent 19212 80526b520497
child 20742 4ae78e8060d6
equal deleted inserted replaced
19438:7de6ae3cecad 19439:57876ed3c426
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package com.sun.security.auth;
    26 package com.sun.security.auth;
    27 
    27 
    28 import java.io.*;
       
    29 import java.lang.reflect.*;
       
    30 import java.net.URL;
       
    31 import java.util.*;
       
    32 
       
    33 import java.security.CodeSource;
    28 import java.security.CodeSource;
    34 import java.security.KeyStore;
       
    35 import java.security.KeyStoreException;
       
    36 import java.security.Permission;
       
    37 import java.security.Permissions;
       
    38 import java.security.PermissionCollection;
    29 import java.security.PermissionCollection;
    39 import java.security.Principal;
       
    40 import java.security.UnresolvedPermission;
       
    41 import java.security.Security;
       
    42 import java.security.cert.Certificate;
       
    43 import java.security.cert.X509Certificate;
       
    44 
       
    45 import javax.security.auth.Subject;
    30 import javax.security.auth.Subject;
    46 import javax.security.auth.PrivateCredentialPermission;
       
    47 
       
    48 import sun.security.util.PropertyExpander;
       
    49 
       
    50 import sun.security.provider.PolicyParser.PrincipalEntry;
       
    51 import sun.security.provider.PolicyParser.GrantEntry;
       
    52 import sun.security.provider.PolicyParser.PermissionEntry;
       
    53 
    31 
    54 /**
    32 /**
    55  * This class represents a default implementation for
    33  * This class represents a default implementation for
    56  * <code>javax.security.auth.Policy</code>.
    34  * <code>javax.security.auth.Policy</code>.
    57  *
    35  *
   238  * @see java.security.Security security properties
   216  * @see java.security.Security security properties
   239  */
   217  */
   240 @Deprecated
   218 @Deprecated
   241 public class PolicyFile extends javax.security.auth.Policy {
   219 public class PolicyFile extends javax.security.auth.Policy {
   242 
   220 
   243     static final java.util.ResourceBundle rb =
   221     private final sun.security.provider.AuthPolicyFile apf;
   244         java.security.AccessController.doPrivileged
       
   245         (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
       
   246             public java.util.ResourceBundle run() {
       
   247                 return (java.util.ResourceBundle.getBundle
       
   248                         ("sun.security.util.AuthResources"));
       
   249             }
       
   250         });
       
   251     // needs to be package private
       
   252 
       
   253     private static final sun.security.util.Debug debug =
       
   254         sun.security.util.Debug.getInstance("policy", "\t[Auth Policy]");
       
   255 
       
   256     private static final String AUTH_POLICY = "java.security.auth.policy";
       
   257     private static final String SECURITY_MANAGER = "java.security.manager";
       
   258     private static final String AUTH_POLICY_URL = "auth.policy.url.";
       
   259 
       
   260     private Vector<PolicyEntry> policyEntries;
       
   261     private Hashtable<Object, Object> aliasMapping;
       
   262 
       
   263     private boolean initialized = false;
       
   264 
       
   265     private boolean expandProperties = true;
       
   266     private boolean ignoreIdentityScope = true;
       
   267 
       
   268     // for use with the reflection API
       
   269 
       
   270     private static final Class[] PARAMS = { String.class, String.class};
       
   271 
   222 
   272     /**
   223     /**
   273      * Initializes the Policy object and reads the default policy
   224      * Initializes the Policy object and reads the default policy
   274      * configuration file(s) into the Policy object.
   225      * configuration file(s) into the Policy object.
   275      */
   226      */
   276     public PolicyFile() {
   227     public PolicyFile() {
   277         // initialize Policy if either the AUTH_POLICY or
   228         apf = new sun.security.provider.AuthPolicyFile();
   278         // SECURITY_MANAGER properties are set
       
   279         String prop = System.getProperty(AUTH_POLICY);
       
   280 
       
   281         if (prop == null) {
       
   282             prop = System.getProperty(SECURITY_MANAGER);
       
   283         }
       
   284         if (prop != null)
       
   285             init();
       
   286     }
       
   287 
       
   288     private synchronized void init() {
       
   289 
       
   290         if (initialized)
       
   291             return;
       
   292 
       
   293         policyEntries = new Vector<PolicyEntry>();
       
   294         aliasMapping = new Hashtable<Object, Object>(11);
       
   295 
       
   296         initPolicyFile();
       
   297         initialized = true;
       
   298     }
   229     }
   299 
   230 
   300     /**
   231     /**
   301      * Refreshes the policy object by re-reading all the policy files.
   232      * Refreshes the policy object by re-reading all the policy files.
   302      *
   233      *
   303      * <p>
   234      * <p>
   304      *
   235      *
   305      * @exception SecurityException if the caller doesn't have permission
   236      * @exception SecurityException if the caller doesn't have permission
   306      *          to refresh the <code>Policy</code>.
   237      *          to refresh the <code>Policy</code>.
   307      */
   238      */
   308     public synchronized void refresh()
   239     @Override
   309     {
   240     public void refresh() {
   310 
   241         apf.refresh();
   311         java.lang.SecurityManager sm = System.getSecurityManager();
       
   312         if (sm != null) {
       
   313             sm.checkPermission(new javax.security.auth.AuthPermission
       
   314                                 ("refreshPolicy"));
       
   315         }
       
   316 
       
   317         // XXX
       
   318         //
       
   319         // 1)   if code instantiates PolicyFile directly, then it will need
       
   320         //      all the permissions required for the PolicyFile initialization
       
   321         // 2)   if code calls Policy.getPolicy, then it simply needs
       
   322         //      AuthPermission(getPolicy), and the javax.security.auth.Policy
       
   323         //      implementation instantiates PolicyFile in a doPrivileged block
       
   324         // 3)   if after instantiating a Policy (either via #1 or #2),
       
   325         //      code calls refresh, it simply needs
       
   326         //      AuthPermission(refreshPolicy).  then PolicyFile wraps
       
   327         //      the refresh in a doPrivileged block.
       
   328         initialized = false;
       
   329         java.security.AccessController.doPrivileged
       
   330             (new java.security.PrivilegedAction<Void>() {
       
   331             public Void run() {
       
   332                 init();
       
   333                 return null;
       
   334             }
       
   335         });
       
   336     }
       
   337 
       
   338     private KeyStore initKeyStore(URL policyUrl, String keyStoreName,
       
   339                                   String keyStoreType) {
       
   340         if (keyStoreName != null) {
       
   341             try {
       
   342                 /*
       
   343                  * location of keystore is specified as absolute URL in policy
       
   344                  * file, or is relative to URL of policy file
       
   345                  */
       
   346                 URL keyStoreUrl = null;
       
   347                 try {
       
   348                     keyStoreUrl = new URL(keyStoreName);
       
   349                     // absolute URL
       
   350                 } catch (java.net.MalformedURLException e) {
       
   351                     // relative URL
       
   352                     keyStoreUrl = new URL(policyUrl, keyStoreName);
       
   353                 }
       
   354 
       
   355                 if (debug != null) {
       
   356                     debug.println("reading keystore"+keyStoreUrl);
       
   357                 }
       
   358 
       
   359                 InputStream inStream =
       
   360                     new BufferedInputStream(getInputStream(keyStoreUrl));
       
   361 
       
   362                 KeyStore ks;
       
   363                 if (keyStoreType != null)
       
   364                     ks = KeyStore.getInstance(keyStoreType);
       
   365                 else
       
   366                     ks = KeyStore.getInstance(KeyStore.getDefaultType());
       
   367                 ks.load(inStream, null);
       
   368                 inStream.close();
       
   369                 return ks;
       
   370             } catch (Exception e) {
       
   371                 // ignore, treat it like we have no keystore
       
   372                 if (debug != null) {
       
   373                     e.printStackTrace();
       
   374                 }
       
   375                 return null;
       
   376             }
       
   377         }
       
   378         return null;
       
   379     }
       
   380 
       
   381     private void initPolicyFile() {
       
   382 
       
   383         String prop = Security.getProperty("policy.expandProperties");
       
   384 
       
   385         if (prop != null) expandProperties = prop.equalsIgnoreCase("true");
       
   386 
       
   387         String iscp = Security.getProperty("policy.ignoreIdentityScope");
       
   388 
       
   389         if (iscp != null) ignoreIdentityScope = iscp.equalsIgnoreCase("true");
       
   390 
       
   391         String allowSys  = Security.getProperty("policy.allowSystemProperty");
       
   392 
       
   393         if ((allowSys!=null) && allowSys.equalsIgnoreCase("true")) {
       
   394 
       
   395             String extra_policy = System.getProperty(AUTH_POLICY);
       
   396             if (extra_policy != null) {
       
   397                 boolean overrideAll = false;
       
   398                 if (extra_policy.startsWith("=")) {
       
   399                     overrideAll = true;
       
   400                     extra_policy = extra_policy.substring(1);
       
   401                 }
       
   402                 try {
       
   403                     extra_policy = PropertyExpander.expand(extra_policy);
       
   404                     URL policyURL;
       
   405                     File policyFile = new File(extra_policy);
       
   406                     if (policyFile.exists()) {
       
   407                         policyURL =
       
   408                             new URL("file:" + policyFile.getCanonicalPath());
       
   409                     } else {
       
   410                         policyURL = new URL(extra_policy);
       
   411                     }
       
   412                     if (debug != null)
       
   413                         debug.println("reading "+policyURL);
       
   414                     init(policyURL);
       
   415                 } catch (Exception e) {
       
   416                     // ignore.
       
   417                     if (debug != null) {
       
   418                         debug.println("caught exception: "+e);
       
   419                     }
       
   420 
       
   421                 }
       
   422                 if (overrideAll) {
       
   423                     if (debug != null) {
       
   424                         debug.println("overriding other policies!");
       
   425                     }
       
   426                     return;
       
   427                 }
       
   428             }
       
   429         }
       
   430 
       
   431         int n = 1;
       
   432         boolean loaded_one = false;
       
   433         String policy_url;
       
   434 
       
   435         while ((policy_url = Security.getProperty(AUTH_POLICY_URL+n)) != null) {
       
   436             try {
       
   437                 policy_url = PropertyExpander.expand(policy_url).replace
       
   438                                                 (File.separatorChar, '/');
       
   439                 if (debug != null)
       
   440                     debug.println("reading "+policy_url);
       
   441                 init(new URL(policy_url));
       
   442                 loaded_one = true;
       
   443             } catch (Exception e) {
       
   444                 if (debug != null) {
       
   445                     debug.println("error reading policy "+e);
       
   446                     e.printStackTrace();
       
   447                 }
       
   448                 // ignore that policy
       
   449             }
       
   450             n++;
       
   451         }
       
   452 
       
   453         if (loaded_one == false) {
       
   454             // do not load a static policy
       
   455         }
       
   456     }
       
   457 
       
   458     /**
       
   459      * Checks public key. If it is marked as trusted in
       
   460      * the identity database, add it to the policy
       
   461      * with the AllPermission.
       
   462      */
       
   463     private boolean checkForTrustedIdentity(final Certificate cert) {
       
   464         // XXX  JAAS has no way to access the SUN package.
       
   465         //      we'll add this back in when JAAS goes into core.
       
   466         return false;
       
   467     }
       
   468 
       
   469     /**
       
   470      * Reads a policy configuration into the Policy object using a
       
   471      * Reader object.
       
   472      *
       
   473      * @param policyFile the policy Reader object.
       
   474      */
       
   475     private void init(URL policy) {
       
   476         sun.security.provider.PolicyParser pp =
       
   477                 new sun.security.provider.PolicyParser(expandProperties);
       
   478         try {
       
   479             InputStreamReader isr
       
   480                 = new InputStreamReader(getInputStream(policy));
       
   481             pp.read(isr);
       
   482             isr.close();
       
   483             KeyStore keyStore = initKeyStore(policy, pp.getKeyStoreUrl(),
       
   484                                              pp.getKeyStoreType());
       
   485             Enumeration<GrantEntry> enum_ = pp.grantElements();
       
   486             while (enum_.hasMoreElements()) {
       
   487                 GrantEntry ge = enum_.nextElement();
       
   488                 addGrantEntry(ge, keyStore);
       
   489             }
       
   490         } catch (sun.security.provider.PolicyParser.ParsingException pe) {
       
   491             System.err.println(AUTH_POLICY +
       
   492                                 rb.getString(".error.parsing.") + policy);
       
   493             System.err.println(AUTH_POLICY +
       
   494                                 rb.getString("COLON") +
       
   495                                 pe.getMessage());
       
   496             if (debug != null)
       
   497                 pe.printStackTrace();
       
   498 
       
   499         } catch (Exception e) {
       
   500             if (debug != null) {
       
   501                 debug.println("error parsing "+policy);
       
   502                 debug.println(e.toString());
       
   503                 e.printStackTrace();
       
   504             }
       
   505         }
       
   506     }
       
   507 
       
   508     /*
       
   509      * Fast path reading from file urls in order to avoid calling
       
   510      * FileURLConnection.connect() which can be quite slow the first time
       
   511      * it is called. We really should clean up FileURLConnection so that
       
   512      * this is not a problem but in the meantime this fix helps reduce
       
   513      * start up time noticeably for the new launcher. -- DAC
       
   514      */
       
   515     private InputStream getInputStream(URL url) throws IOException {
       
   516         if ("file".equals(url.getProtocol())) {
       
   517             String path = url.getFile().replace('/', File.separatorChar);
       
   518             return new FileInputStream(path);
       
   519         } else {
       
   520             return url.openStream();
       
   521         }
       
   522     }
       
   523 
       
   524     /**
       
   525      * Given a PermissionEntry, create a codeSource.
       
   526      *
       
   527      * @return null if signedBy alias is not recognized
       
   528      */
       
   529     CodeSource getCodeSource(GrantEntry ge, KeyStore keyStore)
       
   530             throws java.net.MalformedURLException
       
   531     {
       
   532         Certificate[] certs = null;
       
   533         if (ge.signedBy != null) {
       
   534             certs = getCertificates(keyStore, ge.signedBy);
       
   535             if (certs == null) {
       
   536                 // we don't have a key for this alias,
       
   537                 // just return
       
   538                 if (debug != null) {
       
   539                     debug.println(" no certs for alias " +
       
   540                                        ge.signedBy + ", ignoring.");
       
   541                 }
       
   542                 return null;
       
   543             }
       
   544         }
       
   545 
       
   546         URL location;
       
   547 
       
   548         if (ge.codeBase != null)
       
   549             location = new URL(ge.codeBase);
       
   550         else
       
   551             location = null;
       
   552 
       
   553         if (ge.principals == null || ge.principals.size() == 0) {
       
   554             return (canonicalizeCodebase
       
   555                         (new CodeSource(location, certs),
       
   556                         false));
       
   557         } else {
       
   558             return (canonicalizeCodebase
       
   559                 (new SubjectCodeSource(null, ge.principals, location, certs),
       
   560                 false));
       
   561         }
       
   562     }
       
   563 
       
   564     /**
       
   565      * Add one policy entry to the vector.
       
   566      */
       
   567     private void addGrantEntry(GrantEntry ge, KeyStore keyStore) {
       
   568 
       
   569         if (debug != null) {
       
   570             debug.println("Adding policy entry: ");
       
   571             debug.println("  signedBy " + ge.signedBy);
       
   572             debug.println("  codeBase " + ge.codeBase);
       
   573             if (ge.principals != null && ge.principals.size() > 0) {
       
   574                 ListIterator<PrincipalEntry> li = ge.principals.listIterator();
       
   575                 while (li.hasNext()) {
       
   576                     PrincipalEntry pppe = li.next();
       
   577                     debug.println("  " + pppe.getPrincipalClass() +
       
   578                                         " " + pppe.getPrincipalName());
       
   579                 }
       
   580             }
       
   581             debug.println();
       
   582         }
       
   583 
       
   584         try {
       
   585             CodeSource codesource = getCodeSource(ge, keyStore);
       
   586             // skip if signedBy alias was unknown...
       
   587             if (codesource == null) return;
       
   588 
       
   589             PolicyEntry entry = new PolicyEntry(codesource);
       
   590             Enumeration<PermissionEntry> enum_ = ge.permissionElements();
       
   591             while (enum_.hasMoreElements()) {
       
   592                 PermissionEntry pe = enum_.nextElement();
       
   593                 try {
       
   594                     // XXX special case PrivateCredentialPermission-SELF
       
   595                     Permission perm;
       
   596                     if (pe.permission.equals
       
   597                         ("javax.security.auth.PrivateCredentialPermission") &&
       
   598                         pe.name.endsWith(" self")) {
       
   599                         perm = getInstance(pe.permission,
       
   600                                          pe.name + " \"self\"",
       
   601                                          pe.action);
       
   602                     } else {
       
   603                         perm = getInstance(pe.permission,
       
   604                                          pe.name,
       
   605                                          pe.action);
       
   606                     }
       
   607                     entry.add(perm);
       
   608                     if (debug != null) {
       
   609                         debug.println("  "+perm);
       
   610                     }
       
   611                 } catch (ClassNotFoundException cnfe) {
       
   612                     Certificate certs[];
       
   613                     if (pe.signedBy != null)
       
   614                         certs = getCertificates(keyStore, pe.signedBy);
       
   615                     else
       
   616                         certs = null;
       
   617 
       
   618                     // only add if we had no signer or we had a
       
   619                     // a signer and found the keys for it.
       
   620                     if (certs != null || pe.signedBy == null) {
       
   621                             Permission perm = new UnresolvedPermission(
       
   622                                              pe.permission,
       
   623                                              pe.name,
       
   624                                              pe.action,
       
   625                                              certs);
       
   626                             entry.add(perm);
       
   627                             if (debug != null) {
       
   628                                 debug.println("  "+perm);
       
   629                             }
       
   630                     }
       
   631                 } catch (java.lang.reflect.InvocationTargetException ite) {
       
   632                     System.err.println
       
   633                         (AUTH_POLICY +
       
   634                         rb.getString(".error.adding.Permission.") +
       
   635                         pe.permission +
       
   636                         rb.getString("SPACE") +
       
   637                         ite.getTargetException());
       
   638                 } catch (Exception e) {
       
   639                     System.err.println
       
   640                         (AUTH_POLICY +
       
   641                         rb.getString(".error.adding.Permission.") +
       
   642                         pe.permission +
       
   643                         rb.getString("SPACE") +
       
   644                         e);
       
   645                 }
       
   646             }
       
   647             policyEntries.addElement(entry);
       
   648         } catch (Exception e) {
       
   649             System.err.println
       
   650                 (AUTH_POLICY +
       
   651                 rb.getString(".error.adding.Entry.") +
       
   652                 ge +
       
   653                 rb.getString("SPACE") +
       
   654                 e);
       
   655         }
       
   656 
       
   657         if (debug != null)
       
   658             debug.println();
       
   659     }
       
   660 
       
   661     /**
       
   662      * Returns a new Permission object of the given Type. The Permission is
       
   663      * created by getting the
       
   664      * Class object using the <code>Class.forName</code> method, and using
       
   665      * the reflection API to invoke the (String name, String actions)
       
   666      * constructor on the
       
   667      * object.
       
   668      *
       
   669      * @param type the type of Permission being created.
       
   670      * @param name the name of the Permission being created.
       
   671      * @param actions the actions of the Permission being created.
       
   672      *
       
   673      * @exception  ClassNotFoundException  if the particular Permission
       
   674      *             class could not be found.
       
   675      *
       
   676      * @exception  IllegalAccessException  if the class or initializer is
       
   677      *               not accessible.
       
   678      *
       
   679      * @exception  InstantiationException  if getInstance tries to
       
   680      *               instantiate an abstract class or an interface, or if the
       
   681      *               instantiation fails for some other reason.
       
   682      *
       
   683      * @exception  NoSuchMethodException if the (String, String) constructor
       
   684      *               is not found.
       
   685      *
       
   686      * @exception  InvocationTargetException if the underlying Permission
       
   687      *               constructor throws an exception.
       
   688      *
       
   689      */
       
   690 
       
   691     private static final Permission getInstance(String type,
       
   692                                     String name,
       
   693                                     String actions)
       
   694         throws ClassNotFoundException,
       
   695                InstantiationException,
       
   696                IllegalAccessException,
       
   697                NoSuchMethodException,
       
   698                InvocationTargetException
       
   699     {
       
   700         //XXX we might want to keep a hash of created factories...
       
   701         Class<?> pc = Class.forName(type);
       
   702         Constructor<?> c = pc.getConstructor(PARAMS);
       
   703         return (Permission) c.newInstance(new Object[] { name, actions });
       
   704     }
       
   705 
       
   706     /**
       
   707      * Fetch all certs associated with this alias.
       
   708      */
       
   709     Certificate[] getCertificates(
       
   710                                     KeyStore keyStore, String aliases) {
       
   711 
       
   712         Vector<Certificate> vcerts = null;
       
   713 
       
   714         StringTokenizer st = new StringTokenizer(aliases, ",");
       
   715         int n = 0;
       
   716 
       
   717         while (st.hasMoreTokens()) {
       
   718             String alias = st.nextToken().trim();
       
   719             n++;
       
   720             Certificate cert = null;
       
   721             //See if this alias's cert has already been cached
       
   722             cert = (Certificate) aliasMapping.get(alias);
       
   723             if (cert == null && keyStore != null) {
       
   724 
       
   725                 try {
       
   726                     cert = keyStore.getCertificate(alias);
       
   727                 } catch (KeyStoreException kse) {
       
   728                     // never happens, because keystore has already been loaded
       
   729                     // when we call this
       
   730                 }
       
   731                 if (cert != null) {
       
   732                     aliasMapping.put(alias, cert);
       
   733                     aliasMapping.put(cert, alias);
       
   734                 }
       
   735             }
       
   736 
       
   737             if (cert != null) {
       
   738                 if (vcerts == null)
       
   739                     vcerts = new Vector<Certificate>();
       
   740                 vcerts.addElement(cert);
       
   741             }
       
   742         }
       
   743 
       
   744         // make sure n == vcerts.size, since we are doing a logical *and*
       
   745         if (vcerts != null && n == vcerts.size()) {
       
   746             Certificate[] certs = new Certificate[vcerts.size()];
       
   747             vcerts.copyInto(certs);
       
   748             return certs;
       
   749         } else {
       
   750             return null;
       
   751         }
       
   752     }
       
   753 
       
   754     /**
       
   755      * Enumerate all the entries in the global policy object.
       
   756      * This method is used by policy admin tools.   The tools
       
   757      * should use the Enumeration methods on the returned object
       
   758      * to fetch the elements sequentially.
       
   759      */
       
   760     private final synchronized Enumeration<PolicyEntry> elements(){
       
   761         return policyEntries.elements();
       
   762     }
   242     }
   763 
   243 
   764     /**
   244     /**
   765      * Examines this <code>Policy</code> and returns the Permissions granted
   245      * Examines this <code>Policy</code> and returns the Permissions granted
   766      * to the specified <code>Subject</code> and <code>CodeSource</code>.
   246      * to the specified <code>Subject</code> and <code>CodeSource</code>.
   814      *          are returned.
   294      *          are returned.
   815      *
   295      *
   816      * @return the Permissions granted to the provided <code>Subject</code>
   296      * @return the Permissions granted to the provided <code>Subject</code>
   817      *          <code>CodeSource</code>.
   297      *          <code>CodeSource</code>.
   818      */
   298      */
       
   299     @Override
   819     public PermissionCollection getPermissions(final Subject subject,
   300     public PermissionCollection getPermissions(final Subject subject,
   820                                         final CodeSource codesource) {
   301                                                final CodeSource codesource) {
   821 
   302         return apf.getPermissions(subject, codesource);
   822         // XXX  when JAAS goes into the JDK core,
       
   823         //      we can remove this method and simply
       
   824         //      rely on the getPermissions variant that takes a codesource,
       
   825         //      which no one can use at this point in time.
       
   826         //      at that time, we can also make SubjectCodeSource a public
       
   827         //      class.
       
   828 
       
   829         // XXX
       
   830         //
       
   831         // 1)   if code instantiates PolicyFile directly, then it will need
       
   832         //      all the permissions required for the PolicyFile initialization
       
   833         // 2)   if code calls Policy.getPolicy, then it simply needs
       
   834         //      AuthPermission(getPolicy), and the javax.security.auth.Policy
       
   835         //      implementation instantiates PolicyFile in a doPrivileged block
       
   836         // 3)   if after instantiating a Policy (either via #1 or #2),
       
   837         //      code calls getPermissions, PolicyFile wraps the call
       
   838         //      in a doPrivileged block.
       
   839         return java.security.AccessController.doPrivileged
       
   840             (new java.security.PrivilegedAction<PermissionCollection>() {
       
   841             public PermissionCollection run() {
       
   842                 SubjectCodeSource scs = new SubjectCodeSource
       
   843                     (subject,
       
   844                     null,
       
   845                     codesource == null ? null : codesource.getLocation(),
       
   846                     codesource == null ? null : codesource.getCertificates());
       
   847                 if (initialized)
       
   848                     return getPermissions(new Permissions(), scs);
       
   849                 else
       
   850                     return new PolicyPermissions(PolicyFile.this, scs);
       
   851             }
       
   852         });
       
   853     }
       
   854 
       
   855     /**
       
   856      * Examines the global policy for the specified CodeSource, and
       
   857      * creates a PermissionCollection object with
       
   858      * the set of permissions for that principal's protection domain.
       
   859      *
       
   860      * @param CodeSource the codesource associated with the caller.
       
   861      * This encapsulates the original location of the code (where the code
       
   862      * came from) and the public key(s) of its signer.
       
   863      *
       
   864      * @return the set of permissions according to the policy.
       
   865      */
       
   866     PermissionCollection getPermissions(CodeSource codesource) {
       
   867 
       
   868         if (initialized)
       
   869             return getPermissions(new Permissions(), codesource);
       
   870         else
       
   871             return new PolicyPermissions(this, codesource);
       
   872     }
       
   873 
       
   874     /**
       
   875      * Examines the global policy for the specified CodeSource, and
       
   876      * creates a PermissionCollection object with
       
   877      * the set of permissions for that principal's protection domain.
       
   878      *
       
   879      * @param permissions the permissions to populate
       
   880      * @param codesource the codesource associated with the caller.
       
   881      * This encapsulates the original location of the code (where the code
       
   882      * came from) and the public key(s) of its signer.
       
   883      *
       
   884      * @return the set of permissions according to the policy.
       
   885      */
       
   886     Permissions getPermissions(final Permissions perms,
       
   887                                final CodeSource cs)
       
   888     {
       
   889         if (!initialized) {
       
   890             init();
       
   891         }
       
   892 
       
   893         final CodeSource codesource[] = {null};
       
   894 
       
   895         codesource[0] = canonicalizeCodebase(cs, true);
       
   896 
       
   897         if (debug != null) {
       
   898             debug.println("evaluate("+codesource[0]+")\n");
       
   899         }
       
   900 
       
   901         // needs to be in a begin/endPrivileged block because
       
   902         // codesource.implies calls URL.equals which does an
       
   903         // InetAddress lookup
       
   904 
       
   905         for (int i = 0; i < policyEntries.size(); i++) {
       
   906 
       
   907            PolicyEntry entry = policyEntries.elementAt(i);
       
   908 
       
   909            if (debug != null) {
       
   910                 debug.println("PolicyFile CodeSource implies: " +
       
   911                         entry.codesource.toString() + "\n\n" +
       
   912                         "\t" + codesource[0].toString() + "\n\n");
       
   913            }
       
   914 
       
   915            if (entry.codesource.implies(codesource[0])) {
       
   916                for (int j = 0; j < entry.permissions.size(); j++) {
       
   917                     Permission p = entry.permissions.elementAt(j);
       
   918                     if (debug != null) {
       
   919                        debug.println("  granting " + p);
       
   920                     }
       
   921                     if (!addSelfPermissions(p, entry.codesource,
       
   922                                         codesource[0], perms)) {
       
   923                         // we could check for duplicates
       
   924                         // before adding new permissions,
       
   925                         // but the SubjectDomainCombiner
       
   926                         // already checks for duplicates later
       
   927                         perms.add(p);
       
   928                     }
       
   929                 }
       
   930             }
       
   931         }
       
   932 
       
   933         // now see if any of the keys are trusted ids.
       
   934 
       
   935         if (!ignoreIdentityScope) {
       
   936             Certificate certs[] = codesource[0].getCertificates();
       
   937             if (certs != null) {
       
   938                 for (int k=0; k < certs.length; k++) {
       
   939                     if ((aliasMapping.get(certs[k]) == null) &&
       
   940                         checkForTrustedIdentity(certs[k])) {
       
   941                         // checkForTrustedIdentity added it
       
   942                         // to the policy for us. next time
       
   943                         // around we'll find it. This time
       
   944                         // around we need to add it.
       
   945                         perms.add(new java.security.AllPermission());
       
   946                     }
       
   947                 }
       
   948             }
       
   949         }
       
   950         return perms;
       
   951     }
       
   952 
       
   953     /**
       
   954      * Returns true if 'Self' permissions were added to the provided
       
   955      * 'perms', and false otherwise.
       
   956      *
       
   957      * <p>
       
   958      *
       
   959      * @param p check to see if this Permission is a "SELF"
       
   960      *                  PrivateCredentialPermission. <p>
       
   961      *
       
   962      * @param entryCs the codesource for the Policy entry.
       
   963      *
       
   964      * @param accCs the codesource for from the current AccessControlContext.
       
   965      *
       
   966      * @param perms the PermissionCollection where the individual
       
   967      *                  PrivateCredentialPermissions will be added.
       
   968      */
       
   969     private boolean addSelfPermissions(final Permission p,
       
   970                                 CodeSource entryCs,
       
   971                                 CodeSource accCs,
       
   972                                 Permissions perms) {
       
   973 
       
   974         if (!(p instanceof PrivateCredentialPermission))
       
   975             return false;
       
   976 
       
   977         if (!(entryCs instanceof SubjectCodeSource))
       
   978             return false;
       
   979 
       
   980 
       
   981         PrivateCredentialPermission pcp = (PrivateCredentialPermission)p;
       
   982         SubjectCodeSource scs = (SubjectCodeSource)entryCs;
       
   983 
       
   984         // see if it is a SELF permission
       
   985         String[][] pPrincipals = pcp.getPrincipals();
       
   986         if (pPrincipals.length <= 0 ||
       
   987             !pPrincipals[0][0].equalsIgnoreCase("self") ||
       
   988             !pPrincipals[0][1].equalsIgnoreCase("self")) {
       
   989 
       
   990             // regular PrivateCredentialPermission
       
   991             return false;
       
   992         } else {
       
   993 
       
   994             // granted a SELF permission - create a
       
   995             // PrivateCredentialPermission for each
       
   996             // of the Policy entry's CodeSource Principals
       
   997 
       
   998             if (scs.getPrincipals() == null) {
       
   999                 // XXX SubjectCodeSource has no Subject???
       
  1000                 return true;
       
  1001             }
       
  1002 
       
  1003             ListIterator<PrincipalEntry> pli =
       
  1004                     scs.getPrincipals().listIterator();
       
  1005             while (pli.hasNext()) {
       
  1006 
       
  1007                 PrincipalEntry principal = pli.next();
       
  1008 
       
  1009                 // XXX
       
  1010                 //      if the Policy entry's Principal does not contain a
       
  1011                 //              WILDCARD for the Principal name, then a
       
  1012                 //              new PrivateCredentialPermission is created
       
  1013                 //              for the Principal listed in the Policy entry.
       
  1014                 //      if the Policy entry's Principal contains a WILDCARD
       
  1015                 //              for the Principal name, then a new
       
  1016                 //              PrivateCredentialPermission is created
       
  1017                 //              for each Principal associated with the Subject
       
  1018                 //              in the current ACC.
       
  1019 
       
  1020                 String[][] principalInfo = getPrincipalInfo
       
  1021                                                 (principal, accCs);
       
  1022 
       
  1023                 for (int i = 0; i < principalInfo.length; i++) {
       
  1024 
       
  1025                     // here's the new PrivateCredentialPermission
       
  1026 
       
  1027                     PrivateCredentialPermission newPcp =
       
  1028                         new PrivateCredentialPermission
       
  1029                                 (pcp.getCredentialClass() +
       
  1030                                         " " +
       
  1031                                         principalInfo[i][0] +
       
  1032                                         " " +
       
  1033                                         "\"" + principalInfo[i][1] + "\"",
       
  1034                                 "read");
       
  1035 
       
  1036                     if (debug != null) {
       
  1037                         debug.println("adding SELF permission: " +
       
  1038                                         newPcp.toString());
       
  1039                     }
       
  1040 
       
  1041                     perms.add(newPcp);
       
  1042                 }
       
  1043             }
       
  1044         }
       
  1045         return true;
       
  1046     }
       
  1047 
       
  1048     /**
       
  1049      * return the principal class/name pair in the 2D array.
       
  1050      * array[x][y]:     x corresponds to the array length.
       
  1051      *                  if (y == 0), it's the principal class.
       
  1052      *                  if (y == 1), it's the principal name.
       
  1053      */
       
  1054     private String[][] getPrincipalInfo
       
  1055                 (PrincipalEntry principal, final CodeSource accCs) {
       
  1056 
       
  1057         // there are 3 possibilities:
       
  1058         // 1) the entry's Principal class and name are not wildcarded
       
  1059         // 2) the entry's Principal name is wildcarded only
       
  1060         // 3) the entry's Principal class and name are wildcarded
       
  1061 
       
  1062         if (!principal.getPrincipalClass().equals
       
  1063                 (PrincipalEntry.WILDCARD_CLASS) &&
       
  1064             !principal.getPrincipalName().equals
       
  1065                 (PrincipalEntry.WILDCARD_NAME)) {
       
  1066 
       
  1067             // build a PrivateCredentialPermission for the principal
       
  1068             // from the Policy entry
       
  1069             String[][] info = new String[1][2];
       
  1070             info[0][0] = principal.getPrincipalClass();
       
  1071             info[0][1] = principal.getPrincipalName();
       
  1072             return info;
       
  1073 
       
  1074         } else if (!principal.getPrincipalClass().equals
       
  1075                 (PrincipalEntry.WILDCARD_CLASS) &&
       
  1076             principal.getPrincipalName().equals
       
  1077                 (PrincipalEntry.WILDCARD_NAME)) {
       
  1078 
       
  1079             // build a PrivateCredentialPermission for all
       
  1080             // the Subject's principals that are instances of principalClass
       
  1081 
       
  1082             // the accCs is guaranteed to be a SubjectCodeSource
       
  1083             // because the earlier CodeSource.implies succeeded
       
  1084             SubjectCodeSource scs = (SubjectCodeSource)accCs;
       
  1085 
       
  1086             Set<? extends Principal> principalSet = null;
       
  1087             try {
       
  1088                 // principal.principalClass should extend Principal
       
  1089                 // If it doesn't, we should stop here with a ClassCastException.
       
  1090                 @SuppressWarnings("unchecked")
       
  1091                 Class<? extends Principal> pClass = (Class<? extends Principal>)
       
  1092                         Class.forName(principal.getPrincipalClass(), false,
       
  1093                                       ClassLoader.getSystemClassLoader());
       
  1094                 principalSet = scs.getSubject().getPrincipals(pClass);
       
  1095             } catch (Exception e) {
       
  1096                 if (debug != null) {
       
  1097                     debug.println("problem finding Principal Class " +
       
  1098                                   "when expanding SELF permission: " +
       
  1099                                   e.toString());
       
  1100                 }
       
  1101             }
       
  1102 
       
  1103             if (principalSet == null) {
       
  1104                 // error
       
  1105                 return new String[0][0];
       
  1106             }
       
  1107 
       
  1108             String[][] info = new String[principalSet.size()][2];
       
  1109 
       
  1110             int i = 0;
       
  1111             for (Principal p : principalSet) {
       
  1112                 info[i][0] = p.getClass().getName();
       
  1113                 info[i][1] = p.getName();
       
  1114                 i++;
       
  1115             }
       
  1116             return info;
       
  1117 
       
  1118         } else {
       
  1119 
       
  1120             // build a PrivateCredentialPermission for every
       
  1121             // one of the current Subject's principals
       
  1122 
       
  1123             // the accCs is guaranteed to be a SubjectCodeSource
       
  1124             // because the earlier CodeSource.implies succeeded
       
  1125             SubjectCodeSource scs = (SubjectCodeSource)accCs;
       
  1126             Set<Principal> principalSet = scs.getSubject().getPrincipals();
       
  1127 
       
  1128             String[][] info = new String[principalSet.size()][2];
       
  1129             java.util.Iterator<Principal> pIterator = principalSet.iterator();
       
  1130 
       
  1131             int i = 0;
       
  1132             while (pIterator.hasNext()) {
       
  1133                 Principal p = pIterator.next();
       
  1134                 info[i][0] = p.getClass().getName();
       
  1135                 info[i][1] = p.getName();
       
  1136                 i++;
       
  1137             }
       
  1138             return info;
       
  1139         }
       
  1140     }
       
  1141 
       
  1142     /*
       
  1143      * Returns the signer certificates from the list of certificates associated
       
  1144      * with the given code source.
       
  1145      *
       
  1146      * The signer certificates are those certificates that were used to verify
       
  1147      * signed code originating from the codesource location.
       
  1148      *
       
  1149      * This method assumes that in the given code source, each signer
       
  1150      * certificate is followed by its supporting certificate chain
       
  1151      * (which may be empty), and that the signer certificate and its
       
  1152      * supporting certificate chain are ordered bottom-to-top (i.e., with the
       
  1153      * signer certificate first and the (root) certificate authority last).
       
  1154      */
       
  1155     Certificate[] getSignerCertificates(CodeSource cs) {
       
  1156         Certificate[] certs = null;
       
  1157         if ((certs = cs.getCertificates()) == null)
       
  1158             return null;
       
  1159         for (int i=0; i<certs.length; i++) {
       
  1160             if (!(certs[i] instanceof X509Certificate))
       
  1161                 return cs.getCertificates();
       
  1162         }
       
  1163 
       
  1164         // Do we have to do anything?
       
  1165         int i = 0;
       
  1166         int count = 0;
       
  1167         while (i < certs.length) {
       
  1168             count++;
       
  1169             while (((i+1) < certs.length)
       
  1170                    && ((X509Certificate)certs[i]).getIssuerDN().equals(
       
  1171                            ((X509Certificate)certs[i+1]).getSubjectDN())) {
       
  1172                 i++;
       
  1173             }
       
  1174             i++;
       
  1175         }
       
  1176         if (count == certs.length)
       
  1177             // Done
       
  1178             return certs;
       
  1179 
       
  1180         ArrayList<Certificate> userCertList = new ArrayList<>();
       
  1181         i = 0;
       
  1182         while (i < certs.length) {
       
  1183             userCertList.add(certs[i]);
       
  1184             while (((i+1) < certs.length)
       
  1185                    && ((X509Certificate)certs[i]).getIssuerDN().equals(
       
  1186                            ((X509Certificate)certs[i+1]).getSubjectDN())) {
       
  1187                 i++;
       
  1188             }
       
  1189             i++;
       
  1190         }
       
  1191         Certificate[] userCerts = new Certificate[userCertList.size()];
       
  1192         userCertList.toArray(userCerts);
       
  1193         return userCerts;
       
  1194     }
       
  1195 
       
  1196     private CodeSource canonicalizeCodebase(CodeSource cs,
       
  1197                                             boolean extractSignerCerts) {
       
  1198         CodeSource canonCs = cs;
       
  1199         if (cs.getLocation() != null &&
       
  1200             cs.getLocation().getProtocol().equalsIgnoreCase("file")) {
       
  1201             try {
       
  1202                 String path = cs.getLocation().getFile().replace
       
  1203                                                         ('/',
       
  1204                                                         File.separatorChar);
       
  1205                 URL csUrl = null;
       
  1206                 if (path.endsWith("*")) {
       
  1207                     // remove trailing '*' because it causes canonicalization
       
  1208                     // to fail on win32
       
  1209                     path = path.substring(0, path.length()-1);
       
  1210                     boolean appendFileSep = false;
       
  1211                     if (path.endsWith(File.separator))
       
  1212                         appendFileSep = true;
       
  1213                     if (path.equals("")) {
       
  1214                         path = System.getProperty("user.dir");
       
  1215                     }
       
  1216                     File f = new File(path);
       
  1217                     path = f.getCanonicalPath();
       
  1218                     StringBuffer sb = new StringBuffer(path);
       
  1219                     // reappend '*' to canonicalized filename (note that
       
  1220                     // canonicalization may have removed trailing file
       
  1221                     // separator, so we have to check for that, too)
       
  1222                     if (!path.endsWith(File.separator) &&
       
  1223                         (appendFileSep || f.isDirectory()))
       
  1224                         sb.append(File.separatorChar);
       
  1225                     sb.append('*');
       
  1226                     path = sb.toString();
       
  1227                 } else {
       
  1228                     path = new File(path).getCanonicalPath();
       
  1229                 }
       
  1230                 csUrl = new File(path).toURL();
       
  1231 
       
  1232                 if (cs instanceof SubjectCodeSource) {
       
  1233                     SubjectCodeSource scs = (SubjectCodeSource)cs;
       
  1234                     if (extractSignerCerts) {
       
  1235                         canonCs = new SubjectCodeSource
       
  1236                                                 (scs.getSubject(),
       
  1237                                                 scs.getPrincipals(),
       
  1238                                                 csUrl,
       
  1239                                                 getSignerCertificates(scs));
       
  1240                     } else {
       
  1241                         canonCs = new SubjectCodeSource
       
  1242                                                 (scs.getSubject(),
       
  1243                                                 scs.getPrincipals(),
       
  1244                                                 csUrl,
       
  1245                                                 scs.getCertificates());
       
  1246                     }
       
  1247                 } else {
       
  1248                     if (extractSignerCerts) {
       
  1249                         canonCs = new CodeSource(csUrl,
       
  1250                                                 getSignerCertificates(cs));
       
  1251                     } else {
       
  1252                         canonCs = new CodeSource(csUrl,
       
  1253                                                 cs.getCertificates());
       
  1254                     }
       
  1255                 }
       
  1256             } catch (IOException ioe) {
       
  1257                 // leave codesource as it is, unless we have to extract its
       
  1258                 // signer certificates
       
  1259                 if (extractSignerCerts) {
       
  1260                     if (!(cs instanceof SubjectCodeSource)) {
       
  1261                         canonCs = new CodeSource(cs.getLocation(),
       
  1262                                                 getSignerCertificates(cs));
       
  1263                     } else {
       
  1264                         SubjectCodeSource scs = (SubjectCodeSource)cs;
       
  1265                         canonCs = new SubjectCodeSource(scs.getSubject(),
       
  1266                                                 scs.getPrincipals(),
       
  1267                                                 scs.getLocation(),
       
  1268                                                 getSignerCertificates(scs));
       
  1269                     }
       
  1270                 }
       
  1271             }
       
  1272         } else {
       
  1273             if (extractSignerCerts) {
       
  1274                 if (!(cs instanceof SubjectCodeSource)) {
       
  1275                     canonCs = new CodeSource(cs.getLocation(),
       
  1276                                         getSignerCertificates(cs));
       
  1277                 } else {
       
  1278                     SubjectCodeSource scs = (SubjectCodeSource)cs;
       
  1279                     canonCs = new SubjectCodeSource(scs.getSubject(),
       
  1280                                         scs.getPrincipals(),
       
  1281                                         scs.getLocation(),
       
  1282                                         getSignerCertificates(scs));
       
  1283                 }
       
  1284             }
       
  1285         }
       
  1286         return canonCs;
       
  1287     }
       
  1288 
       
  1289     /**
       
  1290      * Each entry in the policy configuration file is represented by a
       
  1291      * PolicyEntry object.  <p>
       
  1292      *
       
  1293      * A PolicyEntry is a (CodeSource,Permission) pair.  The
       
  1294      * CodeSource contains the (URL, PublicKey) that together identify
       
  1295      * where the Java bytecodes come from and who (if anyone) signed
       
  1296      * them.  The URL could refer to localhost.  The URL could also be
       
  1297      * null, meaning that this policy entry is given to all comers, as
       
  1298      * long as they match the signer field.  The signer could be null,
       
  1299      * meaning the code is not signed. <p>
       
  1300      *
       
  1301      * The Permission contains the (Type, Name, Action) triplet. <p>
       
  1302      *
       
  1303      * For now, the Policy object retrieves the public key from the
       
  1304      * X.509 certificate on disk that corresponds to the signedBy
       
  1305      * alias specified in the Policy config file.  For reasons of
       
  1306      * efficiency, the Policy object keeps a hashtable of certs already
       
  1307      * read in.  This could be replaced by a secure internal key
       
  1308      * store.
       
  1309      *
       
  1310      * <p>
       
  1311      * For example, the entry
       
  1312      * <pre>
       
  1313      *          permission java.io.File "/tmp", "read,write",
       
  1314      *          signedBy "Duke";
       
  1315      * </pre>
       
  1316      * is represented internally
       
  1317      * <pre>
       
  1318      *
       
  1319      * FilePermission f = new FilePermission("/tmp", "read,write");
       
  1320      * PublicKey p = publickeys.get("Duke");
       
  1321      * URL u = InetAddress.getLocalHost();
       
  1322      * CodeBase c = new CodeBase( p, u );
       
  1323      * pe = new PolicyEntry(f, c);
       
  1324      * </pre>
       
  1325      *
       
  1326      * @author Marianne Mueller
       
  1327      * @author Roland Schemers
       
  1328      * @see java.security.CodeSource
       
  1329      * @see java.security.Policy
       
  1330      * @see java.security.Permissions
       
  1331      * @see java.security.ProtectionDomain
       
  1332      */
       
  1333 
       
  1334     private static class PolicyEntry {
       
  1335 
       
  1336         CodeSource codesource;
       
  1337         Vector<Permission> permissions;
       
  1338 
       
  1339         /**
       
  1340          * Given a Permission and a CodeSource, create a policy entry.
       
  1341          *
       
  1342          * XXX Decide if/how to add validity fields and "purpose" fields to
       
  1343          * XXX policy entries
       
  1344          *
       
  1345          * @param cs the CodeSource, which encapsulates the URL and the public
       
  1346          *        key
       
  1347          *        attributes from the policy config file.   Validity checks are
       
  1348          *        performed on the public key before PolicyEntry is called.
       
  1349          *
       
  1350          */
       
  1351         PolicyEntry(CodeSource cs)
       
  1352         {
       
  1353             this.codesource = cs;
       
  1354             this.permissions = new Vector<Permission>();
       
  1355         }
       
  1356 
       
  1357         /**
       
  1358          * add a Permission object to this entry.
       
  1359          */
       
  1360         void add(Permission p) {
       
  1361             permissions.addElement(p);
       
  1362         }
       
  1363 
       
  1364         /**
       
  1365          * Return the CodeSource for this policy entry
       
  1366          */
       
  1367         CodeSource getCodeSource() {
       
  1368             return this.codesource;
       
  1369         }
       
  1370 
       
  1371         public String toString(){
       
  1372             StringBuffer sb = new StringBuffer();
       
  1373             sb.append(rb.getString("LPARAM"));
       
  1374             sb.append(getCodeSource());
       
  1375             sb.append("\n");
       
  1376             for (int j = 0; j < permissions.size(); j++) {
       
  1377                 Permission p = permissions.elementAt(j);
       
  1378                 sb.append(rb.getString("SPACE"));
       
  1379                 sb.append(rb.getString("SPACE"));
       
  1380                 sb.append(p);
       
  1381                 sb.append(rb.getString("NEWLINE"));
       
  1382             }
       
  1383             sb.append(rb.getString("RPARAM"));
       
  1384             sb.append(rb.getString("NEWLINE"));
       
  1385             return sb.toString();
       
  1386         }
       
  1387 
       
  1388     }
   303     }
  1389 }
   304 }
  1390 
       
  1391 @SuppressWarnings("deprecation")
       
  1392 class PolicyPermissions extends PermissionCollection {
       
  1393 
       
  1394     private static final long serialVersionUID = -1954188373270545523L;
       
  1395 
       
  1396     private CodeSource codesource;
       
  1397     private Permissions perms;
       
  1398     private PolicyFile policy;
       
  1399     private boolean notInit; // have we pulled in the policy permissions yet?
       
  1400     private Vector<Permission> additionalPerms;
       
  1401 
       
  1402     PolicyPermissions(PolicyFile policy,
       
  1403                       CodeSource codesource)
       
  1404     {
       
  1405         this.codesource = codesource;
       
  1406         this.policy = policy;
       
  1407         this.perms = null;
       
  1408         this.notInit = true;
       
  1409         this.additionalPerms = null;
       
  1410     }
       
  1411 
       
  1412     public void add(Permission permission) {
       
  1413         if (isReadOnly())
       
  1414             throw new SecurityException
       
  1415             (PolicyFile.rb.getString
       
  1416             ("attempt.to.add.a.Permission.to.a.readonly.PermissionCollection"));
       
  1417 
       
  1418         if (perms == null) {
       
  1419             if (additionalPerms == null)
       
  1420                 additionalPerms = new Vector<Permission>();
       
  1421             additionalPerms.add(permission);
       
  1422         } else {
       
  1423             perms.add(permission);
       
  1424         }
       
  1425     }
       
  1426 
       
  1427     private synchronized void init() {
       
  1428         if (notInit) {
       
  1429             if (perms == null)
       
  1430                 perms = new Permissions();
       
  1431 
       
  1432             if (additionalPerms != null) {
       
  1433                 Enumeration<Permission> e = additionalPerms.elements();
       
  1434                 while (e.hasMoreElements()) {
       
  1435                     perms.add(e.nextElement());
       
  1436                 }
       
  1437                 additionalPerms = null;
       
  1438             }
       
  1439             policy.getPermissions(perms,codesource);
       
  1440             notInit=false;
       
  1441         }
       
  1442     }
       
  1443 
       
  1444     public boolean implies(Permission permission) {
       
  1445         if (notInit)
       
  1446             init();
       
  1447         return perms.implies(permission);
       
  1448     }
       
  1449 
       
  1450     public Enumeration<Permission> elements() {
       
  1451         if (notInit)
       
  1452             init();
       
  1453         return perms.elements();
       
  1454     }
       
  1455 
       
  1456     public String toString() {
       
  1457         if (notInit)
       
  1458             init();
       
  1459         return perms.toString();
       
  1460     }
       
  1461 }