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