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