Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/java/security/AccessControlContext.java
12513 views
1
/*[INCLUDE-IF Sidecar18-SE]*/
2
/*******************************************************************************
3
* Copyright (c) 1998, 2021 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
22
*******************************************************************************/
23
package java.security;
24
25
import java.io.IOException;
26
import java.io.StreamTokenizer;
27
import java.io.StringReader;
28
import java.net.MalformedURLException;
29
import java.net.URL;
30
import java.util.ArrayList;
31
/*[IF Sidecar19-SE]*/
32
import sun.security.util.FilePermCompat;
33
/*[ENDIF] Sidecar19-SE*/
34
import sun.security.util.SecurityConstants;
35
36
/**
37
* An AccessControlContext encapsulates the information which is needed
38
* by class AccessController to detect if a Permission would be granted
39
* at a particular point in a programs execution.
40
*
41
* @author OTI
42
* @version initial
43
*/
44
/*[IF JAVA_SPEC_VERSION >= 17]*/
45
@Deprecated(since="17", forRemoval=true)
46
/*[ENDIF] JAVA_SPEC_VERSION >= 17 */
47
public final class AccessControlContext {
48
49
static final int STATE_NOT_AUTHORIZED = 0; // It has been confirmed that the ACC is NOT authorized
50
static final int STATE_AUTHORIZED = 1; // It has been confirmed that the ACC is authorized
51
static final int STATE_UNKNOWN = 2; // The ACC state is unknown yet.
52
53
private static int debugSetting = -1;
54
private static ArrayList<String> debugPermClassArray;
55
private static ArrayList<String> debugPermNameArray;
56
private static ArrayList<String> debugPermActionsArray;
57
static ArrayList<URL> debugCodeBaseArray;
58
59
/* Constants used to set the value of the debugHasCodebase field */
60
private static final int DEBUG_UNINITIALIZED_HASCODEBASE = 0;
61
private static final int DEBUG_NO_CODEBASE = 1;
62
private static final int DEBUG_HAS_CODEBASE = 2;
63
64
static final int DEBUG_DISABLED = 0;
65
static final int DEBUG_ACCESS_DENIED = 1; // debug is enabled for access denied, and failure
66
static final int DEBUG_ENABLED = 2; // debug is enabled for access allowed, stacks, domains, and threads
67
68
DomainCombiner domainCombiner;
69
/*[PR CMVC 111227] JDK6 expects field to be called "context" */
70
ProtectionDomain[] context;
71
/*[PR CMVC 197399] Improve checking order */
72
int authorizeState = STATE_UNKNOWN;
73
/*[PR JAZZ 66930] j.s.AccessControlContext.checkPermission() invoke untrusted ProtectionDomain.implies */
74
// This flag is to determine if current ACC contains privileged PDs such that
75
// createAccessControlContext permission need to be checked before invoking ProtectionDomain.implies()
76
private boolean containPrivilegedContext = false;
77
// This is the ProtectionDomain of the creator of this ACC
78
private ProtectionDomain callerPD;
79
AccessControlContext doPrivilegedAcc; // AccessControlContext usually coming from a doPrivileged call
80
boolean isLimitedContext = false; // flag to indicate if there are limited permissions
81
Permission[] limitedPerms; // the limited permissions when isLimitedContext is true
82
AccessControlContext nextStackAcc; // AccessControlContext in next call stack when isLimitedContext is true
83
private int debugHasCodebase; // Set to the value of DEBUG_UNINITIALIZED_HASCODEBASE be default. Cache the result of hasDebugCodeBase()
84
85
static final int DEBUG_ACCESS = 1;
86
static final int DEBUG_ACCESS_STACK = 2;
87
static final int DEBUG_ACCESS_DOMAIN = 4;
88
static final int DEBUG_ACCESS_FAILURE = 8;
89
static final int DEBUG_ACCESS_THREAD = 0x10;
90
static final int DEBUG_ALL = 0xff;
91
92
static final class AccessCache {
93
ProtectionDomain[] pdsImplied;
94
Permission[] permsImplied;
95
Permission[] permsNotImplied;
96
}
97
98
static int debugSetting() {
99
if (debugSetting != -1) return debugSetting;
100
debugSetting = 0;
101
String value = com.ibm.oti.vm.VM.getVMLangAccess().internalGetProperties().getProperty("java.security.debug"); //$NON-NLS-1$
102
if (value == null) return debugSetting;
103
StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(value));
104
tokenizer.resetSyntax();
105
tokenizer.wordChars(Character.MIN_CODE_POINT, Character.MAX_CODE_POINT);
106
tokenizer.quoteChar('"');
107
tokenizer.whitespaceChars(',', ',');
108
109
try {
110
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
111
String keyword = tokenizer.sval;
112
if (keyword.equals("all")) { //$NON-NLS-1$
113
debugSetting = DEBUG_ALL;
114
return debugSetting;
115
}
116
if (keyword.startsWith("access:")) { //$NON-NLS-1$
117
debugSetting |= DEBUG_ACCESS;
118
keyword = keyword.substring(7);
119
}
120
121
if (keyword.equals("access")) { //$NON-NLS-1$
122
debugSetting |= DEBUG_ACCESS;
123
} else if (keyword.equals("stack")) { //$NON-NLS-1$
124
debugSetting |= DEBUG_ACCESS_STACK;
125
} else if (keyword.equals("domain")) { //$NON-NLS-1$
126
debugSetting |= DEBUG_ACCESS_DOMAIN;
127
} else if (keyword.equals("failure")) { //$NON-NLS-1$
128
debugSetting |= DEBUG_ACCESS_FAILURE;
129
} else if (keyword.equals("thread")) { //$NON-NLS-1$
130
debugSetting |= DEBUG_ACCESS_THREAD;
131
} else if (keyword.startsWith("permission=")) { //$NON-NLS-1$
132
String debugPermClass = keyword.substring(11);
133
if (debugPermClass.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
134
debugPermClass = tokenizer.sval;
135
}
136
if (null == debugPermClassArray) {
137
debugPermClassArray = new ArrayList<>();
138
}
139
debugPermClassArray.add(debugPermClass);
140
} else if (keyword.startsWith("codebase=")) { //$NON-NLS-1$
141
String codebase = keyword.substring(9);
142
if (codebase.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
143
codebase = tokenizer.sval;
144
}
145
URL debugCodeBase = null;
146
try {
147
debugCodeBase = new URL(codebase);
148
} catch (MalformedURLException e) {
149
System.err.println("Error setting -Djava.security.debug=access:codebase - " + e); //$NON-NLS-1$
150
}
151
if (null != debugCodeBase) {
152
if (null == debugCodeBaseArray) {
153
debugCodeBaseArray = new ArrayList<>();
154
}
155
debugCodeBaseArray.add(debugCodeBase);
156
}
157
} else if (keyword.startsWith("permname=")) { //$NON-NLS-1$
158
String debugPermName = keyword.substring(9);
159
if (debugPermName.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
160
debugPermName = tokenizer.sval;
161
}
162
if (null == debugPermNameArray) {
163
debugPermNameArray = new ArrayList<>();
164
}
165
debugPermNameArray.add(debugPermName);
166
} else if (keyword.startsWith("permactions=")) { //$NON-NLS-1$
167
String debugPermActions = keyword.substring(12);
168
if (debugPermActions.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
169
debugPermActions = tokenizer.sval;
170
}
171
if (null == debugPermActionsArray) {
172
debugPermActionsArray = new ArrayList<>();
173
}
174
debugPermActionsArray.add(debugPermActions);
175
}
176
}
177
} catch (IOException e) {
178
// should not happen with StringReader
179
}
180
if (0 == (debugSetting & DEBUG_ACCESS)) {
181
// If the access keyword is not specified, none of the other keywords have any affect
182
debugSetting = 0;
183
}
184
return debugSetting;
185
}
186
187
/**
188
* Return true if the specified Permission is enabled for debug.
189
* @param perm a Permission instance
190
* @return Return true if the specified Permission is enabled for debug
191
*/
192
static boolean debugPermission(Permission perm) {
193
boolean result = true;
194
if (debugPermClassArray != null) {
195
result = false;
196
String permClassName = perm.getClass().getName();
197
for (String debugPermClass : debugPermClassArray) {
198
if (debugPermClass.equals(permClassName)) {
199
return true;
200
}
201
}
202
}
203
if (debugPermNameArray != null) {
204
result = false;
205
String permName = perm.getName();
206
for (String debugPermName : debugPermNameArray) {
207
if (debugPermName.equals(permName)) {
208
return true;
209
}
210
}
211
}
212
if (debugPermActionsArray != null) {
213
result = false;
214
String permActions = perm.getActions();
215
for (String debugPermActions : debugPermActionsArray) {
216
if (debugPermActions.equals(permActions)) {
217
return true;
218
}
219
}
220
}
221
return result;
222
}
223
224
/**
225
* Check if the receiver contains a ProtectionDomain using the debugCodeBase, which
226
* was parsed from the java.security.debug system property.
227
*
228
* @return true if the AccessControlContext contains a ProtectionDomain which
229
* matches the debug codebase.
230
*/
231
boolean hasDebugCodeBase() {
232
if (debugHasCodebase != DEBUG_UNINITIALIZED_HASCODEBASE) {
233
return debugHasCodebase == DEBUG_HAS_CODEBASE ? true : false;
234
}
235
ProtectionDomain[] pds = this.context;
236
if (pds != null) {
237
for (int i = 0; i < pds.length; ++i) {
238
ProtectionDomain pd = this.context[i];
239
CodeSource cs = null == pd ? null : pd.getCodeSource();
240
if ((cs != null) && debugCodeBase(cs.getLocation())) {
241
debugHasCodebase = DEBUG_HAS_CODEBASE;
242
return true;
243
}
244
}
245
if ((this.doPrivilegedAcc != null) && this.doPrivilegedAcc.hasDebugCodeBase()) {
246
debugHasCodebase = DEBUG_HAS_CODEBASE;
247
return true;
248
}
249
if ((this.nextStackAcc != null) && this.nextStackAcc.hasDebugCodeBase()) {
250
debugHasCodebase = DEBUG_HAS_CODEBASE;
251
return true;
252
}
253
}
254
debugHasCodebase = DEBUG_NO_CODEBASE;
255
return false;
256
}
257
258
/**
259
* Return true if the specified codebase location is enabled for debug.
260
* @param location a codebase URL
261
* @return Return true if the specified codebase location is enabled for debug
262
*/
263
static boolean debugCodeBase(URL location) {
264
if (location != null) {
265
for (URL debugCodeBase : debugCodeBaseArray) {
266
if (debugCodeBase.equals(location)) {
267
return true;
268
}
269
}
270
}
271
272
return false;
273
}
274
275
static void debugPrintAccess() {
276
System.err.print("access: "); //$NON-NLS-1$
277
if ((debugSetting() & DEBUG_ACCESS_THREAD) == DEBUG_ACCESS_THREAD) {
278
System.err.print("(" + Thread.currentThread() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
279
}
280
}
281
282
/**
283
* Constructs a new instance of this class given an array of
284
* protection domains.
285
*
286
* @param fromContext the array of ProtectionDomain
287
*
288
* @exception NullPointerException if fromContext is null
289
*/
290
public AccessControlContext(ProtectionDomain[] fromContext) {
291
/*[PR 94884]*/
292
int length = fromContext.length;
293
if (length == 0) {
294
context = null;
295
} else {
296
int domainIndex = 0;
297
context = new ProtectionDomain[length];
298
next : for (int i = 0; i < length; ++i) {
299
ProtectionDomain current = fromContext[i];
300
if (current == null) continue;
301
for (int j = 0; j < i; ++j)
302
if (current == context[j]) continue next;
303
context[domainIndex++] = current;
304
}
305
if (domainIndex == 0) {
306
context = null;
307
} else if (domainIndex != length) {
308
ProtectionDomain[] copy = new ProtectionDomain[domainIndex];
309
System.arraycopy(context, 0, copy, 0, domainIndex);
310
context = copy;
311
}
312
}
313
// this.containPrivilegedContext is set to false by default
314
// this.authorizeState is STATE_UNKNOWN by default
315
}
316
317
AccessControlContext(ProtectionDomain[] context, int authorizeState) {
318
super();
319
switch (authorizeState) {
320
default:
321
// authorizeState can't be STATE_UNKNOWN, callerPD always is NULL
322
throw new IllegalArgumentException();
323
case STATE_AUTHORIZED:
324
case STATE_NOT_AUTHORIZED:
325
break;
326
}
327
this.context = context;
328
this.authorizeState = authorizeState;
329
this.containPrivilegedContext = true;
330
}
331
332
AccessControlContext(AccessControlContext acc, ProtectionDomain[] context, int authorizeState) {
333
super();
334
switch (authorizeState) {
335
default:
336
// authorizeState can't be STATE_UNKNOWN, callerPD always is NULL
337
throw new IllegalArgumentException();
338
case STATE_AUTHORIZED:
339
if (null != acc) {
340
// inherit the domain combiner when authorized
341
this.domainCombiner = acc.domainCombiner;
342
}
343
break;
344
case STATE_NOT_AUTHORIZED:
345
break;
346
}
347
this.doPrivilegedAcc = acc;
348
this.context = context;
349
this.authorizeState = authorizeState;
350
this.containPrivilegedContext = true;
351
}
352
353
/**
354
* Constructs a new instance of this class given a context
355
* and a DomainCombiner
356
*
357
* @param acc the AccessControlContext
358
* @param combiner the DomainCombiner
359
*
360
* @exception java.security.AccessControlException thrown
361
* when the caller doesn't have the "createAccessControlContext" SecurityPermission
362
* @exception NullPointerException if the provided context is null.
363
*/
364
public AccessControlContext(AccessControlContext acc, DomainCombiner combiner) {
365
this(acc, combiner, false);
366
}
367
368
/**
369
* Constructs a new instance of this class given a context and a DomainCombiner
370
* Skip the Permission "createAccessControlContext" check if preauthorized is true
371
*
372
* @param acc the AccessControlContext
373
* @param combiner the DomainCombiner
374
* @param preauthorized the flag to indicate if the permission check can be skipped
375
*
376
* @exception java.security.AccessControlException thrown
377
* when the caller doesn't have the "createAccessControlContext" SecurityPermission
378
* @exception NullPointerException if the provided context is null.
379
*/
380
AccessControlContext(AccessControlContext acc, DomainCombiner combiner, boolean preauthorized) {
381
if (!preauthorized) {
382
@SuppressWarnings("removal")
383
SecurityManager security = System.getSecurityManager();
384
if (null != security) {
385
security.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION);
386
/*[PR JAZZ 78139] java.security.AccessController.checkPermission invokes untrusted DomainCombiner.combine method */
387
}
388
}
389
// only AccessControlContext with STATE_AUTHORIZED authorizeState could have non-null domainCombiner
390
this.authorizeState = STATE_AUTHORIZED;
391
this.context = acc.context;
392
this.domainCombiner = combiner;
393
this.containPrivilegedContext = acc.containPrivilegedContext;
394
this.isLimitedContext = acc.isLimitedContext;
395
this.limitedPerms = acc.limitedPerms;
396
this.nextStackAcc = acc.nextStackAcc;
397
this.doPrivilegedAcc = acc.doPrivilegedAcc;
398
}
399
400
/**
401
* Combine checked and toBeCombined
402
* Assuming: there are no null or dup elements in checked
403
* there might be nulls or dups in toBeCombined
404
*
405
* @param objPDs the flag to indicate if it is a ProtectionDomain or Permission object element
406
* @param checked the array of objects already checked
407
* @param toBeCombined the array of objects to be combined
408
* @param start the start position in the toBeCombined array
409
* @param len the number of element to be copied
410
* @param justCombine the flag to indicate if null/dup check is needed
411
*
412
* @return the combination of these two array
413
*/
414
private static Object[] combineObjs(boolean objPDs, Object[] checked, Object[] toBeCombined, int start, int len, boolean justCombine) {
415
if (null == toBeCombined) {
416
return checked;
417
}
418
final int lenToBeCombined = Math.min(len, toBeCombined.length - start);
419
if (0 == lenToBeCombined) {
420
return checked;
421
}
422
final int lenChecked = (null == checked) ? 0 : checked.length;
423
Object[] answer;
424
if (objPDs) {
425
answer = new ProtectionDomain[lenChecked + lenToBeCombined];
426
} else {
427
answer = new Permission[lenChecked + lenToBeCombined];
428
}
429
if (0 != lenChecked) {
430
System.arraycopy(checked, 0, answer, 0, lenChecked);
431
}
432
if (justCombine) {
433
// no null/dup check
434
System.arraycopy(toBeCombined, start, answer, lenChecked, lenToBeCombined);
435
} else {
436
// remove the null & dups
437
int answerLength = lenChecked;
438
for (int i = 0; i < lenToBeCombined; ++i) {
439
Object object = toBeCombined[start + i];
440
if (null != object) { // remove null
441
// check starts from newly added elements
442
for (int j = answerLength;;) {
443
j -= 1;
444
if (j < 0) {
445
answer[answerLength] = object;
446
answerLength += 1;
447
break;
448
} else if (object == answer[j]) {
449
break;
450
}
451
}
452
}
453
}
454
if (answerLength < answer.length) {
455
Object[] result;
456
if (objPDs) {
457
result = new ProtectionDomain[answerLength];
458
} else {
459
result = new Permission[answerLength];
460
}
461
System.arraycopy(answer, 0, result, 0, answerLength);
462
answer = result;
463
}
464
}
465
return answer;
466
}
467
468
/**
469
* Combine checked and toBeCombined ProtectionDomain objects
470
* Assuming: there are no null or dup elements in checked
471
* there might be null or dups in toBeCombined
472
*
473
* @param checked the array of objects already checked
474
* @param toBeCombined the array of objects to be combined
475
*
476
* @return the combination of these two array
477
*/
478
static ProtectionDomain[] combinePDObjs(ProtectionDomain[] checked, Object[] toBeCombined) {
479
return (ProtectionDomain[]) combineObjs(true, checked, toBeCombined, 0, (null != toBeCombined) ? toBeCombined.length : 0, false);
480
}
481
482
/**
483
* Combine checked and toBeCombined Permission objects
484
* Assuming: there are no null or dup elements in checked
485
* there might be null or dups in toBeCombined
486
*
487
* @param checked the array of objects already checked
488
* @param toBeCombined the array of objects to be combined
489
* @param start the start position in the toBeCombined array
490
* @param len the number of element to be copied
491
* @param justCombine the flag to indicate if null/dup check is needed
492
*
493
* @return the combination of these two array
494
*/
495
static Permission[] combinePermObjs(Permission[] checked, Permission[] toBeCombined, int start, int len, boolean justCombine) {
496
return (Permission[]) combineObjs(false, checked, toBeCombined, start, len, justCombine);
497
}
498
499
/**
500
* Perform ProtectionDomain.implies(permission) with known ProtectionDomain objects already implied
501
*
502
* @param perm the permission to be checked
503
* @param toCheck the ProtectionDomain to be checked
504
* @param cacheChecked the cached check result which is an array with following three elements:
505
* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied
506
*
507
* @return -1 if toCheck is null, among pdsImplied or each ProtectionDomain within toCheck implies perm,
508
* otherwise the index of ProtectionDomain objects not implied
509
*/
510
static int checkPermWithCachedPDsImplied(Permission perm, Object[] toCheck, AccessCache cacheChecked) {
511
if (null == toCheck) {
512
return -1; // nothing to check, implied
513
}
514
ProtectionDomain[] pdsImplied = (null == cacheChecked) ? null : cacheChecked.pdsImplied;
515
516
// in reverse order as per RI behavior
517
check: for (int i = toCheck.length; i > 0;) {
518
i -= 1;
519
Object domain = toCheck[i];
520
if (null != domain) {
521
if (null != pdsImplied) {
522
for (int j = 0; j < pdsImplied.length; ++j) {
523
if (domain == pdsImplied[j]) {
524
continue check;
525
}
526
}
527
}
528
/*[IF Sidecar19-SE]*/
529
if (!((ProtectionDomain) domain).impliesWithAltFilePerm(perm)) {
530
/*[ELSE]*/
531
if (!((ProtectionDomain) domain).implies(perm)) {
532
/*[ENDIF] Sidecar19-SE*/
533
return i; // NOT implied
534
}
535
}
536
}
537
if (null != cacheChecked) {
538
cacheChecked.pdsImplied = combinePDObjs(pdsImplied, toCheck);
539
}
540
return -1; // all implied
541
}
542
543
/**
544
* Perform Permission.implies(permission) with known Permission objects already implied and NOT implied
545
*
546
* @param perm the permission to be checked
547
* @param permsLimited the limited Permission to be checked
548
* @param cacheChecked the cached check result which is an array with following three elements:
549
* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied
550
*
551
* @return true if there is a limited permission implied perm, otherwise false
552
*/
553
static boolean checkPermWithCachedPermImplied(Permission perm, Permission[] permsLimited, AccessCache cacheChecked) {
554
if (null == permsLimited) {
555
return false;
556
}
557
Permission[] permsImplied = null;
558
Permission[] permsNotImplied = null;
559
if (null != cacheChecked) {
560
permsImplied = cacheChecked.permsImplied;
561
permsNotImplied = cacheChecked.permsNotImplied;
562
}
563
boolean success = false;
564
int lenNotImplied = permsLimited.length;
565
for (int j = 0; j < permsLimited.length; ++j) {
566
if (null != permsLimited[j]) { // go through each non-null limited permission
567
if (null != permsImplied) {
568
for (int k = 0; k < permsImplied.length; ++k) {
569
if (permsLimited[j] == permsImplied[k]) {
570
success = true; // already implied before
571
break;
572
}
573
}
574
if (success) { // already implied
575
lenNotImplied = j;
576
break;
577
}
578
}
579
boolean notImplied = false;
580
if (null != permsNotImplied) {
581
for (int k = 0; k < permsNotImplied.length; ++k) {
582
if (permsLimited[j] == permsNotImplied[k]) {
583
notImplied = true; // already NOT implied before
584
lenNotImplied = j;
585
break;
586
}
587
}
588
}
589
/*[IF Sidecar19-SE]*/
590
permsLimited[j] = FilePermCompat.newPermPlusAltPath(permsLimited[j]);
591
/*[ENDIF] Sidecar19-SE*/
592
if (!notImplied && permsLimited[j].implies(perm)) {
593
success = true; // just implied
594
if (null != cacheChecked) {
595
cacheChecked.permsImplied = combinePermObjs(permsImplied, permsLimited, j, 1, true);
596
}
597
lenNotImplied = j;
598
break;
599
}
600
}
601
}
602
if (0 < lenNotImplied && null != cacheChecked) {
603
cacheChecked.permsNotImplied = combinePermObjs(permsNotImplied, permsLimited, 0, lenNotImplied, false);
604
}
605
return success;
606
}
607
608
/**
609
* Checks if the permission perm is allowed as per incoming
610
* AccessControlContext/ProtectionDomain[]/isLimited/Permission[]
611
* while taking advantage cached
612
* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied
613
*
614
* @param perm the permission to be checked
615
* @param activeDC the DomainCombiner to be invoked
616
* @param accCurrent the current AccessControlContext to be checked
617
* @param debug debug flags
618
* @param pdsContext the current context to be checked
619
* @param isLimited the flag to indicate if there are limited permission(s)
620
* @param permsLimited the limited permission(s) to be checked
621
* @param accNext the next AccessControlContext to be checked
622
* @param cacheChecked the cached check result which is an array with following three elements:
623
* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied
624
*
625
* @return true if the access is granted by a limited permission, otherwise an exception is thrown or
626
* false is returned to indicate the access was NOT granted by any limited permission.
627
*/
628
static boolean checkPermissionWithCache(
629
Permission perm,
630
DomainCombiner activeDC,
631
Object[] pdsContext,
632
int debug,
633
AccessControlContext accCurrent,
634
boolean isLimited,
635
Permission[] permsLimited,
636
AccessControlContext accNext,
637
AccessCache cacheChecked
638
) throws AccessControlException {
639
if (((debug & DEBUG_ENABLED) != 0) && ((debugSetting() & DEBUG_ACCESS_DOMAIN) != 0)) {
640
debugPrintAccess();
641
if (pdsContext == null || pdsContext.length == 0) {
642
System.err.println("domain (context is null)"); //$NON-NLS-1$
643
} else {
644
for (int i = 0; i < pdsContext.length; ++i) {
645
System.err.println("domain " + i + " " + pdsContext[i]); //$NON-NLS-1$ //$NON-NLS-2$
646
}
647
}
648
}
649
if (null != pdsContext) {
650
int i = checkPermWithCachedPDsImplied(perm, pdsContext, cacheChecked);
651
if (0 <= i) {
652
// debug for access denied is not optional
653
if ((debug & DEBUG_ACCESS_DENIED) != 0) {
654
if ((debugSetting() & DEBUG_ACCESS) != 0) {
655
debugPrintAccess();
656
System.err.println("access denied " + perm); //$NON-NLS-1$
657
}
658
if ((debugSetting() & DEBUG_ACCESS_FAILURE) != 0) {
659
new Exception("Stack trace").printStackTrace(); //$NON-NLS-1$
660
System.err.println("domain that failed " + pdsContext[i]); //$NON-NLS-1$
661
}
662
}
663
/*[MSG "K002c", "Access denied {0}"]*/
664
throw new AccessControlException(com.ibm.oti.util.Msg.getString("K002c", perm), perm); //$NON-NLS-1$
665
}
666
}
667
if (null != accCurrent
668
&& (null != accCurrent.context || null != accCurrent.doPrivilegedAcc || null != accCurrent.limitedPerms || null != accCurrent.nextStackAcc)
669
) {
670
ProtectionDomain[] pdCombined;
671
if (activeDC == null) {
672
pdCombined = accCurrent.context;
673
} else {
674
pdCombined = activeDC.combine((ProtectionDomain[])pdsContext, accCurrent.context);
675
}
676
// accCurrent check either throwing a security exception (denied) or continue checking (the return value doesn't matter)
677
checkPermissionWithCache(perm, activeDC, pdCombined, debug, accCurrent.doPrivilegedAcc, accCurrent.isLimitedContext, accCurrent.limitedPerms, accCurrent.nextStackAcc, cacheChecked);
678
}
679
if (isLimited && null != permsLimited) {
680
if (checkPermWithCachedPermImplied(perm, permsLimited, cacheChecked)) {
681
return true; // implied by a limited permission
682
}
683
if (null != accNext) {
684
ProtectionDomain[] pdCombined;
685
if (activeDC == null) {
686
pdCombined = accNext.context;
687
} else {
688
pdCombined = activeDC.combine((ProtectionDomain[])pdsContext, accNext.context);
689
}
690
checkPermissionWithCache(perm, activeDC, pdCombined, debug, accNext.doPrivilegedAcc, accNext.isLimitedContext, accNext.limitedPerms, accNext.nextStackAcc, cacheChecked);
691
}
692
return false; // NOT implied by any limited permission
693
}
694
if ((debug & DEBUG_ENABLED) != 0) {
695
debugPrintAccess();
696
System.err.println("access allowed " + perm); //$NON-NLS-1$
697
}
698
return true;
699
}
700
701
/**
702
* Helper to print debug information for checkPermission().
703
*
704
* @param perm the permission to check
705
* @return if debugging is enabled
706
*/
707
private boolean debugHelper(Permission perm) {
708
boolean debug = true;
709
if (debugCodeBaseArray != null) {
710
debug = hasDebugCodeBase();
711
}
712
if (debug) {
713
debug = debugPermission(perm);
714
}
715
if (debug && ((debugSetting() & DEBUG_ACCESS_STACK) != 0)) {
716
new Exception("Stack trace for " + perm).printStackTrace(); //$NON-NLS-1$
717
}
718
return debug;
719
}
720
721
/**
722
* Checks if the permission <code>perm</code> is allowed in this context.
723
* All ProtectionDomains must grant the permission for it to be granted.
724
*
725
* @param perm java.security.Permission
726
* the permission to check
727
* @exception java.security.AccessControlException
728
* thrown when perm is not granted.
729
* @exception NullPointerException
730
* if perm is null
731
*/
732
public void checkPermission(Permission perm) throws AccessControlException {
733
if (perm == null) throw new NullPointerException();
734
if (null != context && (STATE_AUTHORIZED != authorizeState) && containPrivilegedContext && null != System.getSecurityManager()) {
735
// only check SecurityPermission "createAccessControlContext" when context is not null, not authorized and containPrivilegedContext.
736
if (STATE_UNKNOWN == authorizeState) {
737
if (null == callerPD || callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) {
738
authorizeState = STATE_AUTHORIZED;
739
} else {
740
authorizeState = STATE_NOT_AUTHORIZED;
741
}
742
callerPD = null;
743
}
744
if (STATE_NOT_AUTHORIZED == authorizeState) {
745
/*[MSG "K002d", "Access denied {0} due to untrusted AccessControlContext since {1} is denied"]*/
746
throw new AccessControlException(com.ibm.oti.util.Msg.getString("K002d", perm, SecurityConstants.CREATE_ACC_PERMISSION), perm); //$NON-NLS-1$
747
}
748
}
749
750
boolean debug = (debugSetting() & DEBUG_ACCESS) != 0;
751
if (debug) {
752
debug = debugHelper(perm);
753
}
754
checkPermissionWithCache(perm, null, this.context, debug ? DEBUG_ENABLED | DEBUG_ACCESS_DENIED : DEBUG_DISABLED, this.doPrivilegedAcc,this.isLimitedContext, this.limitedPerms, this.nextStackAcc, new AccessCache());
755
}
756
757
/**
758
* Helper method for equals() checks if the two arrays contain the same sets of objects or nulls.
759
* The order of the elements is not significant.
760
* If either of the given arrays is null it is treated as an empty array.
761
*
762
* @param s1 the first set
763
* @param s2 the second set
764
* @return true if the arrays have the same length and contain the same elements
765
*/
766
private static boolean equalSets(Object[] s1, Object[] s2) {
767
final int length;
768
769
if (s1 == null || (length = s1.length) == 0) {
770
// the first set is empty, the second must be empty as well
771
return s2 == null || s2.length == 0;
772
}
773
774
// the first set is not empty, the second must be the same size
775
if (s2 == null || length != s2.length) {
776
return false;
777
}
778
779
next: for (int i = 0; i < length; ++i) {
780
Object object = s1[i];
781
782
if (object == null) {
783
for (int j = 0; j < length; ++j) {
784
if (s2[j] == null) {
785
continue next;
786
}
787
}
788
} else {
789
for (int j = 0; j < length; ++j) {
790
if (object.equals(s2[j])) {
791
continue next;
792
}
793
}
794
}
795
796
// object was not found in the second set
797
return false;
798
}
799
800
return true;
801
}
802
803
/**
804
* Compares the argument to the receiver, and answers true
805
* if they represent the <em>same</em> object using a class
806
* specific comparison. In this case, they must both be
807
* AccessControlContexts and contain the same protection domains.
808
*
809
* @param o the object to compare with this object
810
* @return <code>true</code>
811
* if the object is the same as this object
812
* <code>false</code>
813
* if it is different from this object
814
* @see #hashCode
815
*/
816
@Override
817
public boolean equals(Object o) {
818
if (this == o) return true;
819
if (o == null || this.getClass() != o.getClass()) return false;
820
AccessControlContext otherContext = (AccessControlContext) o;
821
/*[PR RTC 66684] j.s.AccessControlContext fields isAuthorized/domainCombiner not used in method equals() & hashCode() */
822
// match RI behaviors, i.e., ignore isAuthorized when performing equals
823
if (null != this.domainCombiner) {
824
if (!this.domainCombiner.equals(otherContext.domainCombiner)) {
825
return false;
826
}
827
} else {
828
if (null != otherContext.domainCombiner) {
829
return false;
830
}
831
}
832
if (isLimitedContext != otherContext.isLimitedContext) {
833
return false;
834
}
835
if (!equalSets(context, otherContext.context)) {
836
return false;
837
}
838
if (null != doPrivilegedAcc && !doPrivilegedAcc.equals(otherContext.doPrivilegedAcc)) {
839
return false;
840
}
841
if (isLimitedContext) {
842
if (!equalSets(limitedPerms, otherContext.limitedPerms)) {
843
return false;
844
}
845
if (null != nextStackAcc) {
846
return nextStackAcc.equals(otherContext.nextStackAcc);
847
}
848
}
849
return true;
850
}
851
852
/**
853
* Answers an integer hash code for the receiver. Any two
854
* objects which answer <code>true</code> when passed to
855
* <code>equals</code> must answer the same value for this
856
* method.
857
*
858
* @return the receiver's hash
859
*
860
* @see #equals
861
*/
862
@Override
863
public int hashCode() {
864
int result = 0;
865
int i = context == null ? 0 : context.length;
866
while ((--i >= 0) && (context[i] != null)) {
867
result ^= context[i].hashCode();
868
}
869
870
// RI equals not impacted by limited context,
871
// JCK still passes with following cause the AccessControlContext in question doesn't have limited context
872
// J9 might fail JCK test if JCK hashcode test changes
873
874
if (null != doPrivilegedAcc) {
875
result ^= doPrivilegedAcc.hashCode();
876
}
877
// result = result + (this.isLimitedContext ? 1231 : 1237);
878
if (this.isLimitedContext) {
879
i = (limitedPerms == null) ? 0 : limitedPerms.length;
880
while (--i >= 0) {
881
if (null != limitedPerms[i]) {
882
result ^= limitedPerms[i].hashCode();
883
}
884
}
885
if (null != nextStackAcc) {
886
result ^= nextStackAcc.hashCode();
887
}
888
}
889
return result;
890
}
891
892
/**
893
* Answers the DomainCombiner for the receiver.
894
*
895
* @return the DomainCombiner or null
896
*
897
* @exception java.security.AccessControlException thrown
898
* when the caller doesn't have the "getDomainCombiner" SecurityPermission
899
*/
900
public DomainCombiner getDomainCombiner() {
901
@SuppressWarnings("removal")
902
SecurityManager security = System.getSecurityManager();
903
if (security != null)
904
security.checkPermission(SecurityConstants.GET_COMBINER_PERMISSION);
905
return domainCombiner;
906
}
907
908
/**
909
* Answers the DomainCombiner for the receiver.
910
* This is for internal use without checking "getDomainCombiner" SecurityPermission.
911
*
912
* @return the DomainCombiner or null
913
*
914
*/
915
DomainCombiner getCombiner() {
916
return domainCombiner;
917
}
918
919
/*
920
* Added to resolve: S6907662, CVE-2010-4465: System clipboard should ensure access restrictions
921
* Used internally:
922
* java.awt.AWTEvent
923
* java.awt.Component
924
* java.awt.EventQueue
925
* java.awt.MenuComponent
926
* java.awt.TrayIcon
927
* java.security.ProtectionDomain
928
* javax.swing.Timer
929
* javax.swing.TransferHandler
930
*/
931
ProtectionDomain[] getContext() {
932
return context;
933
}
934
935
/*
936
* Added to resolve: S6907662, CVE-2010-4465: System clipboard should ensure access restrictions
937
* Called internally from java.security.ProtectionDomain
938
*/
939
AccessControlContext(ProtectionDomain[] domains, AccessControlContext acc) {
940
this.context = AccessController.toArrayOfProtectionDomains(domains, acc, 0);
941
this.authorizeState = STATE_AUTHORIZED;
942
this.containPrivilegedContext = true;
943
if ((null != acc) && (STATE_AUTHORIZED == acc.authorizeState)) {
944
// inherit the domain combiner when authorized
945
this.domainCombiner = acc.domainCombiner;
946
}
947
}
948
949
/*
950
* Added to resolve: S6907662, CVE-2010-4465: System clipboard should ensure access restrictions
951
* Called internally from java.security.ProtectionDomain
952
*/
953
AccessControlContext optimize() {
954
return this;
955
}
956
957
}
958
959