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