src/share/classes/javax/security/auth/Subject.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 140,150 ****
* Sets of public and private credentials.
*
* <p> The newly constructed Sets check whether this {@code Subject}
* has been set read-only before permitting subsequent modifications.
* The newly created Sets also prevent illegal modifications
! * by ensuring that callers have sufficient permissions.
*
* <p> To modify the Principals Set, the caller must have
* {@code AuthPermission("modifyPrincipals")}.
* To modify the public credential Set, the caller must have
* {@code AuthPermission("modifyPublicCredentials")}.
--- 140,152 ----
* Sets of public and private credentials.
*
* <p> The newly constructed Sets check whether this {@code Subject}
* has been set read-only before permitting subsequent modifications.
* The newly created Sets also prevent illegal modifications
! * by ensuring that callers have sufficient permissions. These Sets
! * also prohibit null elements, and attempts to add or query a null
! * element will result in a {@code NullPointerException}.
*
* <p> To modify the Principals Set, the caller must have
* {@code AuthPermission("modifyPrincipals")}.
* To modify the public credential Set, the caller must have
* {@code AuthPermission("modifyPublicCredentials")}.
*** 168,178 ****
* <p> The Principals and credentials from the specified Sets
* are copied into newly constructed Sets.
* These newly created Sets check whether this {@code Subject}
* has been set read-only before permitting subsequent modifications.
* The newly created Sets also prevent illegal modifications
! * by ensuring that callers have sufficient permissions.
*
* <p> To modify the Principals Set, the caller must have
* {@code AuthPermission("modifyPrincipals")}.
* To modify the public credential Set, the caller must have
* {@code AuthPermission("modifyPublicCredentials")}.
--- 170,182 ----
* <p> The Principals and credentials from the specified Sets
* are copied into newly constructed Sets.
* These newly created Sets check whether this {@code Subject}
* has been set read-only before permitting subsequent modifications.
* The newly created Sets also prevent illegal modifications
! * by ensuring that callers have sufficient permissions. These Sets
! * also prohibit null elements, and attempts to add or query a null
! * element will result in a {@code NullPointerException}.
*
* <p> To modify the Principals Set, the caller must have
* {@code AuthPermission("modifyPrincipals")}.
* To modify the public credential Set, the caller must have
* {@code AuthPermission("modifyPublicCredentials")}.
*** 192,212 ****
* @param privCredentials the {@code Set} of private credentials
* to be associated with this {@code Subject}.
*
* @exception NullPointerException if the specified
* {@code principals}, {@code pubCredentials},
! * or {@code privCredentials} are {@code null}.
*/
public Subject(boolean readOnly, Set<? extends Principal> principals,
Set<?> pubCredentials, Set<?> privCredentials)
{
!
! if (principals == null ||
! pubCredentials == null ||
! privCredentials == null)
throw new NullPointerException
(ResourcesMgr.getString("invalid.null.input.s."));
this.principals = Collections.synchronizedSet(new SecureSet<Principal>
(this, PRINCIPAL_SET, principals));
this.pubCredentials = Collections.synchronizedSet(new SecureSet<Object>
(this, PUB_CREDENTIAL_SET, pubCredentials));
--- 196,218 ----
* @param privCredentials the {@code Set} of private credentials
* to be associated with this {@code Subject}.
*
* @exception NullPointerException if the specified
* {@code principals}, {@code pubCredentials},
! * or {@code privCredentials} are {@code null},
! * or a null value exists within any of these three
! * Sets.
*/
public Subject(boolean readOnly, Set<? extends Principal> principals,
Set<?> pubCredentials, Set<?> privCredentials)
{
! if (collectionNullClean(principals) == false ||
! collectionNullClean(pubCredentials) == false ||
! collectionNullClean(privCredentials) == false) {
throw new NullPointerException
(ResourcesMgr.getString("invalid.null.input.s."));
+ }
this.principals = Collections.synchronizedSet(new SecureSet<Principal>
(this, PRINCIPAL_SET, principals));
this.pubCredentials = Collections.synchronizedSet(new SecureSet<Object>
(this, PUB_CREDENTIAL_SET, pubCredentials));
*** 968,981 ****
readOnly = gf.get("readOnly", false);
Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
// Rewrap the principals into a SecureSet
- if (inputPrincs == null) {
- throw new NullPointerException
- (ResourcesMgr.getString("invalid.null.input.s."));
- }
try {
principals = Collections.synchronizedSet(new SecureSet<Principal>
(this, PRINCIPAL_SET, inputPrincs));
} catch (NullPointerException npe) {
// Sometimes people deserialize the principals set only.
--- 974,983 ----
*** 991,1007 ****
this.privCredentials = Collections.synchronizedSet
(new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));
}
/**
* Prevent modifications unless caller has permission.
*
* @serial include
*/
private static class SecureSet<E>
! extends AbstractSet<E>
! implements java.io.Serializable {
private static final long serialVersionUID = 7911754171111800359L;
/**
* @serialField this$0 Subject The outer Subject instance.
--- 993,1033 ----
this.privCredentials = Collections.synchronizedSet
(new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));
}
/**
+ * Tests for null-clean collections (both non-null reference and
+ * no null elements)
+ *
+ * @param coll A {@code Collection} to be tested for null references
+ *
+ * @return true if {@code coll} is non-null and contains no null
+ * elements, false otherwise.
+ */
+ private static boolean collectionNullClean(Collection<?> coll) {
+ boolean isClean = false;
+
+ try {
+ isClean = (coll != null) && !coll.contains(null);
+ } catch (NullPointerException npe) {
+ // A null-hostile collection may choose to throw
+ // NullPointerException if contains(null) is called on it
+ // rather than returning false.
+ // If this happens we know the collection is null-clean.
+ isClean = true;
+ }
+
+ return isClean;
+ }
+
+ /**
* Prevent modifications unless caller has permission.
*
* @serial include
*/
private static class SecureSet<E>
! implements Set<E>, java.io.Serializable {
private static final long serialVersionUID = 7911754171111800359L;
/**
* @serialField this$0 Subject The outer Subject instance.
*** 1096,1105 ****
--- 1122,1136 ----
};
}
public boolean add(E o) {
+ if (o == null) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
if (subject.isReadOnly()) {
throw new IllegalStateException
(ResourcesMgr.getString("Subject.is.read.only"));
}
*** 1137,1146 ****
--- 1168,1182 ----
return false;
}
public boolean remove(Object o) {
+ if (o == null) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
final Iterator<E> e = iterator();
while (e.hasNext()) {
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
next = e.next();
*** 1151,1174 ****
return e.next();
}
});
}
! if (next == null) {
! if (o == null) {
! e.remove();
! return true;
! }
! } else if (next.equals(o)) {
e.remove();
return true;
}
}
return false;
}
public boolean contains(Object o) {
final Iterator<E> e = iterator();
while (e.hasNext()) {
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
next = e.next();
--- 1187,1211 ----
return e.next();
}
});
}
! if (next.equals(o)) {
e.remove();
return true;
}
}
return false;
}
public boolean contains(Object o) {
+
+ if (o == null) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
final Iterator<E> e = iterator();
while (e.hasNext()) {
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
next = e.next();
*** 1192,1214 ****
return e.next();
}
});
}
! if (next == null) {
! if (o == null) {
! return true;
! }
! } else if (next.equals(o)) {
return true;
}
}
return false;
}
public boolean removeAll(Collection<?> c) {
! Objects.requireNonNull(c);
boolean modified = false;
final Iterator<E> e = iterator();
while (e.hasNext()) {
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
--- 1229,1266 ----
return e.next();
}
});
}
! if (next.equals(o)) {
return true;
}
}
return false;
}
+ public boolean addAll(Collection<? extends E> c) {
+ boolean result = false;
+
+ if (collectionNullClean(c) == false) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
+ for (E item : c) {
+ result |= this.add(item);
+ }
+
+ return result;
+ }
+
public boolean removeAll(Collection<?> c) {
! if (collectionNullClean(c) == false) {
! throw new NullPointerException
! (ResourcesMgr.getString("invalid.null.input.s."));
! }
!
boolean modified = false;
final Iterator<E> e = iterator();
while (e.hasNext()) {
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
*** 1222,1255 ****
});
}
Iterator<?> ce = c.iterator();
while (ce.hasNext()) {
! Object o = ce.next();
! if (next == null) {
! if (o == null) {
! e.remove();
! modified = true;
! break;
! }
! } else if (next.equals(o)) {
e.remove();
modified = true;
break;
}
}
}
return modified;
}
public boolean retainAll(Collection<?> c) {
! Objects.requireNonNull(c);
boolean modified = false;
- boolean retain = false;
final Iterator<E> e = iterator();
while (e.hasNext()) {
- retain = false;
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
next = e.next();
} else {
next = java.security.AccessController.doPrivileged
--- 1274,1317 ----
});
}
Iterator<?> ce = c.iterator();
while (ce.hasNext()) {
! if (next.equals(ce.next())) {
e.remove();
modified = true;
break;
}
}
}
return modified;
}
+ public boolean containsAll(Collection<?> c) {
+ if (collectionNullClean(c) == false) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
+ for (Object item : c) {
+ if (this.contains(item) == false) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
public boolean retainAll(Collection<?> c) {
! if (collectionNullClean(c) == false) {
! throw new NullPointerException
! (ResourcesMgr.getString("invalid.null.input.s."));
! }
!
boolean modified = false;
final Iterator<E> e = iterator();
while (e.hasNext()) {
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
next = e.next();
} else {
next = java.security.AccessController.doPrivileged
*** 1258,1287 ****
return e.next();
}
});
}
! Iterator<?> ce = c.iterator();
! while (ce.hasNext()) {
! Object o = ce.next();
! if (next == null) {
! if (o == null) {
! retain = true;
! break;
! }
! } else if (next.equals(o)) {
! retain = true;
! break;
! }
! }
!
! if (!retain) {
e.remove();
- retain = false;
modified = true;
}
}
return modified;
}
public void clear() {
final Iterator<E> e = iterator();
--- 1320,1335 ----
return e.next();
}
});
}
! if (c.contains(next) == false) {
e.remove();
modified = true;
}
}
+
return modified;
}
public void clear() {
final Iterator<E> e = iterator();
*** 1299,1308 ****
--- 1347,1406 ----
}
e.remove();
}
}
+ public boolean isEmpty() {
+ return elements.isEmpty();
+ }
+
+ public Object[] toArray() {
+ final Iterator<E> e = iterator();
+ while (e.hasNext()) {
+ // The next() method performs a security manager check
+ // on each element in the SecureSet. If we make it all
+ // the way through we should be able to simply return
+ // element's toArray results. Otherwise we'll let
+ // the SecurityException pass up the call stack.
+ e.next();
+ }
+
+ return elements.toArray();
+ }
+
+ public <T> T[] toArray(T[] a) {
+ final Iterator<E> e = iterator();
+ while (e.hasNext()) {
+ // The next() method performs a security manager check
+ // on each element in the SecureSet. If we make it all
+ // the way through we should be able to simply return
+ // element's toArray results. Otherwise we'll let
+ // the SecurityException pass up the call stack.
+ e.next();
+ }
+
+ return elements.toArray(a);
+ }
+
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+
+ if (!(o instanceof Set))
+ return false;
+ Collection<?> c = (Collection<?>) o;
+ if (c.size() != size())
+ return false;
+ try {
+ return containsAll(c);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+
/**
* Writes this object out to a stream (i.e., serializes it).
*
* <p>
*
*** 1336,1351 ****
--- 1434,1456 ----
ObjectInputStream.GetField fields = ois.readFields();
subject = (Subject) fields.get("this$0", null);
which = fields.get("which", 0);
LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
+
+ if (Subject.collectionNullClean(tmp) == false) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
if (tmp.getClass() != LinkedList.class) {
elements = new LinkedList<E>(tmp);
} else {
elements = tmp;
}
}
+
}
/**
* This class implements a {@code Set} which returns only
* members that are an instance of a specified Class.