Subject.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package javax.security.auth;
  18. import java.io.IOException;
  19. import java.io.ObjectInputStream;
  20. import java.io.ObjectOutputStream;
  21. import java.io.Serializable;
  22. import java.security.AccessControlContext;
  23. import java.security.AccessController;
  24. import java.security.DomainCombiner;
  25. import java.security.Permission;
  26. import java.security.Principal;
  27. import java.security.PrivilegedAction;
  28. import java.security.PrivilegedActionException;
  29. import java.security.PrivilegedExceptionAction;
  30. import java.security.ProtectionDomain;
  31. import java.util.AbstractSet;
  32. import java.util.Collection;
  33. import java.util.Iterator;
  34. import java.util.LinkedList;
  35. import java.util.Set;
  36. import org.apache.harmony.auth.internal.nls.Messages;
  37. /**
  38. * The central class of the {@code javax.security.auth} package representing an
  39. * authenticated user or entity (both referred to as "subject"). IT defines also
  40. * the static methods that allow code to be run, and do modifications according
  41. * to the subject's permissions.
  42. * <p>
  43. * A subject has the following features:
  44. * <ul>
  45. * <li>A set of {@code Principal} objects specifying the identities bound to a
  46. * {@code Subject} that distinguish it.</li>
  47. * <li>Credentials (public and private) such as certificates, keys, or
  48. * authentication proofs such as tickets</li>
  49. * </ul>
  50. */
  51. public final class Subject implements Serializable {
  52. private static final long serialVersionUID = -8308522755600156056L;
  53. private static final AuthPermission _AS = new AuthPermission("doAs"); //$NON-NLS-1$
  54. private static final AuthPermission _AS_PRIVILEGED = new AuthPermission(
  55. "doAsPrivileged"); //$NON-NLS-1$
  56. private static final AuthPermission _SUBJECT = new AuthPermission(
  57. "getSubject"); //$NON-NLS-1$
  58. private static final AuthPermission _PRINCIPALS = new AuthPermission(
  59. "modifyPrincipals"); //$NON-NLS-1$
  60. private static final AuthPermission _PRIVATE_CREDENTIALS = new AuthPermission(
  61. "modifyPrivateCredentials"); //$NON-NLS-1$
  62. private static final AuthPermission _PUBLIC_CREDENTIALS = new AuthPermission(
  63. "modifyPublicCredentials"); //$NON-NLS-1$
  64. private static final AuthPermission _READ_ONLY = new AuthPermission(
  65. "setReadOnly"); //$NON-NLS-1$
  66. private final Set<Principal> principals;
  67. private boolean readOnly;
  68. // set of private credentials
  69. private transient SecureSet<Object> privateCredentials;
  70. // set of public credentials
  71. private transient SecureSet<Object> publicCredentials;
  72. /**
  73. * The default constructor initializing the sets of public and private
  74. * credentials and principals with the empty set.
  75. */
  76. public Subject() {
  77. super();
  78. principals = new SecureSet<Principal>(_PRINCIPALS);
  79. publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
  80. privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
  81. readOnly = false;
  82. }
  83. /**
  84. * The constructor for the subject, setting its public and private
  85. * credentials and principals according to the arguments.
  86. *
  87. * @param readOnly
  88. * {@code true} if this {@code Subject} is read-only, thus
  89. * preventing any modifications to be done.
  90. * @param subjPrincipals
  91. * the set of Principals that are attributed to this {@code
  92. * Subject}.
  93. * @param pubCredentials
  94. * the set of public credentials that distinguish this {@code
  95. * Subject}.
  96. * @param privCredentials
  97. * the set of private credentials that distinguish this {@code
  98. * Subject}.
  99. */
  100. public Subject(boolean readOnly, Set<? extends Principal> subjPrincipals,
  101. Set<?> pubCredentials, Set<?> privCredentials) {
  102. if (subjPrincipals == null || pubCredentials == null || privCredentials == null) {
  103. throw new NullPointerException();
  104. }
  105. principals = new SecureSet<Principal>(_PRINCIPALS, subjPrincipals);
  106. publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS, pubCredentials);
  107. privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS, privCredentials);
  108. this.readOnly = readOnly;
  109. }
  110. /**
  111. * Runs the code defined by {@code action} using the permissions granted to
  112. * the {@code Subject} itself and to the code as well.
  113. *
  114. * @param subject
  115. * the distinguished {@code Subject}.
  116. * @param action
  117. * the code to be run.
  118. * @return the {@code Object} returned when running the {@code action}.
  119. */
  120. @SuppressWarnings("unchecked")
  121. public static Object doAs(Subject subject, PrivilegedAction action) {
  122. checkPermission(_AS);
  123. return doAs_PrivilegedAction(subject, action, AccessController.getContext());
  124. }
  125. /**
  126. * Run the code defined by {@code action} using the permissions granted to
  127. * the {@code Subject} and to the code itself, additionally providing a more
  128. * specific context.
  129. *
  130. * @param subject
  131. * the distinguished {@code Subject}.
  132. * @param action
  133. * the code to be run.
  134. * @param context
  135. * the specific context in which the {@code action} is invoked.
  136. * if {@code null} a new {@link AccessControlContext} is
  137. * instantiated.
  138. * @return the {@code Object} returned when running the {@code action}.
  139. */
  140. @SuppressWarnings("unchecked")
  141. public static Object doAsPrivileged(Subject subject, PrivilegedAction action,
  142. AccessControlContext context) {
  143. checkPermission(_AS_PRIVILEGED);
  144. if (context == null) {
  145. return doAs_PrivilegedAction(subject, action, new AccessControlContext(
  146. new ProtectionDomain[0]));
  147. }
  148. return doAs_PrivilegedAction(subject, action, context);
  149. }
  150. // instantiates a new context and passes it to AccessController
  151. @SuppressWarnings("unchecked")
  152. private static Object doAs_PrivilegedAction(Subject subject, PrivilegedAction action,
  153. final AccessControlContext context) {
  154. AccessControlContext newContext;
  155. final SubjectDomainCombiner combiner;
  156. if (subject == null) {
  157. // performance optimization
  158. // if subject is null there is nothing to combine
  159. combiner = null;
  160. } else {
  161. combiner = new SubjectDomainCombiner(subject);
  162. }
  163. PrivilegedAction dccAction = new PrivilegedAction() {
  164. public Object run() {
  165. return new AccessControlContext(context, combiner);
  166. }
  167. };
  168. newContext = (AccessControlContext) AccessController.doPrivileged(dccAction);
  169. return AccessController.doPrivileged(action, newContext);
  170. }
  171. /**
  172. * Runs the code defined by {@code action} using the permissions granted to
  173. * the subject and to the code itself.
  174. *
  175. * @param subject
  176. * the distinguished {@code Subject}.
  177. * @param action
  178. * the code to be run.
  179. * @return the {@code Object} returned when running the {@code action}.
  180. * @throws PrivilegedActionException
  181. * if running the {@code action} throws an exception.
  182. */
  183. @SuppressWarnings("unchecked")
  184. public static Object doAs(Subject subject, PrivilegedExceptionAction action)
  185. throws PrivilegedActionException {
  186. checkPermission(_AS);
  187. return doAs_PrivilegedExceptionAction(subject, action, AccessController.getContext());
  188. }
  189. /**
  190. * Runs the code defined by {@code action} using the permissions granted to
  191. * the subject and to the code itself, additionally providing a more
  192. * specific context.
  193. *
  194. * @param subject
  195. * the distinguished {@code Subject}.
  196. * @param action
  197. * the code to be run.
  198. * @param context
  199. * the specific context in which the {@code action} is invoked.
  200. * if {@code null} a new {@link AccessControlContext} is
  201. * instantiated.
  202. * @return the {@code Object} returned when running the {@code action}.
  203. * @throws PrivilegedActionException
  204. * if running the {@code action} throws an exception.
  205. */
  206. @SuppressWarnings("unchecked")
  207. public static Object doAsPrivileged(Subject subject,
  208. PrivilegedExceptionAction action, AccessControlContext context)
  209. throws PrivilegedActionException {
  210. checkPermission(_AS_PRIVILEGED);
  211. if (context == null) {
  212. return doAs_PrivilegedExceptionAction(subject, action,
  213. new AccessControlContext(new ProtectionDomain[0]));
  214. }
  215. return doAs_PrivilegedExceptionAction(subject, action, context);
  216. }
  217. // instantiates a new context and passes it to AccessController
  218. @SuppressWarnings("unchecked")
  219. private static Object doAs_PrivilegedExceptionAction(Subject subject,
  220. PrivilegedExceptionAction action, final AccessControlContext context)
  221. throws PrivilegedActionException {
  222. AccessControlContext newContext;
  223. final SubjectDomainCombiner combiner;
  224. if (subject == null) {
  225. // performance optimization
  226. // if subject is null there is nothing to combine
  227. combiner = null;
  228. } else {
  229. combiner = new SubjectDomainCombiner(subject);
  230. }
  231. PrivilegedAction<AccessControlContext> dccAction = new PrivilegedAction<AccessControlContext>() {
  232. public AccessControlContext run() {
  233. return new AccessControlContext(context, combiner);
  234. }
  235. };
  236. newContext = AccessController.doPrivileged(dccAction);
  237. return AccessController.doPrivileged(action, newContext);
  238. }
  239. /**
  240. * Checks two Subjects for equality. More specifically if the principals,
  241. * public and private credentials are equal, equality for two {@code
  242. * Subjects} is implied.
  243. *
  244. * @param obj
  245. * the {@code Object} checked for equality with this {@code
  246. * Subject}.
  247. * @return {@code true} if the specified {@code Subject} is equal to this
  248. * one.
  249. */
  250. @Override
  251. public boolean equals(Object obj) {
  252. if (this == obj) {
  253. return true;
  254. }
  255. if (obj == null || this.getClass() != obj.getClass()) {
  256. return false;
  257. }
  258. Subject that = (Subject) obj;
  259. if (principals.equals(that.principals)
  260. && publicCredentials.equals(that.publicCredentials)
  261. && privateCredentials.equals(that.privateCredentials)) {
  262. return true;
  263. }
  264. return false;
  265. }
  266. /**
  267. * Returns this {@code Subject}'s {@link Principal}.
  268. *
  269. * @return this {@code Subject}'s {@link Principal}.
  270. */
  271. public Set<Principal> getPrincipals() {
  272. return principals;
  273. }
  274. /**
  275. * Returns this {@code Subject}'s {@link Principal} which is a subclass of
  276. * the {@code Class} provided.
  277. *
  278. * @param c
  279. * the {@code Class} as a criteria which the {@code Principal}
  280. * returned must satisfy.
  281. * @return this {@code Subject}'s {@link Principal}. Modifications to the
  282. * returned set of {@code Principal}s do not affect this {@code
  283. * Subject}'s set.
  284. */
  285. public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
  286. return ((SecureSet<Principal>) principals).get(c);
  287. }
  288. /**
  289. * Returns the private credentials associated with this {@code Subject}.
  290. *
  291. * @return the private credentials associated with this {@code Subject}.
  292. */
  293. public Set<Object> getPrivateCredentials() {
  294. return privateCredentials;
  295. }
  296. /**
  297. * Returns this {@code Subject}'s private credentials which are a subclass
  298. * of the {@code Class} provided.
  299. *
  300. * @param c
  301. * the {@code Class} as a criteria which the private credentials
  302. * returned must satisfy.
  303. * @return this {@code Subject}'s private credentials. Modifications to the
  304. * returned set of credentials do not affect this {@code Subject}'s
  305. * credentials.
  306. */
  307. public <T> Set<T> getPrivateCredentials(Class<T> c) {
  308. return privateCredentials.get(c);
  309. }
  310. /**
  311. * Returns the public credentials associated with this {@code Subject}.
  312. *
  313. * @return the public credentials associated with this {@code Subject}.
  314. */
  315. public Set<Object> getPublicCredentials() {
  316. return publicCredentials;
  317. }
  318. /**
  319. * Returns this {@code Subject}'s public credentials which are a subclass of
  320. * the {@code Class} provided.
  321. *
  322. * @param c
  323. * the {@code Class} as a criteria which the public credentials
  324. * returned must satisfy.
  325. * @return this {@code Subject}'s public credentials. Modifications to the
  326. * returned set of credentials do not affect this {@code Subject}'s
  327. * credentials.
  328. */
  329. public <T> Set<T> getPublicCredentials(Class<T> c) {
  330. return publicCredentials.get(c);
  331. }
  332. /**
  333. * Returns a hash code of this {@code Subject}.
  334. *
  335. * @return a hash code of this {@code Subject}.
  336. */
  337. @Override
  338. public int hashCode() {
  339. return principals.hashCode() + privateCredentials.hashCode()
  340. + publicCredentials.hashCode();
  341. }
  342. /**
  343. * Prevents from modifications being done to the credentials and {@link
  344. * Principal} sets. After setting it to read-only this {@code Subject} can
  345. * not be made writable again. The destroy method on the credentials still
  346. * works though.
  347. */
  348. public void setReadOnly() {
  349. checkPermission(_READ_ONLY);
  350. readOnly = true;
  351. }
  352. /**
  353. * Returns whether this {@code Subject} is read-only or not.
  354. *
  355. * @return whether this {@code Subject} is read-only or not.
  356. */
  357. public boolean isReadOnly() {
  358. return readOnly;
  359. }
  360. /**
  361. * Returns a {@code String} representation of this {@code Subject}.
  362. *
  363. * @return a {@code String} representation of this {@code Subject}.
  364. */
  365. @Override
  366. public String toString() {
  367. StringBuilder buf = new StringBuilder("Subject:\n"); //$NON-NLS-1$
  368. Iterator<?> it = principals.iterator();
  369. while (it.hasNext()) {
  370. buf.append("\tPrincipal: "); //$NON-NLS-1$
  371. buf.append(it.next());
  372. buf.append('\n');
  373. }
  374. it = publicCredentials.iterator();
  375. while (it.hasNext()) {
  376. buf.append("\tPublic Credential: "); //$NON-NLS-1$
  377. buf.append(it.next());
  378. buf.append('\n');
  379. }
  380. int offset = buf.length() - 1;
  381. it = privateCredentials.iterator();
  382. try {
  383. while (it.hasNext()) {
  384. buf.append("\tPrivate Credential: "); //$NON-NLS-1$
  385. buf.append(it.next());
  386. buf.append('\n');
  387. }
  388. } catch (SecurityException e) {
  389. buf.delete(offset, buf.length());
  390. buf.append("\tPrivate Credentials: no accessible information\n"); //$NON-NLS-1$
  391. }
  392. return buf.toString();
  393. }
  394. private void readObject(ObjectInputStream in) throws IOException,
  395. ClassNotFoundException {
  396. in.defaultReadObject();
  397. publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
  398. privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
  399. }
  400. private void writeObject(ObjectOutputStream out) throws IOException {
  401. out.defaultWriteObject();
  402. }
  403. /**
  404. * Returns the {@code Subject} that was last associated with the {@code
  405. * context} provided as argument.
  406. *
  407. * @param context
  408. * the {@code context} that was associated with the
  409. * {@code Subject}.
  410. * @return the {@code Subject} that was last associated with the {@code
  411. * context} provided as argument.
  412. */
  413. public static Subject getSubject(final AccessControlContext context) {
  414. checkPermission(_SUBJECT);
  415. if (context == null) {
  416. throw new NullPointerException(Messages.getString("auth.09")); //$NON-NLS-1$
  417. }
  418. PrivilegedAction<DomainCombiner> action = new PrivilegedAction<DomainCombiner>() {
  419. public DomainCombiner run() {
  420. return context.getDomainCombiner();
  421. }
  422. };
  423. DomainCombiner combiner = AccessController.doPrivileged(action);
  424. if ((combiner == null) || !(combiner instanceof SubjectDomainCombiner)) {
  425. return null;
  426. }
  427. return ((SubjectDomainCombiner) combiner).getSubject();
  428. }
  429. // checks passed permission
  430. private static void checkPermission(Permission p) {
  431. SecurityManager sm = System.getSecurityManager();
  432. if (sm != null) {
  433. sm.checkPermission(p);
  434. }
  435. }
  436. // FIXME is used only in two places. remove?
  437. private void checkState() {
  438. if (readOnly) {
  439. throw new IllegalStateException(Messages.getString("auth.0A")); //$NON-NLS-1$
  440. }
  441. }
  442. private final class SecureSet<SST> extends AbstractSet<SST> implements Serializable {
  443. /**
  444. * Compatibility issue: see comments for setType variable
  445. */
  446. private static final long serialVersionUID = 7911754171111800359L;
  447. private LinkedList<SST> elements;
  448. /*
  449. * Is used to define a set type for serialization.
  450. *
  451. * A type can be principal, priv. or pub. credential set. The spec.
  452. * doesn't clearly says that priv. and pub. credential sets can be
  453. * serialized and what classes they are. It is only possible to figure
  454. * out from writeObject method comments that priv. credential set is
  455. * serializable and it is an instance of SecureSet class. So pub.
  456. * credential was implemented by analogy
  457. *
  458. * Compatibility issue: the class follows its specified serial form.
  459. * Also according to the serialization spec. adding new field is a
  460. * compatible change. So is ok for principal set (because the default
  461. * value for integer is zero). But priv. or pub. credential set it is
  462. * not compatible because most probably other implementations resolve
  463. * this issue in other way
  464. */
  465. private int setType;
  466. // Defines principal set for serialization.
  467. private static final int SET_Principal = 0;
  468. // Defines private credential set for serialization.
  469. private static final int SET_PrivCred = 1;
  470. // Defines public credential set for serialization.
  471. private static final int SET_PubCred = 2;
  472. // permission required to modify set
  473. private transient AuthPermission permission;
  474. protected SecureSet(AuthPermission perm) {
  475. permission = perm;
  476. elements = new LinkedList<SST>();
  477. }
  478. // creates set from specified collection with specified permission
  479. // all collection elements are verified before adding
  480. protected SecureSet(AuthPermission perm, Collection<? extends SST> s) {
  481. this(perm);
  482. // Subject's constructor receives a Set, we can trusts if a set is from bootclasspath,
  483. // and not to check whether it contains duplicates or not
  484. boolean trust = s.getClass().getClassLoader() == null;
  485. Iterator<? extends SST> it = s.iterator();
  486. while (it.hasNext()) {
  487. SST o = it.next();
  488. verifyElement(o);
  489. if (trust || !elements.contains(o)) {
  490. elements.add(o);
  491. }
  492. }
  493. }
  494. // verifies new set element
  495. private void verifyElement(Object o) {
  496. if (o == null) {
  497. throw new NullPointerException();
  498. }
  499. if (permission == _PRINCIPALS && !(Principal.class.isAssignableFrom(o.getClass()))) {
  500. throw new IllegalArgumentException(Messages.getString("auth.0B")); //$NON-NLS-1$
  501. }
  502. }
  503. /*
  504. * verifies specified element, checks set state, and security permission
  505. * to modify set before adding new element
  506. */
  507. @Override
  508. public boolean add(SST o) {
  509. verifyElement(o);
  510. checkState();
  511. checkPermission(permission);
  512. if (!elements.contains(o)) {
  513. elements.add(o);
  514. return true;
  515. }
  516. return false;
  517. }
  518. // returns an instance of SecureIterator
  519. @Override
  520. public Iterator<SST> iterator() {
  521. if (permission == _PRIVATE_CREDENTIALS) {
  522. /*
  523. * private credential set requires iterator with additional
  524. * security check (PrivateCredentialPermission)
  525. */
  526. return new SecureIterator(elements.iterator()) {
  527. /*
  528. * checks permission to access next private credential moves
  529. * to the next element even SecurityException was thrown
  530. */
  531. @Override
  532. public SST next() {
  533. SST obj = iterator.next();
  534. checkPermission(new PrivateCredentialPermission(obj
  535. .getClass().getName(), principals));
  536. return obj;
  537. }
  538. };
  539. }
  540. return new SecureIterator(elements.iterator());
  541. }
  542. @Override
  543. public boolean retainAll(Collection<?> c) {
  544. if (c == null) {
  545. throw new NullPointerException();
  546. }
  547. return super.retainAll(c);
  548. }
  549. @Override
  550. public int size() {
  551. return elements.size();
  552. }
  553. /**
  554. * return set with elements that are instances or subclasses of the
  555. * specified class
  556. */
  557. protected final <E> Set<E> get(final Class<E> c) {
  558. if (c == null) {
  559. throw new NullPointerException();
  560. }
  561. AbstractSet<E> s = new AbstractSet<E>() {
  562. private LinkedList<E> elements = new LinkedList<E>();
  563. @Override
  564. public boolean add(E o) {
  565. if (!c.isAssignableFrom(o.getClass())) {
  566. throw new IllegalArgumentException(
  567. Messages.getString("auth.0C", c.getName())); //$NON-NLS-1$
  568. }
  569. if (elements.contains(o)) {
  570. return false;
  571. }
  572. elements.add(o);
  573. return true;
  574. }
  575. @Override
  576. public Iterator<E> iterator() {
  577. return elements.iterator();
  578. }
  579. @Override
  580. public boolean retainAll(Collection<?> c) {
  581. if (c == null) {
  582. throw new NullPointerException();
  583. }
  584. return super.retainAll(c);
  585. }
  586. @Override
  587. public int size() {
  588. return elements.size();
  589. }
  590. };
  591. // FIXME must have permissions for requested priv. credentials
  592. for (Iterator<SST> it = iterator(); it.hasNext();) {
  593. SST o = it.next();
  594. if (c.isAssignableFrom(o.getClass())) {
  595. s.add(c.cast(o));
  596. }
  597. }
  598. return s;
  599. }
  600. private void readObject(ObjectInputStream in) throws IOException,
  601. ClassNotFoundException {
  602. in.defaultReadObject();
  603. switch (setType) {
  604. case SET_Principal:
  605. permission = _PRINCIPALS;
  606. break;
  607. case SET_PrivCred:
  608. permission = _PRIVATE_CREDENTIALS;
  609. break;
  610. case SET_PubCred:
  611. permission = _PUBLIC_CREDENTIALS;
  612. break;
  613. default:
  614. throw new IllegalArgumentException();
  615. }
  616. Iterator<SST> it = elements.iterator();
  617. while (it.hasNext()) {
  618. verifyElement(it.next());
  619. }
  620. }
  621. private void writeObject(ObjectOutputStream out) throws IOException {
  622. if (permission == _PRIVATE_CREDENTIALS) {
  623. // does security check for each private credential
  624. for (Iterator<SST> it = iterator(); it.hasNext();) {
  625. it.next();
  626. }
  627. setType = SET_PrivCred;
  628. } else if (permission == _PRINCIPALS) {
  629. setType = SET_Principal;
  630. } else {
  631. setType = SET_PubCred;
  632. }
  633. out.defaultWriteObject();
  634. }
  635. /**
  636. * Represents iterator for subject's secure set
  637. */
  638. private class SecureIterator implements Iterator<SST> {
  639. protected Iterator<SST> iterator;
  640. protected SecureIterator(Iterator<SST> iterator) {
  641. this.iterator = iterator;
  642. }
  643. public boolean hasNext() {
  644. return iterator.hasNext();
  645. }
  646. public SST next() {
  647. return iterator.next();
  648. }
  649. /**
  650. * checks set state, and security permission to modify set before
  651. * removing current element
  652. */
  653. public void remove() {
  654. checkState();
  655. checkPermission(permission);
  656. iterator.remove();
  657. }
  658. }
  659. }
  660. }