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