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/javax/security/auth/PrivateCredentialPermission.java
38918 views
1
/*
2
* Copyright (c) 1999, 2013, 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 javax.security.auth;
27
28
import java.util.*;
29
import java.text.MessageFormat;
30
import java.security.Permission;
31
import java.security.PermissionCollection;
32
import java.security.Principal;
33
import sun.security.util.ResourcesMgr;
34
35
/**
36
* This class is used to protect access to private Credentials
37
* belonging to a particular {@code Subject}. The {@code Subject}
38
* is represented by a Set of Principals.
39
*
40
* <p> The target name of this {@code Permission} specifies
41
* a Credential class name, and a Set of Principals.
42
* The only valid value for this Permission's actions is, "read".
43
* The target name must abide by the following syntax:
44
*
45
* <pre>
46
* CredentialClass {PrincipalClass "PrincipalName"}*
47
* </pre>
48
*
49
* For example, the following permission grants access to the
50
* com.sun.PrivateCredential owned by Subjects which have
51
* a com.sun.Principal with the name, "duke". Note that although
52
* this example, as well as all the examples below, do not contain
53
* Codebase, SignedBy, or Principal information in the grant statement
54
* (for simplicity reasons), actual policy configurations should
55
* specify that information when appropriate.
56
*
57
* <pre>
58
*
59
* grant {
60
* permission javax.security.auth.PrivateCredentialPermission
61
* "com.sun.PrivateCredential com.sun.Principal \"duke\"",
62
* "read";
63
* };
64
* </pre>
65
*
66
* If CredentialClass is "*", then access is granted to
67
* all private Credentials belonging to the specified
68
* {@code Subject}.
69
* If "PrincipalName" is "*", then access is granted to the
70
* specified Credential owned by any {@code Subject} that has the
71
* specified {@code Principal} (the actual PrincipalName doesn't matter).
72
* For example, the following grants access to the
73
* a.b.Credential owned by any {@code Subject} that has
74
* an a.b.Principal.
75
*
76
* <pre>
77
* grant {
78
* permission javax.security.auth.PrivateCredentialPermission
79
* "a.b.Credential a.b.Principal "*"",
80
* "read";
81
* };
82
* </pre>
83
*
84
* If both the PrincipalClass and "PrincipalName" are "*",
85
* then access is granted to the specified Credential owned by
86
* any {@code Subject}.
87
*
88
* <p> In addition, the PrincipalClass/PrincipalName pairing may be repeated:
89
*
90
* <pre>
91
* grant {
92
* permission javax.security.auth.PrivateCredentialPermission
93
* "a.b.Credential a.b.Principal "duke" c.d.Principal "dukette"",
94
* "read";
95
* };
96
* </pre>
97
*
98
* The above grants access to the private Credential, "a.b.Credential",
99
* belonging to a {@code Subject} with at least two associated Principals:
100
* "a.b.Principal" with the name, "duke", and "c.d.Principal", with the name,
101
* "dukette".
102
*
103
*/
104
public final class PrivateCredentialPermission extends Permission {
105
106
private static final long serialVersionUID = 5284372143517237068L;
107
108
private static final CredOwner[] EMPTY_PRINCIPALS = new CredOwner[0];
109
110
/**
111
* @serial
112
*/
113
private String credentialClass;
114
115
/**
116
* @serial The Principals associated with this permission.
117
* The set contains elements of type,
118
* {@code PrivateCredentialPermission.CredOwner}.
119
*/
120
private Set<Principal> principals; // ignored - kept around for compatibility
121
private transient CredOwner[] credOwners;
122
123
/**
124
* @serial
125
*/
126
private boolean testing = false;
127
128
/**
129
* Create a new {@code PrivateCredentialPermission}
130
* with the specified {@code credentialClass} and Principals.
131
*/
132
PrivateCredentialPermission(String credentialClass,
133
Set<Principal> principals) {
134
135
super(credentialClass);
136
this.credentialClass = credentialClass;
137
138
synchronized(principals) {
139
if (principals.size() == 0) {
140
this.credOwners = EMPTY_PRINCIPALS;
141
} else {
142
this.credOwners = new CredOwner[principals.size()];
143
int index = 0;
144
Iterator<Principal> i = principals.iterator();
145
while (i.hasNext()) {
146
Principal p = i.next();
147
this.credOwners[index++] = new CredOwner
148
(p.getClass().getName(),
149
p.getName());
150
}
151
}
152
}
153
}
154
155
/**
156
* Creates a new {@code PrivateCredentialPermission}
157
* with the specified {@code name}. The {@code name}
158
* specifies both a Credential class and a {@code Principal} Set.
159
*
160
* <p>
161
*
162
* @param name the name specifying the Credential class and
163
* {@code Principal} Set. <p>
164
*
165
* @param actions the actions specifying that the Credential can be read.
166
*
167
* @throws IllegalArgumentException if {@code name} does not conform
168
* to the correct syntax or if {@code actions} is not "read".
169
*/
170
public PrivateCredentialPermission(String name, String actions) {
171
super(name);
172
173
if (!"read".equalsIgnoreCase(actions))
174
throw new IllegalArgumentException
175
(ResourcesMgr.getString("actions.can.only.be.read."));
176
init(name);
177
}
178
179
/**
180
* Returns the Class name of the Credential associated with this
181
* {@code PrivateCredentialPermission}.
182
*
183
* <p>
184
*
185
* @return the Class name of the Credential associated with this
186
* {@code PrivateCredentialPermission}.
187
*/
188
public String getCredentialClass() {
189
return credentialClass;
190
}
191
192
/**
193
* Returns the {@code Principal} classes and names
194
* associated with this {@code PrivateCredentialPermission}.
195
* The information is returned as a two-dimensional array (array[x][y]).
196
* The 'x' value corresponds to the number of {@code Principal}
197
* class and name pairs. When (y==0), it corresponds to
198
* the {@code Principal} class value, and when (y==1),
199
* it corresponds to the {@code Principal} name value.
200
* For example, array[0][0] corresponds to the class name of
201
* the first {@code Principal} in the array. array[0][1]
202
* corresponds to the {@code Principal} name of the
203
* first {@code Principal} in the array.
204
*
205
* <p>
206
*
207
* @return the {@code Principal} class and names associated
208
* with this {@code PrivateCredentialPermission}.
209
*/
210
public String[][] getPrincipals() {
211
212
if (credOwners == null || credOwners.length == 0) {
213
return new String[0][0];
214
}
215
216
String[][] pArray = new String[credOwners.length][2];
217
for (int i = 0; i < credOwners.length; i++) {
218
pArray[i][0] = credOwners[i].principalClass;
219
pArray[i][1] = credOwners[i].principalName;
220
}
221
return pArray;
222
}
223
224
/**
225
* Checks if this {@code PrivateCredentialPermission} implies
226
* the specified {@code Permission}.
227
*
228
* <p>
229
*
230
* This method returns true if:
231
* <ul>
232
* <li> <i>p</i> is an instanceof PrivateCredentialPermission and
233
* <li> the target name for <i>p</i> is implied by this object's
234
* target name. For example:
235
* <pre>
236
* [* P1 "duke"] implies [a.b.Credential P1 "duke"].
237
* [C1 P1 "duke"] implies [C1 P1 "duke" P2 "dukette"].
238
* [C1 P2 "dukette"] implies [C1 P1 "duke" P2 "dukette"].
239
* </pre>
240
* </ul>
241
*
242
* <p>
243
*
244
* @param p the {@code Permission} to check against.
245
*
246
* @return true if this {@code PrivateCredentialPermission} implies
247
* the specified {@code Permission}, false if not.
248
*/
249
public boolean implies(Permission p) {
250
251
if (p == null || !(p instanceof PrivateCredentialPermission))
252
return false;
253
254
PrivateCredentialPermission that = (PrivateCredentialPermission)p;
255
256
if (!impliesCredentialClass(credentialClass, that.credentialClass))
257
return false;
258
259
return impliesPrincipalSet(credOwners, that.credOwners);
260
}
261
262
/**
263
* Checks two {@code PrivateCredentialPermission} objects for
264
* equality. Checks that <i>obj</i> is a
265
* {@code PrivateCredentialPermission},
266
* and has the same credential class as this object,
267
* as well as the same Principals as this object.
268
* The order of the Principals in the respective Permission's
269
* target names is not relevant.
270
*
271
* <p>
272
*
273
* @param obj the object we are testing for equality with this object.
274
*
275
* @return true if obj is a {@code PrivateCredentialPermission},
276
* has the same credential class as this object,
277
* and has the same Principals as this object.
278
*/
279
public boolean equals(Object obj) {
280
if (obj == this)
281
return true;
282
283
if (! (obj instanceof PrivateCredentialPermission))
284
return false;
285
286
PrivateCredentialPermission that = (PrivateCredentialPermission)obj;
287
288
return (this.implies(that) && that.implies(this));
289
}
290
291
/**
292
* Returns the hash code value for this object.
293
*
294
* @return a hash code value for this object.
295
*/
296
public int hashCode() {
297
return this.credentialClass.hashCode();
298
}
299
300
/**
301
* Returns the "canonical string representation" of the actions.
302
* This method always returns the String, "read".
303
*
304
* <p>
305
*
306
* @return the actions (always returns "read").
307
*/
308
public String getActions() {
309
return "read";
310
}
311
312
/**
313
* Return a homogeneous collection of PrivateCredentialPermissions
314
* in a {@code PermissionCollection}.
315
* No such {@code PermissionCollection} is defined,
316
* so this method always returns {@code null}.
317
*
318
* <p>
319
*
320
* @return null in all cases.
321
*/
322
public PermissionCollection newPermissionCollection() {
323
return null;
324
}
325
326
private void init(String name) {
327
328
if (name == null || name.trim().length() == 0) {
329
throw new IllegalArgumentException("invalid empty name");
330
}
331
332
ArrayList<CredOwner> pList = new ArrayList<>();
333
StringTokenizer tokenizer = new StringTokenizer(name, " ", true);
334
String principalClass = null;
335
String principalName = null;
336
337
if (testing)
338
System.out.println("whole name = " + name);
339
340
// get the Credential Class
341
credentialClass = tokenizer.nextToken();
342
if (testing)
343
System.out.println("Credential Class = " + credentialClass);
344
345
if (tokenizer.hasMoreTokens() == false) {
346
MessageFormat form = new MessageFormat(ResourcesMgr.getString
347
("permission.name.name.syntax.invalid."));
348
Object[] source = {name};
349
throw new IllegalArgumentException
350
(form.format(source) + ResourcesMgr.getString
351
("Credential.Class.not.followed.by.a.Principal.Class.and.Name"));
352
}
353
354
while (tokenizer.hasMoreTokens()) {
355
356
// skip delimiter
357
tokenizer.nextToken();
358
359
// get the Principal Class
360
principalClass = tokenizer.nextToken();
361
if (testing)
362
System.out.println(" Principal Class = " + principalClass);
363
364
if (tokenizer.hasMoreTokens() == false) {
365
MessageFormat form = new MessageFormat(ResourcesMgr.getString
366
("permission.name.name.syntax.invalid."));
367
Object[] source = {name};
368
throw new IllegalArgumentException
369
(form.format(source) + ResourcesMgr.getString
370
("Principal.Class.not.followed.by.a.Principal.Name"));
371
}
372
373
// skip delimiter
374
tokenizer.nextToken();
375
376
// get the Principal Name
377
principalName = tokenizer.nextToken();
378
379
if (!principalName.startsWith("\"")) {
380
MessageFormat form = new MessageFormat(ResourcesMgr.getString
381
("permission.name.name.syntax.invalid."));
382
Object[] source = {name};
383
throw new IllegalArgumentException
384
(form.format(source) + ResourcesMgr.getString
385
("Principal.Name.must.be.surrounded.by.quotes"));
386
}
387
388
if (!principalName.endsWith("\"")) {
389
390
// we have a name with spaces in it --
391
// keep parsing until we find the end quote,
392
// and keep the spaces in the name
393
394
while (tokenizer.hasMoreTokens()) {
395
principalName = principalName + tokenizer.nextToken();
396
if (principalName.endsWith("\""))
397
break;
398
}
399
400
if (!principalName.endsWith("\"")) {
401
MessageFormat form = new MessageFormat
402
(ResourcesMgr.getString
403
("permission.name.name.syntax.invalid."));
404
Object[] source = {name};
405
throw new IllegalArgumentException
406
(form.format(source) + ResourcesMgr.getString
407
("Principal.Name.missing.end.quote"));
408
}
409
}
410
411
if (testing)
412
System.out.println("\tprincipalName = '" + principalName + "'");
413
414
principalName = principalName.substring
415
(1, principalName.length() - 1);
416
417
if (principalClass.equals("*") &&
418
!principalName.equals("*")) {
419
throw new IllegalArgumentException(ResourcesMgr.getString
420
("PrivateCredentialPermission.Principal.Class.can.not.be.a.wildcard.value.if.Principal.Name.is.not.a.wildcard.value"));
421
}
422
423
if (testing)
424
System.out.println("\tprincipalName = '" + principalName + "'");
425
426
pList.add(new CredOwner(principalClass, principalName));
427
}
428
429
this.credOwners = new CredOwner[pList.size()];
430
pList.toArray(this.credOwners);
431
}
432
433
private boolean impliesCredentialClass(String thisC, String thatC) {
434
435
// this should never happen
436
if (thisC == null || thatC == null)
437
return false;
438
439
if (testing)
440
System.out.println("credential class comparison: " +
441
thisC + "/" + thatC);
442
443
if (thisC.equals("*"))
444
return true;
445
446
/**
447
* XXX let's not enable this for now --
448
* if people want it, we'll enable it later
449
*/
450
/*
451
if (thisC.endsWith("*")) {
452
String cClass = thisC.substring(0, thisC.length() - 2);
453
return thatC.startsWith(cClass);
454
}
455
*/
456
457
return thisC.equals(thatC);
458
}
459
460
private boolean impliesPrincipalSet(CredOwner[] thisP, CredOwner[] thatP) {
461
462
// this should never happen
463
if (thisP == null || thatP == null)
464
return false;
465
466
if (thatP.length == 0)
467
return true;
468
469
if (thisP.length == 0)
470
return false;
471
472
for (int i = 0; i < thisP.length; i++) {
473
boolean foundMatch = false;
474
for (int j = 0; j < thatP.length; j++) {
475
if (thisP[i].implies(thatP[j])) {
476
foundMatch = true;
477
break;
478
}
479
}
480
if (!foundMatch) {
481
return false;
482
}
483
}
484
return true;
485
}
486
487
/**
488
* Reads this object from a stream (i.e., deserializes it)
489
*/
490
private void readObject(java.io.ObjectInputStream s) throws
491
java.io.IOException,
492
ClassNotFoundException {
493
494
s.defaultReadObject();
495
496
// perform new initialization from the permission name
497
498
if (getName().indexOf(" ") == -1 && getName().indexOf("\"") == -1) {
499
500
// name only has a credential class specified
501
credentialClass = getName();
502
credOwners = EMPTY_PRINCIPALS;
503
504
} else {
505
506
// perform regular initialization
507
init(getName());
508
}
509
}
510
511
/**
512
* @serial include
513
*/
514
static class CredOwner implements java.io.Serializable {
515
516
private static final long serialVersionUID = -5607449830436408266L;
517
518
/**
519
* @serial
520
*/
521
String principalClass;
522
/**
523
* @serial
524
*/
525
String principalName;
526
527
CredOwner(String principalClass, String principalName) {
528
this.principalClass = principalClass;
529
this.principalName = principalName;
530
}
531
532
public boolean implies(Object obj) {
533
if (obj == null || !(obj instanceof CredOwner))
534
return false;
535
536
CredOwner that = (CredOwner)obj;
537
538
if (principalClass.equals("*") ||
539
principalClass.equals(that.principalClass)) {
540
541
if (principalName.equals("*") ||
542
principalName.equals(that.principalName)) {
543
return true;
544
}
545
}
546
547
/**
548
* XXX no code yet to support a.b.*
549
*/
550
551
return false;
552
}
553
554
public String toString() {
555
MessageFormat form = new MessageFormat(ResourcesMgr.getString
556
("CredOwner.Principal.Class.class.Principal.Name.name"));
557
Object[] source = {principalClass, principalName};
558
return (form.format(source));
559
}
560
}
561
}
562
563