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.