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