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 return null if
1013 // contains(null) is called on it rather than returning false.
1014 // If so then we know no nulls are present.
1015 isClean = true;
1016 }
1017
1018 return isClean;
1019 }
1020
1021 /**
1022 * Prevent modifications unless caller has permission.
1023 *
1024 * @serial include
1025 */
1026 private static class SecureSet<E>
1027 implements Set<E>, java.io.Serializable {
1028
1029 private static final long serialVersionUID = 7911754171111800359L;
1030
1031 /**
1032 * @serialField this$0 Subject The outer Subject instance.
1033 * @serialField elements LinkedList The elements in this set.
1034 */
1035 private static final ObjectStreamField[] serialPersistentFields = {
1036 new ObjectStreamField("this$0", Subject.class),
1037 new ObjectStreamField("elements", LinkedList.class),
1038 new ObjectStreamField("which", int.class)
1039 };
1040
1041 Subject subject;
1042 LinkedList<E> elements;
1043
1044 /**
1045 * @serial An integer identifying the type of objects contained
1046 * in this set. If {@code which == 1},
1047 * this is a Principal set and all the elements are
1106 if (sm != null) {
1107 switch (which) {
1108 case Subject.PRINCIPAL_SET:
1109 sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION);
1110 break;
1111 case Subject.PUB_CREDENTIAL_SET:
1112 sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION);
1113 break;
1114 default:
1115 sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION);
1116 break;
1117 }
1118 }
1119 i.remove();
1120 }
1121 };
1122 }
1123
1124 public boolean add(E o) {
1125
1126 if (o == null) {
1127 throw new NullPointerException
1128 (ResourcesMgr.getString("invalid.null.input.s."));
1129 }
1130
1131 if (subject.isReadOnly()) {
1132 throw new IllegalStateException
1133 (ResourcesMgr.getString("Subject.is.read.only"));
1134 }
1135
1136 java.lang.SecurityManager sm = System.getSecurityManager();
1137 if (sm != null) {
1138 switch (which) {
1139 case Subject.PRINCIPAL_SET:
1140 sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION);
1141 break;
1142 case Subject.PUB_CREDENTIAL_SET:
1143 sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION);
1144 break;
1145 default:
1146 sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION);
1147 break;
1148 }
1149 }
1150
1152 case Subject.PRINCIPAL_SET:
1153 if (!(o instanceof Principal)) {
1154 throw new SecurityException(ResourcesMgr.getString
1155 ("attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set"));
1156 }
1157 break;
1158 default:
1159 // ok to add Objects of any kind to credential sets
1160 break;
1161 }
1162
1163 // check for duplicates
1164 if (!elements.contains(o))
1165 return elements.add(o);
1166 else
1167 return false;
1168 }
1169
1170 public boolean remove(Object o) {
1171
1172 if (o == null) {
1173 throw new NullPointerException
1174 (ResourcesMgr.getString("invalid.null.input.s."));
1175 }
1176
1177 final Iterator<E> e = iterator();
1178 while (e.hasNext()) {
1179 E next;
1180 if (which != Subject.PRIV_CREDENTIAL_SET) {
1181 next = e.next();
1182 } else {
1183 next = java.security.AccessController.doPrivileged
1184 (new java.security.PrivilegedAction<E>() {
1185 public E run() {
1186 return e.next();
1187 }
1188 });
1189 }
1190
1191 if (next.equals(o)) {
1192 e.remove();
1193 return true;
1194 }
1195 }
1196 return false;
1197 }
1198
1199 public boolean contains(Object o) {
1200
1201 if (o == null) {
1202 throw new NullPointerException
1203 (ResourcesMgr.getString("invalid.null.input.s."));
1204 }
1205
1206 final Iterator<E> e = iterator();
1207 while (e.hasNext()) {
1208 E next;
1209 if (which != Subject.PRIV_CREDENTIAL_SET) {
1210 next = e.next();
1211 } else {
1212
1213 // For private credentials:
1214 // If the caller does not have read permission for
1215 // for o.getClass(), we throw a SecurityException.
1216 // Otherwise we check the private cred set to see whether
1217 // it contains the Object
1218
1219 SecurityManager sm = System.getSecurityManager();
1220 if (sm != null) {
1221 sm.checkPermission(new PrivateCredentialPermission
1222 (o.getClass().getName(),
1223 subject.getPrincipals()));
1224 }
1225 next = java.security.AccessController.doPrivileged
1226 (new java.security.PrivilegedAction<E>() {
1227 public E run() {
1228 return e.next();
1229 }
1230 });
1231 }
1232
1233 if (next.equals(o)) {
1234 return true;
1235 }
1236 }
1237 return false;
1238 }
1239
1240 public boolean addAll(Collection<? extends E> c) {
1241 boolean result = false;
1242
1243 if (collectionNullClean(c) == false) {
1244 throw new NullPointerException
1245 (ResourcesMgr.getString("invalid.null.input.s."));
1246 }
1247
1248 for (E item : c) {
1249 result |= this.add(item);
1250 }
1251
1252 return result;
1253 }
1254
1255 public boolean removeAll(Collection<?> c) {
1256 if (collectionNullClean(c) == false) {
1257 throw new NullPointerException
1258 (ResourcesMgr.getString("invalid.null.input.s."));
1259 }
1260
1261 boolean modified = false;
1262 final Iterator<E> e = iterator();
1263 while (e.hasNext()) {
1264 E next;
1265 if (which != Subject.PRIV_CREDENTIAL_SET) {
1266 next = e.next();
1267 } else {
1268 next = java.security.AccessController.doPrivileged
1269 (new java.security.PrivilegedAction<E>() {
1270 public E run() {
1271 return e.next();
1272 }
1273 });
1274 }
1275
1276 Iterator<?> ce = c.iterator();
1277 while (ce.hasNext()) {
1278 if (next.equals(ce.next())) {
1279 e.remove();
1280 modified = true;
1281 break;
1282 }
1283 }
1284 }
1285 return modified;
1286 }
1287
1288 public boolean containsAll(Collection<?> c) {
1289 if (collectionNullClean(c) == false) {
1290 throw new NullPointerException
1291 (ResourcesMgr.getString("invalid.null.input.s."));
1292 }
1293
1294 for (Object item : c) {
1295 if (this.contains(item) == false) {
1296 return false;
1297 }
1298 }
1299
1300 return true;
1301 }
1302
1303 public boolean retainAll(Collection<?> c) {
1304 if (collectionNullClean(c) == false) {
1305 throw new NullPointerException
1306 (ResourcesMgr.getString("invalid.null.input.s."));
1307 }
1308
1309 boolean modified = false;
1310 final Iterator<E> e = iterator();
1311 while (e.hasNext()) {
1312 E next;
1313 if (which != Subject.PRIV_CREDENTIAL_SET) {
1314 next = e.next();
1315 } else {
1316 next = java.security.AccessController.doPrivileged
1317 (new java.security.PrivilegedAction<E>() {
1318 public E run() {
1319 return e.next();
1320 }
1321 });
1322 }
1323
1324 if (c.contains(next) == false) {
1325 e.remove();
1326 modified = true;
1327 }
1328 }
1329
1330 return modified;
1331 }
1332
1333 public void clear() {
1334 final Iterator<E> e = iterator();
1335 while (e.hasNext()) {
1336 E next;
1337 if (which != Subject.PRIV_CREDENTIAL_SET) {
1338 next = e.next();
1339 } else {
1340 next = java.security.AccessController.doPrivileged
1341 (new java.security.PrivilegedAction<E>() {
1342 public E run() {
1343 return e.next();
1344 }
1345 });
1346 }
1347 e.remove();
1348 }
1349 }
1350
1351 public boolean isEmpty() {
1352 return elements.isEmpty();
1353 }
1354
1355 public Object[] toArray() {
1356 final Iterator<E> e = iterator();
1357 while (e.hasNext()) {
1358 // The next() method performs a security manager check
1359 // on each element in the SecureSet. If we make it all
1360 // the way through we should be able to simply return
1361 // element's toArray results. Otherwise we'll let
1362 // the SecurityException pass up the call stack.
1363 e.next();
1364 }
1365
1366 return elements.toArray();
1367 }
1368
1369 public <T> T[] toArray(T[] a) {
1370 final Iterator<E> e = iterator();
1371 while (e.hasNext()) {
1372 // The next() method performs a security manager check
1373 // on each element in the SecureSet. If we make it all
1374 // the way through we should be able to simply return
1375 // element's toArray results. Otherwise we'll let
1376 // the SecurityException pass up the call stack.
1377 e.next();
1378 }
1379
1380 return elements.toArray(a);
1381 }
1382
1383 public boolean equals(Object o) {
1384 if (o == this)
1385 return true;
1386
1387 if (!(o instanceof Set))
1388 return false;
1389 Collection<?> c = (Collection<?>) o;
1390 if (c.size() != size())
1391 return false;
1392 try {
1393 return containsAll(c);
1394 } catch (ClassCastException unused) {
1395 return false;
1396 } catch (NullPointerException unused) {
1397 return false;
1398 }
1399 }
1400
1401 /**
1402 * Writes this object out to a stream (i.e., serializes it).
1403 *
1404 * <p>
1405 *
1406 * @serialData If this is a private credential set,
1407 * a security check is performed to ensure that
1408 * the caller has permission to access each credential
1409 * in the set. If the security check passes,
1410 * the set is serialized.
1411 */
1412 private void writeObject(java.io.ObjectOutputStream oos)
1413 throws java.io.IOException {
1414
1415 if (which == Subject.PRIV_CREDENTIAL_SET) {
1416 // check permissions before serializing
1417 Iterator<E> i = iterator();
1418 while (i.hasNext()) {
1419 i.next();
1420 }
1421 }
1422 ObjectOutputStream.PutField fields = oos.putFields();
1423 fields.put("this$0", subject);
1424 fields.put("elements", elements);
1425 fields.put("which", which);
1426 oos.writeFields();
1427 }
1428
1429 @SuppressWarnings("unchecked")
1430 private void readObject(ObjectInputStream ois)
1431 throws IOException, ClassNotFoundException
1432 {
1433 ObjectInputStream.GetField fields = ois.readFields();
1434 subject = (Subject) fields.get("this$0", null);
1435 which = fields.get("which", 0);
1436
1437 LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
1438
1439 if (Subject.collectionNullClean(tmp) == false) {
1440 throw new NullPointerException
1441 (ResourcesMgr.getString("invalid.null.input.s."));
1442 }
1443
1444 if (tmp.getClass() != LinkedList.class) {
1445 elements = new LinkedList<E>(tmp);
1446 } else {
1447 elements = tmp;
1448 }
1449 }
1450
1451 }
1452
1453 /**
1454 * This class implements a {@code Set} which returns only
1455 * members that are an instance of a specified Class.
1456 */
1457 private class ClassSet<T> extends AbstractSet<T> {
1458
1459 private int which;
1460 private Class<T> c;
1461 private Set<T> set;
1462
1463 ClassSet(int which, Class<T> c) {
1464 this.which = which;
1465 this.c = c;
1466 set = new HashSet<T>();
1467
1468 switch (which) {
1469 case Subject.PRINCIPAL_SET:
1470 synchronized(principals) { populateSet(); }
|