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