1 /*
   2  * Copyright (c) 1998, 2024, 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.io.IOException;
  29 import java.io.ObjectInputStream;
  30 import java.io.ObjectOutputStream;
  31 import java.io.ObjectStreamField;
  32 import java.security.*;
  33 import java.text.MessageFormat;
  34 import java.util.*;
  35 import java.util.concurrent.Callable;
  36 import java.util.concurrent.CompletionException;
  37 
  38 import sun.security.util.ResourcesMgr;
  39 
  40 /**
  41  * <p> A {@code Subject} represents a grouping of related information
  42  * for a single entity, such as a person.
  43  * Such information includes the Subject's identities as well as
  44  * its security-related attributes
  45  * (passwords and cryptographic keys, for example).
  46  *
  47  * <p> Subjects may potentially have multiple identities.
  48  * Each identity is represented as a {@code Principal}
  49  * within the {@code Subject}.  Principals simply bind names to a
  50  * {@code Subject}.  For example, a {@code Subject} that happens
  51  * to be a person, Alice, might have two Principals:
  52  * one which binds "Alice Bar", the name on her driver license,
  53  * to the {@code Subject}, and another which binds,
  54  * "999-99-9999", the number on her student identification card,
  55  * to the {@code Subject}.  Both Principals refer to the same
  56  * {@code Subject} even though each has a different name.
  57  *
  58  * <p> A {@code Subject} may also own security-related attributes,
  59  * which are referred to as credentials.
  60  * Sensitive credentials that require special protection, such as
  61  * private cryptographic keys, are stored within a private credential
  62  * {@code Set}.  Credentials intended to be shared, such as
  63  * public key certificates or Kerberos server tickets are stored
  64  * within a public credential {@code Set}.
  65  *
  66  * <p> To retrieve all the Principals associated with a {@code Subject},
  67  * invoke the {@code getPrincipals} method.  To retrieve
  68  * all the public or private credentials belonging to a {@code Subject},
  69  * invoke the {@code getPublicCredentials} method or
  70  * {@code getPrivateCredentials} method, respectively.
  71  * To modify the returned {@code Set} of Principals and credentials,
  72  * use the methods defined in the {@code Set} class.
  73  * For example:
  74  * <pre>
  75  *      Subject subject;
  76  *      Principal principal;
  77  *      Object credential;
  78  *
  79  *      // add a Principal and credential to the Subject
  80  *      subject.getPrincipals().add(principal);
  81  *      subject.getPublicCredentials().add(credential);
  82  * </pre>
  83  *
  84  * <p> This {@code Subject} class implements {@code Serializable}.
  85  * While the Principals associated with the {@code Subject} are serialized,
  86  * the credentials associated with the {@code Subject} are not.
  87  * Note that the {@code java.security.Principal} class
  88  * does not implement {@code Serializable}.  Therefore, all concrete
  89  * {@code Principal} implementations associated with Subjects
  90  * must implement {@code Serializable}.
  91  *
  92  * <h2>Deprecated Methods and Replacements</h2>
  93  *
  94  * <p> The following methods in this class for user-based authorization
  95  * that are dependent on Security Manager APIs are deprecated for removal:
  96  * <ul>
  97  *     <li>{@link #getSubject(AccessControlContext)}
  98  *     <li>{@link #doAs(Subject, PrivilegedAction)}
  99  *     <li>{@link #doAs(Subject, PrivilegedExceptionAction)}
 100  *     <li>{@link #doAsPrivileged(Subject, PrivilegedAction, AccessControlContext)}
 101  *     <li>{@link #doAsPrivileged(Subject, PrivilegedExceptionAction, AccessControlContext)}
 102  * </ul>
 103  * Methods {@link #current()} and {@link #callAs(Subject, Callable)}
 104  * are replacements for these methods, where {@code current} is equivalent to
 105  * {@code getSubject(AccessController.getContext())} (as originally specified)
 106  * and {@code callAs} is similar to {@code doAs} except that the
 107  * input type and exceptions thrown are slightly different.
 108  *
 109  * <p> A {@code doAs} or {@code callAs} call
 110  * binds a {@code Subject} object to the period of execution of an action,
 111  * and the subject can be retrieved using the {@code current} method inside
 112  * the action. This subject can be inherited by child threads if they are
 113  * started and terminate within the execution of its parent thread using
 114  * structured concurrency.
 115  *
 116  * @since 1.4
 117  * @see java.security.Principal
 118  * @see java.security.DomainCombiner
 119  */
 120 public final class Subject implements java.io.Serializable {
 121 
 122     @java.io.Serial
 123     private static final long serialVersionUID = -8308522755600156056L;
 124 
 125     /**
 126      * A {@code Set} that provides a view of all of this
 127      * Subject's Principals
 128      *
 129      * @serial Each element in this set is a
 130      *          {@code java.security.Principal}.
 131      *          The set is a {@code Subject.SecureSet}.
 132      */
 133     @SuppressWarnings("serial") // Not statically typed as Serializable
 134     Set<Principal> principals;
 135 
 136     /**
 137      * Sets that provide a view of all of this
 138      * Subject's Credentials
 139      */
 140     transient Set<Object> pubCredentials;
 141     transient Set<Object> privCredentials;
 142 
 143     /**
 144      * Whether this Subject is read-only
 145      *
 146      * @serial
 147      */
 148     private volatile boolean readOnly;
 149 
 150     private static final int PRINCIPAL_SET = 1;
 151     private static final int PUB_CREDENTIAL_SET = 2;
 152     private static final int PRIV_CREDENTIAL_SET = 3;
 153 
 154     private static final ProtectionDomain[] NULL_PD_ARRAY
 155         = new ProtectionDomain[0];
 156 
 157     /**
 158      * Create an instance of a {@code Subject}
 159      * with an empty {@code Set} of Principals and empty
 160      * Sets of public and private credentials.
 161      *
 162      * <p> The newly constructed Sets check whether this {@code Subject}
 163      * has been set read-only before permitting subsequent modifications.
 164      * These Sets also prohibit null elements, and attempts to add, query,
 165      * or remove a null element will result in a {@code NullPointerException}.
 166      */
 167     public Subject() {
 168 
 169         this.principals = Collections.synchronizedSet
 170                         (new SecureSet<>(this, PRINCIPAL_SET));
 171         this.pubCredentials = Collections.synchronizedSet
 172                         (new SecureSet<>(this, PUB_CREDENTIAL_SET));
 173         this.privCredentials = Collections.synchronizedSet
 174                         (new SecureSet<>(this, PRIV_CREDENTIAL_SET));
 175     }
 176 
 177     /**
 178      * Create an instance of a {@code Subject} with
 179      * Principals and credentials.
 180      *
 181      * <p> The Principals and credentials from the specified Sets
 182      * are copied into newly constructed Sets.
 183      * These newly created Sets check whether this {@code Subject}
 184      * has been set read-only before permitting subsequent modifications.
 185      * These Sets also prohibit null elements, and attempts to add, query,
 186      * or remove a null element will result in a {@code NullPointerException}.
 187      *
 188      * @param readOnly true if the {@code Subject} is to be read-only,
 189      *          and false otherwise.
 190      *
 191      * @param principals the {@code Set} of Principals
 192      *          to be associated with this {@code Subject}.
 193      *
 194      * @param pubCredentials the {@code Set} of public credentials
 195      *          to be associated with this {@code Subject}.
 196      *
 197      * @param privCredentials the {@code Set} of private credentials
 198      *          to be associated with this {@code Subject}.
 199      *
 200      * @throws NullPointerException if the specified
 201      *          {@code principals}, {@code pubCredentials},
 202      *          or {@code privCredentials} are {@code null},
 203      *          or a null value exists within any of these three
 204      *          Sets.
 205      */
 206     public Subject(boolean readOnly, Set<? extends Principal> principals,
 207                    Set<?> pubCredentials, Set<?> privCredentials) {
 208         LinkedList<Principal> principalList
 209                 = collectionNullClean(principals);
 210         LinkedList<Object> pubCredsList
 211                 = collectionNullClean(pubCredentials);
 212         LinkedList<Object> privCredsList
 213                 = collectionNullClean(privCredentials);
 214 
 215         this.principals = Collections.synchronizedSet(
 216                 new SecureSet<>(this, PRINCIPAL_SET, principalList));
 217         this.pubCredentials = Collections.synchronizedSet(
 218                 new SecureSet<>(this, PUB_CREDENTIAL_SET, pubCredsList));
 219         this.privCredentials = Collections.synchronizedSet(
 220                 new SecureSet<>(this, PRIV_CREDENTIAL_SET, privCredsList));
 221         this.readOnly = readOnly;
 222     }
 223 
 224     /**
 225      * Set this {@code Subject} to be read-only.
 226      *
 227      * <p> Modifications (additions and removals) to this Subject's
 228      * {@code Principal} {@code Set} and
 229      * credential Sets will be disallowed.
 230      * The {@code destroy} operation on this Subject's credentials will
 231      * still be permitted.
 232      *
 233      * <p> Subsequent attempts to modify the Subject's {@code Principal}
 234      * and credential Sets will result in an
 235      * {@code IllegalStateException} being thrown.
 236      * Also, once a {@code Subject} is read-only,
 237      * it can not be reset to being writable again.
 238      */
 239     public void setReadOnly() {
 240         this.readOnly = true;
 241     }
 242 
 243     /**
 244      * Query whether this {@code Subject} is read-only.
 245      *
 246      * @return true if this {@code Subject} is read-only, false otherwise.
 247      */
 248     public boolean isReadOnly() {
 249         return this.readOnly;
 250     }
 251 
 252     /**
 253      * Throws {@code UnsupportedOperationException}. A replacement API
 254      * named {@link #current()} has been added which can be used to obtain
 255      * the current subject.
 256      *
 257      * @param  acc ignored
 258      *
 259      * @return  n/a
 260      *
 261      * @throws UnsupportedOperationException always
 262      *
 263      * @deprecated This method used to get the subject associated with the
 264      *       provided {@link AccessControlContext}, which was only useful in
 265      *       conjunction with {@linkplain SecurityManager the Security Manager},
 266      *       which is no longer supported. This method has been changed to
 267      *       always throw {@code UnsupportedOperationException}. A replacement
 268      *       API named {@link #current()} has been added which can be used to
 269      *       obtain the current subject. There is no replacement for the
 270      *       Security Manager.
 271      *
 272      * @see #current()
 273      */
 274     @SuppressWarnings("removal")
 275     @Deprecated(since="17", forRemoval=true)
 276     public static Subject getSubject(final AccessControlContext acc) {
 277         throw new UnsupportedOperationException("getSubject is not supported");
 278     }
 279 
 280     private static final ScopedValue<Subject> SCOPED_SUBJECT =
 281             ScopedValue.newInstance();
 282 
 283     /**
 284      * Returns the current subject.
 285      *
 286      * <p> The current subject is installed by the {@link #callAs} method.
 287      * When {@code callAs(subject, action)} is called, {@code action} is
 288      * executed with {@code subject} as its current subject which can be
 289      * retrieved by this method. After {@code action} is finished, the current
 290      * subject is reset to its previous value. The current
 291      * subject is {@code null} before the first call of {@code callAs()}.
 292      *
 293      * <p> This method returns the
 294      * {@code Subject} bound to the period of the execution of the current
 295      * thread.
 296      *
 297      * @return the current subject, or {@code null} if a current subject is
 298      *      not installed or the current subject is set to {@code null}.
 299      * @see #callAs(Subject, Callable)
 300      * @since 18
 301      */
 302     public static Subject current() {
 303         return SCOPED_SUBJECT.isBound() ? SCOPED_SUBJECT.get() : null;
 304     }
 305 
 306     /**
 307      * Executes a {@code Callable} with {@code subject} as the
 308      * current subject.
 309      *
 310      * <p> This method launches {@code action} and binds {@code subject} to the
 311      * period of its execution.
 312      *
 313      * @param subject the {@code Subject} that the specified {@code action}
 314      *               will run as.  This parameter may be {@code null}.
 315      * @param action the code to be run with {@code subject} as its current
 316      *               subject. Must not be {@code null}.
 317      * @param <T> the type of value returned by the {@code call} method
 318      *            of {@code action}
 319      * @return the value returned by the {@code call} method of {@code action}
 320      * @throws NullPointerException if {@code action} is {@code null}
 321      * @throws CompletionException if {@code action.call()} throws an exception.
 322      *      The cause of the {@code CompletionException} is set to the exception
 323      *      thrown by {@code action.call()}.
 324      * @see #current()
 325      * @since 18
 326      */
 327     public static <T> T callAs(final Subject subject,
 328             final Callable<T> action) throws CompletionException {
 329         Objects.requireNonNull(action);
 330         try {
 331             return ScopedValue.where(SCOPED_SUBJECT, subject).call(action::call);
 332         } catch (Exception e) {
 333             throw new CompletionException(e);
 334         }
 335     }
 336 
 337     /**
 338      * Perform work as a particular {@code Subject}.
 339      *
 340      * <p> This method launches {@code action} and binds {@code subject} to the
 341      * period of its execution.
 342      *
 343      * @param subject the {@code Subject} that the specified
 344      *                  {@code action} will run as.  This parameter
 345      *                  may be {@code null}.
 346      *
 347      * @param <T> the type of the value returned by the PrivilegedAction's
 348      *                  {@code run} method.
 349      *
 350      * @param action the code to be run as the specified
 351      *                  {@code Subject}.
 352      *
 353      * @return the value returned by the PrivilegedAction's
 354      *                  {@code run} method.
 355      *
 356      * @throws NullPointerException if the {@code PrivilegedAction}
 357      *                  is {@code null}.
 358      *
 359      * @deprecated This method originally performed the specified
 360      *       {@code PrivilegedAction} with privileges enabled. Running the
 361      *       action with privileges enabled was only useful in conjunction
 362      *       with {@linkplain SecurityManager the Security Manager}, which is
 363      *       no longer supported. This method has been changed to launch the
 364      *       action as is and bind the subject to the period of its execution.
 365      *       A replacement API named {@link #callAs} has been added which can
 366      *       be used to perform the same work. There is no replacement for the
 367      *       Security Manager.
 368      *
 369      * @see #callAs(Subject, Callable)
 370      */
 371     @Deprecated(since="18", forRemoval=true)
 372     public static <T> T doAs(final Subject subject,
 373                         final java.security.PrivilegedAction<T> action) {
 374 
 375         Objects.requireNonNull(action,
 376                 ResourcesMgr.getString("invalid.null.action.provided"));
 377 
 378         try {
 379             return callAs(subject, action::run);
 380         } catch (CompletionException ce) {
 381             var cause = ce.getCause();
 382             if (cause instanceof RuntimeException re) {
 383                 throw re;
 384             } else if (cause instanceof Error er) {
 385                 throw er;
 386             } else {
 387                 throw new AssertionError(ce);
 388             }
 389         }
 390     }
 391 
 392     /**
 393      * Perform work as a particular {@code Subject}.
 394      *
 395      * <p> This method launches {@code action} and binds {@code subject} to the
 396      * period of its execution.
 397      *
 398      * @param subject the {@code Subject} that the specified
 399      *                  {@code action} will run as.  This parameter
 400      *                  may be {@code null}.
 401      *
 402      * @param <T> the type of the value returned by the
 403      *                  PrivilegedExceptionAction's {@code run} method.
 404      *
 405      * @param action the code to be run as the specified
 406      *                  {@code Subject}.
 407      *
 408      * @return the value returned by the
 409      *                  PrivilegedExceptionAction's {@code run} method.
 410      *
 411      * @throws PrivilegedActionException if the
 412      *                  {@code PrivilegedExceptionAction.run}
 413      *                  method throws a checked exception.
 414      *
 415      * @throws NullPointerException if the specified
 416      *                  {@code PrivilegedExceptionAction} is
 417      *                  {@code null}.
 418      *
 419      * @deprecated This method originally performed the specified
 420      *       {@code PrivilegedExceptionAction} with privileges enabled.
 421      *       Running the action with privileges enabled was only useful in
 422      *       conjunction with {@linkplain SecurityManager the Security Manager},
 423      *       which is no longer supported. This method has been changed to
 424      *       launch the action as is and bind the subject to the period of its
 425      *       execution. A replacement API named {@link #callAs} has been added
 426      *       which can be used to perform the same work. There is no
 427      *       replacement for the Security Manager.
 428      *
 429      * @see #callAs(Subject, Callable)
 430      */
 431     @Deprecated(since="18", forRemoval=true)
 432     public static <T> T doAs(final Subject subject,
 433                         final java.security.PrivilegedExceptionAction<T> action)
 434                         throws java.security.PrivilegedActionException {
 435 
 436         Objects.requireNonNull(action,
 437                 ResourcesMgr.getString("invalid.null.action.provided"));
 438 
 439         try {
 440             return callAs(subject, action::run);
 441         } catch (CompletionException ce) {
 442             var cause = ce.getCause();
 443             if (cause instanceof RuntimeException re) {
 444                 throw re;
 445             } else if (cause instanceof Error er) {
 446                 throw er;
 447             } else if (cause instanceof Exception e) {
 448                 throw new PrivilegedActionException(e);
 449             } else {
 450                 throw new PrivilegedActionException(ce);
 451             }
 452         }
 453     }
 454 
 455     /**
 456      * Perform work as a particular {@code Subject}.
 457      *
 458      * <p> This method launches {@code action} and binds {@code subject} to
 459      * the period of its execution.
 460      *
 461      * @param subject the {@code Subject} that the specified
 462      *                  {@code action} will run as.  This parameter
 463      *                  may be {@code null}.
 464      *
 465      * @param <T> the type of the value returned by the PrivilegedAction's
 466      *                  {@code run} method.
 467      *
 468      * @param action the code to be run as the specified
 469      *                  {@code Subject}.
 470      *
 471      * @param acc ignored
 472      *
 473      * @return the value returned by the PrivilegedAction's
 474      *                  {@code run} method.
 475      *
 476      * @throws NullPointerException if the {@code PrivilegedAction}
 477      *                  is {@code null}.
 478      *
 479      * @deprecated This method originally performed the specified
 480      *       {@code PrivilegedAction} with privileges enabled and restricted
 481      *       by the specified {@code AccessControlContext}. Running the
 482      *       action with privileges enabled was only useful in conjunction
 483      *       with {@linkplain SecurityManager the Security Manager}, which is
 484      *       no longer supported. This method has been changed to ignore the
 485      *       {@code AccessControlContext} and launch the action as is and bind
 486      *       the subject to the period of its execution. A replacement API
 487      *       named {@link #callAs} has been added which can be used to perform
 488      *       the same work. There is no replacement for the Security Manager.
 489      *
 490      * @see #callAs(Subject, Callable)
 491      */
 492     @SuppressWarnings("removal")
 493     @Deprecated(since="17", forRemoval=true)
 494     public static <T> T doAsPrivileged(final Subject subject,
 495                         final java.security.PrivilegedAction<T> action,
 496                         final java.security.AccessControlContext acc) {
 497 
 498         Objects.requireNonNull(action,
 499                 ResourcesMgr.getString("invalid.null.action.provided"));
 500 
 501         try {
 502             return callAs(subject, action::run);
 503         } catch (CompletionException ce) {
 504             var cause = ce.getCause();
 505             if (cause instanceof RuntimeException re) {
 506                 throw re;
 507             } else if (cause instanceof Error er) {
 508                 throw er;
 509             } else {
 510                 throw new AssertionError(ce);
 511             }
 512         }
 513     }
 514 
 515     /**
 516      * Perform work as a particular {@code Subject}.
 517      *
 518      * <p> This method launches {@code action} and binds {@code subject} to
 519      * the period of its execution.
 520      *
 521      * @param subject the {@code Subject} that the specified
 522      *                  {@code action} will run as.  This parameter
 523      *                  may be {@code null}.
 524      *
 525      * @param <T> the type of the value returned by the
 526      *                  PrivilegedExceptionAction's {@code run} method.
 527      *
 528      * @param action the code to be run as the specified
 529      *                  {@code Subject}.
 530      *
 531      * @param acc ignored
 532      *
 533      * @return the value returned by the
 534      *                  PrivilegedExceptionAction's {@code run} method.
 535      *
 536      * @throws PrivilegedActionException if the
 537      *                  {@code PrivilegedExceptionAction.run}
 538      *                  method throws a checked exception.
 539      *
 540      * @throws NullPointerException if the specified
 541      *                  {@code PrivilegedExceptionAction} is
 542      *                  {@code null}.
 543      *
 544      * @deprecated This method originally performed the specified
 545      *       {@code PrivilegedExceptionAction} with privileges enabled and
 546      *       restricted by the specified {@code AccessControlContext}. Running
 547      *       the action with privileges enabled was only useful in conjunction
 548      *       with {@linkplain SecurityManager the Security Manager}, which is
 549      *       no longer supported. This method has been changed to ignore the
 550      *       {@code AccessControlContext} and launch the action as is and bind
 551      *       the subject to the period of its execution. A replacement API
 552      *       named {@link #callAs} has been added which can be used to perform
 553      *       the same work. There is no replacement for the Security Manager.
 554      *
 555      * @see #callAs(Subject, Callable)
 556      */
 557     @SuppressWarnings("removal")
 558     @Deprecated(since="17", forRemoval=true)
 559     public static <T> T doAsPrivileged(final Subject subject,
 560                         final java.security.PrivilegedExceptionAction<T> action,
 561                         final java.security.AccessControlContext acc)
 562                         throws java.security.PrivilegedActionException {
 563 
 564         Objects.requireNonNull(action,
 565                 ResourcesMgr.getString("invalid.null.action.provided"));
 566 
 567         try {
 568             return callAs(subject, action::run);
 569         } catch (CompletionException ce) {
 570             var cause = ce.getCause();
 571             if (cause instanceof RuntimeException re) {
 572                 throw re;
 573             } else if (cause instanceof Error er) {
 574                 throw er;
 575             } else if (cause instanceof Exception e) {
 576                 throw new PrivilegedActionException(e);
 577             } else {
 578                 throw new PrivilegedActionException(ce);
 579             }
 580         }
 581     }
 582 
 583     /**
 584      * Return the {@code Set} of Principals associated with this
 585      * {@code Subject}.  Each {@code Principal} represents
 586      * an identity for this {@code Subject}.
 587      *
 588      * <p> The returned {@code Set} is backed by this Subject's
 589      * internal {@code Principal} {@code Set}.  Any modification
 590      * to the returned {@code Set} affects the internal
 591      * {@code Principal} {@code Set} as well.
 592      *
 593      * @return  the {@code Set} of Principals associated with this
 594      *          {@code Subject}.
 595      */
 596     public Set<Principal> getPrincipals() {
 597 
 598         // always return an empty Set instead of null
 599         // so LoginModules can add to the Set if necessary
 600         return principals;
 601     }
 602 
 603     /**
 604      * Return a {@code Set} of Principals associated with this
 605      * {@code Subject} that are instances or subclasses of the specified
 606      * {@code Class}.
 607      *
 608      * <p> The returned {@code Set} is not backed by this Subject's
 609      * internal {@code Principal} {@code Set}.  A new
 610      * {@code Set} is created and returned for each method invocation.
 611      * Modifications to the returned {@code Set}
 612      * will not affect the internal {@code Principal} {@code Set}.
 613      *
 614      * @param <T> the type of the class modeled by {@code c}
 615      *
 616      * @param c the returned {@code Set} of Principals will all be
 617      *          instances of this class.
 618      *
 619      * @return a {@code Set} of Principals that are instances of the
 620      *          specified {@code Class}.
 621      *
 622      * @throws NullPointerException if the specified {@code Class}
 623      *          is {@code null}.
 624      */
 625     public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
 626 
 627         Objects.requireNonNull(c,
 628                 ResourcesMgr.getString("invalid.null.Class.provided"));
 629 
 630         // always return an empty Set instead of null
 631         // so LoginModules can add to the Set if necessary
 632         return new ClassSet<>(PRINCIPAL_SET, c);
 633     }
 634 
 635     /**
 636      * Return the {@code Set} of public credentials held by this
 637      * {@code Subject}.
 638      *
 639      * <p> The returned {@code Set} is backed by this Subject's
 640      * internal public Credential {@code Set}.  Any modification
 641      * to the returned {@code Set} affects the internal public
 642      * Credential {@code Set} as well.
 643      *
 644      * @return  a {@code Set} of public credentials held by this
 645      *          {@code Subject}.
 646      */
 647     public Set<Object> getPublicCredentials() {
 648 
 649         // always return an empty Set instead of null
 650         // so LoginModules can add to the Set if necessary
 651         return pubCredentials;
 652     }
 653 
 654     /**
 655      * Return the {@code Set} of private credentials held by this
 656      * {@code Subject}.
 657      *
 658      * <p> The returned {@code Set} is backed by this Subject's
 659      * internal private Credential {@code Set}.  Any modification
 660      * to the returned {@code Set} affects the internal private
 661      * Credential {@code Set} as well.
 662      *
 663      * @return  a {@code Set} of private credentials held by this
 664      *          {@code Subject}.
 665      */
 666     public Set<Object> getPrivateCredentials() {
 667 
 668         // always return an empty Set instead of null
 669         // so LoginModules can add to the Set if necessary
 670         return privCredentials;
 671     }
 672 
 673     /**
 674      * Return a {@code Set} of public credentials associated with this
 675      * {@code Subject} that are instances or subclasses of the specified
 676      * {@code Class}.
 677      *
 678      * <p> The returned {@code Set} is not backed by this Subject's
 679      * internal public Credential {@code Set}.  A new
 680      * {@code Set} is created and returned for each method invocation.
 681      * Modifications to the returned {@code Set}
 682      * will not affect the internal public Credential {@code Set}.
 683      *
 684      * @param <T> the type of the class modeled by {@code c}
 685      *
 686      * @param c the returned {@code Set} of public credentials will all be
 687      *          instances of this class.
 688      *
 689      * @return a {@code Set} of public credentials that are instances
 690      *          of the  specified {@code Class}.
 691      *
 692      * @throws NullPointerException if the specified {@code Class}
 693      *          is {@code null}.
 694      */
 695     public <T> Set<T> getPublicCredentials(Class<T> c) {
 696 
 697         Objects.requireNonNull(c,
 698                 ResourcesMgr.getString("invalid.null.Class.provided"));
 699 
 700         // always return an empty Set instead of null
 701         // so LoginModules can add to the Set if necessary
 702         return new ClassSet<>(PUB_CREDENTIAL_SET, c);
 703     }
 704 
 705     /**
 706      * Return a {@code Set} of private credentials associated with this
 707      * {@code Subject} that are instances or subclasses of the specified
 708      * {@code Class}.
 709      *
 710      * <p> The returned {@code Set} is not backed by this Subject's
 711      * internal private Credential {@code Set}.  A new
 712      * {@code Set} is created and returned for each method invocation.
 713      * Modifications to the returned {@code Set}
 714      * will not affect the internal private Credential {@code Set}.
 715      *
 716      * @param <T> the type of the class modeled by {@code c}
 717      *
 718      * @param c the returned {@code Set} of private credentials will all be
 719      *          instances of this class.
 720      *
 721      * @return a {@code Set} of private credentials that are instances
 722      *          of the  specified {@code Class}.
 723      *
 724      * @throws NullPointerException if the specified {@code Class}
 725      *          is {@code null}.
 726      */
 727     public <T> Set<T> getPrivateCredentials(Class<T> c) {
 728 
 729         Objects.requireNonNull(c,
 730                 ResourcesMgr.getString("invalid.null.Class.provided"));
 731 
 732         // always return an empty Set instead of null
 733         // so LoginModules can add to the Set if necessary
 734         return new ClassSet<>(PRIV_CREDENTIAL_SET, c);
 735     }
 736 
 737     /**
 738      * Compares the specified Object with this {@code Subject}
 739      * for equality.  Returns true if the given object is also a Subject
 740      * and the two {@code Subject} instances are equivalent.
 741      * More formally, two {@code Subject} instances are
 742      * equal if their {@code Principal} and {@code Credential}
 743      * Sets are equal.
 744      *
 745      * @param o Object to be compared for equality with this
 746      *          {@code Subject}.
 747      *
 748      * @return true if the specified Object is equal to this
 749      *          {@code Subject}.
 750      */
 751     @Override
 752     public boolean equals(Object o) {
 753 
 754         if (this == o) {
 755             return true;
 756         }
 757 
 758         if (o instanceof final Subject that) {
 759 
 760             // check the principal and credential sets
 761             Set<Principal> thatPrincipals;
 762             synchronized(that.principals) {
 763                 // avoid deadlock from dual locks
 764                 thatPrincipals = new HashSet<>(that.principals);
 765             }
 766             if (!principals.equals(thatPrincipals)) {
 767                 return false;
 768             }
 769 
 770             Set<Object> thatPubCredentials;
 771             synchronized(that.pubCredentials) {
 772                 // avoid deadlock from dual locks
 773                 thatPubCredentials = new HashSet<>(that.pubCredentials);
 774             }
 775             if (!pubCredentials.equals(thatPubCredentials)) {
 776                 return false;
 777             }
 778 
 779             Set<Object> thatPrivCredentials;
 780             synchronized(that.privCredentials) {
 781                 // avoid deadlock from dual locks
 782                 thatPrivCredentials = new HashSet<>(that.privCredentials);
 783             }
 784             return privCredentials.equals(thatPrivCredentials);
 785         }
 786         return false;
 787     }
 788 
 789     /**
 790      * Return the String representation of this {@code Subject}.
 791      *
 792      * @return the String representation of this {@code Subject}.
 793      */
 794     @Override
 795     public String toString() {
 796 
 797         String s = ResourcesMgr.getString("Subject.");
 798         String suffix = "";
 799 
 800         synchronized(principals) {
 801             for (Principal p : principals) {
 802                 suffix = suffix + ResourcesMgr.getString(".Principal.") +
 803                         p.toString() + ResourcesMgr.getString("NEWLINE");
 804             }
 805         }
 806 
 807         synchronized(pubCredentials) {
 808             for (Object o : pubCredentials) {
 809                 suffix = suffix +
 810                         ResourcesMgr.getString(".Public.Credential.") +
 811                         o.toString() + ResourcesMgr.getString("NEWLINE");
 812             }
 813         }
 814 
 815         synchronized(privCredentials) {
 816             Iterator<Object> pI = privCredentials.iterator();
 817             while (pI.hasNext()) {
 818                 try {
 819                     Object o = pI.next();
 820                     suffix += ResourcesMgr.getString
 821                                     (".Private.Credential.") +
 822                                     o.toString() +
 823                                     ResourcesMgr.getString("NEWLINE");
 824                 } catch (SecurityException se) {
 825                     suffix += ResourcesMgr.getString
 826                             (".Private.Credential.inaccessible.");
 827                     break;
 828                 }
 829             }
 830         }
 831         return s + suffix;
 832     }
 833 
 834     /**
 835      * {@return a hashcode for this {@code Subject}}
 836      */
 837     @Override
 838     public int hashCode() {
 839 
 840         /*
 841          * The hashcode is derived exclusive or-ing the
 842          * hashcodes of this Subject's Principals and credentials.
 843          *
 844          * If a particular credential was destroyed
 845          * ({@code credential.hashCode()} throws an
 846          * {@code IllegalStateException}),
 847          * the hashcode for that credential is derived via:
 848          * {@code credential.getClass().toString().hashCode()}.
 849          */
 850 
 851         int hashCode = 0;
 852 
 853         synchronized(principals) {
 854             for (Principal p : principals) {
 855                 hashCode ^= p.hashCode();
 856             }
 857         }
 858 
 859         synchronized(pubCredentials) {
 860             for (Object pubCredential : pubCredentials) {
 861                 hashCode ^= getCredHashCode(pubCredential);
 862             }
 863         }
 864         return hashCode;
 865     }
 866 
 867     /**
 868      * get a credential's hashcode
 869      */
 870     private int getCredHashCode(Object o) {
 871         try {
 872             return o.hashCode();
 873         } catch (IllegalStateException ise) {
 874             return o.getClass().toString().hashCode();
 875         }
 876     }
 877 
 878     /**
 879      * Writes this object out to a stream (i.e., serializes it).
 880      *
 881      * @param  oos the {@code ObjectOutputStream} to which data is written
 882      * @throws IOException if an I/O error occurs
 883      */
 884     @java.io.Serial
 885     private void writeObject(java.io.ObjectOutputStream oos)
 886                 throws java.io.IOException {
 887         synchronized(principals) {
 888             oos.defaultWriteObject();
 889         }
 890     }
 891 
 892     /**
 893      * Reads this object from a stream (i.e., deserializes it)
 894      *
 895      * @param  s the {@code ObjectInputStream} from which data is read
 896      * @throws IOException if an I/O error occurs
 897      * @throws ClassNotFoundException if a serialized class cannot be loaded
 898      */
 899     @SuppressWarnings("unchecked")
 900     @java.io.Serial
 901     private void readObject(java.io.ObjectInputStream s)
 902                 throws java.io.IOException, ClassNotFoundException {
 903 
 904         ObjectInputStream.GetField gf = s.readFields();
 905 
 906         readOnly = gf.get("readOnly", false);
 907 
 908         Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
 909 
 910         Objects.requireNonNull(inputPrincs,
 911                 ResourcesMgr.getString("invalid.null.input.s."));
 912 
 913         // Rewrap the principals into a SecureSet
 914         try {
 915             LinkedList<Principal> principalList = collectionNullClean(inputPrincs);
 916             principals = Collections.synchronizedSet(new SecureSet<>
 917                                 (this, PRINCIPAL_SET, principalList));
 918         } catch (NullPointerException npe) {
 919             // Sometimes people deserialize the principals set only.
 920             // Subject is not accessible, so just don't fail.
 921             principals = Collections.synchronizedSet
 922                         (new SecureSet<>(this, PRINCIPAL_SET));
 923         }
 924 
 925         // The Credential {@code Set} is not serialized, but we do not
 926         // want the default deserialization routine to set it to null.
 927         this.pubCredentials = Collections.synchronizedSet
 928                         (new SecureSet<>(this, PUB_CREDENTIAL_SET));
 929         this.privCredentials = Collections.synchronizedSet
 930                         (new SecureSet<>(this, PRIV_CREDENTIAL_SET));
 931     }
 932 
 933     /**
 934      * Tests for null-clean collections (both non-null reference and
 935      * no null elements)
 936      *
 937      * @param coll A {@code Collection} to be tested for null references
 938      *
 939      * @throws NullPointerException if the specified collection is either
 940      *            {@code null} or contains a {@code null} element
 941      */
 942     private static <E> LinkedList<E> collectionNullClean(
 943             Collection<? extends E> coll) {
 944 
 945         Objects.requireNonNull(coll,
 946                 ResourcesMgr.getString("invalid.null.input.s."));
 947 
 948         LinkedList<E> output = new LinkedList<>();
 949         for (E e : coll) {
 950             output.add(Objects.requireNonNull(e,
 951                     ResourcesMgr.getString("invalid.null.input.s.")));
 952         }
 953         return output;
 954     }
 955 
 956     /**
 957      * Prevent modifications unless caller has permission.
 958      *
 959      * @serial include
 960      */
 961     private static class SecureSet<E>
 962         implements Set<E>, java.io.Serializable {
 963 
 964         @java.io.Serial
 965         private static final long serialVersionUID = 7911754171111800359L;
 966 
 967         /**
 968          * @serialField this$0 Subject The outer Subject instance.
 969          * @serialField elements LinkedList The elements in this set.
 970          */
 971         @java.io.Serial
 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},
 984          *      this is a Principal set and all the elements are
 985          *      of type {@code java.security.Principal}.
 986          *      If {@code which == 2}, this is a public credential
 987          *      set and all the elements are of type {@code Object}.
 988          *      If {@code which == 3}, this is a private credential
 989          *      set and all the elements are of type {@code Object}.
 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<>();
 997         }
 998 
 999         SecureSet(Subject subject, int which, LinkedList<E> list) {
1000             this.subject = subject;
1001             this.which = which;
1002             this.elements = list;
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<>() {
1012                 final ListIterator<E> i = list.listIterator(0);
1013 
1014                 public boolean hasNext() {
1015                     return i.hasNext();
1016                 }
1017 
1018                 public E next() {
1019                     return i.next();
1020                 }
1021 
1022                 public void remove() {
1023 
1024                     if (subject.isReadOnly()) {
1025                         throw new IllegalStateException(ResourcesMgr.getString
1026                                 ("Subject.is.read.only"));
1027                     }
1028 
1029                     i.remove();
1030                 }
1031             };
1032         }
1033 
1034         public boolean add(E o) {
1035 
1036             Objects.requireNonNull(o,
1037                     ResourcesMgr.getString("invalid.null.input.s."));
1038 
1039             if (subject.isReadOnly()) {
1040                 throw new IllegalStateException
1041                         (ResourcesMgr.getString("Subject.is.read.only"));
1042             }
1043 
1044             switch (which) {
1045             case Subject.PRINCIPAL_SET:
1046                 if (!(o instanceof Principal)) {
1047                     throw new SecurityException(ResourcesMgr.getString
1048                         ("attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set"));
1049                 }
1050                 break;
1051             default:
1052                 // ok to add Objects of any kind to credential sets
1053                 break;
1054             }
1055 
1056             // check for duplicates
1057             if (!elements.contains(o))
1058                 return elements.add(o);
1059             else {
1060                 return false;
1061             }
1062         }
1063 
1064         public boolean remove(Object o) {
1065 
1066             Objects.requireNonNull(o,
1067                     ResourcesMgr.getString("invalid.null.input.s."));
1068 
1069             final Iterator<E> e = iterator();
1070             while (e.hasNext()) {
1071                 E next = e.next();
1072 
1073                 if (next.equals(o)) {
1074                     e.remove();
1075                     return true;
1076                 }
1077             }
1078             return false;
1079         }
1080 
1081         public boolean contains(Object o) {
1082 
1083             Objects.requireNonNull(o,
1084                     ResourcesMgr.getString("invalid.null.input.s."));
1085 
1086             final Iterator<E> e = iterator();
1087             while (e.hasNext()) {
1088                 E next = e.next();
1089 
1090                 if (next.equals(o)) {
1091                     return true;
1092                 }
1093             }
1094             return false;
1095         }
1096 
1097         public boolean addAll(Collection<? extends E> c) {
1098             boolean result = false;
1099 
1100             c = collectionNullClean(c);
1101 
1102             for (E item : c) {
1103                 result |= this.add(item);
1104             }
1105 
1106             return result;
1107         }
1108 
1109         public boolean removeAll(Collection<?> c) {
1110             c = collectionNullClean(c);
1111 
1112             boolean modified = false;
1113             final Iterator<E> e = iterator();
1114             while (e.hasNext()) {
1115                 E next = e.next();
1116 
1117                 for (Object o : c) {
1118                     if (next.equals(o)) {
1119                         e.remove();
1120                         modified = true;
1121                         break;
1122                     }
1123                 }
1124             }
1125             return modified;
1126         }
1127 
1128         public boolean containsAll(Collection<?> c) {
1129             c = collectionNullClean(c);
1130 
1131             for (Object item : c) {
1132                 if (!this.contains(item)) {
1133                     return false;
1134                 }
1135             }
1136 
1137             return true;
1138         }
1139 
1140         public boolean retainAll(Collection<?> c) {
1141             c = collectionNullClean(c);
1142 
1143             boolean modified = false;
1144             final Iterator<E> e = iterator();
1145             while (e.hasNext()) {
1146                 E next = e.next();
1147 
1148                 if (c.contains(next) == false) {
1149                     e.remove();
1150                     modified = true;
1151                 }
1152             }
1153 
1154             return modified;
1155         }
1156 
1157         public void clear() {
1158             final Iterator<E> e = iterator();
1159             while (e.hasNext()) {
1160                 E next = e.next();
1161                 e.remove();
1162             }
1163         }
1164 
1165         public boolean isEmpty() {
1166             return elements.isEmpty();
1167         }
1168 
1169         public Object[] toArray() {
1170             return elements.toArray();
1171         }
1172 
1173         public <T> T[] toArray(T[] a) {
1174             return elements.toArray(a);
1175         }
1176 
1177         @Override
1178         public boolean equals(Object o) {
1179             if (o == this) {
1180                 return true;
1181             }
1182 
1183             if (!(o instanceof Set)) {
1184                 return false;
1185             }
1186 
1187             Collection<?> c = (Collection<?>) o;
1188             if (c.size() != size()) {
1189                 return false;
1190             }
1191 
1192             try {
1193                 return containsAll(c);
1194             } catch (ClassCastException | NullPointerException unused) {
1195                 return false;
1196             }
1197         }
1198 
1199         @Override
1200         public int hashCode() {
1201             int h = 0;
1202             for (E obj : this) {
1203                 h += Objects.hashCode(obj);
1204             }
1205             return h;
1206         }
1207 
1208         /**
1209          * Writes this object out to a stream (i.e., serializes it).
1210          *
1211          * @param  oos the {@code ObjectOutputStream} to which data is written
1212          * @throws IOException if an I/O error occurs
1213          */
1214         @java.io.Serial
1215         private void writeObject(java.io.ObjectOutputStream oos)
1216                 throws java.io.IOException {
1217 
1218             ObjectOutputStream.PutField fields = oos.putFields();
1219             fields.put("this$0", subject);
1220             fields.put("elements", elements);
1221             fields.put("which", which);
1222             oos.writeFields();
1223         }
1224 
1225         /**
1226          * Restores the state of this object from the stream.
1227          *
1228          * @param  ois the {@code ObjectInputStream} from which data is read
1229          * @throws IOException if an I/O error occurs
1230          * @throws ClassNotFoundException if a serialized class cannot be loaded
1231          */
1232         @SuppressWarnings("unchecked")
1233         @java.io.Serial
1234         private void readObject(ObjectInputStream ois)
1235             throws IOException, ClassNotFoundException
1236         {
1237             ObjectInputStream.GetField fields = ois.readFields();
1238             subject = (Subject) fields.get("this$0", null);
1239             which = fields.get("which", 0);
1240 
1241             LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
1242 
1243             elements = Subject.collectionNullClean(tmp);
1244         }
1245 
1246     }
1247 
1248     /**
1249      * This class implements a {@code Set} which returns only
1250      * members that are an instance of a specified Class.
1251      */
1252     private class ClassSet<T> extends AbstractSet<T> {
1253 
1254         private final int which;
1255         private final Class<T> c;
1256         private final Set<T> set;
1257 
1258         ClassSet(int which, Class<T> c) {
1259             this.which = which;
1260             this.c = c;
1261             set = new HashSet<>();
1262 
1263             switch (which) {
1264             case Subject.PRINCIPAL_SET:
1265                 synchronized(principals) { populateSet(); }
1266                 break;
1267             case Subject.PUB_CREDENTIAL_SET:
1268                 synchronized(pubCredentials) { populateSet(); }
1269                 break;
1270             default:
1271                 synchronized(privCredentials) { populateSet(); }
1272                 break;
1273             }
1274         }
1275 
1276         @SuppressWarnings("unchecked")
1277         private void populateSet() {
1278             final Iterator<?> iterator;
1279             switch(which) {
1280             case Subject.PRINCIPAL_SET:
1281                 iterator = Subject.this.principals.iterator();
1282                 break;
1283             case Subject.PUB_CREDENTIAL_SET:
1284                 iterator = Subject.this.pubCredentials.iterator();
1285                 break;
1286             default:
1287                 iterator = Subject.this.privCredentials.iterator();
1288                 break;
1289             }
1290 
1291             while (iterator.hasNext()) {
1292                 Object next = iterator.next();
1293                 if (c.isAssignableFrom(next.getClass())) {
1294                     set.add((T)next);
1295                 }
1296             }
1297         }
1298 
1299         @Override
1300         public int size() {
1301             return set.size();
1302         }
1303 
1304         @Override
1305         public Iterator<T> iterator() {
1306             return set.iterator();
1307         }
1308 
1309         @Override
1310         public boolean add(T o) {
1311 
1312             if (!c.isAssignableFrom(o.getClass())) {
1313                 MessageFormat form = new MessageFormat(ResourcesMgr.getString
1314                         ("attempting.to.add.an.object.which.is.not.an.instance.of.class"));
1315                 Object[] source = {c.toString()};
1316                 throw new SecurityException(form.format(source));
1317             }
1318 
1319             return set.add(o);
1320         }
1321     }
1322 }