src/share/classes/javax/security/auth/Subject.java

Print this page


   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


 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}


 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


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 


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(); }


   1 /*
   2  * Copyright (c) 1998, 2014, 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


 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.  These Sets
 146      * also prohibit null elements, and attempts to add or query a null
 147      * element will result in a {@code NullPointerException}.
 148      *
 149      * <p> To modify the Principals Set, the caller must have
 150      * {@code AuthPermission("modifyPrincipals")}.
 151      * To modify the public credential Set, the caller must have
 152      * {@code AuthPermission("modifyPublicCredentials")}.
 153      * To modify the private credential Set, the caller must have
 154      * {@code AuthPermission("modifyPrivateCredentials")}.
 155      */
 156     public Subject() {
 157 
 158         this.principals = Collections.synchronizedSet
 159                         (new SecureSet<Principal>(this, PRINCIPAL_SET));
 160         this.pubCredentials = Collections.synchronizedSet
 161                         (new SecureSet<Object>(this, PUB_CREDENTIAL_SET));
 162         this.privCredentials = Collections.synchronizedSet
 163                         (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));
 164     }
 165 
 166     /**
 167      * Create an instance of a {@code Subject} with
 168      * Principals and credentials.
 169      *
 170      * <p> The Principals and credentials from the specified Sets
 171      * are copied into newly constructed Sets.
 172      * These newly created Sets check whether this {@code Subject}
 173      * has been set read-only before permitting subsequent modifications.
 174      * The newly created Sets also prevent illegal modifications
 175      * by ensuring that callers have sufficient permissions.  These Sets
 176      * also prohibit null elements, and attempts to add or query a null
 177      * element will result in a {@code NullPointerException}.
 178      *
 179      * <p> To modify the Principals Set, the caller must have
 180      * {@code AuthPermission("modifyPrincipals")}.
 181      * To modify the public credential Set, the caller must have
 182      * {@code AuthPermission("modifyPublicCredentials")}.
 183      * To modify the private credential Set, the caller must have
 184      * {@code AuthPermission("modifyPrivateCredentials")}.
 185      * <p>
 186      *
 187      * @param readOnly true if the {@code Subject} is to be read-only,
 188      *          and false otherwise. <p>
 189      *
 190      * @param principals the {@code Set} of Principals
 191      *          to be associated with this {@code Subject}. <p>
 192      *
 193      * @param pubCredentials the {@code Set} of public credentials
 194      *          to be associated with this {@code Subject}. <p>
 195      *
 196      * @param privCredentials the {@code Set} of private credentials
 197      *          to be associated with this {@code Subject}.
 198      *
 199      * @exception NullPointerException if the specified
 200      *          {@code principals}, {@code pubCredentials},
 201      *          or {@code privCredentials} are {@code null},
 202      *          or a null value exists within any of these three
 203      *          Sets.
 204      */
 205     public Subject(boolean readOnly, Set<? extends Principal> principals,
 206                    Set<?> pubCredentials, Set<?> privCredentials)
 207     {
 208         if (collectionNullClean(principals) == false ||
 209             collectionNullClean(pubCredentials) == false ||
 210             collectionNullClean(privCredentials) == false) {

 211             throw new NullPointerException
 212                 (ResourcesMgr.getString("invalid.null.input.s."));
 213         }
 214 
 215         this.principals = Collections.synchronizedSet(new SecureSet<Principal>
 216                                 (this, PRINCIPAL_SET, principals));
 217         this.pubCredentials = Collections.synchronizedSet(new SecureSet<Object>
 218                                 (this, PUB_CREDENTIAL_SET, pubCredentials));
 219         this.privCredentials = Collections.synchronizedSet(new SecureSet<Object>
 220                                 (this, PRIV_CREDENTIAL_SET, privCredentials));
 221         this.readOnly = readOnly;
 222     }
 223 
 224     /**
 225      * Set this {@code Subject} to be read-only.
 226      *
 227      * <p> Modifications (additions and removals) to this Subject's
 228      * {@code Principal} {@code Set} and
 229      * credential Sets will be disallowed.
 230      * The {@code destroy} operation on this Subject's credentials will
 231      * still be permitted.
 232      *
 233      * <p> Subsequent attempts to modify the Subject's {@code Principal}


 959                 throws java.io.IOException {
 960         synchronized(principals) {
 961             oos.defaultWriteObject();
 962         }
 963     }
 964 
 965     /**
 966      * Reads this object from a stream (i.e., deserializes it)
 967      */
 968     @SuppressWarnings("unchecked")
 969     private void readObject(java.io.ObjectInputStream s)
 970                 throws java.io.IOException, ClassNotFoundException {
 971 
 972         ObjectInputStream.GetField gf = s.readFields();
 973 
 974         readOnly = gf.get("readOnly", false);
 975 
 976         Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
 977 
 978         // Rewrap the principals into a SecureSet




 979         try {
 980             principals = Collections.synchronizedSet(new SecureSet<Principal>
 981                                 (this, PRINCIPAL_SET, inputPrincs));
 982         } catch (NullPointerException npe) {
 983             // Sometimes people deserialize the principals set only.
 984             // Subject is not accessible, so just don't fail.
 985             principals = Collections.synchronizedSet
 986                         (new SecureSet<Principal>(this, PRINCIPAL_SET));
 987         }
 988 
 989         // The Credential {@code Set} is not serialized, but we do not
 990         // want the default deserialization routine to set it to null.
 991         this.pubCredentials = Collections.synchronizedSet
 992                         (new SecureSet<Object>(this, PUB_CREDENTIAL_SET));
 993         this.privCredentials = Collections.synchronizedSet
 994                         (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));
 995     }
 996 
 997     /**
 998      * Tests for null-clean collections (both non-null reference and
 999      * no null elements)
1000      *
1001      * @param coll A {@code Collection} to be tested for null references
1002      *
1003      * @return true if {@code coll} is non-null and contains no null
1004      *         elements, false otherwise.
1005      */
1006     private static boolean collectionNullClean(Collection<?> coll) {
1007         boolean isClean = false;
1008 
1009         try {
1010             isClean = (coll != null) && !coll.contains(null);
1011         } catch (NullPointerException npe) {
1012             // A null-hostile collection may choose to throw
1013             // NullPointerException if contains(null) is called on it
1014             // rather than returning false.
1015             // If this happens we know the collection is null-clean.
1016             isClean = true;
1017         }
1018 
1019         return isClean;
1020     }
1021 
1022     /**
1023      * Prevent modifications unless caller has permission.
1024      *
1025      * @serial include
1026      */
1027     private static class SecureSet<E>
1028         implements Set<E>, java.io.Serializable {

1029 
1030         private static final long serialVersionUID = 7911754171111800359L;
1031 
1032         /**
1033          * @serialField this$0 Subject The outer Subject instance.
1034          * @serialField elements LinkedList The elements in this set.
1035          */
1036         private static final ObjectStreamField[] serialPersistentFields = {
1037             new ObjectStreamField("this$0", Subject.class),
1038             new ObjectStreamField("elements", LinkedList.class),
1039             new ObjectStreamField("which", int.class)
1040         };
1041 
1042         Subject subject;
1043         LinkedList<E> elements;
1044 
1045         /**
1046          * @serial An integer identifying the type of objects contained
1047          *      in this set.  If {@code which == 1},
1048          *      this is a Principal set and all the elements are


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                     i.remove();
1121                 }
1122             };
1123         }
1124 
1125         public boolean add(E o) {
1126 
1127             if (o == null) {
1128                 throw new NullPointerException
1129                         (ResourcesMgr.getString("invalid.null.input.s."));
1130             }
1131 
1132             if (subject.isReadOnly()) {
1133                 throw new IllegalStateException
1134                         (ResourcesMgr.getString("Subject.is.read.only"));
1135             }
1136 
1137             java.lang.SecurityManager sm = System.getSecurityManager();
1138             if (sm != null) {
1139                 switch (which) {
1140                 case Subject.PRINCIPAL_SET:
1141                     sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION);
1142                     break;
1143                 case Subject.PUB_CREDENTIAL_SET:
1144                     sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION);
1145                     break;
1146                 default:
1147                     sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION);
1148                     break;
1149                 }
1150             }
1151 


1153             case Subject.PRINCIPAL_SET:
1154                 if (!(o instanceof Principal)) {
1155                     throw new SecurityException(ResourcesMgr.getString
1156                         ("attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set"));
1157                 }
1158                 break;
1159             default:
1160                 // ok to add Objects of any kind to credential sets
1161                 break;
1162             }
1163 
1164             // check for duplicates
1165             if (!elements.contains(o))
1166                 return elements.add(o);
1167             else
1168                 return false;
1169         }
1170 
1171         public boolean remove(Object o) {
1172 
1173             if (o == null) {
1174                 throw new NullPointerException
1175                         (ResourcesMgr.getString("invalid.null.input.s."));
1176             }
1177 
1178             final Iterator<E> e = iterator();
1179             while (e.hasNext()) {
1180                 E next;
1181                 if (which != Subject.PRIV_CREDENTIAL_SET) {
1182                     next = e.next();
1183                 } else {
1184                     next = java.security.AccessController.doPrivileged
1185                         (new java.security.PrivilegedAction<E>() {
1186                         public E run() {
1187                             return e.next();
1188                         }
1189                     });
1190                 }
1191 
1192                 if (next.equals(o)) {





1193                     e.remove();
1194                     return true;
1195                 }
1196             }
1197             return false;
1198         }
1199 
1200         public boolean contains(Object o) {
1201 
1202             if (o == null) {
1203                 throw new NullPointerException
1204                         (ResourcesMgr.getString("invalid.null.input.s."));
1205             }
1206 
1207             final Iterator<E> e = iterator();
1208             while (e.hasNext()) {
1209                 E next;
1210                 if (which != Subject.PRIV_CREDENTIAL_SET) {
1211                     next = e.next();
1212                 } else {
1213 
1214                     // For private credentials:
1215                     // If the caller does not have read permission for
1216                     // for o.getClass(), we throw a SecurityException.
1217                     // Otherwise we check the private cred set to see whether
1218                     // it contains the Object
1219 
1220                     SecurityManager sm = System.getSecurityManager();
1221                     if (sm != null) {
1222                         sm.checkPermission(new PrivateCredentialPermission
1223                                                 (o.getClass().getName(),
1224                                                 subject.getPrincipals()));
1225                     }
1226                     next = java.security.AccessController.doPrivileged
1227                         (new java.security.PrivilegedAction<E>() {
1228                         public E run() {
1229                             return e.next();
1230                         }
1231                     });
1232                 }
1233 
1234                 if (next.equals(o)) {




1235                     return true;
1236                 }
1237             }
1238             return false;
1239         }
1240 
1241         public boolean addAll(Collection<? extends E> c) {
1242             boolean result = false;
1243 
1244             if (collectionNullClean(c) == false) {
1245                 throw new NullPointerException
1246                     (ResourcesMgr.getString("invalid.null.input.s."));
1247             }
1248 
1249             for (E item : c) {
1250                 result |= this.add(item);
1251             }
1252 
1253             return result;
1254         }
1255 
1256         public boolean removeAll(Collection<?> c) {
1257             if (collectionNullClean(c) == false) {
1258                 throw new NullPointerException
1259                     (ResourcesMgr.getString("invalid.null.input.s."));
1260             }
1261 
1262             boolean modified = false;
1263             final Iterator<E> e = iterator();
1264             while (e.hasNext()) {
1265                 E next;
1266                 if (which != Subject.PRIV_CREDENTIAL_SET) {
1267                     next = e.next();
1268                 } else {
1269                     next = java.security.AccessController.doPrivileged
1270                         (new java.security.PrivilegedAction<E>() {
1271                         public E run() {
1272                             return e.next();
1273                         }
1274                     });
1275                 }
1276 
1277                 Iterator<?> ce = c.iterator();
1278                 while (ce.hasNext()) {
1279                     if (next.equals(ce.next())) {







1280                         e.remove();
1281                         modified = true;
1282                         break;
1283                     }
1284                 }
1285             }
1286             return modified;
1287         }
1288 
1289         public boolean containsAll(Collection<?> c) {
1290             if (collectionNullClean(c) == false) {
1291                 throw new NullPointerException
1292                     (ResourcesMgr.getString("invalid.null.input.s."));
1293             }
1294 
1295             for (Object item : c) {
1296                 if (this.contains(item) == false) {
1297                     return false;
1298                 }
1299             }
1300 
1301             return true;
1302         }
1303 
1304         public boolean retainAll(Collection<?> c) {
1305             if (collectionNullClean(c) == false) {
1306                 throw new NullPointerException
1307                     (ResourcesMgr.getString("invalid.null.input.s."));
1308             }
1309 
1310             boolean modified = false;

1311             final Iterator<E> e = iterator();
1312             while (e.hasNext()) {

1313                 E next;
1314                 if (which != Subject.PRIV_CREDENTIAL_SET) {
1315                     next = e.next();
1316                 } else {
1317                     next = java.security.AccessController.doPrivileged
1318                         (new java.security.PrivilegedAction<E>() {
1319                         public E run() {
1320                             return e.next();
1321                         }
1322                     });
1323                 }
1324 
1325                 if (c.contains(next) == false) {














1326                     e.remove();

1327                     modified = true;
1328                 }
1329             }
1330 
1331             return modified;
1332         }
1333 
1334         public void clear() {
1335             final Iterator<E> e = iterator();
1336             while (e.hasNext()) {
1337                 E next;
1338                 if (which != Subject.PRIV_CREDENTIAL_SET) {
1339                     next = e.next();
1340                 } else {
1341                     next = java.security.AccessController.doPrivileged
1342                         (new java.security.PrivilegedAction<E>() {
1343                         public E run() {
1344                             return e.next();
1345                         }
1346                     });
1347                 }
1348                 e.remove();
1349             }
1350         }
1351 
1352         public boolean isEmpty() {
1353             return elements.isEmpty();
1354         } 
1355 
1356         public Object[] toArray() {
1357             final Iterator<E> e = iterator();
1358             while (e.hasNext()) {
1359                 // The next() method performs a security manager check
1360                 // on each element in the SecureSet.  If we make it all
1361                 // the way through we should be able to simply return
1362                 // element's toArray results.  Otherwise we'll let
1363                 // the SecurityException pass up the call stack.
1364                 e.next();
1365             }
1366 
1367             return elements.toArray();
1368         }
1369 
1370         public <T> T[] toArray(T[] a) {
1371             final Iterator<E> e = iterator();
1372             while (e.hasNext()) {
1373                 // The next() method performs a security manager check
1374                 // on each element in the SecureSet.  If we make it all
1375                 // the way through we should be able to simply return
1376                 // element's toArray results.  Otherwise we'll let
1377                 // the SecurityException pass up the call stack.
1378                 e.next();
1379             }
1380 
1381             return elements.toArray(a);
1382         }
1383 
1384         public boolean equals(Object o) {
1385             if (o == this)
1386                 return true;
1387 
1388             if (!(o instanceof Set))
1389                 return false;
1390             Collection<?> c = (Collection<?>) o;
1391             if (c.size() != size())
1392                 return false;
1393             try {
1394                 return containsAll(c);
1395             } catch (ClassCastException unused)   {
1396                 return false;
1397             } catch (NullPointerException unused) {
1398                 return false;
1399             }
1400         }
1401 
1402         /**
1403          * Writes this object out to a stream (i.e., serializes it).
1404          *
1405          * <p>
1406          *
1407          * @serialData If this is a private credential set,
1408          *      a security check is performed to ensure that
1409          *      the caller has permission to access each credential
1410          *      in the set.  If the security check passes,
1411          *      the set is serialized.
1412          */
1413         private void writeObject(java.io.ObjectOutputStream oos)
1414                 throws java.io.IOException {
1415 
1416             if (which == Subject.PRIV_CREDENTIAL_SET) {
1417                 // check permissions before serializing
1418                 Iterator<E> i = iterator();
1419                 while (i.hasNext()) {
1420                     i.next();
1421                 }
1422             }
1423             ObjectOutputStream.PutField fields = oos.putFields();
1424             fields.put("this$0", subject);
1425             fields.put("elements", elements);
1426             fields.put("which", which);
1427             oos.writeFields();
1428         }
1429 
1430         @SuppressWarnings("unchecked")
1431         private void readObject(ObjectInputStream ois)
1432             throws IOException, ClassNotFoundException
1433         {
1434             ObjectInputStream.GetField fields = ois.readFields();
1435             subject = (Subject) fields.get("this$0", null);
1436             which = fields.get("which", 0);
1437 
1438             LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
1439 
1440             if (Subject.collectionNullClean(tmp) == false) {
1441                 throw new NullPointerException
1442                     (ResourcesMgr.getString("invalid.null.input.s."));
1443             }
1444 
1445             if (tmp.getClass() != LinkedList.class) {
1446                 elements = new LinkedList<E>(tmp);
1447             } else {
1448                 elements = tmp;
1449             }
1450         }
1451 
1452     }
1453 
1454     /**
1455      * This class implements a {@code Set} which returns only
1456      * members that are an instance of a specified Class.
1457      */
1458     private class ClassSet<T> extends AbstractSet<T> {
1459 
1460         private int which;
1461         private Class<T> c;
1462         private Set<T> set;
1463 
1464         ClassSet(int which, Class<T> c) {
1465             this.which = which;
1466             this.c = c;
1467             set = new HashSet<T>();
1468 
1469             switch (which) {
1470             case Subject.PRINCIPAL_SET:
1471                 synchronized(principals) { populateSet(); }