Home » openjdk-7 » javax.security » auth » [javadoc | source]

    1   /*
    2    * Copyright (c) 1998, 2010, 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
   23    * questions.
   24    */
   25   
   26   package javax.security.auth;
   27   
   28   import java.util;
   29   import java.io;
   30   import java.lang.reflect;
   31   import java.text.MessageFormat;
   32   import java.security.AccessController;
   33   import java.security.AccessControlContext;
   34   import java.security.DomainCombiner;
   35   import java.security.Permission;
   36   import java.security.PermissionCollection;
   37   import java.security.Principal;
   38   import java.security.PrivilegedAction;
   39   import java.security.PrivilegedExceptionAction;
   40   import java.security.PrivilegedActionException;
   41   import java.security.ProtectionDomain;
   42   import sun.security.util.ResourcesMgr;
   43   
   44   /**
   45    * <p> A <code>Subject</code> represents a grouping of related information
   46    * for a single entity, such as a person.
   47    * Such information includes the Subject's identities as well as
   48    * its security-related attributes
   49    * (passwords and cryptographic keys, for example).
   50    *
   51    * <p> Subjects may potentially have multiple identities.
   52    * Each identity is represented as a <code>Principal</code>
   53    * within the <code>Subject</code>.  Principals simply bind names to a
   54    * <code>Subject</code>.  For example, a <code>Subject</code> that happens
   55    * to be a person, Alice, might have two Principals:
   56    * one which binds "Alice Bar", the name on her driver license,
   57    * to the <code>Subject</code>, and another which binds,
   58    * "999-99-9999", the number on her student identification card,
   59    * to the <code>Subject</code>.  Both Principals refer to the same
   60    * <code>Subject</code> even though each has a different name.
   61    *
   62    * <p> A <code>Subject</code> may also own security-related attributes,
   63    * which are referred to as credentials.
   64    * Sensitive credentials that require special protection, such as
   65    * private cryptographic keys, are stored within a private credential
   66    * <code>Set</code>.  Credentials intended to be shared, such as
   67    * public key certificates or Kerberos server tickets are stored
   68    * within a public credential <code>Set</code>.  Different permissions
   69    * are required to access and modify the different credential Sets.
   70    *
   71    * <p> To retrieve all the Principals associated with a <code>Subject</code>,
   72    * invoke the <code>getPrincipals</code> method.  To retrieve
   73    * all the public or private credentials belonging to a <code>Subject</code>,
   74    * invoke the <code>getPublicCredentials</code> method or
   75    * <code>getPrivateCredentials</code> method, respectively.
   76    * To modify the returned <code>Set</code> of Principals and credentials,
   77    * use the methods defined in the <code>Set</code> class.
   78    * For example:
   79    * <pre>
   80    *      Subject subject;
   81    *      Principal principal;
   82    *      Object credential;
   83    *
   84    *      // add a Principal and credential to the Subject
   85    *      subject.getPrincipals().add(principal);
   86    *      subject.getPublicCredentials().add(credential);
   87    * </pre>
   88    *
   89    * <p> This <code>Subject</code> class implements <code>Serializable</code>.
   90    * While the Principals associated with the <code>Subject</code> are serialized,
   91    * the credentials associated with the <code>Subject</code> are not.
   92    * Note that the <code>java.security.Principal</code> class
   93    * does not implement <code>Serializable</code>.  Therefore all concrete
   94    * <code>Principal</code> implementations associated with Subjects
   95    * must implement <code>Serializable</code>.
   96    *
   97    * @see java.security.Principal
   98    * @see java.security.DomainCombiner
   99    */
  100   public final class Subject implements java.io.Serializable {
  101   
  102       private static final long serialVersionUID = -8308522755600156056L;
  103   
  104       /**
  105        * A <code>Set</code> that provides a view of all of this
  106        * Subject's Principals
  107        *
  108        * <p>
  109        *
  110        * @serial Each element in this set is a
  111        *          <code>java.security.Principal</code>.
  112        *          The set is a <code>Subject.SecureSet</code>.
  113        */
  114       Set<Principal> principals;
  115   
  116       /**
  117        * Sets that provide a view of all of this
  118        * Subject's Credentials
  119        */
  120       transient Set<Object> pubCredentials;
  121       transient Set<Object> privCredentials;
  122   
  123       /**
  124        * Whether this Subject is read-only
  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</code>
  139        * with an empty <code>Set</code> of Principals and empty
  140        * Sets of public and private credentials.
  141        *
  142        * <p> The newly constructed Sets check whether this <code>Subject</code>
  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")</code>.
  149        * To modify the public credential Set, the caller must have
  150        * <code>AuthPermission("modifyPublicCredentials")</code>.
  151        * To modify the private credential Set, the caller must have
  152        * <code>AuthPermission("modifyPrivateCredentials")</code>.
  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</code> 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</code>
  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")</code>.
  177        * To modify the public credential Set, the caller must have
  178        * <code>AuthPermission("modifyPublicCredentials")</code>.
  179        * To modify the private credential Set, the caller must have
  180        * <code>AuthPermission("modifyPrivateCredentials")</code>.
  181        * <p>
  182        *
  183        * @param readOnly true if the <code>Subject</code> is to be read-only,
  184        *          and false otherwise. <p>
  185        *
  186        * @param principals the <code>Set</code> of Principals
  187        *          to be associated with this <code>Subject</code>. <p>
  188        *
  189        * @param pubCredentials the <code>Set</code> of public credentials
  190        *          to be associated with this <code>Subject</code>. <p>
  191        *
  192        * @param privCredentials the <code>Set</code> of private credentials
  193        *          to be associated with this <code>Subject</code>.
  194        *
  195        * @exception NullPointerException if the specified
  196        *          <code>principals</code>, <code>pubCredentials</code>,
  197        *          or <code>privCredentials</code> are <code>null</code>.
  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</code> to be read-only.
  220        *
  221        * <p> Modifications (additions and removals) to this Subject's
  222        * <code>Principal</code> <code>Set</code> and
  223        * credential Sets will be disallowed.
  224        * The <code>destroy</code> operation on this Subject's credentials will
  225        * still be permitted.
  226        *
  227        * <p> Subsequent attempts to modify the Subject's <code>Principal</code>
  228        * and credential Sets will result in an
  229        * <code>IllegalStateException</code> being thrown.
  230        * Also, once a <code>Subject</code> is read-only,
  231        * it can not be reset to being writable again.
  232        *
  233        * <p>
  234        *
  235        * @exception SecurityException if the caller does not have permission
  236        *          to set this <code>Subject</code> to be read-only.
  237        */
  238       public void setReadOnly() {
  239           java.lang.SecurityManager sm = System.getSecurityManager();
  240           if (sm != null) {
  241               sm.checkPermission(AuthPermissionHolder.SET_READ_ONLY_PERMISSION);
  242           }
  243   
  244           this.readOnly = true;
  245       }
  246   
  247       /**
  248        * Query whether this <code>Subject</code> is read-only.
  249        *
  250        * <p>
  251        *
  252        * @return true if this <code>Subject</code> is read-only, false otherwise.
  253        */
  254       public boolean isReadOnly() {
  255           return this.readOnly;
  256       }
  257   
  258       /**
  259        * Get the <code>Subject</code> associated with the provided
  260        * <code>AccessControlContext</code>.
  261        *
  262        * <p> The <code>AccessControlContext</code> may contain many
  263        * Subjects (from nested <code>doAs</code> calls).
  264        * In this situation, the most recent <code>Subject</code> associated
  265        * with the <code>AccessControlContext</code> is returned.
  266        *
  267        * <p>
  268        *
  269        * @param  acc the <code>AccessControlContext</code> from which to retrieve
  270        *          the <code>Subject</code>.
  271        *
  272        * @return  the <code>Subject</code> associated with the provided
  273        *          <code>AccessControlContext</code>, or <code>null</code>
  274        *          if no <code>Subject</code> is associated
  275        *          with the provided <code>AccessControlContext</code>.
  276        *
  277        * @exception SecurityException if the caller does not have permission
  278        *          to get the <code>Subject</code>. <p>
  279        *
  280        * @exception NullPointerException if the provided
  281        *          <code>AccessControlContext</code> is <code>null</code>.
  282        */
  283       public static Subject getSubject(final AccessControlContext acc) {
  284   
  285           java.lang.SecurityManager sm = System.getSecurityManager();
  286           if (sm != null) {
  287               sm.checkPermission(AuthPermissionHolder.GET_SUBJECT_PERMISSION);
  288           }
  289   
  290           if (acc == null) {
  291               throw new NullPointerException(ResourcesMgr.getString
  292                   ("invalid.null.AccessControlContext.provided"));
  293           }
  294   
  295           // return the Subject from the DomainCombiner of the provided context
  296           return AccessController.doPrivileged
  297               (new java.security.PrivilegedAction<Subject>() {
  298               public Subject run() {
  299                   DomainCombiner dc = acc.getDomainCombiner();
  300                   if (!(dc instanceof SubjectDomainCombiner))
  301                       return null;
  302                   SubjectDomainCombiner sdc = (SubjectDomainCombiner)dc;
  303                   return sdc.getSubject();
  304               }
  305           });
  306       }
  307   
  308       /**
  309        * Perform work as a particular <code>Subject</code>.
  310        *
  311        * <p> This method first retrieves the current Thread's
  312        * <code>AccessControlContext</code> via
  313        * <code>AccessController.getContext</code>,
  314        * and then instantiates a new <code>AccessControlContext</code>
  315        * using the retrieved context along with a new
  316        * <code>SubjectDomainCombiner</code> (constructed using
  317        * the provided <code>Subject</code>).
  318        * Finally, this method invokes <code>AccessController.doPrivileged</code>,
  319        * passing it the provided <code>PrivilegedAction</code>,
  320        * as well as the newly constructed <code>AccessControlContext</code>.
  321        *
  322        * <p>
  323        *
  324        * @param subject the <code>Subject</code> that the specified
  325        *                  <code>action</code> will run as.  This parameter
  326        *                  may be <code>null</code>. <p>
  327        *
  328        * @param action the code to be run as the specified
  329        *                  <code>Subject</code>. <p>
  330        *
  331        * @return the value returned by the PrivilegedAction's
  332        *                  <code>run</code> method.
  333        *
  334        * @exception NullPointerException if the <code>PrivilegedAction</code>
  335        *                  is <code>null</code>. <p>
  336        *
  337        * @exception SecurityException if the caller does not have permission
  338        *                  to invoke this method.
  339        */
  340       public static <T> T doAs(final Subject subject,
  341                           final java.security.PrivilegedAction<T> action) {
  342   
  343           java.lang.SecurityManager sm = System.getSecurityManager();
  344           if (sm != null) {
  345               sm.checkPermission(AuthPermissionHolder.DO_AS_PERMISSION);
  346           }
  347           if (action == null)
  348               throw new NullPointerException
  349                   (ResourcesMgr.getString("invalid.null.action.provided"));
  350   
  351           // set up the new Subject-based AccessControlContext
  352           // for doPrivileged
  353           final AccessControlContext currentAcc = AccessController.getContext();
  354   
  355           // call doPrivileged and push this new context on the stack
  356           return java.security.AccessController.doPrivileged
  357                                           (action,
  358                                           createContext(subject, currentAcc));
  359       }
  360   
  361       /**
  362        * Perform work as a particular <code>Subject</code>.
  363        *
  364        * <p> This method first retrieves the current Thread's
  365        * <code>AccessControlContext</code> via
  366        * <code>AccessController.getContext</code>,
  367        * and then instantiates a new <code>AccessControlContext</code>
  368        * using the retrieved context along with a new
  369        * <code>SubjectDomainCombiner</code> (constructed using
  370        * the provided <code>Subject</code>).
  371        * Finally, this method invokes <code>AccessController.doPrivileged</code>,
  372        * passing it the provided <code>PrivilegedExceptionAction</code>,
  373        * as well as the newly constructed <code>AccessControlContext</code>.
  374        *
  375        * <p>
  376        *
  377        * @param subject the <code>Subject</code> that the specified
  378        *                  <code>action</code> will run as.  This parameter
  379        *                  may be <code>null</code>. <p>
  380        *
  381        * @param action the code to be run as the specified
  382        *                  <code>Subject</code>. <p>
  383        *
  384        * @return the value returned by the
  385        *                  PrivilegedExceptionAction's <code>run</code> method.
  386        *
  387        * @exception PrivilegedActionException if the
  388        *                  <code>PrivilegedExceptionAction.run</code>
  389        *                  method throws a checked exception. <p>
  390        *
  391        * @exception NullPointerException if the specified
  392        *                  <code>PrivilegedExceptionAction</code> is
  393        *                  <code>null</code>. <p>
  394        *
  395        * @exception SecurityException if the caller does not have permission
  396        *                  to invoke this method.
  397        */
  398       public static <T> T doAs(final Subject subject,
  399                           final java.security.PrivilegedExceptionAction<T> action)
  400                           throws java.security.PrivilegedActionException {
  401   
  402           java.lang.SecurityManager sm = System.getSecurityManager();
  403           if (sm != null) {
  404               sm.checkPermission(AuthPermissionHolder.DO_AS_PERMISSION);
  405           }
  406   
  407           if (action == null)
  408               throw new NullPointerException
  409                   (ResourcesMgr.getString("invalid.null.action.provided"));
  410   
  411           // set up the new Subject-based AccessControlContext for doPrivileged
  412           final AccessControlContext currentAcc = AccessController.getContext();
  413   
  414           // call doPrivileged and push this new context on the stack
  415           return java.security.AccessController.doPrivileged
  416                                           (action,
  417                                           createContext(subject, currentAcc));
  418       }
  419   
  420       /**
  421        * Perform privileged work as a particular <code>Subject</code>.
  422        *
  423        * <p> This method behaves exactly as <code>Subject.doAs</code>,
  424        * except that instead of retrieving the current Thread's
  425        * <code>AccessControlContext</code>, it uses the provided
  426        * <code>AccessControlContext</code>.  If the provided
  427        * <code>AccessControlContext</code> is <code>null</code>,
  428        * this method instantiates a new <code>AccessControlContext</code>
  429        * with an empty collection of ProtectionDomains.
  430        *
  431        * <p>
  432        *
  433        * @param subject the <code>Subject</code> that the specified
  434        *                  <code>action</code> will run as.  This parameter
  435        *                  may be <code>null</code>. <p>
  436        *
  437        * @param action the code to be run as the specified
  438        *                  <code>Subject</code>. <p>
  439        *
  440        * @param acc the <code>AccessControlContext</code> to be tied to the
  441        *                  specified <i>subject</i> and <i>action</i>. <p>
  442        *
  443        * @return the value returned by the PrivilegedAction's
  444        *                  <code>run</code> method.
  445        *
  446        * @exception NullPointerException if the <code>PrivilegedAction</code>
  447        *                  is <code>null</code>. <p>
  448        *
  449        * @exception SecurityException if the caller does not have permission
  450        *                  to invoke this method.
  451        */
  452       public static <T> T doAsPrivileged(final Subject subject,
  453                           final java.security.PrivilegedAction<T> action,
  454                           final java.security.AccessControlContext acc) {
  455   
  456           java.lang.SecurityManager sm = System.getSecurityManager();
  457           if (sm != null) {
  458               sm.checkPermission(AuthPermissionHolder.DO_AS_PRIVILEGED_PERMISSION);
  459           }
  460   
  461           if (action == null)
  462               throw new NullPointerException
  463                   (ResourcesMgr.getString("invalid.null.action.provided"));
  464   
  465           // set up the new Subject-based AccessControlContext
  466           // for doPrivileged
  467           final AccessControlContext callerAcc =
  468                   (acc == null ?
  469                   new AccessControlContext(NULL_PD_ARRAY) :
  470                   acc);
  471   
  472           // call doPrivileged and push this new context on the stack
  473           return java.security.AccessController.doPrivileged
  474                                           (action,
  475                                           createContext(subject, callerAcc));
  476       }
  477   
  478       /**
  479        * Perform privileged work as a particular <code>Subject</code>.
  480        *
  481        * <p> This method behaves exactly as <code>Subject.doAs</code>,
  482        * except that instead of retrieving the current Thread's
  483        * <code>AccessControlContext</code>, it uses the provided
  484        * <code>AccessControlContext</code>.  If the provided
  485        * <code>AccessControlContext</code> is <code>null</code>,
  486        * this method instantiates a new <code>AccessControlContext</code>
  487        * with an empty collection of ProtectionDomains.
  488        *
  489        * <p>
  490        *
  491        * @param subject the <code>Subject</code> that the specified
  492        *                  <code>action</code> will run as.  This parameter
  493        *                  may be <code>null</code>. <p>
  494        *
  495        * @param action the code to be run as the specified
  496        *                  <code>Subject</code>. <p>
  497        *
  498        * @param acc the <code>AccessControlContext</code> to be tied to the
  499        *                  specified <i>subject</i> and <i>action</i>. <p>
  500        *
  501        * @return the value returned by the
  502        *                  PrivilegedExceptionAction's <code>run</code> method.
  503        *
  504        * @exception PrivilegedActionException if the
  505        *                  <code>PrivilegedExceptionAction.run</code>
  506        *                  method throws a checked exception. <p>
  507        *
  508        * @exception NullPointerException if the specified
  509        *                  <code>PrivilegedExceptionAction</code> is
  510        *                  <code>null</code>. <p>
  511        *
  512        * @exception SecurityException if the caller does not have permission
  513        *                  to invoke this method.
  514        */
  515       public static <T> T doAsPrivileged(final Subject subject,
  516                           final java.security.PrivilegedExceptionAction<T> action,
  517                           final java.security.AccessControlContext acc)
  518                           throws java.security.PrivilegedActionException {
  519   
  520           java.lang.SecurityManager sm = System.getSecurityManager();
  521           if (sm != null) {
  522               sm.checkPermission(AuthPermissionHolder.DO_AS_PRIVILEGED_PERMISSION);
  523           }
  524   
  525           if (action == null)
  526               throw new NullPointerException
  527                   (ResourcesMgr.getString("invalid.null.action.provided"));
  528   
  529           // set up the new Subject-based AccessControlContext for doPrivileged
  530           final AccessControlContext callerAcc =
  531                   (acc == null ?
  532                   new AccessControlContext(NULL_PD_ARRAY) :
  533                   acc);
  534   
  535           // call doPrivileged and push this new context on the stack
  536           return java.security.AccessController.doPrivileged
  537                                           (action,
  538                                           createContext(subject, callerAcc));
  539       }
  540   
  541       private static AccessControlContext createContext(final Subject subject,
  542                                           final AccessControlContext acc) {
  543   
  544   
  545           return java.security.AccessController.doPrivileged
  546               (new java.security.PrivilegedAction<AccessControlContext>() {
  547               public AccessControlContext run() {
  548                   if (subject == null)
  549                       return new AccessControlContext(acc, null);
  550                   else
  551                       return new AccessControlContext
  552                                           (acc,
  553                                           new SubjectDomainCombiner(subject));
  554               }
  555           });
  556       }
  557   
  558       /**
  559        * Return the <code>Set</code> of Principals associated with this
  560        * <code>Subject</code>.  Each <code>Principal</code> represents
  561        * an identity for this <code>Subject</code>.
  562        *
  563        * <p> The returned <code>Set</code> is backed by this Subject's
  564        * internal <code>Principal</code> <code>Set</code>.  Any modification
  565        * to the returned <code>Set</code> affects the internal
  566        * <code>Principal</code> <code>Set</code> as well.
  567        *
  568        * <p>
  569        *
  570        * @return  The <code>Set</code> of Principals associated with this
  571        *          <code>Subject</code>.
  572        */
  573       public Set<Principal> getPrincipals() {
  574   
  575           // always return an empty Set instead of null
  576           // so LoginModules can add to the Set if necessary
  577           return principals;
  578       }
  579   
  580       /**
  581        * Return a <code>Set</code> of Principals associated with this
  582        * <code>Subject</code> that are instances or subclasses of the specified
  583        * <code>Class</code>.
  584        *
  585        * <p> The returned <code>Set</code> is not backed by this Subject's
  586        * internal <code>Principal</code> <code>Set</code>.  A new
  587        * <code>Set</code> is created and returned for each method invocation.
  588        * Modifications to the returned <code>Set</code>
  589        * will not affect the internal <code>Principal</code> <code>Set</code>.
  590        *
  591        * <p>
  592        *
  593        * @param c the returned <code>Set</code> of Principals will all be
  594        *          instances of this class.
  595        *
  596        * @return a <code>Set</code> of Principals that are instances of the
  597        *          specified <code>Class</code>.
  598        *
  599        * @exception NullPointerException if the specified <code>Class</code>
  600        *                  is <code>null</code>.
  601        */
  602       public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
  603   
  604           if (c == null)
  605               throw new NullPointerException
  606                   (ResourcesMgr.getString("invalid.null.Class.provided"));
  607   
  608           // always return an empty Set instead of null
  609           // so LoginModules can add to the Set if necessary
  610           return new ClassSet<T>(PRINCIPAL_SET, c);
  611       }
  612   
  613       /**
  614        * Return the <code>Set</code> of public credentials held by this
  615        * <code>Subject</code>.
  616        *
  617        * <p> The returned <code>Set</code> is backed by this Subject's
  618        * internal public Credential <code>Set</code>.  Any modification
  619        * to the returned <code>Set</code> affects the internal public
  620        * Credential <code>Set</code> as well.
  621        *
  622        * <p>
  623        *
  624        * @return  A <code>Set</code> of public credentials held by this
  625        *          <code>Subject</code>.
  626        */
  627       public Set<Object> getPublicCredentials() {
  628   
  629           // always return an empty Set instead of null
  630           // so LoginModules can add to the Set if necessary
  631           return pubCredentials;
  632       }
  633   
  634       /**
  635        * Return the <code>Set</code> of private credentials held by this
  636        * <code>Subject</code>.
  637        *
  638        * <p> The returned <code>Set</code> is backed by this Subject's
  639        * internal private Credential <code>Set</code>.  Any modification
  640        * to the returned <code>Set</code> affects the internal private
  641        * Credential <code>Set</code> as well.
  642        *
  643        * <p> A caller requires permissions to access the Credentials
  644        * in the returned <code>Set</code>, or to modify the
  645        * <code>Set</code> itself.  A <code>SecurityException</code>
  646        * is thrown if the caller does not have the proper permissions.
  647        *
  648        * <p> While iterating through the <code>Set</code>,
  649        * a <code>SecurityException</code> is thrown
  650        * if the caller does not have permission to access a
  651        * particular Credential.  The <code>Iterator</code>
  652        * is nevertheless advanced to next element in the <code>Set</code>.
  653        *
  654        * <p>
  655        *
  656        * @return  A <code>Set</code> of private credentials held by this
  657        *          <code>Subject</code>.
  658        */
  659       public Set<Object> getPrivateCredentials() {
  660   
  661           // XXX
  662           // we do not need a security check for
  663           // AuthPermission(getPrivateCredentials)
  664           // because we already restrict access to private credentials
  665           // via the PrivateCredentialPermission.  all the extra AuthPermission
  666           // would do is protect the set operations themselves
  667           // (like size()), which don't seem security-sensitive.
  668   
  669           // always return an empty Set instead of null
  670           // so LoginModules can add to the Set if necessary
  671           return privCredentials;
  672       }
  673   
  674       /**
  675        * Return a <code>Set</code> of public credentials associated with this
  676        * <code>Subject</code> that are instances or subclasses of the specified
  677        * <code>Class</code>.
  678        *
  679        * <p> The returned <code>Set</code> is not backed by this Subject's
  680        * internal public Credential <code>Set</code>.  A new
  681        * <code>Set</code> is created and returned for each method invocation.
  682        * Modifications to the returned <code>Set</code>
  683        * will not affect the internal public Credential <code>Set</code>.
  684        *
  685        * <p>
  686        *
  687        * @param c the returned <code>Set</code> of public credentials will all be
  688        *          instances of this class.
  689        *
  690        * @return a <code>Set</code> of public credentials that are instances
  691        *          of the  specified <code>Class</code>.
  692        *
  693        * @exception NullPointerException if the specified <code>Class</code>
  694        *          is <code>null</code>.
  695        */
  696       public <T> Set<T> getPublicCredentials(Class<T> c) {
  697   
  698           if (c == null)
  699               throw new NullPointerException
  700                   (ResourcesMgr.getString("invalid.null.Class.provided"));
  701   
  702           // always return an empty Set instead of null
  703           // so LoginModules can add to the Set if necessary
  704           return new ClassSet<T>(PUB_CREDENTIAL_SET, c);
  705       }
  706   
  707       /**
  708        * Return a <code>Set</code> of private credentials associated with this
  709        * <code>Subject</code> that are instances or subclasses of the specified
  710        * <code>Class</code>.
  711        *
  712        * <p> The caller must have permission to access all of the
  713        * requested Credentials, or a <code>SecurityException</code>
  714        * will be thrown.
  715        *
  716        * <p> The returned <code>Set</code> is not backed by this Subject's
  717        * internal private Credential <code>Set</code>.  A new
  718        * <code>Set</code> is created and returned for each method invocation.
  719        * Modifications to the returned <code>Set</code>
  720        * will not affect the internal private Credential <code>Set</code>.
  721        *
  722        * <p>
  723        *
  724        * @param c the returned <code>Set</code> of private credentials will all be
  725        *          instances of this class.
  726        *
  727        * @return a <code>Set</code> of private credentials that are instances
  728        *          of the  specified <code>Class</code>.
  729        *
  730        * @exception NullPointerException if the specified <code>Class</code>
  731        *          is <code>null</code>.
  732        */
  733       public <T> Set<T> getPrivateCredentials(Class<T> c) {
  734   
  735           // XXX
  736           // we do not need a security check for
  737           // AuthPermission(getPrivateCredentials)
  738           // because we already restrict access to private credentials
  739           // via the PrivateCredentialPermission.  all the extra AuthPermission
  740           // would do is protect the set operations themselves
  741           // (like size()), which don't seem security-sensitive.
  742   
  743           if (c == null)
  744               throw new NullPointerException
  745                   (ResourcesMgr.getString("invalid.null.Class.provided"));
  746   
  747           // always return an empty Set instead of null
  748           // so LoginModules can add to the Set if necessary
  749           return new ClassSet<T>(PRIV_CREDENTIAL_SET, c);
  750       }
  751   
  752       /**
  753        * Compares the specified Object with this <code>Subject</code>
  754        * for equality.  Returns true if the given object is also a Subject
  755        * and the two <code>Subject</code> instances are equivalent.
  756        * More formally, two <code>Subject</code> instances are
  757        * equal if their <code>Principal</code> and <code>Credential</code>
  758        * Sets are equal.
  759        *
  760        * <p>
  761        *
  762        * @param o Object to be compared for equality with this
  763        *          <code>Subject</code>.
  764        *
  765        * @return true if the specified Object is equal to this
  766        *          <code>Subject</code>.
  767        *
  768        * @exception SecurityException if the caller does not have permission
  769        *          to access the private credentials for this <code>Subject</code>,
  770        *          or if the caller does not have permission to access the
  771        *          private credentials for the provided <code>Subject</code>.
  772        */
  773       public boolean equals(Object o) {
  774   
  775           if (o == null)
  776               return false;
  777   
  778           if (this == o)
  779               return true;
  780   
  781           if (o instanceof Subject) {
  782   
  783               final Subject that = (Subject)o;
  784   
  785               // check the principal and credential sets
  786               Set<Principal> thatPrincipals;
  787               synchronized(that.principals) {
  788                   // avoid deadlock from dual locks
  789                   thatPrincipals = new HashSet<Principal>(that.principals);
  790               }
  791               if (!principals.equals(thatPrincipals)) {
  792                   return false;
  793               }
  794   
  795               Set<Object> thatPubCredentials;
  796               synchronized(that.pubCredentials) {
  797                   // avoid deadlock from dual locks
  798                   thatPubCredentials = new HashSet<Object>(that.pubCredentials);
  799               }
  800               if (!pubCredentials.equals(thatPubCredentials)) {
  801                   return false;
  802               }
  803   
  804               Set<Object> thatPrivCredentials;
  805               synchronized(that.privCredentials) {
  806                   // avoid deadlock from dual locks
  807                   thatPrivCredentials = new HashSet<Object>(that.privCredentials);
  808               }
  809               if (!privCredentials.equals(thatPrivCredentials)) {
  810                   return false;
  811               }
  812               return true;
  813           }
  814           return false;
  815       }
  816   
  817       /**
  818        * Return the String representation of this <code>Subject</code>.
  819        *
  820        * <p>
  821        *
  822        * @return the String representation of this <code>Subject</code>.
  823        */
  824       public String toString() {
  825           return toString(true);
  826       }
  827   
  828       /**
  829        * package private convenience method to print out the Subject
  830        * without firing off a security check when trying to access
  831        * the Private Credentials
  832        */
  833       String toString(boolean includePrivateCredentials) {
  834   
  835           String s = ResourcesMgr.getString("Subject.");
  836           String suffix = "";
  837   
  838           synchronized(principals) {
  839               Iterator<Principal> pI = principals.iterator();
  840               while (pI.hasNext()) {
  841                   Principal p = pI.next();
  842                   suffix = suffix + ResourcesMgr.getString(".Principal.") +
  843                           p.toString() + ResourcesMgr.getString("NEWLINE");
  844               }
  845           }
  846   
  847           synchronized(pubCredentials) {
  848               Iterator<Object> pI = pubCredentials.iterator();
  849               while (pI.hasNext()) {
  850                   Object o = pI.next();
  851                   suffix = suffix +
  852                           ResourcesMgr.getString(".Public.Credential.") +
  853                           o.toString() + ResourcesMgr.getString("NEWLINE");
  854               }
  855           }
  856   
  857           if (includePrivateCredentials) {
  858               synchronized(privCredentials) {
  859                   Iterator<Object> pI = privCredentials.iterator();
  860                   while (pI.hasNext()) {
  861                       try {
  862                           Object o = pI.next();
  863                           suffix += ResourcesMgr.getString
  864                                           (".Private.Credential.") +
  865                                           o.toString() +
  866                                           ResourcesMgr.getString("NEWLINE");
  867                       } catch (SecurityException se) {
  868                           suffix += ResourcesMgr.getString
  869                                   (".Private.Credential.inaccessible.");
  870                           break;
  871                       }
  872                   }
  873               }
  874           }
  875           return s + suffix;
  876       }
  877   
  878       /**
  879        * Returns a hashcode for this <code>Subject</code>.
  880        *
  881        * <p>
  882        *
  883        * @return a hashcode for this <code>Subject</code>.
  884        *
  885        * @exception SecurityException if the caller does not have permission
  886        *          to access this Subject's private credentials.
  887        */
  888       public int hashCode() {
  889   
  890           /**
  891            * The hashcode is derived exclusive or-ing the
  892            * hashcodes of this Subject's Principals and credentials.
  893            *
  894            * If a particular credential was destroyed
  895            * (<code>credential.hashCode()</code> throws an
  896            * <code>IllegalStateException</code>),
  897            * the hashcode for that credential is derived via:
  898            * <code>credential.getClass().toString().hashCode()</code>.
  899            */
  900   
  901           int hashCode = 0;
  902   
  903           synchronized(principals) {
  904               Iterator<Principal> pIterator = principals.iterator();
  905               while (pIterator.hasNext()) {
  906                   Principal p = pIterator.next();
  907                   hashCode ^= p.hashCode();
  908               }
  909           }
  910   
  911           synchronized(pubCredentials) {
  912               Iterator<Object> pubCIterator = pubCredentials.iterator();
  913               while (pubCIterator.hasNext()) {
  914                   hashCode ^= getCredHashCode(pubCIterator.next());
  915               }
  916           }
  917           return hashCode;
  918       }
  919   
  920       /**
  921        * get a credential's hashcode
  922        */
  923       private int getCredHashCode(Object o) {
  924           try {
  925               return o.hashCode();
  926           } catch (IllegalStateException ise) {
  927               return o.getClass().toString().hashCode();
  928           }
  929       }
  930   
  931       /**
  932        * Writes this object out to a stream (i.e., serializes it).
  933        */
  934       private void writeObject(java.io.ObjectOutputStream oos)
  935                   throws java.io.IOException {
  936           synchronized(principals) {
  937               oos.defaultWriteObject();
  938           }
  939       }
  940   
  941       /**
  942        * Reads this object from a stream (i.e., deserializes it)
  943        */
  944       private void readObject(java.io.ObjectInputStream s)
  945                   throws java.io.IOException, ClassNotFoundException {
  946   
  947           s.defaultReadObject();
  948   
  949           // The Credential <code>Set</code> is not serialized, but we do not
  950           // want the default deserialization routine to set it to null.
  951           this.pubCredentials = Collections.synchronizedSet
  952                           (new SecureSet<Object>(this, PUB_CREDENTIAL_SET));
  953           this.privCredentials = Collections.synchronizedSet
  954                           (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));
  955       }
  956   
  957       /**
  958        * Prevent modifications unless caller has permission.
  959        *
  960        * @serial include
  961        */
  962       private static class SecureSet<E>
  963           extends AbstractSet<E>
  964           implements java.io.Serializable {
  965   
  966           private static final long serialVersionUID = 7911754171111800359L;
  967   
  968           /**
  969            * @serialField this$0 Subject The outer Subject instance.
  970            * @serialField elements LinkedList The elements in this set.
  971            */
  972           private static final ObjectStreamField[] serialPersistentFields = {
  973               new ObjectStreamField("this$0", Subject.class),
  974               new ObjectStreamField("elements", LinkedList.class),
  975               new ObjectStreamField("which", int.class)
  976           };
  977   
  978           Subject subject;
  979           LinkedList<E> elements;
  980   
  981           /**
  982            * @serial An integer identifying the type of objects contained
  983            *      in this set.  If <code>which == 1</code>,
  984            *      this is a Principal set and all the elements are
  985            *      of type <code>java.security.Principal</code>.
  986            *      If <code>which == 2</code>, this is a public credential
  987            *      set and all the elements are of type <code>Object</code>.
  988            *      If <code>which == 3</code>, this is a private credential
  989            *      set and all the elements are of type <code>Object</code>.
  990            */
  991           private int which;
  992   
  993           SecureSet(Subject subject, int which) {
  994               this.subject = subject;
  995               this.which = which;
  996               this.elements = new LinkedList<E>();
  997           }
  998   
  999           SecureSet(Subject subject, int which, Set<? extends E> set) {
 1000               this.subject = subject;
 1001               this.which = which;
 1002               this.elements = new LinkedList<E>(set);
 1003           }
 1004   
 1005           public int size() {
 1006               return elements.size();
 1007           }
 1008   
 1009           public Iterator<E> iterator() {
 1010               final LinkedList<E> list = elements;
 1011               return new Iterator<E>() {
 1012                   ListIterator<E> i = list.listIterator(0);
 1013   
 1014                   public boolean hasNext() {return i.hasNext();}
 1015   
 1016                   public E next() {
 1017                       if (which != Subject.PRIV_CREDENTIAL_SET) {
 1018                           return i.next();
 1019                       }
 1020   
 1021                       SecurityManager sm = System.getSecurityManager();
 1022                       if (sm != null) {
 1023                           try {
 1024                               sm.checkPermission(new PrivateCredentialPermission
 1025                                   (list.get(i.nextIndex()).getClass().getName(),
 1026                                   subject.getPrincipals()));
 1027                           } catch (SecurityException se) {
 1028                               i.next();
 1029                               throw (se);
 1030                           }
 1031                       }
 1032                       return i.next();
 1033                   }
 1034   
 1035                   public void remove() {
 1036   
 1037                       if (subject.isReadOnly()) {
 1038                           throw new IllegalStateException(ResourcesMgr.getString
 1039                                   ("Subject.is.read.only"));
 1040                       }
 1041   
 1042                       java.lang.SecurityManager sm = System.getSecurityManager();
 1043                       if (sm != null) {
 1044                           switch (which) {
 1045                           case Subject.PRINCIPAL_SET:
 1046                               sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION);
 1047                               break;
 1048                           case Subject.PUB_CREDENTIAL_SET:
 1049                               sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION);
 1050                               break;
 1051                           default:
 1052                               sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION);
 1053                               break;
 1054                           }
 1055                       }
 1056                       i.remove();
 1057                   }
 1058               };
 1059           }
 1060   
 1061           public boolean add(E o) {
 1062   
 1063               if (subject.isReadOnly()) {
 1064                   throw new IllegalStateException
 1065                           (ResourcesMgr.getString("Subject.is.read.only"));
 1066               }
 1067   
 1068               java.lang.SecurityManager sm = System.getSecurityManager();
 1069               if (sm != null) {
 1070                   switch (which) {
 1071                   case Subject.PRINCIPAL_SET:
 1072                       sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION);
 1073                       break;
 1074                   case Subject.PUB_CREDENTIAL_SET:
 1075                       sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION);
 1076                       break;
 1077                   default:
 1078                       sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION);
 1079                       break;
 1080                   }
 1081               }
 1082   
 1083               switch (which) {
 1084               case Subject.PRINCIPAL_SET:
 1085                   if (!(o instanceof Principal)) {
 1086                       throw new SecurityException(ResourcesMgr.getString
 1087                           ("attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set"));
 1088                   }
 1089                   break;
 1090               default:
 1091                   // ok to add Objects of any kind to credential sets
 1092                   break;
 1093               }
 1094   
 1095               // check for duplicates
 1096               if (!elements.contains(o))
 1097                   return elements.add(o);
 1098               else
 1099                   return false;
 1100           }
 1101   
 1102           public boolean remove(Object o) {
 1103   
 1104               final Iterator<E> e = iterator();
 1105               while (e.hasNext()) {
 1106                   E next;
 1107                   if (which != Subject.PRIV_CREDENTIAL_SET) {
 1108                       next = e.next();
 1109                   } else {
 1110                       next = java.security.AccessController.doPrivileged
 1111                           (new java.security.PrivilegedAction<E>() {
 1112                           public E run() {
 1113                               return e.next();
 1114                           }
 1115                       });
 1116                   }
 1117   
 1118                   if (next == null) {
 1119                       if (o == null) {
 1120                           e.remove();
 1121                           return true;
 1122                       }
 1123                   } else if (next.equals(o)) {
 1124                       e.remove();
 1125                       return true;
 1126                   }
 1127               }
 1128               return false;
 1129           }
 1130   
 1131           public boolean contains(Object o) {
 1132               final Iterator<E> e = iterator();
 1133               while (e.hasNext()) {
 1134                   E next;
 1135                   if (which != Subject.PRIV_CREDENTIAL_SET) {
 1136                       next = e.next();
 1137                   } else {
 1138   
 1139                       // For private credentials:
 1140                       // If the caller does not have read permission for
 1141                       // for o.getClass(), we throw a SecurityException.
 1142                       // Otherwise we check the private cred set to see whether
 1143                       // it contains the Object
 1144   
 1145                       SecurityManager sm = System.getSecurityManager();
 1146                       if (sm != null) {
 1147                           sm.checkPermission(new PrivateCredentialPermission
 1148                                                   (o.getClass().getName(),
 1149                                                   subject.getPrincipals()));
 1150                       }
 1151                       next = java.security.AccessController.doPrivileged
 1152                           (new java.security.PrivilegedAction<E>() {
 1153                           public E run() {
 1154                               return e.next();
 1155                           }
 1156                       });
 1157                   }
 1158   
 1159                   if (next == null) {
 1160                       if (o == null) {
 1161                           return true;
 1162                       }
 1163                   } else if (next.equals(o)) {
 1164                       return true;
 1165                   }
 1166               }
 1167               return false;
 1168           }
 1169   
 1170           public boolean removeAll(Collection<?> c) {
 1171   
 1172               boolean modified = false;
 1173               final Iterator<E> e = iterator();
 1174               while (e.hasNext()) {
 1175                   E next;
 1176                   if (which != Subject.PRIV_CREDENTIAL_SET) {
 1177                       next = e.next();
 1178                   } else {
 1179                       next = java.security.AccessController.doPrivileged
 1180                           (new java.security.PrivilegedAction<E>() {
 1181                           public E run() {
 1182                               return e.next();
 1183                           }
 1184                       });
 1185                   }
 1186   
 1187                   Iterator<?> ce = c.iterator();
 1188                   while (ce.hasNext()) {
 1189                       Object o = ce.next();
 1190                       if (next == null) {
 1191                           if (o == null) {
 1192                               e.remove();
 1193                               modified = true;
 1194                               break;
 1195                           }
 1196                       } else if (next.equals(o)) {
 1197                           e.remove();
 1198                           modified = true;
 1199                           break;
 1200                       }
 1201                   }
 1202               }
 1203               return modified;
 1204           }
 1205   
 1206           public boolean retainAll(Collection<?> c) {
 1207   
 1208               boolean modified = false;
 1209               boolean retain = false;
 1210               final Iterator<E> e = iterator();
 1211               while (e.hasNext()) {
 1212                   retain = false;
 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                               retain = true;
 1231                               break;
 1232                           }
 1233                       } else if (next.equals(o)) {
 1234                           retain = true;
 1235                           break;
 1236                       }
 1237                   }
 1238   
 1239                   if (!retain) {
 1240                       e.remove();
 1241                       retain = false;
 1242                       modified = true;
 1243                   }
 1244               }
 1245               return modified;
 1246           }
 1247   
 1248           public void clear() {
 1249               final Iterator<E> e = iterator();
 1250               while (e.hasNext()) {
 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                   e.remove();
 1263               }
 1264           }
 1265   
 1266           /**
 1267            * Writes this object out to a stream (i.e., serializes it).
 1268            *
 1269            * <p>
 1270            *
 1271            * @serialData If this is a private credential set,
 1272            *      a security check is performed to ensure that
 1273            *      the caller has permission to access each credential
 1274            *      in the set.  If the security check passes,
 1275            *      the set is serialized.
 1276            */
 1277           private void writeObject(java.io.ObjectOutputStream oos)
 1278                   throws java.io.IOException {
 1279   
 1280               if (which == Subject.PRIV_CREDENTIAL_SET) {
 1281                   // check permissions before serializing
 1282                   Iterator<E> i = iterator();
 1283                   while (i.hasNext()) {
 1284                       i.next();
 1285                   }
 1286               }
 1287               ObjectOutputStream.PutField fields = oos.putFields();
 1288               fields.put("this$0", subject);
 1289               fields.put("elements", elements);
 1290               fields.put("which", which);
 1291               oos.writeFields();
 1292           }
 1293   
 1294           private void readObject(ObjectInputStream ois)
 1295               throws IOException, ClassNotFoundException
 1296           {
 1297               ObjectInputStream.GetField fields = ois.readFields();
 1298               subject = (Subject) fields.get("this$0", null);
 1299               elements = (LinkedList<E>) fields.get("elements", null);
 1300               which = fields.get("which", 0);
 1301           }
 1302       }
 1303   
 1304       /**
 1305        * This class implements a <code>Set</code> which returns only
 1306        * members that are an instance of a specified Class.
 1307        */
 1308       private class ClassSet<T> extends AbstractSet<T> {
 1309   
 1310           private int which;
 1311           private Class<T> c;
 1312           private Set<T> set;
 1313   
 1314           ClassSet(int which, Class<T> c) {
 1315               this.which = which;
 1316               this.c = c;
 1317               set = new HashSet<T>();
 1318   
 1319               switch (which) {
 1320               case Subject.PRINCIPAL_SET:
 1321                   synchronized(principals) { populateSet(); }
 1322                   break;
 1323               case Subject.PUB_CREDENTIAL_SET:
 1324                   synchronized(pubCredentials) { populateSet(); }
 1325                   break;
 1326               default:
 1327                   synchronized(privCredentials) { populateSet(); }
 1328                   break;
 1329               }
 1330           }
 1331   
 1332           private void populateSet() {
 1333               final Iterator<?> iterator;
 1334               switch(which) {
 1335               case Subject.PRINCIPAL_SET:
 1336                   iterator = Subject.this.principals.iterator();
 1337                   break;
 1338               case Subject.PUB_CREDENTIAL_SET:
 1339                   iterator = Subject.this.pubCredentials.iterator();
 1340                   break;
 1341               default:
 1342                   iterator = Subject.this.privCredentials.iterator();
 1343                   break;
 1344               }
 1345   
 1346               // Check whether the caller has permisson to get
 1347               // credentials of Class c
 1348   
 1349               while (iterator.hasNext()) {
 1350                   Object next;
 1351                   if (which == Subject.PRIV_CREDENTIAL_SET) {
 1352                       next = java.security.AccessController.doPrivileged
 1353                           (new java.security.PrivilegedAction<Object>() {
 1354                           public Object run() {
 1355                               return iterator.next();
 1356                           }
 1357                       });
 1358                   } else {
 1359                       next = iterator.next();
 1360                   }
 1361                   if (c.isAssignableFrom(next.getClass())) {
 1362                       if (which != Subject.PRIV_CREDENTIAL_SET) {
 1363                           set.add((T)next);
 1364                       } else {
 1365                           // Check permission for private creds
 1366                           SecurityManager sm = System.getSecurityManager();
 1367                           if (sm != null) {
 1368                               sm.checkPermission(new PrivateCredentialPermission
 1369                                                   (next.getClass().getName(),
 1370                                                   Subject.this.getPrincipals()));
 1371                           }
 1372                           set.add((T)next);
 1373                       }
 1374                   }
 1375               }
 1376           }
 1377   
 1378           public int size() {
 1379               return set.size();
 1380           }
 1381   
 1382           public Iterator<T> iterator() {
 1383               return set.iterator();
 1384           }
 1385   
 1386           public boolean add(T o) {
 1387   
 1388               if (!o.getClass().isAssignableFrom(c)) {
 1389                   MessageFormat form = new MessageFormat(ResourcesMgr.getString
 1390                           ("attempting.to.add.an.object.which.is.not.an.instance.of.class"));
 1391                   Object[] source = {c.toString()};
 1392                   throw new SecurityException(form.format(source));
 1393               }
 1394   
 1395               return set.add(o);
 1396           }
 1397       }
 1398   
 1399       static class AuthPermissionHolder {
 1400           static final AuthPermission DO_AS_PERMISSION =
 1401               new AuthPermission("doAs");
 1402   
 1403           static final AuthPermission DO_AS_PRIVILEGED_PERMISSION =
 1404               new AuthPermission("doAsPrivileged");
 1405   
 1406           static final AuthPermission SET_READ_ONLY_PERMISSION =
 1407               new AuthPermission("setReadOnly");
 1408   
 1409           static final AuthPermission GET_SUBJECT_PERMISSION =
 1410               new AuthPermission("getSubject");
 1411   
 1412           static final AuthPermission MODIFY_PRINCIPALS_PERMISSION =
 1413               new AuthPermission("modifyPrincipals");
 1414   
 1415           static final AuthPermission MODIFY_PUBLIC_CREDENTIALS_PERMISSION =
 1416               new AuthPermission("modifyPublicCredentials");
 1417   
 1418           static final AuthPermission MODIFY_PRIVATE_CREDENTIALS_PERMISSION =
 1419               new AuthPermission("modifyPrivateCredentials");
 1420       }
 1421   }

Home » openjdk-7 » javax.security » auth » [javadoc | source]