1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53:
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61:
62: public final class Subject implements Serializable
63: {
64:
65:
66:
67: private static final long serialVersionUID = -8308522755600156056L;
68:
69:
73: private final Set principals;
74:
75:
78: private boolean readOnly;
79:
80: private final transient SecureSet pubCred;
81: private final transient SecureSet privCred;
82:
83:
84:
85:
86: public Subject()
87: {
88: principals = new SecureSet (this, SecureSet.PRINCIPALS);
89: pubCred = new SecureSet (this, SecureSet.PUBLIC_CREDENTIALS);
90: privCred = new SecureSet (this, SecureSet.PRIVATE_CREDENTIALS);
91: readOnly = false;
92: }
93:
94: public Subject (final boolean readOnly, final Set principals,
95: final Set pubCred, final Set privCred)
96: {
97: if (principals == null || pubCred == null || privCred == null)
98: {
99: throw new NullPointerException();
100: }
101: this.principals = new SecureSet (this, SecureSet.PRINCIPALS, principals);
102: this.pubCred = new SecureSet (this, SecureSet.PUBLIC_CREDENTIALS, pubCred);
103: this.privCred = new SecureSet (this, SecureSet.PRIVATE_CREDENTIALS, privCred);
104: this.readOnly = readOnly;
105: }
106:
107:
108:
109:
110:
125: public static Subject getSubject (final AccessControlContext context)
126: {
127: final SecurityManager sm = System.getSecurityManager();
128: if (sm != null)
129: {
130: sm.checkPermission (new AuthPermission ("getSubject"));
131: }
132: DomainCombiner dc = context.getDomainCombiner();
133: if (!(dc instanceof SubjectDomainCombiner))
134: {
135: return null;
136: }
137: return ((SubjectDomainCombiner) dc).getSubject();
138: }
139:
140:
152: public static Object doAs (final Subject subject, final PrivilegedAction action)
153: {
154: final SecurityManager sm = System.getSecurityManager();
155: if (sm != null)
156: {
157: sm.checkPermission (new AuthPermission ("doAs"));
158: }
159: AccessControlContext context =
160: new AccessControlContext (AccessController.getContext(),
161: new SubjectDomainCombiner (subject));
162: return AccessController.doPrivileged (action, context);
163: }
164:
165:
178: public static Object doAs (final Subject subject,
179: final PrivilegedExceptionAction action)
180: throws PrivilegedActionException
181: {
182: final SecurityManager sm = System.getSecurityManager();
183: if (sm != null)
184: {
185: sm.checkPermission (new AuthPermission ("doAs"));
186: }
187: AccessControlContext context =
188: new AccessControlContext (AccessController.getContext(),
189: new SubjectDomainCombiner(subject));
190: return AccessController.doPrivileged (action, context);
191: }
192:
193:
207: public static Object doAsPrivileged (final Subject subject,
208: final PrivilegedAction action,
209: final AccessControlContext acc)
210: {
211: final SecurityManager sm = System.getSecurityManager();
212: if (sm != null)
213: {
214: sm.checkPermission (new AuthPermission ("doAsPrivileged"));
215: }
216: AccessControlContext context =
217: new AccessControlContext (acc, new SubjectDomainCombiner (subject));
218: return AccessController.doPrivileged (action, context);
219: }
220:
221:
236: public static Object doAsPrivileged (final Subject subject,
237: final PrivilegedExceptionAction action,
238: AccessControlContext acc)
239: throws PrivilegedActionException
240: {
241: final SecurityManager sm = System.getSecurityManager();
242: if (sm != null)
243: {
244: sm.checkPermission (new AuthPermission ("doAsPrivileged"));
245: }
246: if (acc == null)
247: acc = new AccessControlContext (new java.security.ProtectionDomain[0]);
248: AccessControlContext context =
249: new AccessControlContext (acc, new SubjectDomainCombiner (subject));
250: return AccessController.doPrivileged (action, context);
251: }
252:
253:
254:
255:
256: public boolean equals (Object o)
257: {
258: if (!(o instanceof Subject))
259: {
260: return false;
261: }
262: Subject that = (Subject) o;
263: return principals.containsAll (that.getPrincipals()) &&
264: pubCred.containsAll (that.getPublicCredentials()) &&
265: privCred.containsAll (that.getPrivateCredentials());
266: }
267:
268: public Set getPrincipals()
269: {
270: return principals;
271: }
272:
273: public Set getPrincipals(Class clazz)
274: {
275: HashSet result = new HashSet (principals.size());
276: for (Iterator it = principals.iterator(); it.hasNext(); )
277: {
278: Object o = it.next();
279: if (o != null && clazz.isAssignableFrom (o.getClass()))
280: {
281: result.add(o);
282: }
283: }
284: return Collections.unmodifiableSet (result);
285: }
286:
287: public Set getPrivateCredentials()
288: {
289: return privCred;
290: }
291:
292: public Set getPrivateCredentials (Class clazz)
293: {
294: HashSet result = new HashSet (privCred.size());
295: for (Iterator it = privCred.iterator(); it.hasNext(); )
296: {
297: Object o = it.next();
298: if (o != null && clazz.isAssignableFrom (o.getClass()))
299: {
300: result.add(o);
301: }
302: }
303: return Collections.unmodifiableSet (result);
304: }
305:
306: public Set getPublicCredentials()
307: {
308: return pubCred;
309: }
310:
311: public Set getPublicCredentials (Class clazz)
312: {
313: HashSet result = new HashSet (pubCred.size());
314: for (Iterator it = pubCred.iterator(); it.hasNext(); )
315: {
316: Object o = it.next();
317: if (o != null && clazz.isAssignableFrom (o.getClass()))
318: {
319: result.add(o);
320: }
321: }
322: return Collections.unmodifiableSet (result);
323: }
324:
325: public int hashCode()
326: {
327: return principals.hashCode() + privCred.hashCode() + pubCred.hashCode();
328: }
329:
330:
335: public boolean isReadOnly()
336: {
337: return readOnly;
338: }
339:
340:
347: public void setReadOnly()
348: {
349: final SecurityManager sm = System.getSecurityManager();
350: if (sm != null)
351: {
352: sm.checkPermission (new AuthPermission ("setReadOnly"));
353: }
354: readOnly = true;
355: }
356:
357: public String toString()
358: {
359: return Subject.class.getName() + " [ principals=" + principals +
360: ", private credentials=" + privCred + ", public credentials=" +
361: pubCred + ", read-only=" + readOnly + " ]";
362: }
363:
364:
365:
366:
367:
370: private static class SecureSet extends AbstractSet implements Serializable
371: {
372:
373:
374:
375: private static final long serialVersionUID = 7911754171111800359L;
376:
377: static final int PRINCIPALS = 0;
378: static final int PUBLIC_CREDENTIALS = 1;
379: static final int PRIVATE_CREDENTIALS = 2;
380:
381: private final Subject subject;
382: private final LinkedList elements;
383: private final transient int type;
384:
385:
386:
387:
388: SecureSet (final Subject subject, final int type, final Collection inElements)
389: {
390: this (subject, type);
391: for (Iterator it = inElements.iterator(); it.hasNext(); )
392: {
393: Object o = it.next();
394: if (type == PRINCIPALS && !(o instanceof Principal))
395: {
396: throw new IllegalArgumentException(o+" is not a Principal");
397: }
398: if (!this.elements.contains (o))
399: {
400: this.elements.add (o);
401: }
402: }
403: }
404:
405: SecureSet (final Subject subject, final int type)
406: {
407: this.subject = subject;
408: this.type = type;
409: this.elements = new LinkedList();
410: }
411:
412:
413:
414:
415: public synchronized int size()
416: {
417: return elements.size();
418: }
419:
420: public Iterator iterator()
421: {
422: return elements.iterator();
423: }
424:
425: public synchronized boolean add(Object element)
426: {
427: if (subject.isReadOnly())
428: {
429: throw new IllegalStateException ("subject is read-only");
430: }
431: final SecurityManager sm = System.getSecurityManager();
432: switch (type)
433: {
434: case PRINCIPALS:
435: if (sm != null)
436: {
437: sm.checkPermission (new AuthPermission ("modifyPrincipals"));
438: }
439: if (!(element instanceof Principal))
440: {
441: throw new IllegalArgumentException ("element is not a Principal");
442: }
443: break;
444:
445: case PUBLIC_CREDENTIALS:
446: if (sm != null)
447: {
448: sm.checkPermission (new AuthPermission ("modifyPublicCredentials"));
449: }
450: break;
451:
452: case PRIVATE_CREDENTIALS:
453: if (sm != null)
454: {
455: sm.checkPermission (new AuthPermission ("modifyPrivateCredentials"));
456: }
457: break;
458:
459: default:
460: throw new Error ("this statement should be unreachable");
461: }
462:
463: if (elements.contains (element))
464: {
465: return false;
466: }
467:
468: return elements.add (element);
469: }
470:
471: public synchronized boolean remove (final Object element)
472: {
473: if (subject.isReadOnly())
474: {
475: throw new IllegalStateException ("subject is read-only");
476: }
477: final SecurityManager sm = System.getSecurityManager();
478: switch (type)
479: {
480: case PRINCIPALS:
481: if (sm != null)
482: {
483: sm.checkPermission (new AuthPermission ("modifyPrincipals"));
484: }
485: if (!(element instanceof Principal))
486: {
487: throw new IllegalArgumentException ("element is not a Principal");
488: }
489: break;
490:
491: case PUBLIC_CREDENTIALS:
492: if (sm != null)
493: {
494: sm.checkPermission (new AuthPermission ("modifyPublicCredentials"));
495: }
496: break;
497:
498: case PRIVATE_CREDENTIALS:
499: if (sm != null)
500: {
501: sm.checkPermission (new AuthPermission ("modifyPrivateCredentials"));
502: }
503: break;
504:
505: default:
506: throw new Error("this statement should be unreachable");
507: }
508:
509: return elements.remove(element);
510: }
511:
512: public synchronized boolean contains (final Object element)
513: {
514: return elements.contains (element);
515: }
516:
517: public boolean removeAll (final Collection c)
518: {
519: if (subject.isReadOnly())
520: {
521: throw new IllegalStateException ("subject is read-only");
522: }
523: return super.removeAll (c);
524: }
525:
526: public boolean retainAll (final Collection c)
527: {
528: if (subject.isReadOnly())
529: {
530: throw new IllegalStateException ("subject is read-only");
531: }
532: return super.retainAll (c);
533: }
534:
535: public void clear()
536: {
537: if (subject.isReadOnly())
538: {
539: throw new IllegalStateException ("subject is read-only");
540: }
541: elements.clear();
542: }
543:
544: private synchronized void writeObject (ObjectOutputStream out)
545: throws IOException
546: {
547: throw new UnsupportedOperationException ("FIXME: determine serialization");
548: }
549:
550: private void readObject (ObjectInputStream in)
551: throws ClassNotFoundException, IOException
552: {
553: throw new UnsupportedOperationException ("FIXME: determine serialization");
554: }
555: }
556: }