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 return null if 1013 // contains(null) is called on it rather than returning false. 1014 // If so then we know no nulls are present. 1015 isClean = true; 1016 } 1017 1018 return isClean; 1019 } 1020 1021 /** 1022 * Prevent modifications unless caller has permission. 1023 * 1024 * @serial include 1025 */ 1026 private static class SecureSet<E> 1027 implements Set<E>, java.io.Serializable { 1028 1029 private static final long serialVersionUID = 7911754171111800359L; 1030 1031 /** 1032 * @serialField this$0 Subject The outer Subject instance. 1033 * @serialField elements LinkedList The elements in this set. 1034 */ 1035 private static final ObjectStreamField[] serialPersistentFields = { 1036 new ObjectStreamField("this$0", Subject.class), 1037 new ObjectStreamField("elements", LinkedList.class), 1038 new ObjectStreamField("which", int.class) 1039 }; 1040 1041 Subject subject; 1042 LinkedList<E> elements; 1043 1044 /** 1045 * @serial An integer identifying the type of objects contained 1046 * in this set. If {@code which == 1}, 1047 * this is a Principal set and all the elements are 1048 * of type {@code java.security.Principal}. 1049 * If {@code which == 2}, this is a public credential 1050 * set and all the elements are of type {@code Object}. 1051 * If {@code which == 3}, this is a private credential 1052 * set and all the elements are of type {@code Object}. 1053 */ 1054 private int which; 1055 1056 SecureSet(Subject subject, int which) { 1057 this.subject = subject; 1058 this.which = which; 1059 this.elements = new LinkedList<E>(); 1060 } 1061 1062 SecureSet(Subject subject, int which, Set<? extends E> set) { 1063 this.subject = subject; 1064 this.which = which; 1065 this.elements = new LinkedList<E>(set); 1066 } 1067 1068 public int size() { 1069 return elements.size(); 1070 } 1071 1072 public Iterator<E> iterator() { 1073 final LinkedList<E> list = elements; 1074 return new Iterator<E>() { 1075 ListIterator<E> i = list.listIterator(0); 1076 1077 public boolean hasNext() {return i.hasNext();} 1078 1079 public E next() { 1080 if (which != Subject.PRIV_CREDENTIAL_SET) { 1081 return i.next(); 1082 } 1083 1084 SecurityManager sm = System.getSecurityManager(); 1085 if (sm != null) { 1086 try { 1087 sm.checkPermission(new PrivateCredentialPermission 1088 (list.get(i.nextIndex()).getClass().getName(), 1089 subject.getPrincipals())); 1090 } catch (SecurityException se) { 1091 i.next(); 1092 throw (se); 1093 } 1094 } 1095 return i.next(); 1096 } 1097 1098 public void remove() { 1099 1100 if (subject.isReadOnly()) { 1101 throw new IllegalStateException(ResourcesMgr.getString 1102 ("Subject.is.read.only")); 1103 } 1104 1105 java.lang.SecurityManager sm = System.getSecurityManager(); 1106 if (sm != null) { 1107 switch (which) { 1108 case Subject.PRINCIPAL_SET: 1109 sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION); 1110 break; 1111 case Subject.PUB_CREDENTIAL_SET: 1112 sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION); 1113 break; 1114 default: 1115 sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION); 1116 break; 1117 } 1118 } 1119 i.remove(); 1120 } 1121 }; 1122 } 1123 1124 public boolean add(E o) { 1125 1126 if (o == null) { 1127 throw new NullPointerException 1128 (ResourcesMgr.getString("invalid.null.input.s.")); 1129 } 1130 1131 if (subject.isReadOnly()) { 1132 throw new IllegalStateException 1133 (ResourcesMgr.getString("Subject.is.read.only")); 1134 } 1135 1136 java.lang.SecurityManager sm = System.getSecurityManager(); 1137 if (sm != null) { 1138 switch (which) { 1139 case Subject.PRINCIPAL_SET: 1140 sm.checkPermission(AuthPermissionHolder.MODIFY_PRINCIPALS_PERMISSION); 1141 break; 1142 case Subject.PUB_CREDENTIAL_SET: 1143 sm.checkPermission(AuthPermissionHolder.MODIFY_PUBLIC_CREDENTIALS_PERMISSION); 1144 break; 1145 default: 1146 sm.checkPermission(AuthPermissionHolder.MODIFY_PRIVATE_CREDENTIALS_PERMISSION); 1147 break; 1148 } 1149 } 1150 1151 switch (which) { 1152 case Subject.PRINCIPAL_SET: 1153 if (!(o instanceof Principal)) { 1154 throw new SecurityException(ResourcesMgr.getString 1155 ("attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set")); 1156 } 1157 break; 1158 default: 1159 // ok to add Objects of any kind to credential sets 1160 break; 1161 } 1162 1163 // check for duplicates 1164 if (!elements.contains(o)) 1165 return elements.add(o); 1166 else 1167 return false; 1168 } 1169 1170 public boolean remove(Object o) { 1171 1172 if (o == null) { 1173 throw new NullPointerException 1174 (ResourcesMgr.getString("invalid.null.input.s.")); 1175 } 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 if (o == null) { 1202 throw new NullPointerException 1203 (ResourcesMgr.getString("invalid.null.input.s.")); 1204 } 1205 1206 final Iterator<E> e = iterator(); 1207 while (e.hasNext()) { 1208 E next; 1209 if (which != Subject.PRIV_CREDENTIAL_SET) { 1210 next = e.next(); 1211 } else { 1212 1213 // For private credentials: 1214 // If the caller does not have read permission for 1215 // for o.getClass(), we throw a SecurityException. 1216 // Otherwise we check the private cred set to see whether 1217 // it contains the Object 1218 1219 SecurityManager sm = System.getSecurityManager(); 1220 if (sm != null) { 1221 sm.checkPermission(new PrivateCredentialPermission 1222 (o.getClass().getName(), 1223 subject.getPrincipals())); 1224 } 1225 next = java.security.AccessController.doPrivileged 1226 (new java.security.PrivilegedAction<E>() { 1227 public E run() { 1228 return e.next(); 1229 } 1230 }); 1231 } 1232 1233 if (next.equals(o)) { 1234 return true; 1235 } 1236 } 1237 return false; 1238 } 1239 1240 public boolean addAll(Collection<? extends E> c) { 1241 boolean result = false; 1242 1243 if (collectionNullClean(c) == false) { 1244 throw new NullPointerException 1245 (ResourcesMgr.getString("invalid.null.input.s.")); 1246 } 1247 1248 for (E item : c) { 1249 result |= this.add(item); 1250 } 1251 1252 return result; 1253 } 1254 1255 public boolean removeAll(Collection<?> c) { 1256 if (collectionNullClean(c) == false) { 1257 throw new NullPointerException 1258 (ResourcesMgr.getString("invalid.null.input.s.")); 1259 } 1260 1261 boolean modified = false; 1262 final Iterator<E> e = iterator(); 1263 while (e.hasNext()) { 1264 E next; 1265 if (which != Subject.PRIV_CREDENTIAL_SET) { 1266 next = e.next(); 1267 } else { 1268 next = java.security.AccessController.doPrivileged 1269 (new java.security.PrivilegedAction<E>() { 1270 public E run() { 1271 return e.next(); 1272 } 1273 }); 1274 } 1275 1276 Iterator<?> ce = c.iterator(); 1277 while (ce.hasNext()) { 1278 if (next.equals(ce.next())) { 1279 e.remove(); 1280 modified = true; 1281 break; 1282 } 1283 } 1284 } 1285 return modified; 1286 } 1287 1288 public boolean containsAll(Collection<?> c) { 1289 if (collectionNullClean(c) == false) { 1290 throw new NullPointerException 1291 (ResourcesMgr.getString("invalid.null.input.s.")); 1292 } 1293 1294 for (Object item : c) { 1295 if (this.contains(item) == false) { 1296 return false; 1297 } 1298 } 1299 1300 return true; 1301 } 1302 1303 public boolean retainAll(Collection<?> c) { 1304 if (collectionNullClean(c) == false) { 1305 throw new NullPointerException 1306 (ResourcesMgr.getString("invalid.null.input.s.")); 1307 } 1308 1309 boolean modified = false; 1310 final Iterator<E> e = iterator(); 1311 while (e.hasNext()) { 1312 E next; 1313 if (which != Subject.PRIV_CREDENTIAL_SET) { 1314 next = e.next(); 1315 } else { 1316 next = java.security.AccessController.doPrivileged 1317 (new java.security.PrivilegedAction<E>() { 1318 public E run() { 1319 return e.next(); 1320 } 1321 }); 1322 } 1323 1324 if (c.contains(next) == false) { 1325 e.remove(); 1326 modified = true; 1327 } 1328 } 1329 1330 return modified; 1331 } 1332 1333 public void clear() { 1334 final Iterator<E> e = iterator(); 1335 while (e.hasNext()) { 1336 E next; 1337 if (which != Subject.PRIV_CREDENTIAL_SET) { 1338 next = e.next(); 1339 } else { 1340 next = java.security.AccessController.doPrivileged 1341 (new java.security.PrivilegedAction<E>() { 1342 public E run() { 1343 return e.next(); 1344 } 1345 }); 1346 } 1347 e.remove(); 1348 } 1349 } 1350 1351 public boolean isEmpty() { 1352 return elements.isEmpty(); 1353 } 1354 1355 public Object[] toArray() { 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(); 1367 } 1368 1369 public <T> T[] toArray(T[] a) { 1370 final Iterator<E> e = iterator(); 1371 while (e.hasNext()) { 1372 // The next() method performs a security manager check 1373 // on each element in the SecureSet. If we make it all 1374 // the way through we should be able to simply return 1375 // element's toArray results. Otherwise we'll let 1376 // the SecurityException pass up the call stack. 1377 e.next(); 1378 } 1379 1380 return elements.toArray(a); 1381 } 1382 1383 public boolean equals(Object o) { 1384 if (o == this) 1385 return true; 1386 1387 if (!(o instanceof Set)) 1388 return false; 1389 Collection<?> c = (Collection<?>) o; 1390 if (c.size() != size()) 1391 return false; 1392 try { 1393 return containsAll(c); 1394 } catch (ClassCastException unused) { 1395 return false; 1396 } catch (NullPointerException unused) { 1397 return false; 1398 } 1399 } 1400 1401 /** 1402 * Writes this object out to a stream (i.e., serializes it). 1403 * 1404 * <p> 1405 * 1406 * @serialData If this is a private credential set, 1407 * a security check is performed to ensure that 1408 * the caller has permission to access each credential 1409 * in the set. If the security check passes, 1410 * the set is serialized. 1411 */ 1412 private void writeObject(java.io.ObjectOutputStream oos) 1413 throws java.io.IOException { 1414 1415 if (which == Subject.PRIV_CREDENTIAL_SET) { 1416 // check permissions before serializing 1417 Iterator<E> i = iterator(); 1418 while (i.hasNext()) { 1419 i.next(); 1420 } 1421 } 1422 ObjectOutputStream.PutField fields = oos.putFields(); 1423 fields.put("this$0", subject); 1424 fields.put("elements", elements); 1425 fields.put("which", which); 1426 oos.writeFields(); 1427 } 1428 1429 @SuppressWarnings("unchecked") 1430 private void readObject(ObjectInputStream ois) 1431 throws IOException, ClassNotFoundException 1432 { 1433 ObjectInputStream.GetField fields = ois.readFields(); 1434 subject = (Subject) fields.get("this$0", null); 1435 which = fields.get("which", 0); 1436 1437 LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null); 1438 1439 if (Subject.collectionNullClean(tmp) == false) { 1440 throw new NullPointerException 1441 (ResourcesMgr.getString("invalid.null.input.s.")); 1442 } 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 }