Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/provider/PolicyFile.java
38830 views
1
/*
2
* Copyright (c) 1997, 2017, 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 sun.security.provider;
27
28
import java.io.*;
29
import java.lang.reflect.*;
30
import java.net.MalformedURLException;
31
import java.net.URL;
32
import java.net.URI;
33
import java.util.*;
34
import java.text.MessageFormat;
35
import java.security.*;
36
import java.security.cert.Certificate;
37
import java.security.cert.X509Certificate;
38
import javax.security.auth.Subject;
39
import javax.security.auth.x500.X500Principal;
40
import java.io.FilePermission;
41
import java.net.SocketPermission;
42
import java.net.NetPermission;
43
import sun.misc.JavaSecurityProtectionDomainAccess;
44
import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
45
import sun.misc.SharedSecrets;
46
import sun.security.util.PolicyUtil;
47
import sun.security.util.PropertyExpander;
48
import sun.security.util.Debug;
49
import sun.security.util.ResourcesMgr;
50
import sun.security.util.SecurityConstants;
51
import sun.net.www.ParseUtil;
52
53
/**
54
* This class represents a default implementation for
55
* <code>java.security.Policy</code>.
56
*
57
* Note:
58
* For backward compatibility with JAAS 1.0 it loads
59
* both java.auth.policy and java.policy. However it
60
* is recommended that java.auth.policy be not used
61
* and the java.policy contain all grant entries including
62
* that contain principal-based entries.
63
*
64
*
65
* <p> This object stores the policy for entire Java runtime,
66
* and is the amalgamation of multiple static policy
67
* configurations that resides in files.
68
* The algorithm for locating the policy file(s) and reading their
69
* information into this <code>Policy</code> object is:
70
*
71
* <ol>
72
* <li>
73
* Loop through the <code>java.security.Security</code> properties,
74
* <i>policy.url.1</i>, <i>policy.url.2</i>, ...,
75
* <i>policy.url.X</i>" and
76
* <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,
77
* <i>auth.policy.url.X</i>". These properties are set
78
* in the Java security properties file, which is located in the file named
79
* &lt;JAVA_HOME&gt;/lib/security/java.security.
80
* &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
81
* and specifies the directory where the JRE is installed.
82
* Each property value specifies a <code>URL</code> pointing to a
83
* policy file to be loaded. Read in and load each policy.
84
*
85
* <i>auth.policy.url</i> is supported only for backward compatibility.
86
*
87
* <li>
88
* The <code>java.lang.System</code> property <i>java.security.policy</i>
89
* may also be set to a <code>URL</code> pointing to another policy file
90
* (which is the case when a user uses the -D switch at runtime).
91
* If this property is defined, and its use is allowed by the
92
* security property file (the Security property,
93
* <i>policy.allowSystemProperty</i> is set to <i>true</i>),
94
* also load that policy.
95
*
96
* <li>
97
* The <code>java.lang.System</code> property
98
* <i>java.security.auth.policy</i> may also be set to a
99
* <code>URL</code> pointing to another policy file
100
* (which is the case when a user uses the -D switch at runtime).
101
* If this property is defined, and its use is allowed by the
102
* security property file (the Security property,
103
* <i>policy.allowSystemProperty</i> is set to <i>true</i>),
104
* also load that policy.
105
*
106
* <i>java.security.auth.policy</i> is supported only for backward
107
* compatibility.
108
*
109
* If the <i>java.security.policy</i> or
110
* <i>java.security.auth.policy</i> property is defined using
111
* "==" (rather than "="), then ignore all other specified
112
* policies and only load this policy.
113
* </ol>
114
*
115
* Each policy file consists of one or more grant entries, each of
116
* which consists of a number of permission entries.
117
*
118
* <pre>
119
* grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",
120
* principal <b>principalClass</b> "<b>principalName</b>",
121
* principal <b>principalClass</b> "<b>principalName</b>",
122
* ... {
123
*
124
* permission <b>Type</b> "<b>name</b> "<b>action</b>",
125
* signedBy "<b>alias</b>";
126
* permission <b>Type</b> "<b>name</b> "<b>action</b>",
127
* signedBy "<b>alias</b>";
128
* ....
129
* };
130
* </pre>
131
*
132
* All non-bold items above must appear as is (although case
133
* doesn't matter and some are optional, as noted below).
134
* principal entries are optional and need not be present.
135
* Italicized items represent variable values.
136
*
137
* <p> A grant entry must begin with the word <code>grant</code>.
138
* The <code>signedBy</code>,<code>codeBase</code> and <code>principal</code>
139
* name/value pairs are optional.
140
* If they are not present, then any signer (including unsigned code)
141
* will match, and any codeBase will match.
142
* Note that the <i>principalClass</i>
143
* may be set to the wildcard value, *, which allows it to match
144
* any <code>Principal</code> class. In addition, the <i>principalName</i>
145
* may also be set to the wildcard value, *, allowing it to match
146
* any <code>Principal</code> name. When setting the <i>principalName</i>
147
* to the *, do not surround the * with quotes.
148
*
149
* <p> A permission entry must begin with the word <code>permission</code>.
150
* The word <code><i>Type</i></code> in the template above is
151
* a specific permission type, such as <code>java.io.FilePermission</code>
152
* or <code>java.lang.RuntimePermission</code>.
153
*
154
* <p> The "<i>action</i>" is required for
155
* many permission types, such as <code>java.io.FilePermission</code>
156
* (where it specifies what type of file access that is permitted).
157
* It is not required for categories such as
158
* <code>java.lang.RuntimePermission</code>
159
* where it is not necessary - you either have the
160
* permission specified by the <code>"<i>name</i>"</code>
161
* value following the type name or you don't.
162
*
163
* <p> The <code>signedBy</code> name/value pair for a permission entry
164
* is optional. If present, it indicates a signed permission. That is,
165
* the permission class itself must be signed by the given alias in
166
* order for it to be granted. For example,
167
* suppose you have the following grant entry:
168
*
169
* <pre>
170
* grant principal foo.com.Principal "Duke" {
171
* permission Foo "foobar", signedBy "FooSoft";
172
* }
173
* </pre>
174
*
175
* <p> Then this permission of type <i>Foo</i> is granted if the
176
* <code>Foo.class</code> permission has been signed by the
177
* "FooSoft" alias, or if XXX <code>Foo.class</code> is a
178
* system class (i.e., is found on the CLASSPATH).
179
*
180
*
181
* <p> Items that appear in an entry must appear in the specified order
182
* (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
183
* "<i>action</i>"). An entry is terminated with a semicolon.
184
*
185
* <p> Case is unimportant for the identifiers (<code>permission</code>,
186
* <code>signedBy</code>, <code>codeBase</code>, etc.) but is
187
* significant for the <i>Type</i>
188
* or for any string that is passed in as a value. <p>
189
*
190
* <p> An example of two entries in a policy configuration file is
191
* <pre>
192
* // if the code is comes from "foo.com" and is running as "Duke",
193
* // grant it read/write to all files in /tmp.
194
*
195
* grant codeBase "foo.com", principal foo.com.Principal "Duke" {
196
* permission java.io.FilePermission "/tmp/*", "read,write";
197
* };
198
*
199
* // grant any code running as "Duke" permission to read
200
* // the "java.vendor" Property.
201
*
202
* grant principal foo.com.Principal "Duke" {
203
* permission java.util.PropertyPermission "java.vendor";
204
*
205
*
206
* </pre>
207
* This Policy implementation supports special handling of any
208
* permission that contains the string, "<b>${{self}}</b>", as part of
209
* its target name. When such a permission is evaluated
210
* (such as during a security check), <b>${{self}}</b> is replaced
211
* with one or more Principal class/name pairs. The exact
212
* replacement performed depends upon the contents of the
213
* grant clause to which the permission belongs.
214
*<p>
215
*
216
* If the grant clause does not contain any principal information,
217
* the permission will be ignored (permissions containing
218
* <b>${{self}}</b> in their target names are only valid in the context
219
* of a principal-based grant clause). For example, BarPermission
220
* will always be ignored in the following grant clause:
221
*
222
*<pre>
223
* grant codebase "www.foo.com", signedby "duke" {
224
* permission BarPermission "... ${{self}} ...";
225
* };
226
*</pre>
227
*
228
* If the grant clause contains principal information, <b>${{self}}</b>
229
* will be replaced with that same principal information.
230
* For example, <b>${{self}}</b> in BarPermission will be replaced by
231
* <b>javax.security.auth.x500.X500Principal "cn=Duke"</b>
232
* in the following grant clause:
233
*
234
* <pre>
235
* grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
236
* permission BarPermission "... ${{self}} ...";
237
* };
238
* </pre>
239
*
240
* If there is a comma-separated list of principals in the grant
241
* clause, then <b>${{self}}</b> will be replaced by the same
242
* comma-separated list or principals.
243
* In the case where both the principal class and name are
244
* wildcarded in the grant clause, <b>${{self}}</b> is replaced
245
* with all the principals associated with the <code>Subject</code>
246
* in the current <code>AccessControlContext</code>.
247
*
248
*
249
* <p> For PrivateCredentialPermissions, you can also use "<b>self</b>"
250
* instead of "<b>${{self}}</b>". However the use of "<b>self</b>" is
251
* deprecated in favour of "<b>${{self}}</b>".
252
*
253
* @see java.security.CodeSource
254
* @see java.security.Permissions
255
* @see java.security.ProtectionDomain
256
*/
257
public class PolicyFile extends java.security.Policy {
258
259
private static final Debug debug = Debug.getInstance("policy");
260
261
private static final String NONE = "NONE";
262
private static final String P11KEYSTORE = "PKCS11";
263
264
private static final String SELF = "${{self}}";
265
private static final String X500PRINCIPAL =
266
"javax.security.auth.x500.X500Principal";
267
private static final String POLICY = "java.security.policy";
268
private static final String SECURITY_MANAGER = "java.security.manager";
269
private static final String POLICY_URL = "policy.url.";
270
private static final String AUTH_POLICY = "java.security.auth.policy";
271
private static final String AUTH_POLICY_URL = "auth.policy.url.";
272
273
private static final int DEFAULT_CACHE_SIZE = 1;
274
275
// contains the policy grant entries, PD cache, and alias mapping
276
// can be updated if refresh() is called
277
private volatile PolicyInfo policyInfo;
278
private boolean constructed = false;
279
280
private boolean expandProperties = true;
281
private boolean ignoreIdentityScope = true;
282
private boolean allowSystemProperties = true;
283
private boolean notUtf8 = false;
284
private URL url;
285
286
// for use with the reflection API
287
288
private static final Class[] PARAMS0 = { };
289
private static final Class[] PARAMS1 = { String.class };
290
private static final Class[] PARAMS2 = { String.class, String.class };
291
292
/**
293
* Initializes the Policy object and reads the default policy
294
* configuration file(s) into the Policy object.
295
*/
296
public PolicyFile() {
297
init((URL)null);
298
}
299
300
/**
301
* Initializes the Policy object and reads the default policy
302
* from the specified URL only.
303
*/
304
public PolicyFile(URL url) {
305
this.url = url;
306
init(url);
307
}
308
309
/**
310
* Initializes the Policy object and reads the default policy
311
* configuration file(s) into the Policy object.
312
*
313
* The algorithm for locating the policy file(s) and reading their
314
* information into the Policy object is:
315
* <pre>
316
* loop through the Security Properties named "policy.url.1",
317
* ""policy.url.2", "auth.policy.url.1", "auth.policy.url.2" etc, until
318
* you don't find one. Each of these specify a policy file.
319
*
320
* if none of these could be loaded, use a builtin static policy
321
* equivalent to the default lib/security/java.policy file.
322
*
323
* if the system property "java.policy" or "java.auth.policy" is defined
324
* (which is the
325
* case when the user uses the -D switch at runtime), and
326
* its use is allowed by the security property file,
327
* also load it.
328
* </pre>
329
*
330
* Each policy file consists of one or more grant entries, each of
331
* which consists of a number of permission entries.
332
* <pre>
333
* grant signedBy "<i>alias</i>", codeBase "<i>URL</i>" {
334
* permission <i>Type</i> "<i>name</i>", "<i>action</i>",
335
* signedBy "<i>alias</i>";
336
* ....
337
* permission <i>Type</i> "<i>name</i>", "<i>action</i>",
338
* signedBy "<i>alias</i>";
339
* };
340
*
341
* </pre>
342
*
343
* All non-italicized items above must appear as is (although case
344
* doesn't matter and some are optional, as noted below).
345
* Italicized items represent variable values.
346
*
347
* <p> A grant entry must begin with the word <code>grant</code>.
348
* The <code>signedBy</code> and <code>codeBase</code> name/value
349
* pairs are optional.
350
* If they are not present, then any signer (including unsigned code)
351
* will match, and any codeBase will match.
352
*
353
* <p> A permission entry must begin with the word <code>permission</code>.
354
* The word <code><i>Type</i></code> in the template above would actually
355
* be a specific permission type, such as
356
* <code>java.io.FilePermission</code> or
357
* <code>java.lang.RuntimePermission</code>.
358
*
359
* <p>The "<i>action</i>" is required for
360
* many permission types, such as <code>java.io.FilePermission</code>
361
* (where it specifies what type of file access is permitted).
362
* It is not required for categories such as
363
* <code>java.lang.RuntimePermission</code>
364
* where it is not necessary - you either have the
365
* permission specified by the <code>"<i>name</i>"</code>
366
* value following the type name or you don't.
367
*
368
* <p>The <code>signedBy</code> name/value pair for a permission entry
369
* is optional. If present, it indicates a signed permission. That is,
370
* the permission class itself must be signed by the given alias in
371
* order for it to be granted. For example,
372
* suppose you have the following grant entry:
373
*
374
* <pre>
375
* grant {
376
* permission Foo "foobar", signedBy "FooSoft";
377
* }
378
* </pre>
379
*
380
* <p>Then this permission of type <i>Foo</i> is granted if the
381
* <code>Foo.class</code> permission has been signed by the
382
* "FooSoft" alias, or if <code>Foo.class</code> is a
383
* system class (i.e., is found on the CLASSPATH).
384
*
385
* <p>Items that appear in an entry must appear in the specified order
386
* (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
387
* "<i>action</i>"). An entry is terminated with a semicolon.
388
*
389
* <p>Case is unimportant for the identifiers (<code>permission</code>,
390
* <code>signedBy</code>, <code>codeBase</code>, etc.) but is
391
* significant for the <i>Type</i>
392
* or for any string that is passed in as a value. <p>
393
*
394
* <p>An example of two entries in a policy configuration file is
395
* <pre>
396
* // if the code is signed by "Duke", grant it read/write to all
397
* // files in /tmp.
398
*
399
* grant signedBy "Duke" {
400
* permission java.io.FilePermission "/tmp/*", "read,write";
401
* };
402
* <p>
403
* // grant everyone the following permission
404
*
405
* grant {
406
* permission java.util.PropertyPermission "java.vendor";
407
* };
408
* </pre>
409
*/
410
private void init(URL url) {
411
// Properties are set once for each init(); ignore changes between
412
// between diff invocations of initPolicyFile(policy, url, info).
413
String numCacheStr =
414
AccessController.doPrivileged(new PrivilegedAction<String>() {
415
public String run() {
416
expandProperties = "true".equalsIgnoreCase
417
(Security.getProperty("policy.expandProperties"));
418
ignoreIdentityScope = "true".equalsIgnoreCase
419
(Security.getProperty("policy.ignoreIdentityScope"));
420
allowSystemProperties = "true".equalsIgnoreCase
421
(Security.getProperty("policy.allowSystemProperty"));
422
notUtf8 = "false".equalsIgnoreCase
423
(System.getProperty("sun.security.policy.utf8"));
424
return System.getProperty("sun.security.policy.numcaches");
425
}});
426
427
int numCaches;
428
if (numCacheStr != null) {
429
try {
430
numCaches = Integer.parseInt(numCacheStr);
431
} catch (NumberFormatException e) {
432
numCaches = DEFAULT_CACHE_SIZE;
433
}
434
} else {
435
numCaches = DEFAULT_CACHE_SIZE;
436
}
437
// System.out.println("number caches=" + numCaches);
438
PolicyInfo newInfo = new PolicyInfo(numCaches);
439
initPolicyFile(newInfo, url);
440
policyInfo = newInfo;
441
}
442
443
private void initPolicyFile(final PolicyInfo newInfo, final URL url) {
444
445
if (url != null) {
446
447
/**
448
* If the caller specified a URL via Policy.getInstance,
449
* we only read from that URL
450
*/
451
452
if (debug != null) {
453
debug.println("reading "+url);
454
}
455
AccessController.doPrivileged(new PrivilegedAction<Void>() {
456
public Void run() {
457
if (init(url, newInfo) == false) {
458
// use static policy if all else fails
459
initStaticPolicy(newInfo);
460
}
461
return null;
462
}
463
});
464
465
} else {
466
467
/**
468
* Caller did not specify URL via Policy.getInstance.
469
* Read from URLs listed in the java.security properties file.
470
*
471
* We call initPolicyFile with POLICY , POLICY_URL and then
472
* call it with AUTH_POLICY and AUTH_POLICY_URL
473
* So first we will process the JAVA standard policy
474
* and then process the JAVA AUTH Policy.
475
* This is for backward compatibility as well as to handle
476
* cases where the user has a single unified policyfile
477
* with both java policy entries and auth entries
478
*/
479
480
boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo);
481
// To maintain strict backward compatibility
482
// we load the static policy only if POLICY load failed
483
if (!loaded_one) {
484
// use static policy if all else fails
485
initStaticPolicy(newInfo);
486
}
487
488
initPolicyFile(AUTH_POLICY, AUTH_POLICY_URL, newInfo);
489
}
490
}
491
492
private boolean initPolicyFile(final String propname, final String urlname,
493
final PolicyInfo newInfo) {
494
Boolean loadedPolicy =
495
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
496
public Boolean run() {
497
boolean loaded_policy = false;
498
499
if (allowSystemProperties) {
500
String extra_policy = System.getProperty(propname);
501
if (extra_policy != null) {
502
boolean overrideAll = false;
503
if (extra_policy.startsWith("=")) {
504
overrideAll = true;
505
extra_policy = extra_policy.substring(1);
506
}
507
try {
508
extra_policy =
509
PropertyExpander.expand(extra_policy);
510
URL policyURL;
511
512
File policyFile = new File(extra_policy);
513
if (policyFile.exists()) {
514
policyURL = ParseUtil.fileToEncodedURL
515
(new File(policyFile.getCanonicalPath()));
516
} else {
517
policyURL = new URL(extra_policy);
518
}
519
if (debug != null)
520
debug.println("reading "+policyURL);
521
if (init(policyURL, newInfo))
522
loaded_policy = true;
523
} catch (Exception e) {
524
// ignore.
525
if (debug != null) {
526
debug.println("caught exception: "+e);
527
}
528
}
529
if (overrideAll) {
530
if (debug != null) {
531
debug.println("overriding other policies!");
532
}
533
return Boolean.valueOf(loaded_policy);
534
}
535
}
536
}
537
538
int n = 1;
539
String policy_uri;
540
541
while ((policy_uri = Security.getProperty(urlname+n)) != null) {
542
try {
543
URL policy_url = null;
544
String expanded_uri = PropertyExpander.expand
545
(policy_uri).replace(File.separatorChar, '/');
546
547
if (policy_uri.startsWith("file:${java.home}/") ||
548
policy_uri.startsWith("file:${user.home}/")) {
549
550
// this special case accommodates
551
// the situation java.home/user.home
552
// expand to a single slash, resulting in
553
// a file://foo URI
554
policy_url = new File
555
(expanded_uri.substring(5)).toURI().toURL();
556
} else {
557
policy_url = new URI(expanded_uri).toURL();
558
}
559
560
if (debug != null)
561
debug.println("reading "+policy_url);
562
if (init(policy_url, newInfo))
563
loaded_policy = true;
564
} catch (Exception e) {
565
if (debug != null) {
566
debug.println(
567
"Debug info only. Error reading policy " +e);
568
e.printStackTrace();
569
}
570
// ignore that policy
571
}
572
n++;
573
}
574
return Boolean.valueOf(loaded_policy);
575
}
576
});
577
578
return loadedPolicy.booleanValue();
579
}
580
581
/**
582
* Reads a policy configuration into the Policy object using a
583
* Reader object.
584
*
585
* @param policyFile the policy Reader object.
586
*/
587
private boolean init(URL policy, PolicyInfo newInfo) {
588
boolean success = false;
589
PolicyParser pp = new PolicyParser(expandProperties);
590
InputStreamReader isr = null;
591
try {
592
593
// read in policy using UTF-8 by default
594
//
595
// check non-standard system property to see if
596
// the default encoding should be used instead
597
598
if (notUtf8) {
599
isr = new InputStreamReader
600
(PolicyUtil.getInputStream(policy));
601
} else {
602
isr = new InputStreamReader
603
(PolicyUtil.getInputStream(policy), "UTF-8");
604
}
605
606
pp.read(isr);
607
608
KeyStore keyStore = null;
609
try {
610
keyStore = PolicyUtil.getKeyStore
611
(policy,
612
pp.getKeyStoreUrl(),
613
pp.getKeyStoreType(),
614
pp.getKeyStoreProvider(),
615
pp.getStorePassURL(),
616
debug);
617
} catch (Exception e) {
618
// ignore, treat it like we have no keystore
619
if (debug != null) {
620
debug.println("Debug info only. Ignoring exception.");
621
e.printStackTrace();
622
}
623
}
624
625
Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements();
626
while (enum_.hasMoreElements()) {
627
PolicyParser.GrantEntry ge = enum_.nextElement();
628
addGrantEntry(ge, keyStore, newInfo);
629
}
630
} catch (PolicyParser.ParsingException pe) {
631
MessageFormat form = new MessageFormat(ResourcesMgr.getString
632
(POLICY + ".error.parsing.policy.message"));
633
Object[] source = {policy, pe.getLocalizedMessage()};
634
System.err.println(form.format(source));
635
if (debug != null)
636
pe.printStackTrace();
637
638
} catch (Exception e) {
639
if (debug != null) {
640
debug.println("error parsing "+policy);
641
debug.println(e.toString());
642
e.printStackTrace();
643
}
644
} finally {
645
if (isr != null) {
646
try {
647
isr.close();
648
success = true;
649
} catch (IOException e) {
650
// ignore the exception
651
}
652
} else {
653
success = true;
654
}
655
}
656
657
return success;
658
}
659
660
private void initStaticPolicy(final PolicyInfo newInfo) {
661
AccessController.doPrivileged(new PrivilegedAction<Void>() {
662
public Void run() {
663
PolicyEntry pe = new PolicyEntry(new CodeSource(null,
664
(Certificate[]) null));
665
pe.add(SecurityConstants.LOCAL_LISTEN_PERMISSION);
666
pe.add(new PropertyPermission("java.version",
667
SecurityConstants.PROPERTY_READ_ACTION));
668
pe.add(new PropertyPermission("java.vendor",
669
SecurityConstants.PROPERTY_READ_ACTION));
670
pe.add(new PropertyPermission("java.vendor.url",
671
SecurityConstants.PROPERTY_READ_ACTION));
672
pe.add(new PropertyPermission("java.class.version",
673
SecurityConstants.PROPERTY_READ_ACTION));
674
pe.add(new PropertyPermission("os.name",
675
SecurityConstants.PROPERTY_READ_ACTION));
676
pe.add(new PropertyPermission("os.version",
677
SecurityConstants.PROPERTY_READ_ACTION));
678
pe.add(new PropertyPermission("os.arch",
679
SecurityConstants.PROPERTY_READ_ACTION));
680
pe.add(new PropertyPermission("file.separator",
681
SecurityConstants.PROPERTY_READ_ACTION));
682
pe.add(new PropertyPermission("path.separator",
683
SecurityConstants.PROPERTY_READ_ACTION));
684
pe.add(new PropertyPermission("line.separator",
685
SecurityConstants.PROPERTY_READ_ACTION));
686
pe.add(new PropertyPermission
687
("java.specification.version",
688
SecurityConstants.PROPERTY_READ_ACTION));
689
pe.add(new PropertyPermission
690
("java.specification.vendor",
691
SecurityConstants.PROPERTY_READ_ACTION));
692
pe.add(new PropertyPermission
693
("java.specification.name",
694
SecurityConstants.PROPERTY_READ_ACTION));
695
pe.add(new PropertyPermission
696
("java.vm.specification.version",
697
SecurityConstants.PROPERTY_READ_ACTION));
698
pe.add(new PropertyPermission
699
("java.vm.specification.vendor",
700
SecurityConstants.PROPERTY_READ_ACTION));
701
pe.add(new PropertyPermission
702
("java.vm.specification.name",
703
SecurityConstants.PROPERTY_READ_ACTION));
704
pe.add(new PropertyPermission("java.vm.version",
705
SecurityConstants.PROPERTY_READ_ACTION));
706
pe.add(new PropertyPermission("java.vm.vendor",
707
SecurityConstants.PROPERTY_READ_ACTION));
708
pe.add(new PropertyPermission("java.vm.name",
709
SecurityConstants.PROPERTY_READ_ACTION));
710
711
// No need to sync because noone has access to newInfo yet
712
newInfo.policyEntries.add(pe);
713
714
// Add AllPermissions for standard extensions
715
String[] extCodebases = PolicyParser.parseExtDirs(
716
PolicyParser.EXTDIRS_EXPANSION, 0);
717
if (extCodebases != null && extCodebases.length > 0) {
718
for (int i = 0; i < extCodebases.length; i++) {
719
try {
720
pe = new PolicyEntry(canonicalizeCodebase(
721
new CodeSource(new URL(extCodebases[i]),
722
(Certificate[]) null), false ));
723
pe.add(SecurityConstants.ALL_PERMISSION);
724
725
// No need to sync because noone has access to
726
// newInfo yet
727
newInfo.policyEntries.add(pe);
728
} catch (Exception e) {
729
// this is probably bad (though not dangerous).
730
// What should we do?
731
}
732
}
733
}
734
return null;
735
}
736
});
737
}
738
739
/**
740
* Given a GrantEntry, create a codeSource.
741
*
742
* @return null if signedBy alias is not recognized
743
*/
744
private CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore,
745
PolicyInfo newInfo) throws java.net.MalformedURLException
746
{
747
Certificate[] certs = null;
748
if (ge.signedBy != null) {
749
certs = getCertificates(keyStore, ge.signedBy, newInfo);
750
if (certs == null) {
751
// we don't have a key for this alias,
752
// just return
753
if (debug != null) {
754
debug.println(" -- No certs for alias '" +
755
ge.signedBy + "' - ignoring entry");
756
}
757
return null;
758
}
759
}
760
761
URL location;
762
763
if (ge.codeBase != null)
764
location = new URL(ge.codeBase);
765
else
766
location = null;
767
768
return (canonicalizeCodebase(new CodeSource(location, certs),false));
769
}
770
771
/**
772
* Add one policy entry to the list.
773
*/
774
private void addGrantEntry(PolicyParser.GrantEntry ge,
775
KeyStore keyStore, PolicyInfo newInfo) {
776
777
if (debug != null) {
778
debug.println("Adding policy entry: ");
779
debug.println(" signedBy " + ge.signedBy);
780
debug.println(" codeBase " + ge.codeBase);
781
if (ge.principals != null) {
782
for (PolicyParser.PrincipalEntry pppe : ge.principals) {
783
debug.println(" " + pppe.toString());
784
}
785
}
786
}
787
788
try {
789
CodeSource codesource = getCodeSource(ge, keyStore, newInfo);
790
// skip if signedBy alias was unknown...
791
if (codesource == null) return;
792
793
// perform keystore alias principal replacement.
794
// for example, if alias resolves to X509 certificate,
795
// replace principal with: <X500Principal class> <SubjectDN>
796
// -- skip if alias is unknown
797
if (replacePrincipals(ge.principals, keyStore) == false)
798
return;
799
PolicyEntry entry = new PolicyEntry(codesource, ge.principals);
800
Enumeration<PolicyParser.PermissionEntry> enum_ =
801
ge.permissionElements();
802
while (enum_.hasMoreElements()) {
803
PolicyParser.PermissionEntry pe = enum_.nextElement();
804
805
try {
806
// perform ${{ ... }} expansions within permission name
807
expandPermissionName(pe, keyStore);
808
809
// XXX special case PrivateCredentialPermission-SELF
810
Permission perm;
811
if (pe.permission.equals
812
("javax.security.auth.PrivateCredentialPermission") &&
813
pe.name.endsWith(" self")) {
814
pe.name = pe.name.substring(0, pe.name.indexOf("self"))
815
+ SELF;
816
}
817
// check for self
818
if (pe.name != null && pe.name.indexOf(SELF) != -1) {
819
// Create a "SelfPermission" , it could be an
820
// an unresolved permission which will be resolved
821
// when implies is called
822
// Add it to entry
823
Certificate certs[];
824
if (pe.signedBy != null) {
825
certs = getCertificates(keyStore,
826
pe.signedBy,
827
newInfo);
828
} else {
829
certs = null;
830
}
831
perm = new SelfPermission(pe.permission,
832
pe.name,
833
pe.action,
834
certs);
835
} else {
836
perm = getInstance(pe.permission,
837
pe.name,
838
pe.action);
839
}
840
entry.add(perm);
841
if (debug != null) {
842
debug.println(" "+perm);
843
}
844
} catch (ClassNotFoundException cnfe) {
845
Certificate certs[];
846
if (pe.signedBy != null) {
847
certs = getCertificates(keyStore,
848
pe.signedBy,
849
newInfo);
850
} else {
851
certs = null;
852
}
853
854
// only add if we had no signer or we had a
855
// a signer and found the keys for it.
856
if (certs != null || pe.signedBy == null) {
857
Permission perm = new UnresolvedPermission(
858
pe.permission,
859
pe.name,
860
pe.action,
861
certs);
862
entry.add(perm);
863
if (debug != null) {
864
debug.println(" "+perm);
865
}
866
}
867
} catch (java.lang.reflect.InvocationTargetException ite) {
868
MessageFormat form = new MessageFormat
869
(ResourcesMgr.getString
870
(POLICY +
871
".error.adding.Permission.perm.message"));
872
Object[] source = {pe.permission,
873
ite.getTargetException().toString()};
874
System.err.println(form.format(source));
875
} catch (Exception e) {
876
MessageFormat form = new MessageFormat
877
(ResourcesMgr.getString
878
(POLICY +
879
".error.adding.Permission.perm.message"));
880
Object[] source = {pe.permission,
881
e.toString()};
882
System.err.println(form.format(source));
883
}
884
}
885
886
// No need to sync because noone has access to newInfo yet
887
newInfo.policyEntries.add(entry);
888
} catch (Exception e) {
889
MessageFormat form = new MessageFormat(ResourcesMgr.getString
890
(POLICY
891
+ ".error.adding.Entry.message"));
892
Object[] source = {e.toString()};
893
System.err.println(form.format(source));
894
}
895
if (debug != null)
896
debug.println();
897
}
898
899
/**
900
* Returns a new Permission object of the given Type. The Permission is
901
* created by getting the
902
* Class object using the <code>Class.forName</code> method, and using
903
* the reflection API to invoke the (String name, String actions)
904
* constructor on the
905
* object.
906
*
907
* @param type the type of Permission being created.
908
* @param name the name of the Permission being created.
909
* @param actions the actions of the Permission being created.
910
*
911
* @exception ClassNotFoundException if the particular Permission
912
* class could not be found.
913
*
914
* @exception IllegalAccessException if the class or initializer is
915
* not accessible.
916
*
917
* @exception InstantiationException if getInstance tries to
918
* instantiate an abstract class or an interface, or if the
919
* instantiation fails for some other reason.
920
*
921
* @exception NoSuchMethodException if the (String, String) constructor
922
* is not found.
923
*
924
* @exception InvocationTargetException if the underlying Permission
925
* constructor throws an exception.
926
*
927
*/
928
929
private static final Permission getInstance(String type,
930
String name,
931
String actions)
932
throws ClassNotFoundException,
933
InstantiationException,
934
IllegalAccessException,
935
NoSuchMethodException,
936
InvocationTargetException
937
{
938
//XXX we might want to keep a hash of created factories...
939
Class<?> pc = Class.forName(type, false, null);
940
Permission answer = getKnownInstance(pc, name, actions);
941
if (answer != null) {
942
return answer;
943
}
944
if (!Permission.class.isAssignableFrom(pc)) {
945
// not the right subtype
946
throw new ClassCastException(type + " is not a Permission");
947
}
948
949
if (name == null && actions == null) {
950
try {
951
Constructor<?> c = pc.getConstructor(PARAMS0);
952
return (Permission) c.newInstance(new Object[] {});
953
} catch (NoSuchMethodException ne) {
954
try {
955
Constructor<?> c = pc.getConstructor(PARAMS1);
956
return (Permission) c.newInstance(
957
new Object[] { name});
958
} catch (NoSuchMethodException ne1 ) {
959
Constructor<?> c = pc.getConstructor(PARAMS2);
960
return (Permission) c.newInstance(
961
new Object[] { name, actions });
962
}
963
}
964
} else {
965
if (name != null && actions == null) {
966
try {
967
Constructor<?> c = pc.getConstructor(PARAMS1);
968
return (Permission) c.newInstance(new Object[] { name});
969
} catch (NoSuchMethodException ne) {
970
Constructor<?> c = pc.getConstructor(PARAMS2);
971
return (Permission) c.newInstance(
972
new Object[] { name, actions });
973
}
974
} else {
975
Constructor<?> c = pc.getConstructor(PARAMS2);
976
return (Permission) c.newInstance(
977
new Object[] { name, actions });
978
}
979
}
980
}
981
982
/**
983
* Creates one of the well-known permissions directly instead of
984
* via reflection. Keep list short to not penalize non-JDK-defined
985
* permissions.
986
*/
987
private static final Permission getKnownInstance(Class<?> claz,
988
String name, String actions) {
989
if (claz.equals(FilePermission.class)) {
990
return new FilePermission(name, actions);
991
} else if (claz.equals(SocketPermission.class)) {
992
return new SocketPermission(name, actions);
993
} else if (claz.equals(RuntimePermission.class)) {
994
return new RuntimePermission(name, actions);
995
} else if (claz.equals(PropertyPermission.class)) {
996
return new PropertyPermission(name, actions);
997
} else if (claz.equals(NetPermission.class)) {
998
return new NetPermission(name, actions);
999
} else if (claz.equals(AllPermission.class)) {
1000
return SecurityConstants.ALL_PERMISSION;
1001
} else {
1002
return null;
1003
}
1004
}
1005
1006
/**
1007
* Fetch all certs associated with this alias.
1008
*/
1009
private Certificate[] getCertificates
1010
(KeyStore keyStore, String aliases, PolicyInfo newInfo) {
1011
1012
List<Certificate> vcerts = null;
1013
1014
StringTokenizer st = new StringTokenizer(aliases, ",");
1015
int n = 0;
1016
1017
while (st.hasMoreTokens()) {
1018
String alias = st.nextToken().trim();
1019
n++;
1020
Certificate cert = null;
1021
// See if this alias's cert has already been cached
1022
synchronized (newInfo.aliasMapping) {
1023
cert = (Certificate)newInfo.aliasMapping.get(alias);
1024
1025
if (cert == null && keyStore != null) {
1026
1027
try {
1028
cert = keyStore.getCertificate(alias);
1029
} catch (KeyStoreException kse) {
1030
// never happens, because keystore has already been loaded
1031
// when we call this
1032
}
1033
if (cert != null) {
1034
newInfo.aliasMapping.put(alias, cert);
1035
newInfo.aliasMapping.put(cert, alias);
1036
}
1037
}
1038
}
1039
1040
if (cert != null) {
1041
if (vcerts == null)
1042
vcerts = new ArrayList<>();
1043
vcerts.add(cert);
1044
}
1045
}
1046
1047
// make sure n == vcerts.size, since we are doing a logical *and*
1048
if (vcerts != null && n == vcerts.size()) {
1049
Certificate[] certs = new Certificate[vcerts.size()];
1050
vcerts.toArray(certs);
1051
return certs;
1052
} else {
1053
return null;
1054
}
1055
}
1056
1057
/**
1058
* Refreshes the policy object by re-reading all the policy files.
1059
*/
1060
@Override public void refresh() {
1061
init(url);
1062
}
1063
1064
/**
1065
* Evaluates the the global policy for the permissions granted to
1066
* the ProtectionDomain and tests whether the permission is
1067
* granted.
1068
*
1069
* @param domain the ProtectionDomain to test
1070
* @param permission the Permission object to be tested for implication.
1071
*
1072
* @return true if "permission" is a proper subset of a permission
1073
* granted to this ProtectionDomain.
1074
*
1075
* @see java.security.ProtectionDomain
1076
*/
1077
@Override
1078
public boolean implies(ProtectionDomain pd, Permission p) {
1079
ProtectionDomainCache pdMap = policyInfo.getPdMapping();
1080
PermissionCollection pc = pdMap.get(pd);
1081
1082
if (pc != null) {
1083
return pc.implies(p);
1084
}
1085
1086
pc = getPermissions(pd);
1087
if (pc == null) {
1088
return false;
1089
}
1090
1091
// cache mapping of protection domain to its PermissionCollection
1092
pdMap.put(pd, pc);
1093
return pc.implies(p);
1094
}
1095
1096
/**
1097
* Examines this <code>Policy</code> and returns the permissions granted
1098
* to the specified <code>ProtectionDomain</code>. This includes
1099
* the permissions currently associated with the domain as well
1100
* as the policy permissions granted to the domain's
1101
* CodeSource, ClassLoader, and Principals.
1102
*
1103
* <p> Note that this <code>Policy</code> implementation has
1104
* special handling for PrivateCredentialPermissions.
1105
* When this method encounters a <code>PrivateCredentialPermission</code>
1106
* which specifies "self" as the <code>Principal</code> class and name,
1107
* it does not add that <code>Permission</code> to the returned
1108
* <code>PermissionCollection</code>. Instead, it builds
1109
* a new <code>PrivateCredentialPermission</code>
1110
* for each <code>Principal</code> associated with the provided
1111
* <code>Subject</code>. Each new <code>PrivateCredentialPermission</code>
1112
* contains the same Credential class as specified in the
1113
* originally granted permission, as well as the Class and name
1114
* for the respective <code>Principal</code>.
1115
*
1116
* <p>
1117
*
1118
* @param domain the Permissions granted to this
1119
* <code>ProtectionDomain</code> are returned.
1120
*
1121
* @return the Permissions granted to the provided
1122
* <code>ProtectionDomain</code>.
1123
*/
1124
@Override
1125
public PermissionCollection getPermissions(ProtectionDomain domain) {
1126
Permissions perms = new Permissions();
1127
1128
if (domain == null)
1129
return perms;
1130
1131
// first get policy perms
1132
getPermissions(perms, domain);
1133
1134
// add static perms
1135
// - adding static perms after policy perms is necessary
1136
// to avoid a regression for 4301064
1137
PermissionCollection pc = domain.getPermissions();
1138
if (pc != null) {
1139
synchronized (pc) {
1140
Enumeration<Permission> e = pc.elements();
1141
while (e.hasMoreElements()) {
1142
perms.add(e.nextElement());
1143
}
1144
}
1145
}
1146
1147
return perms;
1148
}
1149
1150
/**
1151
* Examines this Policy and creates a PermissionCollection object with
1152
* the set of permissions for the specified CodeSource.
1153
*
1154
* @param CodeSource the codesource associated with the caller.
1155
* This encapsulates the original location of the code (where the code
1156
* came from) and the public key(s) of its signer.
1157
*
1158
* @return the set of permissions according to the policy.
1159
*/
1160
@Override
1161
public PermissionCollection getPermissions(CodeSource codesource) {
1162
return getPermissions(new Permissions(), codesource);
1163
}
1164
1165
/**
1166
* Examines the global policy and returns the provided Permissions
1167
* object with additional permissions granted to the specified
1168
* ProtectionDomain.
1169
*
1170
* @param perm the Permissions to populate
1171
* @param pd the ProtectionDomain associated with the caller.
1172
*
1173
* @return the set of Permissions according to the policy.
1174
*/
1175
private PermissionCollection getPermissions(Permissions perms,
1176
ProtectionDomain pd ) {
1177
if (debug != null) {
1178
debug.println("getPermissions:\n\t" + printPD(pd));
1179
}
1180
1181
final CodeSource cs = pd.getCodeSource();
1182
if (cs == null)
1183
return perms;
1184
1185
CodeSource canonCodeSource = AccessController.doPrivileged(
1186
new java.security.PrivilegedAction<CodeSource>(){
1187
public CodeSource run() {
1188
return canonicalizeCodebase(cs, true);
1189
}
1190
});
1191
return getPermissions(perms, canonCodeSource, pd.getPrincipals());
1192
}
1193
1194
/**
1195
* Examines the global policy and returns the provided Permissions
1196
* object with additional permissions granted to the specified
1197
* CodeSource.
1198
*
1199
* @param permissions the permissions to populate
1200
* @param codesource the codesource associated with the caller.
1201
* This encapsulates the original location of the code (where the code
1202
* came from) and the public key(s) of its signer.
1203
*
1204
* @return the set of permissions according to the policy.
1205
*/
1206
private PermissionCollection getPermissions(Permissions perms,
1207
final CodeSource cs) {
1208
1209
if (cs == null)
1210
return perms;
1211
1212
CodeSource canonCodeSource = AccessController.doPrivileged(
1213
new java.security.PrivilegedAction<CodeSource>(){
1214
public CodeSource run() {
1215
return canonicalizeCodebase(cs, true);
1216
}
1217
});
1218
1219
return getPermissions(perms, canonCodeSource, null);
1220
}
1221
1222
private Permissions getPermissions(Permissions perms,
1223
final CodeSource cs,
1224
Principal[] principals) {
1225
PolicyInfo pi = policyInfo;
1226
1227
for (PolicyEntry entry : pi.policyEntries) {
1228
addPermissions(perms, cs, principals, entry);
1229
}
1230
1231
// Go through policyEntries gotten from identity db; sync required
1232
// because checkForTrustedIdentity (below) might update list
1233
synchronized (pi.identityPolicyEntries) {
1234
for (PolicyEntry entry : pi.identityPolicyEntries) {
1235
addPermissions(perms, cs, principals, entry);
1236
}
1237
}
1238
1239
// now see if any of the keys are trusted ids.
1240
if (!ignoreIdentityScope) {
1241
Certificate certs[] = cs.getCertificates();
1242
if (certs != null) {
1243
for (int k=0; k < certs.length; k++) {
1244
Object idMap = pi.aliasMapping.get(certs[k]);
1245
if (idMap == null &&
1246
checkForTrustedIdentity(certs[k], pi)) {
1247
// checkForTrustedIdentity added it
1248
// to the policy for us. next time
1249
// around we'll find it. This time
1250
// around we need to add it.
1251
perms.add(SecurityConstants.ALL_PERMISSION);
1252
}
1253
}
1254
}
1255
}
1256
return perms;
1257
}
1258
1259
private void addPermissions(Permissions perms,
1260
final CodeSource cs,
1261
Principal[] principals,
1262
final PolicyEntry entry) {
1263
1264
if (debug != null) {
1265
debug.println("evaluate codesources:\n" +
1266
"\tPolicy CodeSource: " + entry.getCodeSource() + "\n" +
1267
"\tActive CodeSource: " + cs);
1268
}
1269
1270
// check to see if the CodeSource implies
1271
Boolean imp = AccessController.doPrivileged
1272
(new PrivilegedAction<Boolean>() {
1273
public Boolean run() {
1274
return new Boolean(entry.getCodeSource().implies(cs));
1275
}
1276
});
1277
if (!imp.booleanValue()) {
1278
if (debug != null) {
1279
debug.println("evaluation (codesource) failed");
1280
}
1281
1282
// CodeSource does not imply - return and try next policy entry
1283
return;
1284
}
1285
1286
// check to see if the Principals imply
1287
1288
List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();
1289
if (debug != null) {
1290
List<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();
1291
if (principals != null) {
1292
for (int i = 0; i < principals.length; i++) {
1293
accPs.add(new PolicyParser.PrincipalEntry
1294
(principals[i].getClass().getName(),
1295
principals[i].getName()));
1296
}
1297
}
1298
debug.println("evaluate principals:\n" +
1299
"\tPolicy Principals: " + entryPs + "\n" +
1300
"\tActive Principals: " + accPs);
1301
}
1302
1303
if (entryPs == null || entryPs.isEmpty()) {
1304
1305
// policy entry has no principals -
1306
// add perms regardless of principals in current ACC
1307
1308
addPerms(perms, principals, entry);
1309
if (debug != null) {
1310
debug.println("evaluation (codesource/principals) passed");
1311
}
1312
return;
1313
1314
} else if (principals == null || principals.length == 0) {
1315
1316
// current thread has no principals but this policy entry
1317
// has principals - perms are not added
1318
1319
if (debug != null) {
1320
debug.println("evaluation (principals) failed");
1321
}
1322
return;
1323
}
1324
1325
// current thread has principals and this policy entry
1326
// has principals. see if policy entry principals match
1327
// principals in current ACC
1328
1329
for (PolicyParser.PrincipalEntry pppe : entryPs) {
1330
1331
// Check for wildcards
1332
if (pppe.isWildcardClass()) {
1333
// a wildcard class matches all principals in current ACC
1334
continue;
1335
}
1336
1337
if (pppe.isWildcardName()) {
1338
// a wildcard name matches any principal with the same class
1339
if (wildcardPrincipalNameImplies(pppe.principalClass,
1340
principals)) {
1341
continue;
1342
}
1343
if (debug != null) {
1344
debug.println("evaluation (principal name wildcard) failed");
1345
}
1346
// policy entry principal not in current ACC -
1347
// immediately return and go to next policy entry
1348
return;
1349
}
1350
1351
Set<Principal> pSet = new HashSet<>(Arrays.asList(principals));
1352
Subject subject = new Subject(true, pSet,
1353
Collections.EMPTY_SET,
1354
Collections.EMPTY_SET);
1355
try {
1356
ClassLoader cl = Thread.currentThread().getContextClassLoader();
1357
Class<?> pClass = Class.forName(pppe.principalClass, false, cl);
1358
if (!Principal.class.isAssignableFrom(pClass)) {
1359
// not the right subtype
1360
throw new ClassCastException(pppe.principalClass +
1361
" is not a Principal");
1362
}
1363
1364
Constructor<?> c = pClass.getConstructor(PARAMS1);
1365
Principal p = (Principal)c.newInstance(new Object[] {
1366
pppe.principalName });
1367
1368
if (debug != null) {
1369
debug.println("found Principal " + p.getClass().getName());
1370
}
1371
1372
// check if the Principal implies the current
1373
// thread's principals
1374
if (!p.implies(subject)) {
1375
if (debug != null) {
1376
debug.println("evaluation (principal implies) failed");
1377
}
1378
1379
// policy principal does not imply the current Subject -
1380
// immediately return and go to next policy entry
1381
return;
1382
}
1383
} catch (Exception e) {
1384
// fall back to default principal comparison.
1385
// see if policy entry principal is in current ACC
1386
1387
if (debug != null) {
1388
e.printStackTrace();
1389
}
1390
1391
if (!pppe.implies(subject)) {
1392
if (debug != null) {
1393
debug.println("evaluation (default principal implies) failed");
1394
}
1395
1396
// policy entry principal not in current ACC -
1397
// immediately return and go to next policy entry
1398
return;
1399
}
1400
}
1401
1402
// either the principal information matched,
1403
// or the Principal.implies succeeded.
1404
// continue loop and test the next policy principal
1405
}
1406
1407
// all policy entry principals were found in the current ACC -
1408
// grant the policy permissions
1409
1410
if (debug != null) {
1411
debug.println("evaluation (codesource/principals) passed");
1412
}
1413
addPerms(perms, principals, entry);
1414
}
1415
1416
/**
1417
* Returns true if the array of principals contains at least one
1418
* principal of the specified class.
1419
*/
1420
private static boolean wildcardPrincipalNameImplies(String principalClass,
1421
Principal[] principals)
1422
{
1423
for (Principal p : principals) {
1424
if (principalClass.equals(p.getClass().getName())) {
1425
return true;
1426
}
1427
}
1428
return false;
1429
}
1430
1431
private void addPerms(Permissions perms,
1432
Principal[] accPs,
1433
PolicyEntry entry) {
1434
for (int i = 0; i < entry.permissions.size(); i++) {
1435
Permission p = entry.permissions.get(i);
1436
if (debug != null) {
1437
debug.println(" granting " + p);
1438
}
1439
1440
if (p instanceof SelfPermission) {
1441
// handle "SELF" permissions
1442
expandSelf((SelfPermission)p,
1443
entry.getPrincipals(),
1444
accPs,
1445
perms);
1446
} else {
1447
perms.add(p);
1448
}
1449
}
1450
}
1451
1452
/**
1453
* <p>
1454
*
1455
* @param sp the SelfPermission that needs to be expanded <p>
1456
*
1457
* @param entryPs list of principals for the Policy entry.
1458
*
1459
* @param pdp Principal array from the current ProtectionDomain.
1460
*
1461
* @param perms the PermissionCollection where the individual
1462
* Permissions will be added after expansion.
1463
*/
1464
1465
private void expandSelf(SelfPermission sp,
1466
List<PolicyParser.PrincipalEntry> entryPs,
1467
Principal[] pdp,
1468
Permissions perms) {
1469
1470
if (entryPs == null || entryPs.isEmpty()) {
1471
// No principals in the grant to substitute
1472
if (debug != null) {
1473
debug.println("Ignoring permission "
1474
+ sp.getSelfType()
1475
+ " with target name ("
1476
+ sp.getSelfName() + "). "
1477
+ "No Principal(s) specified "
1478
+ "in the grant clause. "
1479
+ "SELF-based target names are "
1480
+ "only valid in the context "
1481
+ "of a Principal-based grant entry."
1482
);
1483
}
1484
return;
1485
}
1486
int startIndex = 0;
1487
int v;
1488
StringBuilder sb = new StringBuilder();
1489
while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) {
1490
1491
// add non-SELF string
1492
sb.append(sp.getSelfName().substring(startIndex, v));
1493
1494
// expand SELF
1495
Iterator<PolicyParser.PrincipalEntry> pli = entryPs.iterator();
1496
while (pli.hasNext()) {
1497
PolicyParser.PrincipalEntry pppe = pli.next();
1498
String[][] principalInfo = getPrincipalInfo(pppe,pdp);
1499
for (int i = 0; i < principalInfo.length; i++) {
1500
if (i != 0) {
1501
sb.append(", ");
1502
}
1503
sb.append(principalInfo[i][0] + " " +
1504
"\"" + principalInfo[i][1] + "\"");
1505
}
1506
if (pli.hasNext()) {
1507
sb.append(", ");
1508
}
1509
}
1510
startIndex = v + SELF.length();
1511
}
1512
// add remaining string (might be the entire string)
1513
sb.append(sp.getSelfName().substring(startIndex));
1514
1515
if (debug != null) {
1516
debug.println(" expanded:\n\t" + sp.getSelfName()
1517
+ "\n into:\n\t" + sb.toString());
1518
}
1519
try {
1520
// first try to instantiate the permission
1521
perms.add(getInstance(sp.getSelfType(),
1522
sb.toString(),
1523
sp.getSelfActions()));
1524
} catch (ClassNotFoundException cnfe) {
1525
// ok, the permission is not in the bootclasspath.
1526
// before we add an UnresolvedPermission, check to see
1527
// whether this perm already belongs to the collection.
1528
// if so, use that perm's ClassLoader to create a new
1529
// one.
1530
Class<?> pc = null;
1531
synchronized (perms) {
1532
Enumeration<Permission> e = perms.elements();
1533
while (e.hasMoreElements()) {
1534
Permission pElement = e.nextElement();
1535
if (pElement.getClass().getName().equals(sp.getSelfType())) {
1536
pc = pElement.getClass();
1537
break;
1538
}
1539
}
1540
}
1541
if (pc == null) {
1542
// create an UnresolvedPermission
1543
perms.add(new UnresolvedPermission(sp.getSelfType(),
1544
sb.toString(),
1545
sp.getSelfActions(),
1546
sp.getCerts()));
1547
} else {
1548
try {
1549
// we found an instantiated permission.
1550
// use its class loader to instantiate a new permission.
1551
Constructor<?> c;
1552
// name parameter can not be null
1553
if (sp.getSelfActions() == null) {
1554
try {
1555
c = pc.getConstructor(PARAMS1);
1556
perms.add((Permission)c.newInstance
1557
(new Object[] {sb.toString()}));
1558
} catch (NoSuchMethodException ne) {
1559
c = pc.getConstructor(PARAMS2);
1560
perms.add((Permission)c.newInstance
1561
(new Object[] {sb.toString(),
1562
sp.getSelfActions() }));
1563
}
1564
} else {
1565
c = pc.getConstructor(PARAMS2);
1566
perms.add((Permission)c.newInstance
1567
(new Object[] {sb.toString(),
1568
sp.getSelfActions()}));
1569
}
1570
} catch (Exception nme) {
1571
if (debug != null) {
1572
debug.println("self entry expansion " +
1573
" instantiation failed: "
1574
+ nme.toString());
1575
}
1576
}
1577
}
1578
} catch (Exception e) {
1579
if (debug != null) {
1580
debug.println(e.toString());
1581
}
1582
}
1583
}
1584
1585
/**
1586
* return the principal class/name pair in the 2D array.
1587
* array[x][y]: x corresponds to the array length.
1588
* if (y == 0), it's the principal class.
1589
* if (y == 1), it's the principal name.
1590
*/
1591
private String[][] getPrincipalInfo
1592
(PolicyParser.PrincipalEntry pe, Principal[] pdp) {
1593
1594
// there are 3 possibilities:
1595
// 1) the entry's Principal class and name are not wildcarded
1596
// 2) the entry's Principal name is wildcarded only
1597
// 3) the entry's Principal class and name are wildcarded
1598
1599
if (!pe.isWildcardClass() && !pe.isWildcardName()) {
1600
1601
// build an info array for the principal
1602
// from the Policy entry
1603
String[][] info = new String[1][2];
1604
info[0][0] = pe.principalClass;
1605
info[0][1] = pe.principalName;
1606
return info;
1607
1608
} else if (!pe.isWildcardClass() && pe.isWildcardName()) {
1609
1610
// build an info array for every principal
1611
// in the current domain which has a principal class
1612
// that is equal to policy entry principal class name
1613
List<Principal> plist = new ArrayList<>();
1614
for (int i = 0; i < pdp.length; i++) {
1615
if (pe.principalClass.equals(pdp[i].getClass().getName()))
1616
plist.add(pdp[i]);
1617
}
1618
String[][] info = new String[plist.size()][2];
1619
int i = 0;
1620
for (Principal p : plist) {
1621
info[i][0] = p.getClass().getName();
1622
info[i][1] = p.getName();
1623
i++;
1624
}
1625
return info;
1626
1627
} else {
1628
1629
// build an info array for every
1630
// one of the current Domain's principals
1631
1632
String[][] info = new String[pdp.length][2];
1633
1634
for (int i = 0; i < pdp.length; i++) {
1635
info[i][0] = pdp[i].getClass().getName();
1636
info[i][1] = pdp[i].getName();
1637
}
1638
return info;
1639
}
1640
}
1641
1642
/*
1643
* Returns the signer certificates from the list of certificates
1644
* associated with the given code source.
1645
*
1646
* The signer certificates are those certificates that were used
1647
* to verifysigned code originating from the codesource location.
1648
*
1649
* This method assumes that in the given code source, each signer
1650
* certificate is followed by its supporting certificate chain
1651
* (which may be empty), and that the signer certificate and its
1652
* supporting certificate chain are ordered bottom-to-top
1653
* (i.e., with the signer certificate first and the (root) certificate
1654
* authority last).
1655
*/
1656
protected Certificate[] getSignerCertificates(CodeSource cs) {
1657
Certificate[] certs = null;
1658
if ((certs = cs.getCertificates()) == null)
1659
return null;
1660
for (int i=0; i<certs.length; i++) {
1661
if (!(certs[i] instanceof X509Certificate))
1662
return cs.getCertificates();
1663
}
1664
1665
// Do we have to do anything?
1666
int i = 0;
1667
int count = 0;
1668
while (i < certs.length) {
1669
count++;
1670
while (((i+1) < certs.length)
1671
&& ((X509Certificate)certs[i]).getIssuerDN().equals(
1672
((X509Certificate)certs[i+1]).getSubjectDN())) {
1673
i++;
1674
}
1675
i++;
1676
}
1677
if (count == certs.length)
1678
// Done
1679
return certs;
1680
1681
List<Certificate> userCertList = new ArrayList<>();
1682
i = 0;
1683
while (i < certs.length) {
1684
userCertList.add(certs[i]);
1685
while (((i+1) < certs.length)
1686
&& ((X509Certificate)certs[i]).getIssuerDN().equals(
1687
((X509Certificate)certs[i+1]).getSubjectDN())) {
1688
i++;
1689
}
1690
i++;
1691
}
1692
Certificate[] userCerts = new Certificate[userCertList.size()];
1693
userCertList.toArray(userCerts);
1694
return userCerts;
1695
}
1696
1697
private CodeSource canonicalizeCodebase(CodeSource cs,
1698
boolean extractSignerCerts) {
1699
1700
String path = null;
1701
1702
CodeSource canonCs = cs;
1703
URL u = cs.getLocation();
1704
if (u != null) {
1705
if (u.getProtocol().equals("jar")) {
1706
// unwrap url embedded inside jar url
1707
String spec = u.getFile();
1708
int separator = spec.indexOf("!/");
1709
if (separator != -1) {
1710
try {
1711
u = new URL(spec.substring(0, separator));
1712
} catch (MalformedURLException e) {
1713
// Fail silently. In this case, url stays what
1714
// it was above
1715
}
1716
}
1717
}
1718
if (u.getProtocol().equals("file")) {
1719
boolean isLocalFile = false;
1720
String host = u.getHost();
1721
isLocalFile = (host == null || host.equals("") ||
1722
host.equals("~") || host.equalsIgnoreCase("localhost"));
1723
1724
if (isLocalFile) {
1725
path = u.getFile().replace('/', File.separatorChar);
1726
path = ParseUtil.decode(path);
1727
}
1728
}
1729
}
1730
1731
if (path != null) {
1732
try {
1733
URL csUrl = null;
1734
path = canonPath(path);
1735
csUrl = ParseUtil.fileToEncodedURL(new File(path));
1736
1737
if (extractSignerCerts) {
1738
canonCs = new CodeSource(csUrl,
1739
getSignerCertificates(cs));
1740
} else {
1741
canonCs = new CodeSource(csUrl,
1742
cs.getCertificates());
1743
}
1744
} catch (IOException ioe) {
1745
// leave codesource as it is, unless we have to extract its
1746
// signer certificates
1747
if (extractSignerCerts) {
1748
canonCs = new CodeSource(cs.getLocation(),
1749
getSignerCertificates(cs));
1750
}
1751
}
1752
} else {
1753
if (extractSignerCerts) {
1754
canonCs = new CodeSource(cs.getLocation(),
1755
getSignerCertificates(cs));
1756
}
1757
}
1758
return canonCs;
1759
}
1760
1761
// Wrapper to return a canonical path that avoids calling getCanonicalPath()
1762
// with paths that are intended to match all entries in the directory
1763
private static String canonPath(String path) throws IOException {
1764
if (path.endsWith("*")) {
1765
path = path.substring(0, path.length()-1) + "-";
1766
path = new File(path).getCanonicalPath();
1767
return path.substring(0, path.length()-1) + "*";
1768
} else {
1769
return new File(path).getCanonicalPath();
1770
}
1771
}
1772
1773
private String printPD(ProtectionDomain pd) {
1774
Principal[] principals = pd.getPrincipals();
1775
String pals = "<no principals>";
1776
if (principals != null && principals.length > 0) {
1777
StringBuilder palBuf = new StringBuilder("(principals ");
1778
for (int i = 0; i < principals.length; i++) {
1779
palBuf.append(principals[i].getClass().getName() +
1780
" \"" + principals[i].getName() +
1781
"\"");
1782
if (i < principals.length-1)
1783
palBuf.append(", ");
1784
else
1785
palBuf.append(")");
1786
}
1787
pals = palBuf.toString();
1788
}
1789
return "PD CodeSource: "
1790
+ pd.getCodeSource()
1791
+"\n\t" + "PD ClassLoader: "
1792
+ pd.getClassLoader()
1793
+"\n\t" + "PD Principals: "
1794
+ pals;
1795
}
1796
1797
/**
1798
* return true if no replacement was performed,
1799
* or if replacement succeeded.
1800
*/
1801
private boolean replacePrincipals(
1802
List<PolicyParser.PrincipalEntry> principals, KeyStore keystore) {
1803
1804
if (principals == null || principals.isEmpty() || keystore == null)
1805
return true;
1806
1807
for (PolicyParser.PrincipalEntry pppe : principals) {
1808
if (pppe.isReplaceName()) {
1809
1810
// perform replacement
1811
// (only X509 replacement is possible now)
1812
String name;
1813
if ((name = getDN(pppe.principalName, keystore)) == null) {
1814
return false;
1815
}
1816
1817
if (debug != null) {
1818
debug.println(" Replacing \"" +
1819
pppe.principalName +
1820
"\" with " +
1821
X500PRINCIPAL + "/\"" +
1822
name +
1823
"\"");
1824
}
1825
1826
pppe.principalClass = X500PRINCIPAL;
1827
pppe.principalName = name;
1828
}
1829
}
1830
// return true if no replacement was performed,
1831
// or if replacement succeeded
1832
return true;
1833
}
1834
1835
private void expandPermissionName(PolicyParser.PermissionEntry pe,
1836
KeyStore keystore) throws Exception {
1837
// short cut the common case
1838
if (pe.name == null || pe.name.indexOf("${{", 0) == -1) {
1839
return;
1840
}
1841
1842
int startIndex = 0;
1843
int b, e;
1844
StringBuilder sb = new StringBuilder();
1845
while ((b = pe.name.indexOf("${{", startIndex)) != -1) {
1846
e = pe.name.indexOf("}}", b);
1847
if (e < 1) {
1848
break;
1849
}
1850
sb.append(pe.name.substring(startIndex, b));
1851
1852
// get the value in ${{...}}
1853
String value = pe.name.substring(b+3, e);
1854
1855
// parse up to the first ':'
1856
int colonIndex;
1857
String prefix = value;
1858
String suffix;
1859
if ((colonIndex = value.indexOf(":")) != -1) {
1860
prefix = value.substring(0, colonIndex);
1861
}
1862
1863
// handle different prefix possibilities
1864
if (prefix.equalsIgnoreCase("self")) {
1865
// do nothing - handled later
1866
sb.append(pe.name.substring(b, e+2));
1867
startIndex = e+2;
1868
continue;
1869
} else if (prefix.equalsIgnoreCase("alias")) {
1870
// get the suffix and perform keystore alias replacement
1871
if (colonIndex == -1) {
1872
MessageFormat form = new MessageFormat
1873
(ResourcesMgr.getString
1874
("alias.name.not.provided.pe.name."));
1875
Object[] source = {pe.name};
1876
throw new Exception(form.format(source));
1877
}
1878
suffix = value.substring(colonIndex+1);
1879
if ((suffix = getDN(suffix, keystore)) == null) {
1880
MessageFormat form = new MessageFormat
1881
(ResourcesMgr.getString
1882
("unable.to.perform.substitution.on.alias.suffix"));
1883
Object[] source = {value.substring(colonIndex+1)};
1884
throw new Exception(form.format(source));
1885
}
1886
1887
sb.append(X500PRINCIPAL + " \"" + suffix + "\"");
1888
startIndex = e+2;
1889
} else {
1890
MessageFormat form = new MessageFormat
1891
(ResourcesMgr.getString
1892
("substitution.value.prefix.unsupported"));
1893
Object[] source = {prefix};
1894
throw new Exception(form.format(source));
1895
}
1896
}
1897
1898
// copy the rest of the value
1899
sb.append(pe.name.substring(startIndex));
1900
1901
// replace the name with expanded value
1902
if (debug != null) {
1903
debug.println(" Permission name expanded from:\n\t" +
1904
pe.name + "\nto\n\t" + sb.toString());
1905
}
1906
pe.name = sb.toString();
1907
}
1908
1909
private String getDN(String alias, KeyStore keystore) {
1910
Certificate cert = null;
1911
try {
1912
cert = keystore.getCertificate(alias);
1913
} catch (Exception e) {
1914
if (debug != null) {
1915
debug.println(" Error retrieving certificate for '" +
1916
alias +
1917
"': " +
1918
e.toString());
1919
}
1920
return null;
1921
}
1922
1923
if (cert == null || !(cert instanceof X509Certificate)) {
1924
if (debug != null) {
1925
debug.println(" -- No certificate for '" +
1926
alias +
1927
"' - ignoring entry");
1928
}
1929
return null;
1930
} else {
1931
X509Certificate x509Cert = (X509Certificate)cert;
1932
1933
// 4702543: X500 names with an EmailAddress
1934
// were encoded incorrectly. create new
1935
// X500Principal name with correct encoding
1936
1937
X500Principal p = new X500Principal
1938
(x509Cert.getSubjectX500Principal().toString());
1939
return p.getName();
1940
}
1941
}
1942
1943
/**
1944
* Checks public key. If it is marked as trusted in
1945
* the identity database, add it to the policy
1946
* with the AllPermission.
1947
*/
1948
private boolean checkForTrustedIdentity(final Certificate cert,
1949
PolicyInfo myInfo)
1950
{
1951
return false;
1952
}
1953
1954
/**
1955
* Each entry in the policy configuration file is represented by a
1956
* PolicyEntry object. <p>
1957
*
1958
* A PolicyEntry is a (CodeSource,Permission) pair. The
1959
* CodeSource contains the (URL, PublicKey) that together identify
1960
* where the Java bytecodes come from and who (if anyone) signed
1961
* them. The URL could refer to localhost. The URL could also be
1962
* null, meaning that this policy entry is given to all comers, as
1963
* long as they match the signer field. The signer could be null,
1964
* meaning the code is not signed. <p>
1965
*
1966
* The Permission contains the (Type, Name, Action) triplet. <p>
1967
*
1968
* For now, the Policy object retrieves the public key from the
1969
* X.509 certificate on disk that corresponds to the signedBy
1970
* alias specified in the Policy config file. For reasons of
1971
* efficiency, the Policy object keeps a hashtable of certs already
1972
* read in. This could be replaced by a secure internal key
1973
* store.
1974
*
1975
* <p>
1976
* For example, the entry
1977
* <pre>
1978
* permission java.io.File "/tmp", "read,write",
1979
* signedBy "Duke";
1980
* </pre>
1981
* is represented internally
1982
* <pre>
1983
*
1984
* FilePermission f = new FilePermission("/tmp", "read,write");
1985
* PublicKey p = publickeys.get("Duke");
1986
* URL u = InetAddress.getLocalHost();
1987
* CodeBase c = new CodeBase( p, u );
1988
* pe = new PolicyEntry(f, c);
1989
* </pre>
1990
*
1991
* @author Marianne Mueller
1992
* @author Roland Schemers
1993
* @see java.security.CodeSource
1994
* @see java.security.Policy
1995
* @see java.security.Permissions
1996
* @see java.security.ProtectionDomain
1997
*/
1998
private static class PolicyEntry {
1999
2000
private final CodeSource codesource;
2001
final List<Permission> permissions;
2002
private final List<PolicyParser.PrincipalEntry> principals;
2003
2004
/**
2005
* Given a Permission and a CodeSource, create a policy entry.
2006
*
2007
* XXX Decide if/how to add validity fields and "purpose" fields to
2008
* XXX policy entries
2009
*
2010
* @param cs the CodeSource, which encapsulates the URL and the
2011
* public key
2012
* attributes from the policy config file. Validity checks
2013
* are performed on the public key before PolicyEntry is
2014
* called.
2015
*
2016
*/
2017
PolicyEntry(CodeSource cs, List<PolicyParser.PrincipalEntry> principals)
2018
{
2019
this.codesource = cs;
2020
this.permissions = new ArrayList<Permission>();
2021
this.principals = principals; // can be null
2022
}
2023
2024
PolicyEntry(CodeSource cs)
2025
{
2026
this(cs, null);
2027
}
2028
2029
List<PolicyParser.PrincipalEntry> getPrincipals() {
2030
return principals; // can be null
2031
}
2032
2033
/**
2034
* add a Permission object to this entry.
2035
* No need to sync add op because perms are added to entry only
2036
* while entry is being initialized
2037
*/
2038
void add(Permission p) {
2039
permissions.add(p);
2040
}
2041
2042
/**
2043
* Return the CodeSource for this policy entry
2044
*/
2045
CodeSource getCodeSource() {
2046
return codesource;
2047
}
2048
2049
@Override public String toString(){
2050
StringBuilder sb = new StringBuilder();
2051
sb.append(ResourcesMgr.getString("LPARAM"));
2052
sb.append(getCodeSource());
2053
sb.append("\n");
2054
for (int j = 0; j < permissions.size(); j++) {
2055
Permission p = permissions.get(j);
2056
sb.append(ResourcesMgr.getString("SPACE"));
2057
sb.append(ResourcesMgr.getString("SPACE"));
2058
sb.append(p);
2059
sb.append(ResourcesMgr.getString("NEWLINE"));
2060
}
2061
sb.append(ResourcesMgr.getString("RPARAM"));
2062
sb.append(ResourcesMgr.getString("NEWLINE"));
2063
return sb.toString();
2064
}
2065
}
2066
2067
private static class SelfPermission extends Permission {
2068
2069
private static final long serialVersionUID = -8315562579967246806L;
2070
2071
/**
2072
* The class name of the Permission class that will be
2073
* created when this self permission is expanded .
2074
*
2075
* @serial
2076
*/
2077
private String type;
2078
2079
/**
2080
* The permission name.
2081
*
2082
* @serial
2083
*/
2084
private String name;
2085
2086
/**
2087
* The actions of the permission.
2088
*
2089
* @serial
2090
*/
2091
private String actions;
2092
2093
/**
2094
* The certs of the permission.
2095
*
2096
* @serial
2097
*/
2098
private Certificate certs[];
2099
2100
/**
2101
* Creates a new SelfPermission containing the permission
2102
* information needed later to expand the self
2103
* @param type the class name of the Permission class that will be
2104
* created when this permission is expanded and if necessary resolved.
2105
* @param name the name of the permission.
2106
* @param actions the actions of the permission.
2107
* @param certs the certificates the permission's class was signed with.
2108
* This is a list of certificate chains, where each chain is composed of
2109
* a signer certificate and optionally its supporting certificate chain.
2110
* Each chain is ordered bottom-to-top (i.e., with the signer
2111
* certificate first and the (root) certificate authority last).
2112
*/
2113
public SelfPermission(String type, String name, String actions,
2114
Certificate certs[])
2115
{
2116
super(type);
2117
if (type == null) {
2118
throw new NullPointerException
2119
(ResourcesMgr.getString("type.can.t.be.null"));
2120
}
2121
this.type = type;
2122
this.name = name;
2123
this.actions = actions;
2124
if (certs != null) {
2125
// Extract the signer certs from the list of certificates.
2126
for (int i=0; i<certs.length; i++) {
2127
if (!(certs[i] instanceof X509Certificate)) {
2128
// there is no concept of signer certs, so we store the
2129
// entire cert array
2130
this.certs = certs.clone();
2131
break;
2132
}
2133
}
2134
2135
if (this.certs == null) {
2136
// Go through the list of certs and see if all the certs are
2137
// signer certs.
2138
int i = 0;
2139
int count = 0;
2140
while (i < certs.length) {
2141
count++;
2142
while (((i+1) < certs.length) &&
2143
((X509Certificate)certs[i]).getIssuerDN().equals(
2144
((X509Certificate)certs[i+1]).getSubjectDN())) {
2145
i++;
2146
}
2147
i++;
2148
}
2149
if (count == certs.length) {
2150
// All the certs are signer certs, so we store the
2151
// entire array
2152
this.certs = certs.clone();
2153
}
2154
2155
if (this.certs == null) {
2156
// extract the signer certs
2157
List<Certificate> signerCerts = new ArrayList<>();
2158
i = 0;
2159
while (i < certs.length) {
2160
signerCerts.add(certs[i]);
2161
while (((i+1) < certs.length) &&
2162
((X509Certificate)certs[i]).getIssuerDN().equals(
2163
((X509Certificate)certs[i+1]).getSubjectDN())) {
2164
i++;
2165
}
2166
i++;
2167
}
2168
this.certs = new Certificate[signerCerts.size()];
2169
signerCerts.toArray(this.certs);
2170
}
2171
}
2172
}
2173
}
2174
2175
/**
2176
* This method always returns false for SelfPermission permissions.
2177
* That is, an SelfPermission never considered to
2178
* imply another permission.
2179
*
2180
* @param p the permission to check against.
2181
*
2182
* @return false.
2183
*/
2184
@Override public boolean implies(Permission p) {
2185
return false;
2186
}
2187
2188
/**
2189
* Checks two SelfPermission objects for equality.
2190
*
2191
* Checks that <i>obj</i> is an SelfPermission, and has
2192
* the same type (class) name, permission name, actions, and
2193
* certificates as this object.
2194
*
2195
* @param obj the object we are testing for equality with this object.
2196
*
2197
* @return true if obj is an SelfPermission, and has the same
2198
* type (class) name, permission name, actions, and
2199
* certificates as this object.
2200
*/
2201
@Override public boolean equals(Object obj) {
2202
if (obj == this)
2203
return true;
2204
2205
if (! (obj instanceof SelfPermission))
2206
return false;
2207
SelfPermission that = (SelfPermission) obj;
2208
2209
if (!(this.type.equals(that.type) &&
2210
this.name.equals(that.name) &&
2211
this.actions.equals(that.actions)))
2212
return false;
2213
2214
if (this.certs.length != that.certs.length)
2215
return false;
2216
2217
int i,j;
2218
boolean match;
2219
2220
for (i = 0; i < this.certs.length; i++) {
2221
match = false;
2222
for (j = 0; j < that.certs.length; j++) {
2223
if (this.certs[i].equals(that.certs[j])) {
2224
match = true;
2225
break;
2226
}
2227
}
2228
if (!match) return false;
2229
}
2230
2231
for (i = 0; i < that.certs.length; i++) {
2232
match = false;
2233
for (j = 0; j < this.certs.length; j++) {
2234
if (that.certs[i].equals(this.certs[j])) {
2235
match = true;
2236
break;
2237
}
2238
}
2239
if (!match) return false;
2240
}
2241
return true;
2242
}
2243
2244
/**
2245
* Returns the hash code value for this object.
2246
*
2247
* @return a hash code value for this object.
2248
*/
2249
@Override public int hashCode() {
2250
int hash = type.hashCode();
2251
if (name != null)
2252
hash ^= name.hashCode();
2253
if (actions != null)
2254
hash ^= actions.hashCode();
2255
return hash;
2256
}
2257
2258
/**
2259
* Returns the canonical string representation of the actions,
2260
* which currently is the empty string "", since there are no actions
2261
* for an SelfPermission. That is, the actions for the
2262
* permission that will be created when this SelfPermission
2263
* is resolved may be non-null, but an SelfPermission
2264
* itself is never considered to have any actions.
2265
*
2266
* @return the empty string "".
2267
*/
2268
@Override public String getActions() {
2269
return "";
2270
}
2271
2272
public String getSelfType() {
2273
return type;
2274
}
2275
2276
public String getSelfName() {
2277
return name;
2278
}
2279
2280
public String getSelfActions() {
2281
return actions;
2282
}
2283
2284
public Certificate[] getCerts() {
2285
return certs;
2286
}
2287
2288
/**
2289
* Returns a string describing this SelfPermission. The convention
2290
* is to specify the class name, the permission name, and the actions,
2291
* in the following format: '(unresolved "ClassName" "name" "actions")'.
2292
*
2293
* @return information about this SelfPermission.
2294
*/
2295
@Override public String toString() {
2296
return "(SelfPermission " + type + " " + name + " " + actions + ")";
2297
}
2298
}
2299
2300
/**
2301
* holds policy information that we need to synch on
2302
*/
2303
private static class PolicyInfo {
2304
private static final boolean verbose = false;
2305
2306
// Stores grant entries in the policy
2307
final List<PolicyEntry> policyEntries;
2308
2309
// Stores grant entries gotten from identity database
2310
// Use separate lists to avoid sync on policyEntries
2311
final List<PolicyEntry> identityPolicyEntries;
2312
2313
// Maps aliases to certs
2314
final Map<Object, Object> aliasMapping;
2315
2316
// Maps ProtectionDomain to PermissionCollection
2317
private final ProtectionDomainCache[] pdMapping;
2318
private java.util.Random random;
2319
2320
PolicyInfo(int numCaches) {
2321
policyEntries = new ArrayList<>();
2322
identityPolicyEntries =
2323
Collections.synchronizedList(new ArrayList<PolicyEntry>(2));
2324
aliasMapping = Collections.synchronizedMap(new HashMap<>(11));
2325
2326
pdMapping = new ProtectionDomainCache[numCaches];
2327
JavaSecurityProtectionDomainAccess jspda
2328
= SharedSecrets.getJavaSecurityProtectionDomainAccess();
2329
for (int i = 0; i < numCaches; i++) {
2330
pdMapping[i] = jspda.getProtectionDomainCache();
2331
}
2332
if (numCaches > 1) {
2333
random = new java.util.Random();
2334
}
2335
}
2336
ProtectionDomainCache getPdMapping() {
2337
if (pdMapping.length == 1) {
2338
return pdMapping[0];
2339
} else {
2340
int i = java.lang.Math.abs(random.nextInt() % pdMapping.length);
2341
return pdMapping[i];
2342
}
2343
}
2344
}
2345
}
2346
2347