KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > security > auth > PolicyFile


1 /*
2  * @(#)PolicyFile.java 1.34 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.security.auth;
9
10 import java.io.*;
11 import java.lang.RuntimePermission JavaDoc;
12 import java.lang.reflect.*;
13 import java.net.MalformedURLException JavaDoc;
14 import java.net.URL JavaDoc;
15 import java.util.*;
16
17 import java.security.AccessController JavaDoc;
18 import java.security.CodeSource JavaDoc;
19 import java.security.Identity JavaDoc;
20 import java.security.IdentityScope JavaDoc;
21 import java.security.KeyStore JavaDoc;
22 import java.security.KeyStoreException JavaDoc;
23 import java.security.Permission JavaDoc;
24 import java.security.Permissions JavaDoc;
25 import java.security.PermissionCollection JavaDoc;
26 import java.security.Principal JavaDoc;
27 import java.security.UnresolvedPermission JavaDoc;
28 import java.security.Security JavaDoc;
29 import java.security.cert.Certificate JavaDoc;
30 import java.security.cert.X509Certificate JavaDoc;
31
32 import javax.security.auth.Subject JavaDoc;
33 import javax.security.auth.PrivateCredentialPermission JavaDoc;
34
35 import sun.security.util.PropertyExpander;
36
37 /**
38  * This class represents a default implementation for
39  * <code>javax.security.auth.Policy</code>.
40  *
41  * <p> This object stores the policy for entire Java runtime,
42  * and is the amalgamation of multiple static policy
43  * configurations that resides in files.
44  * The algorithm for locating the policy file(s) and reading their
45  * information into this <code>Policy</code> object is:
46  *
47  * <ol>
48  * <li>
49  * Loop through the <code>java.security.Security</code> properties,
50  * <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,
51  * <i>auth.policy.url.X</i>". These properties are set
52  * in the Java security properties file, which is located in the file named
53  * &lt;JAVA_HOME&gt;/lib/security/java.security, where &lt;JAVA_HOME&gt;
54  * refers to the directory where the JDK was installed.
55  * Each property value specifies a <code>URL</code> pointing to a
56  * policy file to be loaded. Read in and load each policy.
57  *
58  * <li>
59  * The <code>java.lang.System</code> property <i>java.security.auth.policy</i>
60  * may also be set to a <code>URL</code> pointing to another policy file
61  * (which is the case when a user uses the -D switch at runtime).
62  * If this property is defined, and its use is allowed by the
63  * security property file (the Security property,
64  * <i>policy.allowSystemProperty</i> is set to <i>true</i>),
65  * also load that policy.
66  *
67  * <li>
68  * If the <i>java.security.auth.policy</i> property is defined using
69  * "==" (rather than "="), then ignore all other specified
70  * policies and only load this policy.
71  * </ol>
72  *
73  * Each policy file consists of one or more grant entries, each of
74  * which consists of a number of permission entries.
75  *
76  * <pre>
77  * grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",
78  * principal <b>principalClass</b> "<b>principalName</b>",
79  * principal <b>principalClass</b> "<b>principalName</b>",
80  * ... {
81  *
82  * permission <b>Type</b> "<b>name</b> "<b>action</b>",
83  * signedBy "<b>alias</b>";
84  * permission <b>Type</b> "<b>name</b> "<b>action</b>",
85  * signedBy "<b>alias</b>";
86  * ....
87  * };
88  * </pre>
89  *
90  * All non-bold items above must appear as is (although case
91  * doesn't matter and some are optional, as noted below).
92  * Italicized items represent variable values.
93  *
94  * <p> A grant entry must begin with the word <code>grant</code>.
95  * The <code>signedBy</code> and <code>codeBase</code>
96  * name/value pairs are optional.
97  * If they are not present, then any signer (including unsigned code)
98  * will match, and any codeBase will match. Note that the
99  * <code>principal</code> name/value pair is not optional.
100  * This <code>Policy</code> implementation only permits
101  * Principal-based grant entries. Note that the <i>principalClass</i>
102  * may be set to the wildcard value, *, which allows it to match
103  * any <code>Principal</code> class. In addition, the <i>principalName</i>
104  * may also be set to the wildcard value, *, allowing it to match
105  * any <code>Principal</code> name. When setting the <i>principalName</i>
106  * to the *, do not surround the * with quotes.
107  *
108  * <p> A permission entry must begin with the word <code>permission</code>.
109  * The word <code><i>Type</i></code> in the template above is
110  * a specific permission type, such as <code>java.io.FilePermission</code>
111  * or <code>java.lang.RuntimePermission</code>.
112  *
113  * <p> The "<i>action</i>" is required for
114  * many permission types, such as <code>java.io.FilePermission</code>
115  * (where it specifies what type of file access that is permitted).
116  * It is not required for categories such as
117  * <code>java.lang.RuntimePermission</code>
118  * where it is not necessary - you either have the
119  * permission specified by the <code>"<i>name</i>"</code>
120  * value following the type name or you don't.
121  *
122  * <p> The <code>signedBy</code> name/value pair for a permission entry
123  * is optional. If present, it indicates a signed permission. That is,
124  * the permission class itself must be signed by the given alias in
125  * order for it to be granted. For example,
126  * suppose you have the following grant entry:
127  *
128  * <pre>
129  * grant principal foo.com.Principal "Duke" {
130  * permission Foo "foobar", signedBy "FooSoft";
131  * }
132  * </pre>
133  *
134  * <p> Then this permission of type <i>Foo</i> is granted if the
135  * <code>Foo.class</code> permission has been signed by the
136  * "FooSoft" alias, or if <code>Foo.class</code> is a
137  * system class (i.e., is found on the CLASSPATH).
138  *
139  * <p> Items that appear in an entry must appear in the specified order
140  * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
141  * "<i>action</i>"). An entry is terminated with a semicolon.
142  *
143  * <p> Case is unimportant for the identifiers (<code>permission</code>,
144  * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
145  * significant for the <i>Type</i>
146  * or for any string that is passed in as a value. <p>
147  *
148  * <p> An example of two entries in a policy configuration file is
149  * <pre>
150  * // if the code is comes from "foo.com" and is running as "Duke",
151  * // grant it read/write to all files in /tmp.
152  *
153  * grant codeBase "foo.com", principal foo.com.Principal "Duke" {
154  * permission java.io.FilePermission "/tmp/*", "read,write";
155  * };
156  *
157  * // grant any code running as "Duke" permission to read
158  * // the "java.vendor" Property.
159  *
160  * grant principal foo.com.Principal "Duke" {
161  * permission java.util.PropertyPermission "java.vendor";
162  * </pre>
163  *
164  * <p> This <code>Policy</code> implementation supports
165  * special handling for PrivateCredentialPermissions.
166  * If a grant entry is configured with a
167  * <code>PrivateCredentialPermission</code>,
168  * and the "Principal Class/Principal Name" for that
169  * <code>PrivateCredentialPermission</code> is "self",
170  * then the entry grants the specified <code>Subject</code> permission to
171  * access its own private Credential. For example,
172  * the following grants the <code>Subject</code> "Duke"
173  * access to its own a.b.Credential.
174  *
175  * <pre>
176  * grant principal foo.com.Principal "Duke" {
177  * permission javax.security.auth.PrivateCredentialPermission
178  * "a.b.Credential self",
179  * "read";
180  * };
181  * </pre>
182  *
183  * The following grants the <code>Subject</code> "Duke"
184  * access to all of its own private Credentials:
185  *
186  * <pre>
187  * grant principal foo.com.Principal "Duke" {
188  * permission javax.security.auth.PrivateCredentialPermission
189  * "* self",
190  * "read";
191  * };
192  * </pre>
193  *
194  * The following grants all Subjects authenticated as a
195  * <code>SolarisPrincipal</code> (regardless of their respective names)
196  * permission to access their own private Credentials:
197  *
198  * <pre>
199  * grant principal com.sun.security.auth.SolarisPrincipal * {
200  * permission javax.security.auth.PrivateCredentialPermission
201  * "* self",
202  * "read";
203  * };
204  * </pre>
205  *
206  * The following grants all Subjects permission to access their own
207  * private Credentials:
208  *
209  * <pre>
210  * grant principal * * {
211  * permission javax.security.auth.PrivateCredentialPermission
212  * "* self",
213  * "read";
214  * };
215  * </pre>
216  
217  * @deprecated As of JDK&nbsp;1.4, replaced by
218  * {@link sun.security.provider.PolicyFile}.
219  * This class is entirely deprecated.
220  *
221  * @version 1.22, 01/25/00
222  * @see java.security.CodeSource
223  * @see java.security.Permissions
224  * @see java.security.ProtectionDomain
225  */

226 @Deprecated JavaDoc
227 public class PolicyFile extends javax.security.auth.Policy JavaDoc {
228
229     static final java.util.ResourceBundle JavaDoc rb =
230           (java.util.ResourceBundle JavaDoc)java.security.AccessController.doPrivileged
231           (new java.security.PrivilegedAction JavaDoc() {
232               public Object JavaDoc run() {
233                   return (java.util.ResourceBundle.getBundle
234                                 ("sun.security.util.AuthResources"));
235               }
236        });
237     // needs to be package private
238

239     private static final sun.security.util.Debug debug =
240     sun.security.util.Debug.getInstance("policy", "\t[Auth Policy]");
241
242     private static final String JavaDoc AUTH_POLICY = "java.security.auth.policy";
243     private static final String JavaDoc SECURITY_MANAGER = "java.security.manager";
244     private static final String JavaDoc AUTH_POLICY_URL = "auth.policy.url.";
245
246     private Vector policyEntries;
247     private Hashtable aliasMapping;
248
249     private boolean initialized = false;
250
251     private boolean expandProperties = true;
252     private boolean ignoreIdentityScope = false;
253
254     // for use with the reflection API
255

256     private static final Class JavaDoc[] PARAMS = { String JavaDoc.class, String JavaDoc.class};
257
258     /**
259      * Initializes the Policy object and reads the default policy
260      * configuration file(s) into the Policy object.
261      */

262     public PolicyFile() {
263     // initialize Policy if either the AUTH_POLICY or
264
// SECURITY_MANAGER properties are set
265
String JavaDoc prop = System.getProperty(AUTH_POLICY);
266
267     if (prop == null) {
268         prop = System.getProperty(SECURITY_MANAGER);
269     }
270     if (prop != null)
271         init();
272     }
273
274     private synchronized void init() {
275
276     if (initialized)
277         return;
278
279     policyEntries = new Vector();
280     aliasMapping = new Hashtable(11);
281     
282     initPolicyFile();
283     initialized = true;
284     }
285
286     /**
287      * Refreshes the policy object by re-reading all the policy files.
288      *
289      * <p>
290      *
291      * @exception SecurityException if the caller doesn't have permission
292      * to refresh the <code>Policy</code>.
293      */

294     public synchronized void refresh()
295     {
296
297     java.lang.SecurityManager JavaDoc sm = System.getSecurityManager();
298     if (sm != null) {
299         sm.checkPermission(new javax.security.auth.AuthPermission JavaDoc
300                 ("refreshPolicy"));
301     }
302
303     // XXX
304
//
305
// 1) if code instantiates PolicyFile directly, then it will need
306
// all the permissions required for the PolicyFile initialization
307
// 2) if code calls Policy.getPolicy, then it simply needs
308
// AuthPermission(getPolicy), and the javax.security.auth.Policy
309
// implementation instantiates PolicyFile in a doPrivileged block
310
// 3) if after instantiating a Policy (either via #1 or #2),
311
// code calls refresh, it simply needs
312
// AuthPermission(refreshPolicy). then PolicyFile wraps
313
// the refresh in a doPrivileged block.
314
initialized = false;
315     java.security.AccessController.doPrivileged
316         (new java.security.PrivilegedAction JavaDoc() {
317         public Object JavaDoc run() {
318         init();
319         return null;
320         }
321     });
322     }
323
324     private KeyStore JavaDoc initKeyStore(URL JavaDoc policyUrl, String JavaDoc keyStoreName,
325                   String JavaDoc keyStoreType) {
326     if (keyStoreName != null) {
327         try {
328         /*
329          * location of keystore is specified as absolute URL in policy
330          * file, or is relative to URL of policy file
331          */

332         URL JavaDoc keyStoreUrl = null;
333         try {
334             keyStoreUrl = new URL JavaDoc(keyStoreName);
335             // absolute URL
336
} catch (java.net.MalformedURLException JavaDoc e) {
337             // relative URL
338
keyStoreUrl = new URL JavaDoc(policyUrl, keyStoreName);
339         }
340
341         if (debug != null) {
342             debug.println("reading keystore"+keyStoreUrl);
343         }
344
345         InputStream inStream =
346             new BufferedInputStream(getInputStream(keyStoreUrl));
347
348         KeyStore JavaDoc ks;
349         if (keyStoreType != null)
350             ks = KeyStore.getInstance(keyStoreType);
351         else
352             ks = KeyStore.getInstance(KeyStore.getDefaultType());
353         ks.load(inStream, null);
354         inStream.close();
355         return ks;
356         } catch (Exception JavaDoc e) {
357         // ignore, treat it like we have no keystore
358
if (debug != null) {
359             e.printStackTrace();
360         }
361         return null;
362         }
363     }
364     return null;
365     }
366
367     private void initPolicyFile() {
368
369     String JavaDoc prop = Security.getProperty("policy.expandProperties");
370
371     if (prop != null) expandProperties = prop.equalsIgnoreCase("true");
372
373     String JavaDoc iscp = Security.getProperty("policy.ignoreIdentityScope");
374
375     if (iscp != null) ignoreIdentityScope = iscp.equalsIgnoreCase("true");
376
377     String JavaDoc allowSys = Security.getProperty("policy.allowSystemProperty");
378
379     if ((allowSys!=null) && allowSys.equalsIgnoreCase("true")) {
380
381         String JavaDoc extra_policy = System.getProperty(AUTH_POLICY);
382         if (extra_policy != null) {
383         boolean overrideAll = false;
384         if (extra_policy.startsWith("=")) {
385             overrideAll = true;
386             extra_policy = extra_policy.substring(1);
387         }
388         try {
389             extra_policy = PropertyExpander.expand(extra_policy);
390             URL JavaDoc policyURL;;
391             File policyFile = new File(extra_policy);
392             if (policyFile.exists()) {
393             policyURL =
394                 new URL JavaDoc("file:" + policyFile.getCanonicalPath());
395             } else {
396             policyURL = new URL JavaDoc(extra_policy);
397             }
398             if (debug != null)
399             debug.println("reading "+policyURL);
400             init(policyURL);
401         } catch (Exception JavaDoc e) {
402             // ignore.
403
if (debug != null) {
404             debug.println("caught exception: "+e);
405             }
406
407         }
408         if (overrideAll) {
409             if (debug != null) {
410             debug.println("overriding other policies!");
411             }
412             return;
413         }
414         }
415     }
416
417     int n = 1;
418     boolean loaded_one = false;
419     String JavaDoc policy_url;
420
421     while ((policy_url = Security.getProperty(AUTH_POLICY_URL+n)) != null) {
422         try {
423         policy_url = PropertyExpander.expand(policy_url).replace
424                         (File.separatorChar, '/');
425         if (debug != null)
426             debug.println("reading "+policy_url);
427         init(new URL JavaDoc(policy_url));
428         loaded_one = true;
429         } catch (Exception JavaDoc e) {
430         if (debug != null) {
431             debug.println("error reading policy "+e);
432             e.printStackTrace();
433         }
434         // ignore that policy
435
}
436         n++;
437     }
438
439     if (loaded_one == false) {
440         // do not load a static policy
441
}
442     }
443
444     /** the scope to check */
445     private static IdentityScope JavaDoc scope = null;
446
447     /**
448      * Checks public key. If it is marked as trusted in
449      * the identity database, add it to the policy
450      * with the AllPermission.
451      */

452     private boolean checkForTrustedIdentity(final Certificate JavaDoc cert) {
453     // XXX JAAS has no way to access the SUN package.
454
// we'll add this back in when JAAS goes into core.
455
return false;
456     }
457
458     /**
459      * Reads a policy configuration into the Policy object using a
460      * Reader object.
461      *
462      * @param policyFile the policy Reader object.
463      */

464     private void init(URL JavaDoc policy) {
465     PolicyParser pp = new PolicyParser(expandProperties);
466     try {
467         InputStreamReader isr
468         = new InputStreamReader(getInputStream(policy));
469         pp.read(isr);
470         isr.close();
471         KeyStore JavaDoc keyStore = initKeyStore(policy, pp.getKeyStoreUrl(),
472                          pp.getKeyStoreType());
473         Enumeration enum_ = pp.grantElements();
474         while (enum_.hasMoreElements()) {
475         PolicyParser.GrantEntry ge =
476             (PolicyParser.GrantEntry) enum_.nextElement();
477         addGrantEntry(ge, keyStore);
478         }
479     } catch (PolicyParser.ParsingException pe) {
480         System.err.println(AUTH_POLICY +
481                 rb.getString(": error parsing ") + policy);
482         System.err.println(AUTH_POLICY +
483                 rb.getString(": ") +
484                 pe.getMessage());
485         if (debug != null)
486         pe.printStackTrace();
487
488     } catch (Exception JavaDoc e) {
489         if (debug != null) {
490         debug.println("error parsing "+policy);
491         debug.println(e.toString());
492         e.printStackTrace();
493         }
494     }
495     }
496
497     /*
498      * Fast path reading from file urls in order to avoid calling
499      * FileURLConnection.connect() which can be quite slow the first time
500      * it is called. We really should clean up FileURLConnection so that
501      * this is not a problem but in the meantime this fix helps reduce
502      * start up time noticeably for the new launcher. -- DAC
503      */

504     private InputStream getInputStream(URL JavaDoc url) throws IOException {
505     if ("file".equals(url.getProtocol())) {
506         String JavaDoc path = url.getFile().replace('/', File.separatorChar);
507         return new FileInputStream(path);
508     } else {
509         return url.openStream();
510     }
511     }
512
513     /**
514      * Given a PermissionEntry, create a codeSource.
515      *
516      * @return null if signedBy alias is not recognized
517      */

518     CodeSource JavaDoc getCodeSource(PolicyParser.GrantEntry ge, KeyStore JavaDoc keyStore)
519     throws java.net.MalformedURLException JavaDoc
520     {
521     Certificate JavaDoc[] certs = null;
522     if (ge.signedBy != null) {
523         certs = getCertificates(keyStore, ge.signedBy);
524         if (certs == null) {
525         // we don't have a key for this alias,
526
// just return
527
if (debug != null) {
528             debug.println(" no certs for alias " +
529                        ge.signedBy + ", ignoring.");
530         }
531         return null;
532         }
533     }
534     
535     URL JavaDoc location;
536
537     if (ge.codeBase != null)
538         location = new URL JavaDoc(ge.codeBase);
539     else
540         location = null;
541
542     if (ge.principals == null || ge.principals.size() == 0) {
543         return (canonicalizeCodebase
544             (new CodeSource JavaDoc(location, certs),
545             false));
546     } else {
547         return (canonicalizeCodebase
548         (new SubjectCodeSource(null, ge.principals, location, certs),
549         false));
550     }
551     }
552
553     /**
554      * Add one policy entry to the vector.
555      */

556     private void addGrantEntry(PolicyParser.GrantEntry ge,
557                    KeyStore JavaDoc keyStore) {
558
559     if (debug != null) {
560         debug.println("Adding policy entry: ");
561         debug.println(" signedBy " + ge.signedBy);
562         debug.println(" codeBase " + ge.codeBase);
563         if (ge.principals != null && ge.principals.size() > 0) {
564         ListIterator li = ge.principals.listIterator();
565         while (li.hasNext()) {
566             PolicyParser.PrincipalEntry pppe =
567             (PolicyParser.PrincipalEntry)li.next();
568             debug.println(" " + pppe.principalClass +
569                     " " + pppe.principalName);
570         }
571         }
572         debug.println();
573     }
574
575     try {
576         CodeSource JavaDoc codesource = getCodeSource(ge, keyStore);
577         // skip if signedBy alias was unknown...
578
if (codesource == null) return;
579
580         PolicyEntry entry = new PolicyEntry(codesource);
581         Enumeration enum_ = ge.permissionElements();
582         while (enum_.hasMoreElements()) {
583         PolicyParser.PermissionEntry pe =
584             (PolicyParser.PermissionEntry) enum_.nextElement();
585         try {
586             // XXX special case PrivateCredentialPermission-SELF
587
Permission JavaDoc perm;
588             if (pe.permission.equals
589             ("javax.security.auth.PrivateCredentialPermission") &&
590             pe.name.endsWith(" self")) {
591             perm = getInstance(pe.permission,
592                      pe.name + " \"self\"",
593                      pe.action);
594             } else {
595             perm = getInstance(pe.permission,
596                      pe.name,
597                      pe.action);
598             }
599             entry.add(perm);
600             if (debug != null) {
601             debug.println(" "+perm);
602             }
603         } catch (ClassNotFoundException JavaDoc cnfe) {
604             Certificate JavaDoc certs[];
605             if (pe.signedBy != null)
606             certs = getCertificates(keyStore, pe.signedBy);
607             else
608             certs = null;
609
610             // only add if we had no signer or we had a
611
// a signer and found the keys for it.
612
if (certs != null || pe.signedBy == null) {
613                 Permission JavaDoc perm = new UnresolvedPermission JavaDoc(
614                          pe.permission,
615                          pe.name,
616                          pe.action,
617                          certs);
618                 entry.add(perm);
619                 if (debug != null) {
620                 debug.println(" "+perm);
621                 }
622             }
623         } catch (java.lang.reflect.InvocationTargetException JavaDoc ite) {
624             System.err.println
625             (AUTH_POLICY +
626             rb.getString(": error adding Permission ") +
627             pe.permission +
628             rb.getString(" ") +
629             ite.getTargetException());
630         } catch (Exception JavaDoc e) {
631             System.err.println
632             (AUTH_POLICY +
633             rb.getString(": error adding Permission ") +
634             pe.permission +
635             rb.getString(" ") +
636             e);
637         }
638         }
639         policyEntries.addElement(entry);
640     } catch (Exception JavaDoc e) {
641         System.err.println
642         (AUTH_POLICY +
643         rb.getString(": error adding Entry ") +
644         ge +
645         rb.getString(" ") +
646         e);
647     }
648
649     if (debug != null)
650         debug.println();
651     }
652
653     /**
654      * Returns a new Permission object of the given Type. The Permission is
655      * created by getting the
656      * Class object using the <code>Class.forName</code> method, and using
657      * the reflection API to invoke the (String name, String actions)
658      * constructor on the
659      * object.
660      *
661      * @param type the type of Permission being created.
662      * @param name the name of the Permission being created.
663      * @param actions the actions of the Permission being created.
664      *
665      * @exception ClassNotFoundException if the particular Permission
666      * class could not be found.
667      *
668      * @exception IllegalAccessException if the class or initializer is
669      * not accessible.
670      *
671      * @exception InstantiationException if getInstance tries to
672      * instantiate an abstract class or an interface, or if the
673      * instantiation fails for some other reason.
674      *
675      * @exception NoSuchMethodException if the (String, String) constructor
676      * is not found.
677      *
678      * @exception InvocationTargetException if the underlying Permission
679      * constructor throws an exception.
680      *
681      */

682
683     private static final Permission JavaDoc getInstance(String JavaDoc type,
684                     String JavaDoc name,
685                     String JavaDoc actions)
686     throws ClassNotFoundException JavaDoc,
687            InstantiationException JavaDoc,
688            IllegalAccessException JavaDoc,
689            NoSuchMethodException JavaDoc,
690            InvocationTargetException
691     {
692     //XXX we might want to keep a hash of created factories...
693
Class JavaDoc pc = Class.forName(type);
694     Constructor c = pc.getConstructor(PARAMS);
695     return (Permission JavaDoc) c.newInstance(new Object JavaDoc[] { name, actions });
696     }
697
698     /**
699      * Fetch all certs associated with this alias.
700      */

701     Certificate JavaDoc[] getCertificates(
702                     KeyStore JavaDoc keyStore, String JavaDoc aliases) {
703
704     Vector vcerts = null;
705
706     StringTokenizer st = new StringTokenizer(aliases, ",");
707     int n = 0;
708
709     while (st.hasMoreTokens()) {
710         String JavaDoc alias = st.nextToken().trim();
711         n++;
712         Certificate JavaDoc cert = null;
713         //See if this alias's cert has already been cached
714
cert = (Certificate JavaDoc) aliasMapping.get(alias);
715         if (cert == null && keyStore != null) {
716
717         try {
718             cert = keyStore.getCertificate(alias);
719         } catch (KeyStoreException JavaDoc kse) {
720             // never happens, because keystore has already been loaded
721
// when we call this
722
}
723         if (cert != null) {
724             aliasMapping.put(alias, cert);
725             aliasMapping.put(cert, alias);
726         }
727         }
728
729         if (cert != null) {
730         if (vcerts == null)
731             vcerts = new Vector();
732         vcerts.addElement(cert);
733         }
734     }
735
736     // make sure n == vcerts.size, since we are doing a logical *and*
737
if (vcerts != null && n == vcerts.size()) {
738         Certificate JavaDoc[] certs = new Certificate JavaDoc[vcerts.size()];
739         vcerts.copyInto(certs);
740         return certs;
741     } else {
742         return null;
743     }
744     }
745
746     /**
747      * Enumerate all the entries in the global policy object.
748      * This method is used by policy admin tools. The tools
749      * should use the Enumeration methods on the returned object
750      * to fetch the elements sequentially.
751      */

752     private final synchronized Enumeration elements(){
753     return policyEntries.elements();
754     }
755
756     /**
757      * Examines this <code>Policy</code> and returns the Permissions granted
758      * to the specified <code>Subject</code> and <code>CodeSource</code>.
759      *
760      * <p> Permissions for a particular <i>grant</i> entry are returned
761      * if the <code>CodeSource</code> constructed using the codebase and
762      * signedby values specified in the entry <code>implies</code>
763      * the <code>CodeSource</code> provided to this method, and if the
764      * <code>Subject</code> provided to this method contains all of the
765      * Principals specified in the entry.
766      *
767      * <p> The <code>Subject</code> provided to this method contains all
768      * of the Principals specified in the entry if, for each
769      * <code>Principal</code>, "P1", specified in the <i>grant</i> entry
770      * one of the following two conditions is met:
771      *
772      * <p>
773      * <ol>
774      * <li> the <code>Subject</code> has a
775      * <code>Principal</code>, "P2", where
776      * <code>P2.getClass().getName()</code> equals the
777      * P1's class name, and where
778      * <code>P2.getName()</code> equals the P1's name.
779      *
780      * <li> P1 implements
781      * <code>com.sun.security.auth.PrincipalComparator</code>,
782      * and <code>P1.implies</code> the provided <code>Subject</code>.
783      * </ol>
784      *
785      * <p> Note that this <code>Policy</code> implementation has
786      * special handling for PrivateCredentialPermissions.
787      * When this method encounters a <code>PrivateCredentialPermission</code>
788      * which specifies "self" as the <code>Principal</code> class and name,
789      * it does not add that <code>Permission</code> to the returned
790      * <code>PermissionCollection</code>. Instead, it builds
791      * a new <code>PrivateCredentialPermission</code>
792      * for each <code>Principal</code> associated with the provided
793      * <code>Subject</code>. Each new <code>PrivateCredentialPermission</code>
794      * contains the same Credential class as specified in the
795      * originally granted permission, as well as the Class and name
796      * for the respective <code>Principal</code>.
797      *
798      * <p>
799      *
800      * @param subject the Permissions granted to this <code>Subject</code>
801      * and the additionally provided <code>CodeSource</code>
802      * are returned. <p>
803      *
804      * @param codesource the Permissions granted to this <code>CodeSource</code>
805      * and the additionally provided <code>Subject</code>
806      * are returned.
807      *
808      * @return the Permissions granted to the provided <code>Subject</code>
809      * <code>CodeSource</code>.
810      */

811     public PermissionCollection JavaDoc getPermissions(final Subject JavaDoc subject,
812                     final CodeSource JavaDoc codesource) {
813
814     // XXX when JAAS goes into the JDK core,
815
// we can remove this method and simply
816
// rely on the getPermissions variant that takes a codesource,
817
// which no one can use at this point in time.
818
// at that time, we can also make SubjectCodeSource a public
819
// class.
820

821     // XXX
822
//
823
// 1) if code instantiates PolicyFile directly, then it will need
824
// all the permissions required for the PolicyFile initialization
825
// 2) if code calls Policy.getPolicy, then it simply needs
826
// AuthPermission(getPolicy), and the javax.security.auth.Policy
827
// implementation instantiates PolicyFile in a doPrivileged block
828
// 3) if after instantiating a Policy (either via #1 or #2),
829
// code calls getPermissions, PolicyFile wraps the call
830
// in a doPrivileged block.
831
return (PermissionCollection JavaDoc)java.security.AccessController.doPrivileged
832         (new java.security.PrivilegedAction JavaDoc() {
833         public Object JavaDoc run() {
834         SubjectCodeSource scs = new SubjectCodeSource
835             (subject,
836             null,
837             codesource == null ? null : codesource.getLocation(),
838             codesource == null ? null : codesource.getCertificates());
839         if (initialized)
840             return getPermissions(new Permissions JavaDoc(), scs);
841         else
842             return new PolicyPermissions(PolicyFile.this, scs);
843         }
844     });
845     }
846
847     /**
848      * Examines the global policy for the specified CodeSource, and
849      * creates a PermissionCollection object with
850      * the set of permissions for that principal's protection domain.
851      *
852      * @param CodeSource the codesource associated with the caller.
853      * This encapsulates the original location of the code (where the code
854      * came from) and the public key(s) of its signer.
855      *
856      * @return the set of permissions according to the policy.
857      */

858     PermissionCollection JavaDoc getPermissions(CodeSource JavaDoc codesource) {
859
860     if (initialized)
861         return getPermissions(new Permissions JavaDoc(), codesource);
862     else
863         return new PolicyPermissions(this, codesource);
864     }
865
866     /**
867      * Examines the global policy for the specified CodeSource, and
868      * creates a PermissionCollection object with
869      * the set of permissions for that principal's protection domain.
870      *
871      * @param permissions the permissions to populate
872      * @param codesource the codesource associated with the caller.
873      * This encapsulates the original location of the code (where the code
874      * came from) and the public key(s) of its signer.
875      *
876      * @return the set of permissions according to the policy.
877      */

878     Permissions JavaDoc getPermissions(final Permissions JavaDoc perms,
879                    final CodeSource JavaDoc cs)
880     {
881     if (!initialized) {
882         init();
883     }
884
885     final CodeSource JavaDoc codesource[] = {null};
886
887     codesource[0] = canonicalizeCodebase(cs, true);
888
889     if (debug != null) {
890         debug.println("evaluate("+codesource[0]+")\n");
891     }
892         
893     // needs to be in a begin/endPrivileged block because
894
// codesource.implies calls URL.equals which does an
895
// InetAddress lookup
896

897     for (int i = 0; i < policyEntries.size(); i++) {
898
899        PolicyEntry entry = (PolicyEntry)policyEntries.elementAt(i);
900
901        if (debug != null) {
902         debug.println("PolicyFile CodeSource implies: " +
903             entry.codesource.toString() + "\n\n" +
904             "\t" + codesource[0].toString() + "\n\n");
905        }
906
907        if (entry.codesource.implies(codesource[0])) {
908            for (int j = 0; j < entry.permissions.size(); j++) {
909             Permission JavaDoc p =
910                (Permission JavaDoc) entry.permissions.elementAt(j);
911             if (debug != null) {
912                debug.println(" granting " + p);
913             }
914             if (!addSelfPermissions(p, entry.codesource,
915                     codesource[0], perms)) {
916             // we could check for duplicates
917
// before adding new permissions,
918
// but the SubjectDomainCombiner
919
// already checks for duplicates later
920
perms.add(p);
921             }
922         }
923         }
924     }
925
926     // now see if any of the keys are trusted ids.
927

928     if (!ignoreIdentityScope) {
929         Certificate JavaDoc certs[] = codesource[0].getCertificates();
930         if (certs != null) {
931         for (int k=0; k < certs.length; k++) {
932             if ((aliasMapping.get(certs[k]) == null) &&
933             checkForTrustedIdentity(certs[k])) {
934             // checkForTrustedIdentity added it
935
// to the policy for us. next time
936
// around we'll find it. This time
937
// around we need to add it.
938
perms.add(new java.security.AllPermission JavaDoc());
939             }
940         }
941         }
942     }
943     return perms;
944     }
945
946     /**
947      * Returns true if 'Self' permissions were added to the provided
948      * 'perms', and false otherwise.
949      *
950      * <p>
951      *
952      * @param p check to see if this Permission is a "SELF"
953      * PrivateCredentialPermission. <p>
954      *
955      * @param entryCs the codesource for the Policy entry.
956      *
957      * @param accCs the codesource for from the current AccessControlContext.
958      *
959      * @param perms the PermissionCollection where the individual
960      * PrivateCredentialPermissions will be added.
961      */

962     private boolean addSelfPermissions(final Permission JavaDoc p,
963                 CodeSource JavaDoc entryCs,
964                 CodeSource JavaDoc accCs,
965                 Permissions JavaDoc perms) {
966
967     if (!(p instanceof PrivateCredentialPermission JavaDoc))
968         return false;
969
970     if (!(entryCs instanceof SubjectCodeSource))
971         return false;
972
973
974     PrivateCredentialPermission JavaDoc pcp = (PrivateCredentialPermission JavaDoc)p;
975     SubjectCodeSource scs = (SubjectCodeSource)entryCs;
976
977     // see if it is a SELF permission
978
String JavaDoc[][] pPrincipals = pcp.getPrincipals();
979     if (pPrincipals.length <= 0 ||
980         !pPrincipals[0][0].equalsIgnoreCase("self") ||
981         !pPrincipals[0][1].equalsIgnoreCase("self")) {
982
983         // regular PrivateCredentialPermission
984
return false;
985     } else {
986
987         // granted a SELF permission - create a
988
// PrivateCredentialPermission for each
989
// of the Policy entry's CodeSource Principals
990

991         if (scs.getPrincipals() == null) {
992         // XXX SubjectCodeSource has no Subject???
993
return true;
994         }
995
996         ListIterator pli = scs.getPrincipals().listIterator();
997         while (pli.hasNext()) {
998
999         PolicyParser.PrincipalEntry principal =
1000                (PolicyParser.PrincipalEntry)pli.next();
1001
1002        // XXX
1003
// if the Policy entry's Principal does not contain a
1004
// WILDCARD for the Principal name, then a
1005
// new PrivateCredentialPermission is created
1006
// for the Principal listed in the Policy entry.
1007
// if the Policy entry's Principal contains a WILDCARD
1008
// for the Principal name, then a new
1009
// PrivateCredentialPermission is created
1010
// for each Principal associated with the Subject
1011
// in the current ACC.
1012

1013        String JavaDoc[][] principalInfo = getPrincipalInfo
1014                        (principal, accCs);
1015
1016        for (int i = 0; i < principalInfo.length; i++) {
1017
1018            // here's the new PrivateCredentialPermission
1019

1020            PrivateCredentialPermission JavaDoc newPcp =
1021            new PrivateCredentialPermission JavaDoc
1022                (pcp.getCredentialClass() +
1023                    " " +
1024                    principalInfo[i][0] +
1025                    " " +
1026                    "\"" + principalInfo[i][1] + "\"",
1027                "read");
1028
1029            if (debug != null) {
1030            debug.println("adding SELF permission: " +
1031                    newPcp.toString());
1032            }
1033
1034            perms.add(newPcp);
1035        }
1036        }
1037    }
1038    return true;
1039    }
1040
1041    /**
1042     * return the principal class/name pair in the 2D array.
1043     * array[x][y]: x corresponds to the array length.
1044     * if (y == 0), it's the principal class.
1045     * if (y == 1), it's the principal name.
1046     */

1047    private String JavaDoc[][] getPrincipalInfo
1048        (PolicyParser.PrincipalEntry principal,
1049        final CodeSource JavaDoc accCs) {
1050
1051    // there are 3 possibilities:
1052
// 1) the entry's Principal class and name are not wildcarded
1053
// 2) the entry's Principal name is wildcarded only
1054
// 3) the entry's Principal class and name are wildcarded
1055

1056    if (!principal.principalClass.equals
1057        (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
1058        !principal.principalName.equals
1059        (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
1060
1061        // build a PrivateCredentialPermission for the principal
1062
// from the Policy entry
1063
String JavaDoc[][] info = new String JavaDoc[1][2];
1064        info[0][0] = principal.principalClass;
1065        info[0][1] = principal.principalName;
1066        return info;
1067
1068    } else if (!principal.principalClass.equals
1069        (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
1070        principal.principalName.equals
1071        (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
1072
1073        // build a PrivateCredentialPermission for all
1074
// the Subject's principals that are instances of principalClass
1075

1076        // the accCs is guaranteed to be a SubjectCodeSource
1077
// because the earlier CodeSource.implies succeeded
1078
SubjectCodeSource scs = (SubjectCodeSource)accCs;
1079
1080        Set principalSet = null;
1081        try {
1082        Class JavaDoc pClass = Class.forName(principal.principalClass, false,
1083                ClassLoader.getSystemClassLoader());
1084        principalSet = scs.getSubject().getPrincipals(pClass);
1085        } catch (Exception JavaDoc e) {
1086        if (debug != null) {
1087            debug.println("problem finding Principal Class " +
1088                "when expanding SELF permission: " +
1089                e.toString());
1090        }
1091        }
1092
1093        if (principalSet == null) {
1094        // error
1095
return new String JavaDoc[0][0];
1096        }
1097
1098        String JavaDoc[][] info = new String JavaDoc[principalSet.size()][2];
1099        java.util.Iterator JavaDoc pIterator = principalSet.iterator();
1100
1101        int i = 0;
1102        while (pIterator.hasNext()) {
1103        Principal JavaDoc p = (Principal JavaDoc)pIterator.next();
1104        info[i][0] = p.getClass().getName();
1105        info[i][1] = p.getName();
1106        i++;
1107        }
1108        return info;
1109
1110    } else {
1111
1112        // build a PrivateCredentialPermission for every
1113
// one of the current Subject's principals
1114

1115        // the accCs is guaranteed to be a SubjectCodeSource
1116
// because the earlier CodeSource.implies succeeded
1117
SubjectCodeSource scs = (SubjectCodeSource)accCs;
1118        Set principalSet = scs.getSubject().getPrincipals();
1119
1120        String JavaDoc[][] info = new String JavaDoc[principalSet.size()][2];
1121        java.util.Iterator JavaDoc pIterator = principalSet.iterator();
1122
1123        int i = 0;
1124        while (pIterator.hasNext()) {
1125        Principal JavaDoc p = (Principal JavaDoc)pIterator.next();
1126        info[i][0] = p.getClass().getName();
1127        info[i][1] = p.getName();
1128        i++;
1129        }
1130        return info;
1131    }
1132    }
1133
1134    /*
1135     * Returns the signer certificates from the list of certificates associated
1136     * with the given code source.
1137     *
1138     * The signer certificates are those certificates that were used to verify
1139     * signed code originating from the codesource location.
1140     *
1141     * This method assumes that in the given code source, each signer
1142     * certificate is followed by its supporting certificate chain
1143     * (which may be empty), and that the signer certificate and its
1144     * supporting certificate chain are ordered bottom-to-top (i.e., with the
1145     * signer certificate first and the (root) certificate authority last).
1146     */

1147    Certificate JavaDoc[] getSignerCertificates(CodeSource JavaDoc cs) {
1148    Certificate JavaDoc[] certs = null;
1149    if ((certs = cs.getCertificates()) == null)
1150        return null;
1151    for (int i=0; i<certs.length; i++) {
1152        if (!(certs[i] instanceof X509Certificate JavaDoc))
1153        return cs.getCertificates();
1154    }
1155
1156    // Do we have to do anything?
1157
int i = 0;
1158    int count = 0;
1159    while (i < certs.length) {
1160        count++;
1161        while (((i+1) < certs.length)
1162           && ((X509Certificate JavaDoc)certs[i]).getIssuerDN().equals(
1163                   ((X509Certificate JavaDoc)certs[i+1]).getSubjectDN())) {
1164        i++;
1165        }
1166        i++;
1167    }
1168    if (count == certs.length)
1169        // Done
1170
return certs;
1171
1172    ArrayList userCertList = new ArrayList();
1173    i = 0;
1174    while (i < certs.length) {
1175        userCertList.add(certs[i]);
1176        while (((i+1) < certs.length)
1177           && ((X509Certificate JavaDoc)certs[i]).getIssuerDN().equals(
1178                   ((X509Certificate JavaDoc)certs[i+1]).getSubjectDN())) {
1179        i++;
1180        }
1181        i++;
1182    }
1183    Certificate JavaDoc[] userCerts = new Certificate JavaDoc[userCertList.size()];
1184    userCertList.toArray(userCerts);
1185    return userCerts;
1186    }
1187
1188    private CodeSource JavaDoc canonicalizeCodebase(CodeSource JavaDoc cs,
1189                        boolean extractSignerCerts) {
1190    CodeSource JavaDoc canonCs = cs;
1191    if (cs.getLocation() != null &&
1192        cs.getLocation().getProtocol().equalsIgnoreCase("file")) {
1193        try {
1194        String JavaDoc path = cs.getLocation().getFile().replace
1195                            ('/',
1196                            File.separatorChar);
1197        URL JavaDoc csUrl = null;
1198        if (path.endsWith("*")) {
1199            // remove trailing '*' because it causes canonicalization
1200
// to fail on win32
1201
path = path.substring(0, path.length()-1);
1202            boolean appendFileSep = false;
1203            if (path.endsWith(File.separator))
1204            appendFileSep = true;
1205            if (path.equals("")) {
1206            path = System.getProperty("user.dir");
1207            }
1208            File f = new File(path);
1209            path = f.getCanonicalPath();
1210            StringBuffer JavaDoc sb = new StringBuffer JavaDoc(path);
1211            // reappend '*' to canonicalized filename (note that
1212
// canonicalization may have removed trailing file
1213
// separator, so we have to check for that, too)
1214
if (!path.endsWith(File.separator) &&
1215            (appendFileSep || f.isDirectory()))
1216            sb.append(File.separatorChar);
1217            sb.append('*');
1218            path = sb.toString();
1219        } else {
1220            path = new File(path).getCanonicalPath();
1221        }
1222        csUrl = new File(path).toURL();
1223
1224        if (cs instanceof SubjectCodeSource) {
1225            SubjectCodeSource scs = (SubjectCodeSource)cs;
1226            if (extractSignerCerts) {
1227            canonCs = new SubjectCodeSource
1228                        (scs.getSubject(),
1229                        scs.getPrincipals(),
1230                        csUrl,
1231                        getSignerCertificates(scs));
1232            } else {
1233            canonCs = new SubjectCodeSource
1234                        (scs.getSubject(),
1235                        scs.getPrincipals(),
1236                        csUrl,
1237                        scs.getCertificates());
1238            }
1239        } else {
1240            if (extractSignerCerts) {
1241            canonCs = new CodeSource JavaDoc(csUrl,
1242                        getSignerCertificates(cs));
1243            } else {
1244            canonCs = new CodeSource JavaDoc(csUrl,
1245                        cs.getCertificates());
1246            }
1247        }
1248        } catch (IOException ioe) {
1249        // leave codesource as it is, unless we have to extract its
1250
// signer certificates
1251
if (extractSignerCerts) {
1252            if (!(cs instanceof SubjectCodeSource)) {
1253            canonCs = new CodeSource JavaDoc(cs.getLocation(),
1254                        getSignerCertificates(cs));
1255            } else {
1256            SubjectCodeSource scs = (SubjectCodeSource)cs;
1257            canonCs = new SubjectCodeSource(scs.getSubject(),
1258                        scs.getPrincipals(),
1259                        scs.getLocation(),
1260                        getSignerCertificates(scs));
1261            }
1262        }
1263        }
1264    } else {
1265        if (extractSignerCerts) {
1266        if (!(cs instanceof SubjectCodeSource)) {
1267            canonCs = new CodeSource JavaDoc(cs.getLocation(),
1268                    getSignerCertificates(cs));
1269        } else {
1270            SubjectCodeSource scs = (SubjectCodeSource)cs;
1271            canonCs = new SubjectCodeSource(scs.getSubject(),
1272                    scs.getPrincipals(),
1273                    scs.getLocation(),
1274                    getSignerCertificates(scs));
1275        }
1276        }
1277    }
1278    return canonCs;
1279    }
1280
1281    /**
1282     * Each entry in the policy configuration file is represented by a
1283     * PolicyEntry object. <p>
1284     *
1285     * A PolicyEntry is a (CodeSource,Permission) pair. The
1286     * CodeSource contains the (URL, PublicKey) that together identify
1287     * where the Java bytecodes come from and who (if anyone) signed
1288     * them. The URL could refer to localhost. The URL could also be
1289     * null, meaning that this policy entry is given to all comers, as
1290     * long as they match the signer field. The signer could be null,
1291     * meaning the code is not signed. <p>
1292     *
1293     * The Permission contains the (Type, Name, Action) triplet. <p>
1294     *
1295     * For now, the Policy object retrieves the public key from the
1296     * X.509 certificate on disk that corresponds to the signedBy
1297     * alias specified in the Policy config file. For reasons of
1298     * efficiency, the Policy object keeps a hashtable of certs already
1299     * read in. This could be replaced by a secure internal key
1300     * store.
1301     *
1302     * <p>
1303     * For example, the entry
1304     * <pre>
1305     * permission java.io.File "/tmp", "read,write",
1306     * signedBy "Duke";
1307     * </pre>
1308     * is represented internally
1309     * <pre>
1310     *
1311     * FilePermission f = new FilePermission("/tmp", "read,write");
1312     * PublicKey p = publickeys.get("Duke");
1313     * URL u = InetAddress.getLocalHost();
1314     * CodeBase c = new CodeBase( p, u );
1315     * pe = new PolicyEntry(f, c);
1316     * </pre>
1317     *
1318     * @author Marianne Mueller
1319     * @author Roland Schemers
1320     * @version 1.6, 03/04/97
1321     * @see java.security.CodeSource
1322     * @see java.security.Policy
1323     * @see java.security.Permissions
1324     * @see java.security.ProtectionDomain
1325     */

1326
1327    private static class PolicyEntry {
1328
1329    CodeSource JavaDoc codesource;
1330    Vector permissions;
1331
1332    /**
1333     * Given a Permission and a CodeSource, create a policy entry.
1334     *
1335     * XXX Decide if/how to add validity fields and "purpose" fields to
1336     * XXX policy entries
1337     *
1338     * @param cs the CodeSource, which encapsulates the URL and the public
1339     * key
1340     * attributes from the policy config file. Validity checks are
1341     * performed on the public key before PolicyEntry is called.
1342     *
1343     */

1344    PolicyEntry(CodeSource JavaDoc cs)
1345    {
1346        this.codesource = cs;
1347        this.permissions = new Vector();
1348    }
1349
1350    /**
1351     * add a Permission object to this entry.
1352     */

1353    void add(Permission JavaDoc p) {
1354        permissions.addElement(p);
1355    }
1356
1357    /**
1358     * Return the CodeSource for this policy entry
1359     */

1360    CodeSource JavaDoc getCodeSource() {
1361        return this.codesource;
1362    }
1363
1364    public String JavaDoc toString(){
1365        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1366        sb.append(rb.getString("("));
1367        sb.append(getCodeSource());
1368        sb.append("\n");
1369        for (int j = 0; j < permissions.size(); j++) {
1370        Permission JavaDoc p = (Permission JavaDoc) permissions.elementAt(j);
1371        sb.append(rb.getString(" "));
1372        sb.append(rb.getString(" "));
1373        sb.append(p);
1374        sb.append(rb.getString("\n"));
1375        }
1376        sb.append(rb.getString(")"));
1377        sb.append(rb.getString("\n"));
1378        return sb.toString();
1379    }
1380
1381    }
1382}
1383
1384class PolicyPermissions extends PermissionCollection JavaDoc {
1385
1386    private static final long serialVersionUID = -1954188373270545523L;
1387
1388    private CodeSource JavaDoc codesource;
1389    private Permissions JavaDoc perms;
1390    private PolicyFile policy;
1391    private boolean notInit; // have we pulled in the policy permissions yet?
1392
private Vector additionalPerms;
1393
1394    PolicyPermissions(PolicyFile policy,
1395              CodeSource JavaDoc codesource)
1396    {
1397    this.codesource = codesource;
1398    this.policy = policy;
1399    this.perms = null;
1400    this.notInit = true;
1401    this.additionalPerms = null;
1402    }
1403
1404    public void add(Permission JavaDoc permission) {
1405    if (isReadOnly())
1406        throw new SecurityException JavaDoc
1407        (PolicyFile.rb.getString
1408        ("attempt to add a Permission to a readonly PermissionCollection"));
1409
1410    if (perms == null) {
1411        if (additionalPerms == null)
1412        additionalPerms = new Vector();
1413        additionalPerms.add(permission);
1414    } else {
1415        perms.add(permission);
1416    }
1417    }
1418
1419    private synchronized void init() {
1420    if (notInit) {
1421        if (perms == null)
1422        perms = new Permissions JavaDoc();
1423
1424        if (additionalPerms != null) {
1425        Enumeration e = additionalPerms.elements();
1426        while (e.hasMoreElements()) {
1427            perms.add((Permission JavaDoc)e.nextElement());
1428        }
1429        additionalPerms = null;
1430        }
1431        policy.getPermissions(perms,codesource);
1432        notInit=false;
1433    }
1434    }
1435
1436    public boolean implies(Permission JavaDoc permission) {
1437    if (notInit)
1438        init();
1439    return perms.implies(permission);
1440    }
1441
1442    public Enumeration elements() {
1443    if (notInit)
1444        init();
1445    return perms.elements();
1446    }
1447
1448    public String JavaDoc toString() {
1449    if (notInit)
1450        init();
1451    return perms.toString();
1452    }
1453}
1454
Popular Tags