History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/security/auth/PolicyFile.java (1 of 18352 files). Show all

Unified · Split

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