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