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