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

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