137 * with an empty {@code Set} of Principals and empty
138 * Sets of public and private credentials.
139 *
140 * <p> The newly constructed Sets check whether this {@code Subject}
141 * has been set read-only before permitting subsequent modifications.
142 * The newly created Sets also prevent illegal modifications
143 * by ensuring that callers have sufficient permissions. These Sets
144 * also prohibit null elements, and attempts to add or query a null
145 * element will result in a {@code NullPointerException}.
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. These Sets
174 * also prohibit null elements, and attempts to add or query a null
175 * element will result in a {@code NullPointerException}.
176 *
177 * <p> To modify the Principals Set, the caller must have
178 * {@code AuthPermission("modifyPrincipals")}.
179 * To modify the public credential Set, the caller must have
180 * {@code AuthPermission("modifyPublicCredentials")}.
181 * To modify the private credential Set, the caller must have
189 *
190 * @param pubCredentials the {@code Set} of public credentials
191 * to be associated with this {@code Subject}.
192 *
193 * @param privCredentials the {@code Set} of private credentials
194 * to be associated with this {@code Subject}.
195 *
196 * @throws NullPointerException if the specified
197 * {@code principals}, {@code pubCredentials},
198 * or {@code privCredentials} are {@code null},
199 * or a null value exists within any of these three
200 * Sets.
201 */
202 public Subject(boolean readOnly, Set<? extends Principal> principals,
203 Set<?> pubCredentials, Set<?> privCredentials)
204 {
205 collectionNullClean(principals);
206 collectionNullClean(pubCredentials);
207 collectionNullClean(privCredentials);
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 * @throws SecurityException if a security manager is installed and the
275 * caller does not have an
276 * {@link AuthPermission#AuthPermission(String)
277 * AuthPermission("getSubject")} permission to get the
278 * {@code Subject}.
279 *
280 * @throws 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 Objects.requireNonNull(acc, ResourcesMgr.getString
291 ("invalid.null.AccessControlContext.provided"));
292
293 // return the Subject from the DomainCombiner of the provided context
294 return AccessController.doPrivileged
295 (new java.security.PrivilegedAction<Subject>() {
296 public Subject run() {
297 DomainCombiner dc = acc.getDomainCombiner();
298 if (!(dc instanceof SubjectDomainCombiner)) {
299 return null;
300 }
301 SubjectDomainCombiner sdc = (SubjectDomainCombiner)dc;
302 return sdc.getSubject();
303 }
304 });
305 }
306
307 /**
308 * Perform work as a particular {@code Subject}.
309 *
310 * <p> This method first retrieves the current Thread's
311 * {@code AccessControlContext} via
312 * {@code AccessController.getContext},
313 * and then instantiates a new {@code AccessControlContext}
314 * using the retrieved context along with a new
315 * {@code SubjectDomainCombiner} (constructed using
538 Objects.requireNonNull(action,
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 /**
572 * Return the {@code Set} of Principals associated with this
573 * {@code Subject}. Each {@code Principal} represents
574 * an identity for this {@code Subject}.
575 *
576 * <p> The returned {@code Set} is backed by this Subject's
577 * internal {@code Principal} {@code Set}. Any modification
578 * to the returned {@code Set} affects the internal
784 */
785 @Override
786 public boolean equals(Object o) {
787
788 if (o == null) {
789 return false;
790 }
791
792 if (this == o) {
793 return true;
794 }
795
796 if (o instanceof Subject) {
797
798 final Subject that = (Subject)o;
799
800 // check the principal and credential sets
801 Set<Principal> thatPrincipals;
802 synchronized(that.principals) {
803 // avoid deadlock from dual locks
804 thatPrincipals = new HashSet<Principal>(that.principals);
805 }
806 if (!principals.equals(thatPrincipals)) {
807 return false;
808 }
809
810 Set<Object> thatPubCredentials;
811 synchronized(that.pubCredentials) {
812 // avoid deadlock from dual locks
813 thatPubCredentials = new HashSet<Object>(that.pubCredentials);
814 }
815 if (!pubCredentials.equals(thatPubCredentials)) {
816 return false;
817 }
818
819 Set<Object> thatPrivCredentials;
820 synchronized(that.privCredentials) {
821 // avoid deadlock from dual locks
822 thatPrivCredentials = new HashSet<Object>(that.privCredentials);
823 }
824 if (!privCredentials.equals(thatPrivCredentials)) {
825 return false;
826 }
827 return true;
828 }
829 return false;
830 }
831
832 /**
833 * Return the String representation of this {@code Subject}.
834 *
835 * @return the String representation of this {@code Subject}.
836 */
837 @Override
838 public String toString() {
839 return toString(true);
840 }
841
842 /**
953 }
954
955 /**
956 * Reads this object from a stream (i.e., deserializes it)
957 */
958 @SuppressWarnings("unchecked")
959 private void readObject(java.io.ObjectInputStream s)
960 throws java.io.IOException, ClassNotFoundException {
961
962 ObjectInputStream.GetField gf = s.readFields();
963
964 readOnly = gf.get("readOnly", false);
965
966 Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
967
968 Objects.requireNonNull(inputPrincs,
969 ResourcesMgr.getString("invalid.null.input.s."));
970
971 // Rewrap the principals into a SecureSet
972 try {
973 principals = Collections.synchronizedSet(new SecureSet<Principal>
974 (this, PRINCIPAL_SET, inputPrincs));
975 } catch (NullPointerException npe) {
976 // Sometimes people deserialize the principals set only.
977 // Subject is not accessible, so just don't fail.
978 principals = Collections.synchronizedSet
979 (new SecureSet<Principal>(this, PRINCIPAL_SET));
980 }
981
982 // The Credential {@code Set} is not serialized, but we do not
983 // want the default deserialization routine to set it to null.
984 this.pubCredentials = Collections.synchronizedSet
985 (new SecureSet<Object>(this, PUB_CREDENTIAL_SET));
986 this.privCredentials = Collections.synchronizedSet
987 (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));
988 }
989
990 /**
991 * Tests for null-clean collections (both non-null reference and
992 * no null elements)
993 *
994 * @param coll A {@code Collection} to be tested for null references
995 *
996 * @throws NullPointerException if the specified collection is either
997 * {@code null} or contains a {@code null} element
998 */
999 private static void collectionNullClean(Collection<?> coll) {
1000 boolean hasNullElements = false;
1001
1002 Objects.requireNonNull(coll,
1003 ResourcesMgr.getString("invalid.null.input.s."));
1004
1005 try {
1006 hasNullElements = coll.contains(null);
1007 } catch (NullPointerException npe) {
1480 final Iterator<?> iterator;
1481 switch(which) {
1482 case Subject.PRINCIPAL_SET:
1483 iterator = Subject.this.principals.iterator();
1484 break;
1485 case Subject.PUB_CREDENTIAL_SET:
1486 iterator = Subject.this.pubCredentials.iterator();
1487 break;
1488 default:
1489 iterator = Subject.this.privCredentials.iterator();
1490 break;
1491 }
1492
1493 // Check whether the caller has permisson to get
1494 // credentials of Class c
1495
1496 while (iterator.hasNext()) {
1497 Object next;
1498 if (which == Subject.PRIV_CREDENTIAL_SET) {
1499 next = java.security.AccessController.doPrivileged
1500 (new java.security.PrivilegedAction<Object>() {
1501 public Object run() {
1502 return iterator.next();
1503 }
1504 });
1505 } else {
1506 next = iterator.next();
1507 }
1508 if (c.isAssignableFrom(next.getClass())) {
1509 if (which != Subject.PRIV_CREDENTIAL_SET) {
1510 set.add((T)next);
1511 } else {
1512 // Check permission for private creds
1513 SecurityManager sm = System.getSecurityManager();
1514 if (sm != null) {
1515 sm.checkPermission(new PrivateCredentialPermission
1516 (next.getClass().getName(),
1517 Subject.this.getPrincipals()));
1518 }
1519 set.add((T)next);
1520 }
|
137 * with an empty {@code Set} of Principals and empty
138 * Sets of public and private credentials.
139 *
140 * <p> The newly constructed Sets check whether this {@code Subject}
141 * has been set read-only before permitting subsequent modifications.
142 * The newly created Sets also prevent illegal modifications
143 * by ensuring that callers have sufficient permissions. These Sets
144 * also prohibit null elements, and attempts to add or query a null
145 * element will result in a {@code NullPointerException}.
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<>(this, PRINCIPAL_SET));
158 this.pubCredentials = Collections.synchronizedSet
159 (new SecureSet<>(this, PUB_CREDENTIAL_SET));
160 this.privCredentials = Collections.synchronizedSet
161 (new SecureSet<>(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. These Sets
174 * also prohibit null elements, and attempts to add or query a null
175 * element will result in a {@code NullPointerException}.
176 *
177 * <p> To modify the Principals Set, the caller must have
178 * {@code AuthPermission("modifyPrincipals")}.
179 * To modify the public credential Set, the caller must have
180 * {@code AuthPermission("modifyPublicCredentials")}.
181 * To modify the private credential Set, the caller must have
189 *
190 * @param pubCredentials the {@code Set} of public credentials
191 * to be associated with this {@code Subject}.
192 *
193 * @param privCredentials the {@code Set} of private credentials
194 * to be associated with this {@code Subject}.
195 *
196 * @throws NullPointerException if the specified
197 * {@code principals}, {@code pubCredentials},
198 * or {@code privCredentials} are {@code null},
199 * or a null value exists within any of these three
200 * Sets.
201 */
202 public Subject(boolean readOnly, Set<? extends Principal> principals,
203 Set<?> pubCredentials, Set<?> privCredentials)
204 {
205 collectionNullClean(principals);
206 collectionNullClean(pubCredentials);
207 collectionNullClean(privCredentials);
208
209 this.principals = Collections.synchronizedSet(new SecureSet<>
210 (this, PRINCIPAL_SET, principals));
211 this.pubCredentials = Collections.synchronizedSet(new SecureSet<>
212 (this, PUB_CREDENTIAL_SET, pubCredentials));
213 this.privCredentials = Collections.synchronizedSet(new SecureSet<>
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 * @throws SecurityException if a security manager is installed and the
275 * caller does not have an
276 * {@link AuthPermission#AuthPermission(String)
277 * AuthPermission("getSubject")} permission to get the
278 * {@code Subject}.
279 *
280 * @throws 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 Objects.requireNonNull(acc, ResourcesMgr.getString
291 ("invalid.null.AccessControlContext.provided"));
292
293 // return the Subject from the DomainCombiner of the provided context
294 return AccessController.doPrivileged
295 (new java.security.PrivilegedAction<>() {
296 public Subject run() {
297 DomainCombiner dc = acc.getDomainCombiner();
298 if (!(dc instanceof SubjectDomainCombiner)) {
299 return null;
300 }
301 SubjectDomainCombiner sdc = (SubjectDomainCombiner)dc;
302 return sdc.getSubject();
303 }
304 });
305 }
306
307 /**
308 * Perform work as a particular {@code Subject}.
309 *
310 * <p> This method first retrieves the current Thread's
311 * {@code AccessControlContext} via
312 * {@code AccessController.getContext},
313 * and then instantiates a new {@code AccessControlContext}
314 * using the retrieved context along with a new
315 * {@code SubjectDomainCombiner} (constructed using
538 Objects.requireNonNull(action,
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<>() {
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 /**
572 * Return the {@code Set} of Principals associated with this
573 * {@code Subject}. Each {@code Principal} represents
574 * an identity for this {@code Subject}.
575 *
576 * <p> The returned {@code Set} is backed by this Subject's
577 * internal {@code Principal} {@code Set}. Any modification
578 * to the returned {@code Set} affects the internal
784 */
785 @Override
786 public boolean equals(Object o) {
787
788 if (o == null) {
789 return false;
790 }
791
792 if (this == o) {
793 return true;
794 }
795
796 if (o instanceof Subject) {
797
798 final Subject that = (Subject)o;
799
800 // check the principal and credential sets
801 Set<Principal> thatPrincipals;
802 synchronized(that.principals) {
803 // avoid deadlock from dual locks
804 thatPrincipals = new HashSet<>(that.principals);
805 }
806 if (!principals.equals(thatPrincipals)) {
807 return false;
808 }
809
810 Set<Object> thatPubCredentials;
811 synchronized(that.pubCredentials) {
812 // avoid deadlock from dual locks
813 thatPubCredentials = new HashSet<>(that.pubCredentials);
814 }
815 if (!pubCredentials.equals(thatPubCredentials)) {
816 return false;
817 }
818
819 Set<Object> thatPrivCredentials;
820 synchronized(that.privCredentials) {
821 // avoid deadlock from dual locks
822 thatPrivCredentials = new HashSet<>(that.privCredentials);
823 }
824 if (!privCredentials.equals(thatPrivCredentials)) {
825 return false;
826 }
827 return true;
828 }
829 return false;
830 }
831
832 /**
833 * Return the String representation of this {@code Subject}.
834 *
835 * @return the String representation of this {@code Subject}.
836 */
837 @Override
838 public String toString() {
839 return toString(true);
840 }
841
842 /**
953 }
954
955 /**
956 * Reads this object from a stream (i.e., deserializes it)
957 */
958 @SuppressWarnings("unchecked")
959 private void readObject(java.io.ObjectInputStream s)
960 throws java.io.IOException, ClassNotFoundException {
961
962 ObjectInputStream.GetField gf = s.readFields();
963
964 readOnly = gf.get("readOnly", false);
965
966 Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
967
968 Objects.requireNonNull(inputPrincs,
969 ResourcesMgr.getString("invalid.null.input.s."));
970
971 // Rewrap the principals into a SecureSet
972 try {
973 principals = Collections.synchronizedSet(new SecureSet<>
974 (this, PRINCIPAL_SET, inputPrincs));
975 } catch (NullPointerException npe) {
976 // Sometimes people deserialize the principals set only.
977 // Subject is not accessible, so just don't fail.
978 principals = Collections.synchronizedSet
979 (new SecureSet<>(this, PRINCIPAL_SET));
980 }
981
982 // The Credential {@code Set} is not serialized, but we do not
983 // want the default deserialization routine to set it to null.
984 this.pubCredentials = Collections.synchronizedSet
985 (new SecureSet<>(this, PUB_CREDENTIAL_SET));
986 this.privCredentials = Collections.synchronizedSet
987 (new SecureSet<>(this, PRIV_CREDENTIAL_SET));
988 }
989
990 /**
991 * Tests for null-clean collections (both non-null reference and
992 * no null elements)
993 *
994 * @param coll A {@code Collection} to be tested for null references
995 *
996 * @throws NullPointerException if the specified collection is either
997 * {@code null} or contains a {@code null} element
998 */
999 private static void collectionNullClean(Collection<?> coll) {
1000 boolean hasNullElements = false;
1001
1002 Objects.requireNonNull(coll,
1003 ResourcesMgr.getString("invalid.null.input.s."));
1004
1005 try {
1006 hasNullElements = coll.contains(null);
1007 } catch (NullPointerException npe) {
1480 final Iterator<?> iterator;
1481 switch(which) {
1482 case Subject.PRINCIPAL_SET:
1483 iterator = Subject.this.principals.iterator();
1484 break;
1485 case Subject.PUB_CREDENTIAL_SET:
1486 iterator = Subject.this.pubCredentials.iterator();
1487 break;
1488 default:
1489 iterator = Subject.this.privCredentials.iterator();
1490 break;
1491 }
1492
1493 // Check whether the caller has permisson to get
1494 // credentials of Class c
1495
1496 while (iterator.hasNext()) {
1497 Object next;
1498 if (which == Subject.PRIV_CREDENTIAL_SET) {
1499 next = java.security.AccessController.doPrivileged
1500 (new java.security.PrivilegedAction<>() {
1501 public Object run() {
1502 return iterator.next();
1503 }
1504 });
1505 } else {
1506 next = iterator.next();
1507 }
1508 if (c.isAssignableFrom(next.getClass())) {
1509 if (which != Subject.PRIV_CREDENTIAL_SET) {
1510 set.add((T)next);
1511 } else {
1512 // Check permission for private creds
1513 SecurityManager sm = System.getSecurityManager();
1514 if (sm != null) {
1515 sm.checkPermission(new PrivateCredentialPermission
1516 (next.getClass().getName(),
1517 Subject.this.getPrincipals()));
1518 }
1519 set.add((T)next);
1520 }
|