Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/javax/security/auth/Subject.java
41159 views
1
/*
2
* Copyright (c) 1998, 2021, 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.io.*;
30
import java.lang.reflect.*;
31
import java.text.MessageFormat;
32
import java.security.AccessController;
33
import java.security.AccessControlContext;
34
import java.security.DomainCombiner;
35
import java.security.Permission;
36
import java.security.PermissionCollection;
37
import java.security.Principal;
38
import java.security.PrivilegedAction;
39
import java.security.PrivilegedExceptionAction;
40
import java.security.PrivilegedActionException;
41
import java.security.ProtectionDomain;
42
import sun.security.util.ResourcesMgr;
43
44
/**
45
* <p> A {@code Subject} represents a grouping of related information
46
* for a single entity, such as a person.
47
* Such information includes the Subject's identities as well as
48
* its security-related attributes
49
* (passwords and cryptographic keys, for example).
50
*
51
* <p> Subjects may potentially have multiple identities.
52
* Each identity is represented as a {@code Principal}
53
* within the {@code Subject}. Principals simply bind names to a
54
* {@code Subject}. For example, a {@code Subject} that happens
55
* to be a person, Alice, might have two Principals:
56
* one which binds "Alice Bar", the name on her driver license,
57
* to the {@code Subject}, and another which binds,
58
* "999-99-9999", the number on her student identification card,
59
* to the {@code Subject}. Both Principals refer to the same
60
* {@code Subject} even though each has a different name.
61
*
62
* <p> A {@code Subject} may also own security-related attributes,
63
* which are referred to as credentials.
64
* Sensitive credentials that require special protection, such as
65
* private cryptographic keys, are stored within a private credential
66
* {@code Set}. Credentials intended to be shared, such as
67
* public key certificates or Kerberos server tickets are stored
68
* within a public credential {@code Set}. Different permissions
69
* are required to access and modify the different credential Sets.
70
*
71
* <p> To retrieve all the Principals associated with a {@code Subject},
72
* invoke the {@code getPrincipals} method. To retrieve
73
* all the public or private credentials belonging to a {@code Subject},
74
* invoke the {@code getPublicCredentials} method or
75
* {@code getPrivateCredentials} method, respectively.
76
* To modify the returned {@code Set} of Principals and credentials,
77
* use the methods defined in the {@code Set} class.
78
* For example:
79
* <pre>
80
* Subject subject;
81
* Principal principal;
82
* Object credential;
83
*
84
* // add a Principal and credential to the Subject
85
* subject.getPrincipals().add(principal);
86
* subject.getPublicCredentials().add(credential);
87
* </pre>
88
*
89
* <p> This {@code Subject} class implements {@code Serializable}.
90
* While the Principals associated with the {@code Subject} are serialized,
91
* the credentials associated with the {@code Subject} are not.
92
* Note that the {@code java.security.Principal} class
93
* does not implement {@code Serializable}. Therefore all concrete
94
* {@code Principal} implementations associated with Subjects
95
* must implement {@code Serializable}.
96
*
97
* @since 1.4
98
* @see java.security.Principal
99
* @see java.security.DomainCombiner
100
*/
101
public final class Subject implements java.io.Serializable {
102
103
@java.io.Serial
104
private static final long serialVersionUID = -8308522755600156056L;
105
106
/**
107
* A {@code Set} that provides a view of all of this
108
* Subject's Principals
109
*
110
* @serial Each element in this set is a
111
* {@code java.security.Principal}.
112
* The set is a {@code Subject.SecureSet}.
113
*/
114
@SuppressWarnings("serial") // Not statically typed as Serializable
115
Set<Principal> principals;
116
117
/**
118
* Sets that provide a view of all of this
119
* Subject's Credentials
120
*/
121
transient Set<Object> pubCredentials;
122
transient Set<Object> privCredentials;
123
124
/**
125
* Whether this Subject is read-only
126
*
127
* @serial
128
*/
129
private volatile boolean readOnly;
130
131
private static final int PRINCIPAL_SET = 1;
132
private static final int PUB_CREDENTIAL_SET = 2;
133
private static final int PRIV_CREDENTIAL_SET = 3;
134
135
private static final ProtectionDomain[] NULL_PD_ARRAY
136
= new ProtectionDomain[0];
137
138
/**
139
* Create an instance of a {@code Subject}
140
* with an empty {@code Set} of Principals and empty
141
* Sets of public and private credentials.
142
*
143
* <p> The newly constructed Sets check whether this {@code Subject}
144
* has been set read-only before permitting subsequent modifications.
145
* The newly created Sets also prevent illegal modifications
146
* by ensuring that callers have sufficient permissions. These Sets
147
* also prohibit null elements, and attempts to add or query a null
148
* element will result in a {@code NullPointerException}.
149
*
150
* <p> To modify the Principals Set, the caller must have
151
* {@code AuthPermission("modifyPrincipals")}.
152
* To modify the public credential Set, the caller must have
153
* {@code AuthPermission("modifyPublicCredentials")}.
154
* To modify the private credential Set, the caller must have
155
* {@code AuthPermission("modifyPrivateCredentials")}.
156
*/
157
public Subject() {
158
159
this.principals = Collections.synchronizedSet
160
(new SecureSet<>(this, PRINCIPAL_SET));
161
this.pubCredentials = Collections.synchronizedSet
162
(new SecureSet<>(this, PUB_CREDENTIAL_SET));
163
this.privCredentials = Collections.synchronizedSet
164
(new SecureSet<>(this, PRIV_CREDENTIAL_SET));
165
}
166
167
/**
168
* Create an instance of a {@code Subject} with
169
* Principals and credentials.
170
*
171
* <p> The Principals and credentials from the specified Sets
172
* are copied into newly constructed Sets.
173
* These newly created Sets check whether this {@code Subject}
174
* has been set read-only before permitting subsequent modifications.
175
* The newly created Sets also prevent illegal modifications
176
* by ensuring that callers have sufficient permissions. These Sets
177
* also prohibit null elements, and attempts to add or query a null
178
* element will result in a {@code NullPointerException}.
179
*
180
* <p> To modify the Principals Set, the caller must have
181
* {@code AuthPermission("modifyPrincipals")}.
182
* To modify the public credential Set, the caller must have
183
* {@code AuthPermission("modifyPublicCredentials")}.
184
* To modify the private credential Set, the caller must have
185
* {@code AuthPermission("modifyPrivateCredentials")}.
186
*
187
* @param readOnly true if the {@code Subject} is to be read-only,
188
* and false otherwise.
189
*
190
* @param principals the {@code Set} of Principals
191
* to be associated with this {@code Subject}.
192
*
193
* @param pubCredentials the {@code Set} of public credentials
194
* to be associated with this {@code Subject}.
195
*
196
* @param privCredentials the {@code Set} of private credentials
197
* to be associated with this {@code Subject}.
198
*
199
* @throws NullPointerException if the specified
200
* {@code principals}, {@code pubCredentials},
201
* or {@code privCredentials} are {@code null},
202
* or a null value exists within any of these three
203
* Sets.
204
*/
205
public Subject(boolean readOnly, Set<? extends Principal> principals,
206
Set<?> pubCredentials, Set<?> privCredentials) {
207
LinkedList<Principal> principalList
208
= collectionNullClean(principals);
209
LinkedList<Object> pubCredsList
210
= collectionNullClean(pubCredentials);
211
LinkedList<Object> privCredsList
212
= collectionNullClean(privCredentials);
213
214
this.principals = Collections.synchronizedSet(
215
new SecureSet<>(this, PRINCIPAL_SET, principalList));
216
this.pubCredentials = Collections.synchronizedSet(
217
new SecureSet<>(this, PUB_CREDENTIAL_SET, pubCredsList));
218
this.privCredentials = Collections.synchronizedSet(
219
new SecureSet<>(this, PRIV_CREDENTIAL_SET, privCredsList));
220
this.readOnly = readOnly;
221
}
222
223
/**
224
* Set this {@code Subject} to be read-only.
225
*
226
* <p> Modifications (additions and removals) to this Subject's
227
* {@code Principal} {@code Set} and
228
* credential Sets will be disallowed.
229
* The {@code destroy} operation on this Subject's credentials will
230
* still be permitted.
231
*
232
* <p> Subsequent attempts to modify the Subject's {@code Principal}
233
* and credential Sets will result in an
234
* {@code IllegalStateException} being thrown.
235
* Also, once a {@code Subject} is read-only,
236
* it can not be reset to being writable again.
237
*
238
* @throws SecurityException if a security manager is installed and the
239
* caller does not have an
240
* {@link AuthPermission#AuthPermission(String)
241
* AuthPermission("setReadOnly")} permission to set this
242
* {@code Subject} to be read-only.
243
*/
244
public void setReadOnly() {
245
@SuppressWarnings("removal")
246
java.lang.SecurityManager sm = System.getSecurityManager();
247
if (sm != null) {
248
sm.checkPermission(AuthPermissionHolder.SET_READ_ONLY_PERMISSION);
249
}
250
251
this.readOnly = true;
252
}
253
254
/**
255
* Query whether this {@code Subject} is read-only.
256
*
257
* @return true if this {@code Subject} is read-only, false otherwise.
258
*/
259
public boolean isReadOnly() {
260
return this.readOnly;
261
}
262
263
/**
264
* Get the {@code Subject} associated with the provided
265
* {@code AccessControlContext}.
266
*
267
* <p> The {@code AccessControlContext} may contain many
268
* Subjects (from nested {@code doAs} calls).
269
* In this situation, the most recent {@code Subject} associated
270
* with the {@code AccessControlContext} is returned.
271
*
272
* @param acc the {@code AccessControlContext} from which to retrieve
273
* the {@code Subject}.
274
*
275
* @return the {@code Subject} associated with the provided
276
* {@code AccessControlContext}, or {@code null}
277
* if no {@code Subject} is associated
278
* with the provided {@code AccessControlContext}.
279
*
280
* @throws SecurityException if a security manager is installed and the
281
* caller does not have an
282
* {@link AuthPermission#AuthPermission(String)
283
* AuthPermission("getSubject")} permission to get the
284
* {@code Subject}.
285
*
286
* @throws NullPointerException if the provided
287
* {@code AccessControlContext} is {@code null}.
288
*
289
* @deprecated This method depends on {@link AccessControlContext}
290
* which, in conjunction with
291
* {@linkplain SecurityManager the Security Manager}, is deprecated
292
* and subject to removal in a future release. However, obtaining a
293
* Subject is useful independent of the Security Manager, so a
294
* replacement for this method may be added in a future release.
295
*/
296
@SuppressWarnings("removal")
297
@Deprecated(since="17", forRemoval=true)
298
public static Subject getSubject(final AccessControlContext acc) {
299
300
java.lang.SecurityManager sm = System.getSecurityManager();
301
if (sm != null) {
302
sm.checkPermission(AuthPermissionHolder.GET_SUBJECT_PERMISSION);
303
}
304
305
Objects.requireNonNull(acc, ResourcesMgr.getString
306
("invalid.null.AccessControlContext.provided"));
307
308
// return the Subject from the DomainCombiner of the provided context
309
return AccessController.doPrivileged
310
(new java.security.PrivilegedAction<>() {
311
public Subject run() {
312
DomainCombiner dc = acc.getDomainCombiner();
313
if (!(dc instanceof SubjectDomainCombiner)) {
314
return null;
315
}
316
SubjectDomainCombiner sdc = (SubjectDomainCombiner)dc;
317
return sdc.getSubject();
318
}
319
});
320
}
321
322
/**
323
* Perform work as a particular {@code Subject}.
324
*
325
* <p> This method first retrieves the current Thread's
326
* {@code AccessControlContext} via
327
* {@code AccessController.getContext},
328
* and then instantiates a new {@code AccessControlContext}
329
* using the retrieved context along with a new
330
* {@code SubjectDomainCombiner} (constructed using
331
* the provided {@code Subject}).
332
* Finally, this method invokes {@code AccessController.doPrivileged},
333
* passing it the provided {@code PrivilegedAction},
334
* as well as the newly constructed {@code AccessControlContext}.
335
*
336
* @param subject the {@code Subject} that the specified
337
* {@code action} will run as. This parameter
338
* may be {@code null}.
339
*
340
* @param <T> the type of the value returned by the PrivilegedAction's
341
* {@code run} method.
342
*
343
* @param action the code to be run as the specified
344
* {@code Subject}.
345
*
346
* @return the value returned by the PrivilegedAction's
347
* {@code run} method.
348
*
349
* @throws NullPointerException if the {@code PrivilegedAction}
350
* is {@code null}.
351
*
352
* @throws SecurityException if a security manager is installed and the
353
* caller does not have an
354
* {@link AuthPermission#AuthPermission(String)
355
* AuthPermission("doAs")} permission to invoke this
356
* method.
357
*/
358
@SuppressWarnings("removal")
359
public static <T> T doAs(final Subject subject,
360
final java.security.PrivilegedAction<T> action) {
361
362
java.lang.SecurityManager sm = System.getSecurityManager();
363
if (sm != null) {
364
sm.checkPermission(AuthPermissionHolder.DO_AS_PERMISSION);
365
}
366
367
Objects.requireNonNull(action,
368
ResourcesMgr.getString("invalid.null.action.provided"));
369
370
// set up the new Subject-based AccessControlContext
371
// for doPrivileged
372
final AccessControlContext currentAcc = AccessController.getContext();
373
374
// call doPrivileged and push this new context on the stack
375
return java.security.AccessController.doPrivileged
376
(action,
377
createContext(subject, currentAcc));
378
}
379
380
/**
381
* Perform work as a particular {@code Subject}.
382
*
383
* <p> This method first retrieves the current Thread's
384
* {@code AccessControlContext} via
385
* {@code AccessController.getContext},
386
* and then instantiates a new {@code AccessControlContext}
387
* using the retrieved context along with a new
388
* {@code SubjectDomainCombiner} (constructed using
389
* the provided {@code Subject}).
390
* Finally, this method invokes {@code AccessController.doPrivileged},
391
* passing it the provided {@code PrivilegedExceptionAction},
392
* as well as the newly constructed {@code AccessControlContext}.
393
*
394
* @param subject the {@code Subject} that the specified
395
* {@code action} will run as. This parameter
396
* may be {@code null}.
397
*
398
* @param <T> the type of the value returned by the
399
* PrivilegedExceptionAction's {@code run} method.
400
*
401
* @param action the code to be run as the specified
402
* {@code Subject}.
403
*
404
* @return the value returned by the
405
* PrivilegedExceptionAction's {@code run} method.
406
*
407
* @throws PrivilegedActionException if the
408
* {@code PrivilegedExceptionAction.run}
409
* method throws a checked exception.
410
*
411
* @throws NullPointerException if the specified
412
* {@code PrivilegedExceptionAction} is
413
* {@code null}.
414
*
415
* @throws SecurityException if a security manager is installed and the
416
* caller does not have an
417
* {@link AuthPermission#AuthPermission(String)
418
* AuthPermission("doAs")} permission to invoke this
419
* method.
420
*/
421
@SuppressWarnings("removal")
422
public static <T> T doAs(final Subject subject,
423
final java.security.PrivilegedExceptionAction<T> action)
424
throws java.security.PrivilegedActionException {
425
426
java.lang.SecurityManager sm = System.getSecurityManager();
427
if (sm != null) {
428
sm.checkPermission(AuthPermissionHolder.DO_AS_PERMISSION);
429
}
430
431
Objects.requireNonNull(action,
432
ResourcesMgr.getString("invalid.null.action.provided"));
433
434
// set up the new Subject-based AccessControlContext for doPrivileged
435
final AccessControlContext currentAcc = AccessController.getContext();
436
437
// call doPrivileged and push this new context on the stack
438
return java.security.AccessController.doPrivileged
439
(action,
440
createContext(subject, currentAcc));
441
}
442
443
/**
444
* Perform privileged work as a particular {@code Subject}.
445
*
446
* <p> This method behaves exactly as {@code Subject.doAs},
447
* except that instead of retrieving the current Thread's
448
* {@code AccessControlContext}, it uses the provided
449
* {@code AccessControlContext}. If the provided
450
* {@code AccessControlContext} is {@code null},
451
* this method instantiates a new {@code AccessControlContext}
452
* with an empty collection of ProtectionDomains.
453
*
454
* @param subject the {@code Subject} that the specified
455
* {@code action} will run as. This parameter
456
* may be {@code null}.
457
*
458
* @param <T> the type of the value returned by the PrivilegedAction's
459
* {@code run} method.
460
*
461
* @param action the code to be run as the specified
462
* {@code Subject}.
463
*
464
* @param acc the {@code AccessControlContext} to be tied to the
465
* specified <i>subject</i> and <i>action</i>.
466
*
467
* @return the value returned by the PrivilegedAction's
468
* {@code run} method.
469
*
470
* @throws NullPointerException if the {@code PrivilegedAction}
471
* is {@code null}.
472
*
473
* @throws SecurityException if a security manager is installed and the
474
* caller does not have a
475
* {@link AuthPermission#AuthPermission(String)
476
* AuthPermission("doAsPrivileged")} permission to invoke
477
* this method.
478
*
479
* @deprecated This method is only useful in conjunction with
480
* {@linkplain SecurityManager the Security Manager}, which is
481
* deprecated and subject to removal in a future release.
482
* Consequently, this method is also deprecated and subject to
483
* removal. There is no replacement for the Security Manager or this
484
* method.
485
*/
486
@SuppressWarnings("removal")
487
@Deprecated(since="17", forRemoval=true)
488
public static <T> T doAsPrivileged(final Subject subject,
489
final java.security.PrivilegedAction<T> action,
490
final java.security.AccessControlContext acc) {
491
492
java.lang.SecurityManager sm = System.getSecurityManager();
493
if (sm != null) {
494
sm.checkPermission(AuthPermissionHolder.DO_AS_PRIVILEGED_PERMISSION);
495
}
496
497
Objects.requireNonNull(action,
498
ResourcesMgr.getString("invalid.null.action.provided"));
499
500
// set up the new Subject-based AccessControlContext
501
// for doPrivileged
502
final AccessControlContext callerAcc =
503
(acc == null ?
504
new AccessControlContext(NULL_PD_ARRAY) :
505
acc);
506
507
// call doPrivileged and push this new context on the stack
508
return java.security.AccessController.doPrivileged
509
(action,
510
createContext(subject, callerAcc));
511
}
512
513
/**
514
* Perform privileged work as a particular {@code Subject}.
515
*
516
* <p> This method behaves exactly as {@code Subject.doAs},
517
* except that instead of retrieving the current Thread's
518
* {@code AccessControlContext}, it uses the provided
519
* {@code AccessControlContext}. If the provided
520
* {@code AccessControlContext} is {@code null},
521
* this method instantiates a new {@code AccessControlContext}
522
* with an empty collection of ProtectionDomains.
523
*
524
* @param subject the {@code Subject} that the specified
525
* {@code action} will run as. This parameter
526
* may be {@code null}.
527
*
528
* @param <T> the type of the value returned by the
529
* PrivilegedExceptionAction's {@code run} method.
530
*
531
* @param action the code to be run as the specified
532
* {@code Subject}.
533
*
534
* @param acc the {@code AccessControlContext} to be tied to the
535
* specified <i>subject</i> and <i>action</i>.
536
*
537
* @return the value returned by the
538
* PrivilegedExceptionAction's {@code run} method.
539
*
540
* @throws PrivilegedActionException if the
541
* {@code PrivilegedExceptionAction.run}
542
* method throws a checked exception.
543
*
544
* @throws NullPointerException if the specified
545
* {@code PrivilegedExceptionAction} is
546
* {@code null}.
547
*
548
* @throws SecurityException if a security manager is installed and the
549
* caller does not have a
550
* {@link AuthPermission#AuthPermission(String)
551
* AuthPermission("doAsPrivileged")} permission to invoke
552
* this method.
553
*
554
* @deprecated This method is only useful in conjunction with
555
* {@linkplain SecurityManager the Security Manager}, which is
556
* deprecated and subject to removal in a future release.
557
* Consequently, this method is also deprecated and subject to
558
* removal. There is no replacement for the Security Manager or this
559
* method.
560
*/
561
@SuppressWarnings("removal")
562
@Deprecated(since="17", forRemoval=true)
563
public static <T> T doAsPrivileged(final Subject subject,
564
final java.security.PrivilegedExceptionAction<T> action,
565
final java.security.AccessControlContext acc)
566
throws java.security.PrivilegedActionException {
567
568
java.lang.SecurityManager sm = System.getSecurityManager();
569
if (sm != null) {
570
sm.checkPermission(AuthPermissionHolder.DO_AS_PRIVILEGED_PERMISSION);
571
}
572
573
Objects.requireNonNull(action,
574
ResourcesMgr.getString("invalid.null.action.provided"));
575
576
// set up the new Subject-based AccessControlContext for doPrivileged
577
final AccessControlContext callerAcc =
578
(acc == null ?
579
new AccessControlContext(NULL_PD_ARRAY) :
580
acc);
581
582
// call doPrivileged and push this new context on the stack
583
return java.security.AccessController.doPrivileged
584
(action,
585
createContext(subject, callerAcc));
586
}
587
588
@SuppressWarnings("removal")
589
private static AccessControlContext createContext(final Subject subject,
590
final AccessControlContext acc) {
591
592
593
return java.security.AccessController.doPrivileged
594
(new java.security.PrivilegedAction<>() {
595
public AccessControlContext run() {
596
if (subject == null) {
597
return new AccessControlContext(acc, null);
598
} else {
599
return new AccessControlContext
600
(acc,
601
new SubjectDomainCombiner(subject));
602
}
603
}
604
});
605
}
606
607
/**
608
* Return the {@code Set} of Principals associated with this
609
* {@code Subject}. Each {@code Principal} represents
610
* an identity for this {@code Subject}.
611
*
612
* <p> The returned {@code Set} is backed by this Subject's
613
* internal {@code Principal} {@code Set}. Any modification
614
* to the returned {@code Set} affects the internal
615
* {@code Principal} {@code Set} as well.
616
*
617
* <p> If a security manager is installed, the caller must have a
618
* {@link AuthPermission#AuthPermission(String)
619
* AuthPermission("modifyPrincipals")} permission to modify
620
* the returned set, or a {@code SecurityException} will be thrown.
621
*
622
* @return the {@code Set} of Principals associated with this
623
* {@code Subject}.
624
*/
625
public Set<Principal> getPrincipals() {
626
627
// always return an empty Set instead of null
628
// so LoginModules can add to the Set if necessary
629
return principals;
630
}
631
632
/**
633
* Return a {@code Set} of Principals associated with this
634
* {@code Subject} that are instances or subclasses of the specified
635
* {@code Class}.
636
*
637
* <p> The returned {@code Set} is not backed by this Subject's
638
* internal {@code Principal} {@code Set}. A new
639
* {@code Set} is created and returned for each method invocation.
640
* Modifications to the returned {@code Set}
641
* will not affect the internal {@code Principal} {@code Set}.
642
*
643
* @param <T> the type of the class modeled by {@code c}
644
*
645
* @param c the returned {@code Set} of Principals will all be
646
* instances of this class.
647
*
648
* @return a {@code Set} of Principals that are instances of the
649
* specified {@code Class}.
650
*
651
* @throws NullPointerException if the specified {@code Class}
652
* is {@code null}.
653
*/
654
public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
655
656
Objects.requireNonNull(c,
657
ResourcesMgr.getString("invalid.null.Class.provided"));
658
659
// always return an empty Set instead of null
660
// so LoginModules can add to the Set if necessary
661
return new ClassSet<T>(PRINCIPAL_SET, c);
662
}
663
664
/**
665
* Return the {@code Set} of public credentials held by this
666
* {@code Subject}.
667
*
668
* <p> The returned {@code Set} is backed by this Subject's
669
* internal public Credential {@code Set}. Any modification
670
* to the returned {@code Set} affects the internal public
671
* Credential {@code Set} as well.
672
*
673
* <p> If a security manager is installed, the caller must have a
674
* {@link AuthPermission#AuthPermission(String)
675
* AuthPermission("modifyPublicCredentials")} permission to modify
676
* the returned set, or a {@code SecurityException} will be thrown.
677
*
678
* @return a {@code Set} of public credentials held by this
679
* {@code Subject}.
680
*/
681
public Set<Object> getPublicCredentials() {
682
683
// always return an empty Set instead of null
684
// so LoginModules can add to the Set if necessary
685
return pubCredentials;
686
}
687
688
/**
689
* Return the {@code Set} of private credentials held by this
690
* {@code Subject}.
691
*
692
* <p> The returned {@code Set} is backed by this Subject's
693
* internal private Credential {@code Set}. Any modification
694
* to the returned {@code Set} affects the internal private
695
* Credential {@code Set} as well.
696
*
697
* <p> If a security manager is installed, the caller must have a
698
* {@link AuthPermission#AuthPermission(String)
699
* AuthPermission("modifyPrivateCredentials")} permission to modify
700
* the returned set, or a {@code SecurityException} will be thrown.
701
*
702
* <p> While iterating through the {@code Set},
703
* a {@code SecurityException} is thrown if a security manager is installed
704
* and the caller does not have a {@link PrivateCredentialPermission}
705
* to access a particular Credential. The {@code Iterator}
706
* is nevertheless advanced to the next element in the {@code Set}.
707
*
708
* @return a {@code Set} of private credentials held by this
709
* {@code Subject}.
710
*/
711
public Set<Object> getPrivateCredentials() {
712
713
// XXX
714
// we do not need a security check for
715
// AuthPermission(getPrivateCredentials)
716
// because we already restrict access to private credentials
717
// via the PrivateCredentialPermission. all the extra AuthPermission
718
// would do is protect the set operations themselves
719
// (like size()), which don't seem security-sensitive.
720
721
// always return an empty Set instead of null
722
// so LoginModules can add to the Set if necessary
723
return privCredentials;
724
}
725
726
/**
727
* Return a {@code Set} of public credentials associated with this
728
* {@code Subject} that are instances or subclasses of the specified
729
* {@code Class}.
730
*
731
* <p> The returned {@code Set} is not backed by this Subject's
732
* internal public Credential {@code Set}. A new
733
* {@code Set} is created and returned for each method invocation.
734
* Modifications to the returned {@code Set}
735
* will not affect the internal public Credential {@code Set}.
736
*
737
* @param <T> the type of the class modeled by {@code c}
738
*
739
* @param c the returned {@code Set} of public credentials will all be
740
* instances of this class.
741
*
742
* @return a {@code Set} of public credentials that are instances
743
* of the specified {@code Class}.
744
*
745
* @throws NullPointerException if the specified {@code Class}
746
* is {@code null}.
747
*/
748
public <T> Set<T> getPublicCredentials(Class<T> c) {
749
750
Objects.requireNonNull(c,
751
ResourcesMgr.getString("invalid.null.Class.provided"));
752
753
// always return an empty Set instead of null
754
// so LoginModules can add to the Set if necessary
755
return new ClassSet<T>(PUB_CREDENTIAL_SET, c);
756
}
757
758
/**
759
* Return a {@code Set} of private credentials associated with this
760
* {@code Subject} that are instances or subclasses of the specified
761
* {@code Class}.
762
*
763
* <p> If a security manager is installed, the caller must have a
764
* {@link PrivateCredentialPermission} to access all of the requested
765
* Credentials, or a {@code SecurityException} will be thrown.
766
*
767
* <p> The returned {@code Set} is not backed by this Subject's
768
* internal private Credential {@code Set}. A new
769
* {@code Set} is created and returned for each method invocation.
770
* Modifications to the returned {@code Set}
771
* will not affect the internal private Credential {@code Set}.
772
*
773
* @param <T> the type of the class modeled by {@code c}
774
*
775
* @param c the returned {@code Set} of private credentials will all be
776
* instances of this class.
777
*
778
* @return a {@code Set} of private credentials that are instances
779
* of the specified {@code Class}.
780
*
781
* @throws NullPointerException if the specified {@code Class}
782
* is {@code null}.
783
*/
784
public <T> Set<T> getPrivateCredentials(Class<T> c) {
785
786
// XXX
787
// we do not need a security check for
788
// AuthPermission(getPrivateCredentials)
789
// because we already restrict access to private credentials
790
// via the PrivateCredentialPermission. all the extra AuthPermission
791
// would do is protect the set operations themselves
792
// (like size()), which don't seem security-sensitive.
793
794
Objects.requireNonNull(c,
795
ResourcesMgr.getString("invalid.null.Class.provided"));
796
797
// always return an empty Set instead of null
798
// so LoginModules can add to the Set if necessary
799
return new ClassSet<T>(PRIV_CREDENTIAL_SET, c);
800
}
801
802
/**
803
* Compares the specified Object with this {@code Subject}
804
* for equality. Returns true if the given object is also a Subject
805
* and the two {@code Subject} instances are equivalent.
806
* More formally, two {@code Subject} instances are
807
* equal if their {@code Principal} and {@code Credential}
808
* Sets are equal.
809
*
810
* @param o Object to be compared for equality with this
811
* {@code Subject}.
812
*
813
* @return true if the specified Object is equal to this
814
* {@code Subject}.
815
*
816
* @throws SecurityException if a security manager is installed and the
817
* caller does not have a {@link PrivateCredentialPermission}
818
* permission to access the private credentials for this
819
* {@code Subject} or the provided {@code Subject}.
820
*/
821
@Override
822
public boolean equals(Object o) {
823
824
if (o == null) {
825
return false;
826
}
827
828
if (this == o) {
829
return true;
830
}
831
832
if (o instanceof Subject) {
833
834
final Subject that = (Subject)o;
835
836
// check the principal and credential sets
837
Set<Principal> thatPrincipals;
838
synchronized(that.principals) {
839
// avoid deadlock from dual locks
840
thatPrincipals = new HashSet<>(that.principals);
841
}
842
if (!principals.equals(thatPrincipals)) {
843
return false;
844
}
845
846
Set<Object> thatPubCredentials;
847
synchronized(that.pubCredentials) {
848
// avoid deadlock from dual locks
849
thatPubCredentials = new HashSet<>(that.pubCredentials);
850
}
851
if (!pubCredentials.equals(thatPubCredentials)) {
852
return false;
853
}
854
855
Set<Object> thatPrivCredentials;
856
synchronized(that.privCredentials) {
857
// avoid deadlock from dual locks
858
thatPrivCredentials = new HashSet<>(that.privCredentials);
859
}
860
if (!privCredentials.equals(thatPrivCredentials)) {
861
return false;
862
}
863
return true;
864
}
865
return false;
866
}
867
868
/**
869
* Return the String representation of this {@code Subject}.
870
*
871
* @return the String representation of this {@code Subject}.
872
*/
873
@Override
874
public String toString() {
875
return toString(true);
876
}
877
878
/**
879
* package private convenience method to print out the Subject
880
* without firing off a security check when trying to access
881
* the Private Credentials
882
*/
883
String toString(boolean includePrivateCredentials) {
884
885
String s = ResourcesMgr.getString("Subject.");
886
String suffix = "";
887
888
synchronized(principals) {
889
Iterator<Principal> pI = principals.iterator();
890
while (pI.hasNext()) {
891
Principal p = pI.next();
892
suffix = suffix + ResourcesMgr.getString(".Principal.") +
893
p.toString() + ResourcesMgr.getString("NEWLINE");
894
}
895
}
896
897
synchronized(pubCredentials) {
898
Iterator<Object> pI = pubCredentials.iterator();
899
while (pI.hasNext()) {
900
Object o = pI.next();
901
suffix = suffix +
902
ResourcesMgr.getString(".Public.Credential.") +
903
o.toString() + ResourcesMgr.getString("NEWLINE");
904
}
905
}
906
907
if (includePrivateCredentials) {
908
synchronized(privCredentials) {
909
Iterator<Object> pI = privCredentials.iterator();
910
while (pI.hasNext()) {
911
try {
912
Object o = pI.next();
913
suffix += ResourcesMgr.getString
914
(".Private.Credential.") +
915
o.toString() +
916
ResourcesMgr.getString("NEWLINE");
917
} catch (SecurityException se) {
918
suffix += ResourcesMgr.getString
919
(".Private.Credential.inaccessible.");
920
break;
921
}
922
}
923
}
924
}
925
return s + suffix;
926
}
927
928
/**
929
* Returns a hashcode for this {@code Subject}.
930
*
931
* @return a hashcode for this {@code Subject}.
932
*
933
* @throws SecurityException if a security manager is installed and the
934
* caller does not have a {@link PrivateCredentialPermission}
935
* permission to access this Subject's private credentials.
936
*/
937
@Override
938
public int hashCode() {
939
940
/**
941
* The hashcode is derived exclusive or-ing the
942
* hashcodes of this Subject's Principals and credentials.
943
*
944
* If a particular credential was destroyed
945
* ({@code credential.hashCode()} throws an
946
* {@code IllegalStateException}),
947
* the hashcode for that credential is derived via:
948
* {@code credential.getClass().toString().hashCode()}.
949
*/
950
951
int hashCode = 0;
952
953
synchronized(principals) {
954
Iterator<Principal> pIterator = principals.iterator();
955
while (pIterator.hasNext()) {
956
Principal p = pIterator.next();
957
hashCode ^= p.hashCode();
958
}
959
}
960
961
synchronized(pubCredentials) {
962
Iterator<Object> pubCIterator = pubCredentials.iterator();
963
while (pubCIterator.hasNext()) {
964
hashCode ^= getCredHashCode(pubCIterator.next());
965
}
966
}
967
return hashCode;
968
}
969
970
/**
971
* get a credential's hashcode
972
*/
973
private int getCredHashCode(Object o) {
974
try {
975
return o.hashCode();
976
} catch (IllegalStateException ise) {
977
return o.getClass().toString().hashCode();
978
}
979
}
980
981
/**
982
* Writes this object out to a stream (i.e., serializes it).
983
*
984
* @param oos the {@code ObjectOutputStream} to which data is written
985
* @throws IOException if an I/O error occurs
986
*/
987
@java.io.Serial
988
private void writeObject(java.io.ObjectOutputStream oos)
989
throws java.io.IOException {
990
synchronized(principals) {
991
oos.defaultWriteObject();
992
}
993
}
994
995
/**
996
* Reads this object from a stream (i.e., deserializes it)
997
*
998
* @param s the {@code ObjectInputStream} from which data is read
999
* @throws IOException if an I/O error occurs
1000
* @throws ClassNotFoundException if a serialized class cannot be loaded
1001
*/
1002
@SuppressWarnings("unchecked")
1003
@java.io.Serial
1004
private void readObject(java.io.ObjectInputStream s)
1005
throws java.io.IOException, ClassNotFoundException {
1006
1007
ObjectInputStream.GetField gf = s.readFields();
1008
1009
readOnly = gf.get("readOnly", false);
1010
1011
Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
1012
1013
Objects.requireNonNull(inputPrincs,
1014
ResourcesMgr.getString("invalid.null.input.s."));
1015
1016
// Rewrap the principals into a SecureSet
1017
try {
1018
LinkedList<Principal> principalList = collectionNullClean(inputPrincs);
1019
principals = Collections.synchronizedSet(new SecureSet<>
1020
(this, PRINCIPAL_SET, principalList));
1021
} catch (NullPointerException npe) {
1022
// Sometimes people deserialize the principals set only.
1023
// Subject is not accessible, so just don't fail.
1024
principals = Collections.synchronizedSet
1025
(new SecureSet<>(this, PRINCIPAL_SET));
1026
}
1027
1028
// The Credential {@code Set} is not serialized, but we do not
1029
// want the default deserialization routine to set it to null.
1030
this.pubCredentials = Collections.synchronizedSet
1031
(new SecureSet<>(this, PUB_CREDENTIAL_SET));
1032
this.privCredentials = Collections.synchronizedSet
1033
(new SecureSet<>(this, PRIV_CREDENTIAL_SET));
1034
}
1035
1036
/**
1037
* Tests for null-clean collections (both non-null reference and
1038
* no null elements)
1039
*
1040
* @param coll A {@code Collection} to be tested for null references
1041
*
1042
* @throws NullPointerException if the specified collection is either
1043
* {@code null} or contains a {@code null} element
1044
*/
1045
private static <E> LinkedList<E> collectionNullClean(
1046
Collection<? extends E> coll) {
1047
1048
Objects.requireNonNull(coll,
1049
ResourcesMgr.getString("invalid.null.input.s."));
1050
1051
LinkedList<E> output = new LinkedList<>();
1052
for (E e : coll) {
1053
output.add(Objects.requireNonNull(e,
1054
ResourcesMgr.getString("invalid.null.input.s.")));
1055
}
1056
return output;
1057
}
1058
1059
/**
1060
* Prevent modifications unless caller has permission.
1061
*
1062
* @serial include
1063
*/
1064
private static class SecureSet<E>
1065
implements Set<E>, java.io.Serializable {
1066
1067
@java.io.Serial
1068
private static final long serialVersionUID = 7911754171111800359L;
1069
1070
/**
1071
* @serialField this$0 Subject The outer Subject instance.
1072
* @serialField elements LinkedList The elements in this set.
1073
*/
1074
@java.io.Serial
1075
private static final ObjectStreamField[] serialPersistentFields = {
1076
new ObjectStreamField("this$0", Subject.class),
1077
new ObjectStreamField("elements", LinkedList.class),
1078
new ObjectStreamField("which", int.class)
1079
};
1080
1081
Subject subject;
1082
LinkedList<E> elements;
1083
1084
/**
1085
* @serial An integer identifying the type of objects contained
1086
* in this set. If {@code which == 1},
1087
* this is a Principal set and all the elements are
1088
* of type {@code java.security.Principal}.
1089
* If {@code which == 2}, this is a public credential
1090
* set and all the elements are of type {@code Object}.
1091
* If {@code which == 3}, this is a private credential
1092
* set and all the elements are of type {@code Object}.
1093
*/
1094
private int which;
1095
1096
SecureSet(Subject subject, int which) {
1097
this.subject = subject;
1098
this.which = which;
1099
this.elements = new LinkedList<E>();
1100
}
1101
1102
SecureSet(Subject subject, int which, LinkedList<E> list) {
1103
this.subject = subject;
1104
this.which = which;
1105
this.elements = list;
1106
}
1107
1108
public int size() {
1109
return elements.size();
1110
}
1111
1112
public Iterator<E> iterator() {
1113
final LinkedList<E> list = elements;
1114
return new Iterator<E>() {
1115
ListIterator<E> i = list.listIterator(0);
1116
1117
public boolean hasNext() {return i.hasNext();}
1118
1119
public E next() {
1120
if (which != Subject.PRIV_CREDENTIAL_SET) {
1121
return i.next();
1122
}
1123
1124
@SuppressWarnings("removal")
1125
SecurityManager sm = System.getSecurityManager();
1126
if (sm != null) {
1127
try {
1128
sm.checkPermission(new PrivateCredentialPermission
1129
(list.get(i.nextIndex()).getClass().getName(),
1130
subject.getPrincipals()));
1131
} catch (SecurityException se) {
1132
i.next();
1133
throw (se);
1134
}
1135
}
1136
return i.next();
1137
}
1138
1139
public void remove() {
1140
1141
if (subject.isReadOnly()) {
1142
throw new IllegalStateException(ResourcesMgr.getString
1143
("Subject.is.read.only"));
1144
}
1145
1146
@SuppressWarnings("removal")
1147
java.lang.SecurityManager sm = System.getSecurityManager();
1148
if (sm != null) {
1149
switch (which) {
1150
case Subject.PRINCIPAL_SET:
1151
sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION);
1152
break;
1153
case Subject.PUB_CREDENTIAL_SET:
1154
sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION);
1155
break;
1156
default:
1157
sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION);
1158
break;
1159
}
1160
}
1161
i.remove();
1162
}
1163
};
1164
}
1165
1166
public boolean add(E o) {
1167
1168
Objects.requireNonNull(o,
1169
ResourcesMgr.getString("invalid.null.input.s."));
1170
1171
if (subject.isReadOnly()) {
1172
throw new IllegalStateException
1173
(ResourcesMgr.getString("Subject.is.read.only"));
1174
}
1175
1176
@SuppressWarnings("removal")
1177
java.lang.SecurityManager sm = System.getSecurityManager();
1178
if (sm != null) {
1179
switch (which) {
1180
case Subject.PRINCIPAL_SET:
1181
sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION);
1182
break;
1183
case Subject.PUB_CREDENTIAL_SET:
1184
sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION);
1185
break;
1186
default:
1187
sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION);
1188
break;
1189
}
1190
}
1191
1192
switch (which) {
1193
case Subject.PRINCIPAL_SET:
1194
if (!(o instanceof Principal)) {
1195
throw new SecurityException(ResourcesMgr.getString
1196
("attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set"));
1197
}
1198
break;
1199
default:
1200
// ok to add Objects of any kind to credential sets
1201
break;
1202
}
1203
1204
// check for duplicates
1205
if (!elements.contains(o))
1206
return elements.add(o);
1207
else {
1208
return false;
1209
}
1210
}
1211
1212
@SuppressWarnings("removal")
1213
public boolean remove(Object o) {
1214
1215
Objects.requireNonNull(o,
1216
ResourcesMgr.getString("invalid.null.input.s."));
1217
1218
final Iterator<E> e = iterator();
1219
while (e.hasNext()) {
1220
E next;
1221
if (which != Subject.PRIV_CREDENTIAL_SET) {
1222
next = e.next();
1223
} else {
1224
next = java.security.AccessController.doPrivileged
1225
(new java.security.PrivilegedAction<E>() {
1226
public E run() {
1227
return e.next();
1228
}
1229
});
1230
}
1231
1232
if (next.equals(o)) {
1233
e.remove();
1234
return true;
1235
}
1236
}
1237
return false;
1238
}
1239
1240
@SuppressWarnings("removal")
1241
public boolean contains(Object o) {
1242
1243
Objects.requireNonNull(o,
1244
ResourcesMgr.getString("invalid.null.input.s."));
1245
1246
final Iterator<E> e = iterator();
1247
while (e.hasNext()) {
1248
E next;
1249
if (which != Subject.PRIV_CREDENTIAL_SET) {
1250
next = e.next();
1251
} else {
1252
1253
// For private credentials:
1254
// If the caller does not have read permission for
1255
// for o.getClass(), we throw a SecurityException.
1256
// Otherwise we check the private cred set to see whether
1257
// it contains the Object
1258
1259
SecurityManager sm = System.getSecurityManager();
1260
if (sm != null) {
1261
sm.checkPermission(new PrivateCredentialPermission
1262
(o.getClass().getName(),
1263
subject.getPrincipals()));
1264
}
1265
next = java.security.AccessController.doPrivileged
1266
(new java.security.PrivilegedAction<E>() {
1267
public E run() {
1268
return e.next();
1269
}
1270
});
1271
}
1272
1273
if (next.equals(o)) {
1274
return true;
1275
}
1276
}
1277
return false;
1278
}
1279
1280
public boolean addAll(Collection<? extends E> c) {
1281
boolean result = false;
1282
1283
c = collectionNullClean(c);
1284
1285
for (E item : c) {
1286
result |= this.add(item);
1287
}
1288
1289
return result;
1290
}
1291
1292
@SuppressWarnings("removal")
1293
public boolean removeAll(Collection<?> c) {
1294
c = collectionNullClean(c);
1295
1296
boolean modified = false;
1297
final Iterator<E> e = iterator();
1298
while (e.hasNext()) {
1299
E next;
1300
if (which != Subject.PRIV_CREDENTIAL_SET) {
1301
next = e.next();
1302
} else {
1303
next = java.security.AccessController.doPrivileged
1304
(new java.security.PrivilegedAction<E>() {
1305
public E run() {
1306
return e.next();
1307
}
1308
});
1309
}
1310
1311
Iterator<?> ce = c.iterator();
1312
while (ce.hasNext()) {
1313
if (next.equals(ce.next())) {
1314
e.remove();
1315
modified = true;
1316
break;
1317
}
1318
}
1319
}
1320
return modified;
1321
}
1322
1323
public boolean containsAll(Collection<?> c) {
1324
c = collectionNullClean(c);
1325
1326
for (Object item : c) {
1327
if (this.contains(item) == false) {
1328
return false;
1329
}
1330
}
1331
1332
return true;
1333
}
1334
1335
@SuppressWarnings("removal")
1336
public boolean retainAll(Collection<?> c) {
1337
c = collectionNullClean(c);
1338
1339
boolean modified = false;
1340
final Iterator<E> e = iterator();
1341
while (e.hasNext()) {
1342
E next;
1343
if (which != Subject.PRIV_CREDENTIAL_SET) {
1344
next = e.next();
1345
} else {
1346
next = java.security.AccessController.doPrivileged
1347
(new java.security.PrivilegedAction<E>() {
1348
public E run() {
1349
return e.next();
1350
}
1351
});
1352
}
1353
1354
if (c.contains(next) == false) {
1355
e.remove();
1356
modified = true;
1357
}
1358
}
1359
1360
return modified;
1361
}
1362
1363
@SuppressWarnings("removal")
1364
public void clear() {
1365
final Iterator<E> e = iterator();
1366
while (e.hasNext()) {
1367
E next;
1368
if (which != Subject.PRIV_CREDENTIAL_SET) {
1369
next = e.next();
1370
} else {
1371
next = java.security.AccessController.doPrivileged
1372
(new java.security.PrivilegedAction<E>() {
1373
public E run() {
1374
return e.next();
1375
}
1376
});
1377
}
1378
e.remove();
1379
}
1380
}
1381
1382
public boolean isEmpty() {
1383
return elements.isEmpty();
1384
}
1385
1386
public Object[] toArray() {
1387
final Iterator<E> e = iterator();
1388
while (e.hasNext()) {
1389
// The next() method performs a security manager check
1390
// on each element in the SecureSet. If we make it all
1391
// the way through we should be able to simply return
1392
// element's toArray results. Otherwise we'll let
1393
// the SecurityException pass up the call stack.
1394
e.next();
1395
}
1396
1397
return elements.toArray();
1398
}
1399
1400
public <T> T[] toArray(T[] a) {
1401
final Iterator<E> e = iterator();
1402
while (e.hasNext()) {
1403
// The next() method performs a security manager check
1404
// on each element in the SecureSet. If we make it all
1405
// the way through we should be able to simply return
1406
// element's toArray results. Otherwise we'll let
1407
// the SecurityException pass up the call stack.
1408
e.next();
1409
}
1410
1411
return elements.toArray(a);
1412
}
1413
1414
public boolean equals(Object o) {
1415
if (o == this) {
1416
return true;
1417
}
1418
1419
if (!(o instanceof Set)) {
1420
return false;
1421
}
1422
1423
Collection<?> c = (Collection<?>) o;
1424
if (c.size() != size()) {
1425
return false;
1426
}
1427
1428
try {
1429
return containsAll(c);
1430
} catch (ClassCastException unused) {
1431
return false;
1432
} catch (NullPointerException unused) {
1433
return false;
1434
}
1435
}
1436
1437
public int hashCode() {
1438
int h = 0;
1439
Iterator<E> i = iterator();
1440
while (i.hasNext()) {
1441
E obj = i.next();
1442
if (obj != null) {
1443
h += obj.hashCode();
1444
}
1445
}
1446
return h;
1447
}
1448
1449
/**
1450
* Writes this object out to a stream (i.e., serializes it).
1451
*
1452
* @serialData If this is a private credential set,
1453
* a security check is performed to ensure that
1454
* the caller has permission to access each credential
1455
* in the set. If the security check passes,
1456
* the set is serialized.
1457
*
1458
* @param oos the {@code ObjectOutputStream} to which data is written
1459
* @throws IOException if an I/O error occurs
1460
*/
1461
@java.io.Serial
1462
private void writeObject(java.io.ObjectOutputStream oos)
1463
throws java.io.IOException {
1464
1465
if (which == Subject.PRIV_CREDENTIAL_SET) {
1466
// check permissions before serializing
1467
Iterator<E> i = iterator();
1468
while (i.hasNext()) {
1469
i.next();
1470
}
1471
}
1472
ObjectOutputStream.PutField fields = oos.putFields();
1473
fields.put("this$0", subject);
1474
fields.put("elements", elements);
1475
fields.put("which", which);
1476
oos.writeFields();
1477
}
1478
1479
/**
1480
* Restores the state of this object from the stream.
1481
*
1482
* @param ois the {@code ObjectInputStream} from which data is read
1483
* @throws IOException if an I/O error occurs
1484
* @throws ClassNotFoundException if a serialized class cannot be loaded
1485
*/
1486
@SuppressWarnings("unchecked")
1487
@java.io.Serial
1488
private void readObject(ObjectInputStream ois)
1489
throws IOException, ClassNotFoundException
1490
{
1491
ObjectInputStream.GetField fields = ois.readFields();
1492
subject = (Subject) fields.get("this$0", null);
1493
which = fields.get("which", 0);
1494
1495
LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
1496
1497
elements = Subject.collectionNullClean(tmp);
1498
}
1499
1500
}
1501
1502
/**
1503
* This class implements a {@code Set} which returns only
1504
* members that are an instance of a specified Class.
1505
*/
1506
private class ClassSet<T> extends AbstractSet<T> {
1507
1508
private int which;
1509
private Class<T> c;
1510
private Set<T> set;
1511
1512
ClassSet(int which, Class<T> c) {
1513
this.which = which;
1514
this.c = c;
1515
set = new HashSet<T>();
1516
1517
switch (which) {
1518
case Subject.PRINCIPAL_SET:
1519
synchronized(principals) { populateSet(); }
1520
break;
1521
case Subject.PUB_CREDENTIAL_SET:
1522
synchronized(pubCredentials) { populateSet(); }
1523
break;
1524
default:
1525
synchronized(privCredentials) { populateSet(); }
1526
break;
1527
}
1528
}
1529
1530
@SuppressWarnings({"removal","unchecked"}) /*To suppress warning from line 1374*/
1531
private void populateSet() {
1532
final Iterator<?> iterator;
1533
switch(which) {
1534
case Subject.PRINCIPAL_SET:
1535
iterator = Subject.this.principals.iterator();
1536
break;
1537
case Subject.PUB_CREDENTIAL_SET:
1538
iterator = Subject.this.pubCredentials.iterator();
1539
break;
1540
default:
1541
iterator = Subject.this.privCredentials.iterator();
1542
break;
1543
}
1544
1545
// Check whether the caller has permisson to get
1546
// credentials of Class c
1547
1548
while (iterator.hasNext()) {
1549
Object next;
1550
if (which == Subject.PRIV_CREDENTIAL_SET) {
1551
next = java.security.AccessController.doPrivileged
1552
(new java.security.PrivilegedAction<>() {
1553
public Object run() {
1554
return iterator.next();
1555
}
1556
});
1557
} else {
1558
next = iterator.next();
1559
}
1560
if (c.isAssignableFrom(next.getClass())) {
1561
if (which != Subject.PRIV_CREDENTIAL_SET) {
1562
set.add((T)next);
1563
} else {
1564
// Check permission for private creds
1565
SecurityManager sm = System.getSecurityManager();
1566
if (sm != null) {
1567
sm.checkPermission(new PrivateCredentialPermission
1568
(next.getClass().getName(),
1569
Subject.this.getPrincipals()));
1570
}
1571
set.add((T)next);
1572
}
1573
}
1574
}
1575
}
1576
1577
@Override
1578
public int size() {
1579
return set.size();
1580
}
1581
1582
@Override
1583
public Iterator<T> iterator() {
1584
return set.iterator();
1585
}
1586
1587
@Override
1588
public boolean add(T o) {
1589
1590
if (!c.isAssignableFrom(o.getClass())) {
1591
MessageFormat form = new MessageFormat(ResourcesMgr.getString
1592
("attempting.to.add.an.object.which.is.not.an.instance.of.class"));
1593
Object[] source = {c.toString()};
1594
throw new SecurityException(form.format(source));
1595
}
1596
1597
return set.add(o);
1598
}
1599
}
1600
1601
static final class AuthPermissionHolder {
1602
static final AuthPermission DO_AS_PERMISSION =
1603
new AuthPermission("doAs");
1604
1605
static final AuthPermission DO_AS_PRIVILEGED_PERMISSION =
1606
new AuthPermission("doAsPrivileged");
1607
1608
static final AuthPermission SET_READ_ONLY_PERMISSION =
1609
new AuthPermission("setReadOnly");
1610
1611
static final AuthPermission GET_SUBJECT_PERMISSION =
1612
new AuthPermission("getSubject");
1613
1614
static final AuthPermission MODIFY_PRINCIPALS_PERMISSION =
1615
new AuthPermission("modifyPrincipals");
1616
1617
static final AuthPermission MODIFY_PUBLIC_CREDENTIALS_PERMISSION =
1618
new AuthPermission("modifyPublicCredentials");
1619
1620
static final AuthPermission MODIFY_PRIVATE_CREDENTIALS_PERMISSION =
1621
new AuthPermission("modifyPrivateCredentials");
1622
}
1623
}
1624
1625