001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: AuthContext.java,v 1.10 2009/01/28 05:34:52 ww203982 Exp $ 026 * 027 * Portions Copyrighted 2011-2014 ForgeRock AS. 028 */ 029 030package com.sun.identity.authentication.internal; 031 032import java.io.ByteArrayInputStream; 033import java.io.ByteArrayOutputStream; 034import java.io.IOException; 035import java.io.ObjectInputStream; 036import java.io.ObjectOutputStream; 037import java.net.InetAddress; 038import java.security.Principal; 039import java.security.SecureRandom; 040import java.util.Iterator; 041import java.util.Set; 042 043import javax.security.auth.callback.Callback; 044import javax.security.auth.callback.ChoiceCallback; 045import javax.security.auth.callback.NameCallback; 046import javax.security.auth.callback.PasswordCallback; 047import javax.security.auth.callback.TextInputCallback; 048import javax.security.auth.callback.TextOutputCallback; 049import javax.security.auth.login.LoginException; 050 051import com.sun.identity.shared.ldap.util.DN; 052import com.sun.identity.shared.ldap.LDAPDN; 053 054import com.sun.identity.shared.debug.Debug; 055import com.iplanet.am.util.SecureRandomManager; 056import com.iplanet.am.util.SystemProperties; 057import com.iplanet.services.util.I18n; 058import com.iplanet.sso.SSOToken; 059import com.sun.identity.authentication.internal.server.AuthSPrincipal; 060import com.sun.identity.authentication.internal.util.AuthI18n; 061import com.sun.identity.shared.Constants; 062import com.sun.identity.sm.ServiceManager; 063 064 065/** 066 * The AuthContext provides the implementation for authenticating users using 067 * the JAAS technology. It complements <code>LoginContext 068 * </code> provided by 069 * JAAS by supporting organization environments that cannot handle sessions, for 070 * example, HTTP/HTML. 071 * <p> 072 * A typical caller instantiates this class and starts the login process. The 073 * caller then obtains an array of <code>Callback</code> objects, which 074 * contains the information required by the authentication plug-in module. The 075 * caller requests information from the user. On receiving the information from 076 * the user, the caller submits the same to this class. If more information is 077 * required, the above process continues until all the information required by 078 * the plug-ins has been supplied. The caller then checks if the user has 079 * successfully been authenticated. If successfully authenticated, the caller 080 * can then get the <code> 081 * Subject</code> for the user; if not successfully 082 * authenticated, the caller obtains the LoginException. 083 * 084 * @supported.api 085 */ 086public final class AuthContext extends Object { 087 088 /** 089 * This login status indicates that the login process 090 * has not started yet. Basically, it means that the method 091 * <code>startLogin</code> has not been called. 092 * 093 * @supported.api 094 */ 095 public static final int AUTH_NOT_STARTED = 1; 096 097 /** 098 * This login status indicates that the login process 099 * is in progress. Basically, it means that the <code>startLogin</code> 100 * method has been called and that this object is waiting for the user to 101 * send authentication information. 102 * 103 * @supported.api 104 */ 105 public static final int AUTH_IN_PROGRESS = 2; 106 107 /** 108 * This login status indicates that the login process 109 * has succeeded. 110 * 111 * @supported.api 112 */ 113 public static final int AUTH_SUCCESS = 3; 114 115 /** 116 * This login status indicates that the login process 117 * has failed. 118 * 119 * @supported.api 120 */ 121 public static final int AUTH_FAILED = 4; 122 123 /** 124 * This login status indicates that the user has been 125 * successfully logged out. 126 * 127 * @supported.api 128 */ 129 public static final int AUTH_COMPLETED = 5; 130 131 /* 132 * Protected variables used locally 133 */ 134 protected final String authComponentName = "Authentication"; 135 136 protected final static String authKeyName = "authContext"; 137 138 // Debug class 139 protected final static String authDebugName = "amAuthInternal"; 140 141 protected static Debug authDebug = Debug.getInstance(authDebugName); 142 143 protected String organizationName = null; 144 145 protected String applicationName = null; 146 147 protected int loginStatus; 148 149 protected LoginException loginException; 150 151 protected Callback[] informationRequired; 152 153 protected Callback[] submittedInformation; 154 155 protected AuthLoginThread loginThread; 156 157 protected LoginContext loginContext; 158 159 protected SSOToken token; 160 161 protected static I18n myAuthI18n = AuthI18n.authI18n; 162 163 private static boolean isEnableHostLookUp = Boolean.valueOf( 164 SystemProperties.get(Constants.ENABLE_HOST_LOOKUP)).booleanValue(); 165 166 // 167 // overall, AuthContext is a "conduit" between the application and the 168 // login module. the Principal implementation must be agreed upon at 169 // those two endpoints; AuthContext just passes the Subject that contains 170 // the Principal(s). 171 // 172 173 /** 174 * Constructor to get an instance of 175 * <code>AuthContext</code>. Caller would then use 176 * <code>getRequirements()</code> and <code>submitRequirements()</code> 177 * to pass the credentials needed for authentication by the plugin modules. 178 * 179 * @throws LoginException 180 * 181 * @supported.api 182 */ 183 public AuthContext() throws LoginException { 184 // initialize 185 this(""); 186 } 187 188 /** 189 * Constructor to get an authenticated instance 190 * of this class given the <code>java.security.Principal</code> the user 191 * would like to be authenticated as, and the <code>password</code> for 192 * the user. 193 * 194 * @param principal 195 * name of the user to be authenticated 196 * @param password 197 * password for the user 198 * @throws LoginException 199 * 200 * @supported.api 201 */ 202 public AuthContext(Principal principal, char[] password) 203 throws LoginException { 204 this(null, principal, password); 205 } 206 207 /* 208 * Constructor for DPro to provide hostname and port for LDAP 209 * authentication. 210 */ 211 public AuthContext(Principal principal, char[] password, String hostname, 212 int port) throws LoginException { 213 this(LoginContext.LDAP_AUTH_URL + hostname + ":" + port, principal, 214 password); 215 } 216 217 /** 218 * Constructor to get an instance of this class 219 * given the organization name <code>orgName</code> the user would like to 220 * access, the <code>java.security.Principal 221 * </code>the user would like to 222 * be authenticated as, and the <code>password</code> for the user. 223 * 224 * @param orgName 225 * name of the user's organization 226 * @param principal 227 * name of the user to be authenticated 228 * @param password 229 * password for the user 230 * @throws LoginException 231 * 232 * @supported.api 233 */ 234 public AuthContext(String orgName, Principal principal, char[] password) 235 throws LoginException { 236 // Make sure principal and password are not null 237 if (principal == null) 238 throw (new LoginException(myAuthI18n 239 .getString("com.iplanet.auth.invalid-username"))); 240 if (password == null) 241 throw (new LoginException(myAuthI18n 242 .getString("com.iplanet.auth.invalid-password"))); 243 244 AuthSubject subject = new AuthSubject(); 245 246 if (orgName != null) 247 organizationName = orgName; 248 reset(subject); 249 250 // Set the username and password in LoginContext's sharedState 251 loginContext.updateSharedState(principal.getName(), password); 252 253 boolean gotName = false; 254 boolean gotPassword = false; 255 Callback[] callbacks; 256 257 if (authDebug.messageEnabled()) { 258 authDebug.message("Instantiated AuthContext with parameters " 259 + "organization name: " 260 + organizationName 261 + "; " 262 + ((principal == null) ? "principal is null" 263 : "principal: ") 264 + principal 265 + "; " 266 + ((password.length == 0) ? "password is empty\n" 267 : "password present\n")); 268 } 269 this.startLogin(); 270 271 // 272 // assume that there are requirements, and they are NameCallback and 273 // PasswordCallback. then submit those. 274 // 275 while (this.hasMoreRequirements()) { 276 authDebug.message("AuthContext::init() Has requirements"); 277 callbacks = this.getRequirements(); 278 for (int i = 0; i < callbacks.length; i++) { 279 if (callbacks[i] instanceof NameCallback) { 280 authDebug.message("Got NameCallback"); 281 NameCallback nc = (NameCallback) callbacks[i]; 282 Set sops = subject.getPrincipals(); 283 AuthSPrincipal[] aps = (AuthSPrincipal[]) sops 284 .toArray(new AuthSPrincipal[0]); 285 if (aps.length == 1) { 286 nc.setName(aps[0].getName()); 287 authDebug.message("Set namecallback name = " 288 + aps[0].getName()); 289 gotName = true; 290 } 291 } else if (callbacks[i] instanceof PasswordCallback) { 292 authDebug.message("Got PasswordCallback"); 293 PasswordCallback pc = (PasswordCallback) callbacks[i]; 294 pc.setPassword(password); 295 gotPassword = true; 296 } else if (callbacks[i] instanceof TextOutputCallback) { 297 authDebug.message( 298 "AuthContext::init() Got TextOutputCallback"); 299 } else if (callbacks[i] instanceof TextInputCallback) { 300 authDebug.message( 301 "AuthContext::init() Got TextInputCallback"); 302 } else if (callbacks[i] instanceof ChoiceCallback) { 303 authDebug.message("AuthContext::init() Got ChoiceCallback"); 304 ChoiceCallback cc = (ChoiceCallback) callbacks[i]; 305 cc.setSelectedIndex(0); 306 } else { 307 authDebug.message( 308 "AuthContext::init() Got Unknown Callback"); 309 } 310 311 } 312 this.submitRequiredInformation(callbacks); 313 } 314 315 // Debug messages 316 if (authDebug.messageEnabled() && gotName && gotPassword) { 317 authDebug.message( 318 "AuthContext::init() Got name and password callbacks"); 319 } 320 if (authDebug.messageEnabled()) { 321 authDebug.message("AuthContext::init() Login status: " 322 + this.getLoginStatus()); 323 } 324 325 // Check login status 326 if (getLoginStatus() == AUTH_FAILED) { 327 throw (getLoginException()); 328 } 329 } 330 331 /** 332 * Constructor to get an instance of this class given the organization name 333 * <code>orgName</code> the user would like to access, and the principal's 334 * <code>subject</code> the user would like to be authenticated as. 335 */ 336 protected AuthContext(String orgName, AuthSubject subject) 337 throws LoginException { 338 String orgname = orgName; 339 340 if (authDebug.messageEnabled()) { 341 authDebug.message("Instantiating AuthContext with parameters " 342 + "organization name: " 343 + orgName 344 + "; " 345 + ((subject == null) ? "subject is null" : "subject: " 346 + subject)); 347 } 348 349 if (orgName != null) { 350 if (orgName.startsWith("auth://")) { 351 int i2, offset; 352 String subsample; 353 String appName = null; 354 355 offset = 7; // char count of "auth://" 356 subsample = orgName.substring(offset); 357 // the org + appname, supposedly 358 i2 = subsample.indexOf("/"); 359 if (i2 != -1) { 360 // 361 // from offset to i2 should be the orgName 362 // 363 orgname = subsample.substring(0, i2); 364 authDebug.message("AuthContext::init() auth:// " 365 + "form, orgname = " + orgname); 366 367 // 368 // get past the "/" after the orgName; look for appName 369 // 370 subsample = subsample.substring(i2 + 1); 371 if (subsample.length() > 0) { 372 // 373 // the next check could be for a "?", this is for 374 // possible 375 // future use where parameters such as 376 // "?userid=<userid>&password=<pswd>" could be passed 377 // 378 i2 = subsample.indexOf("?"); 379 if (i2 != -1) { 380 // 381 // parameters specified; pick off appName first 382 // 383 appName = subsample.substring(0, i2); 384 385 // 386 // the rest assumes the userid and password 387 // parameters as 388 // described above. To be implmented 389 // 390 // subsample = subsample.substring(i2+1); 391 } else { 392 // 393 // Only appName was provided, no user name and 394 // password 395 // 396 appName = subsample; 397 } 398 } else { 399 // 400 // no appName, just OrgName and "/" at the end 401 // 402 appName = null; 403 } 404 } else { 405 // 406 // means just the orgName was specified 407 // 408 orgname = subsample; 409 } 410 if (appName != null) { 411 applicationName = appName; 412 } 413 } else if (orgName.startsWith("local://")) { 414 authDebug.message("local form AuthContext specified; " 415 + orgName); 416 int offset = 8; // char count of "local://" 417 orgname = orgName.substring(offset); // just the org, 418 // hopefully 419 } 420 } 421 422 this.organizationName = orgname; 423 reset(subject); 424 } 425 426 // An alternate form of the <code>orgName</code> is 427 // "auth://<orgName>/<appName>" 428 // 429 // note that a private form of orgName is 430 // "local://...". this is for administrative-type 431 // configuration information for install commands, 432 // for example. 433 // 434 /** 435 * Constructor to get an instance of this class 436 * given the organization name <code>orgName</code>. The plug-in modules 437 * would then query for the user name and related information. 438 * 439 * @param orgName organization name. 440 * @throws LoginException 441 * 442 * @supported.api 443 */ 444 public AuthContext(String orgName) throws LoginException { 445 this(orgName, null); 446 authDebug.message("Instantiated AuthContext with organization name: " 447 + orgName); 448 } 449 450 /** 451 * Constructor to re-create a limited instance of this class given the 452 * ByteArray, which was originally obtained using the 453 * <code>toByteArray()</code> method. Using this constructor, the only 454 * methods that will provide valid return values are 455 * <code>getSubject()</code>, <code>getLoginStatus()</code>, 456 * <code>getAuthPrincipal()</code>, and <code>getAuthPrincipals()</code>. 457 */ 458 protected AuthContext(byte[] bArray) throws LoginException { 459 try { 460 ByteArrayInputStream bis = new ByteArrayInputStream(bArray); 461 ObjectInputStream bin = new ObjectInputStream(bis); 462 463 String readOrgName = (String) bin.readObject(); 464 int readStatus = bin.readInt(); 465 AuthSubject readSubject = (AuthSubject) bin.readObject(); 466 467 this.organizationName = readOrgName; 468 reset(readSubject); 469 setLoginStatus(readStatus); // change status from starting 470 } catch (IOException e) { 471 authDebug.message("AuthContext::bArray constructor():IOException" 472 + e); 473 throw (new LoginException(e.getMessage())); 474 } catch (ClassNotFoundException e) { 475 authDebug.message( 476 "AuthContext::bArray constructor():ClassNotFoundException" 477 + e); 478 throw (new LoginException(e.getMessage())); 479 } 480 } 481 482 /** 483 * Method to reset this instance of <code>AuthContext</code> object, so 484 * that a new login process can be initiated. Authenticates the user to the 485 * same organization or resource this object was instantiated with. If this 486 * object was instantiated with a <code> 487 * Subject</code>, it will be 488 * ignored. 489 */ 490 protected void reset() throws LoginException { 491 authDebug.message("AuthContext::reset()"); 492 reset(null); 493 authDebug.message("AuthContext::reset() exiting"); 494 } 495 496 /** 497 * Method to reset this instance of <code>AuthContext</code> object, so 498 * that a new login process can be initiated for the given 499 * <code>Subject</code>. Authenticates the user to the same organization 500 * or resource this object was instantiated with. 501 */ 502 protected void reset(AuthSubject subject) throws LoginException { 503 504 if (authDebug.messageEnabled()) { 505 authDebug.message("AuthContext::reset(" + organizationName + ", " 506 + ((subject == null) ? "null" : subject.toString()) + ")"); 507 } 508 509 loginStatus = AUTH_NOT_STARTED; 510 informationRequired = null; 511 submittedInformation = null; 512 loginException = null; 513 loginThread = new AuthLoginThread(this); 514 authDebug.message("AuthLoginThread isAlive = " + loginThread.isAlive()); 515 516 String contextName = null; 517 518 if (applicationName == null) { 519 contextName = organizationName; 520 } else { 521 contextName = organizationName + "%" + applicationName; 522 } 523 524 authDebug 525 .message("AuthContext::reset:using contextName=" + contextName); 526 if (subject == null) { 527 loginContext = new LoginContext(contextName, loginThread); 528 } else { 529 loginContext = new LoginContext(contextName, subject, loginThread); 530 } 531 532 if (authDebug.messageEnabled()) { 533 authDebug 534 .message("Successfully reset AuthContext for organization: " 535 + organizationName 536 + ((subject == null) ? " with no subject name " 537 : " with subjects: " + subject)); 538 } 539 } 540 541 /** 542 * Returns the set of Principals the user has been authenticated as. This 543 * can be invoked only after successful authentication. If the 544 * authentication fails, this will return <code>null</code>. 545 */ 546 protected AuthSubject getSubject() { 547 authDebug.message("AuthContext::getSubject()"); 548 return (loginContext.getSubject()); 549 } 550 551 /** 552 * Method to start the login process. This method will 553 * read the plug-ins configured for the application and initialize them. 554 * 555 * @throws LoginException 556 * 557 * @supported.api 558 */ 559 public void startLogin() throws LoginException { 560 561 authDebug.message("AuthContext::startLogin() called"); 562 563 // Make sure we are the current state 564 if (getLoginStatus() != AUTH_NOT_STARTED) { 565 566 authDebug.message("AuthContext::startLogin called " 567 + "when the current login state is" + getLoginStatus()); 568 569 throw (new LoginException(myAuthI18n 570 .getString("authError-invalidMethod" + getLoginStatus()))); 571 } 572 573 // Change the login status 574 loginStatus = AUTH_IN_PROGRESS; 575 576 // Initiate the login 577 authDebug.message("AuthContext::startLogin() " 578 + "starting a new thread to run the login process"); 579 580 try { 581 loginThread.start(); 582 } catch (Exception ex) { 583 authDebug.message("exception starting thread: " + ex); 584 throw (new LoginException(ex.getMessage())); 585 } 586 } 587 588 /** 589 * Returns true if the login process requires more 590 * information from the user to complete the authentication. 591 * 592 * @return true if the login process requires more information from the user 593 * to complete the authentication. 594 * 595 * @supported.api 596 */ 597 public boolean hasMoreRequirements() { 598 authDebug.message("AuthContext::requiresMoreInformation()"); 599 600 if (getRequirements() == null) 601 return (false); 602 else 603 return (true); 604 } 605 606 /** 607 * Returns an array of <code>Callback</code> objects 608 * that must be populated by the user and returned back. These objects are 609 * requested by the authentication plug-ins, and these are usually displayed 610 * to the user. The user then provides the requested information for it to 611 * be authenticated. 612 * 613 * @return an array of <code>Callback</code> objects that must be 614 * populated by the user and returned back. 615 * 616 * @supported.api 617 */ 618 public Callback[] getRequirements() { 619 authDebug.message("AuthContext::getInformationRequired()"); 620 621 // Check the status of LOGIN 622 if (getLoginStatus() != AUTH_IN_PROGRESS) { 623 624 authDebug.message("AuthContext:getInformationRequired() " 625 + "called when the current login state is: " 626 + getLoginStatus()); 627 628 // Login has completed, could be either success or failure 629 return (null); 630 } 631 632 // Check if information required is present 633 while ((informationRequired == null) 634 && (getLoginStatus() == AUTH_IN_PROGRESS)) { 635 // wait for required information to be available 636 try { 637 authDebug.message("AuthContext::getInformationRequired" 638 + "() waiting for Callback array"); 639 640 synchronized (loginThread) { 641 if ((informationRequired == null) 642 && (getLoginStatus() == AUTH_IN_PROGRESS)) { 643 loginThread.wait(); 644 } 645 } 646 647 authDebug.message("AuthContext::getInformationRequired" 648 + "() returned from waiting for Callback array"); 649 650 } catch (InterruptedException ie) { 651 // do nothing 652 } 653 } 654 return (informationRequired); 655 } 656 657 /** 658 * Submits the populated <code>Callback</code> 659 * objects to the authentication plug-in modules. Called after 660 * <code>getInformationRequired</code> method and obtaining user's 661 * response to these requests. 662 * 663 * @param info 664 * array of <code>Callback</code> objects. 665 * 666 * @supported.api 667 */ 668 public void submitRequiredInformation(Callback[] info) { 669 authDebug.message("AuthContext::submitRequestedInformation()"); 670 671 informationRequired = null; 672 673 // Set the submitted info & wake up the callback hander thread 674 synchronized (loginThread) { 675 submittedInformation = info; 676 loginThread.notify(); 677 } 678 authDebug.message("AuthContext::submitRequestedInformation" 679 + "() sending notify to sleeping threads"); 680 } 681 682 /** 683 * Logs the user out. 684 * 685 * @throws LoginException 686 * 687 * @supported.api 688 */ 689 public void logout() throws LoginException { 690 authDebug.message("AuthContext::logout()"); 691 loginContext.logout(); 692 693 authDebug.message("Called LoginContext::logout()"); 694 loginStatus = AUTH_COMPLETED; 695 } 696 697 /** 698 * Returns login exception, if any, during the 699 * authentication process. Typically set when the login fails. 700 * 701 * @return login exception. 702 * 703 * @supported.api 704 */ 705 public LoginException getLoginException() { 706 authDebug.message("AuthContext::getLoginException()"); 707 return (loginException); 708 } 709 710 /** 711 * Returns the current state of the login process. 712 * Possible states are listed above. 713 * 714 * @return the current state of the login process. 715 * 716 * @supported.api 717 */ 718 public int getLoginStatus() { 719 authDebug.message("AuthContext::getLoginStatus()"); 720 return (loginStatus); 721 } 722 723 /** 724 * Method to set the login status. Used internally and not visible outside 725 * this package. 726 */ 727 protected void setLoginStatus(int status) { 728 authDebug.message("AuthContext::setLoginStatus()"); 729 loginStatus = status; 730 } 731 732 /** 733 * Returns the (first) <code>AuthPrincipal</code> in 734 * the <code>Subject</code>. Returns the first <code>Principal</code>, 735 * if more than one exists. 736 * 737 * @return the (first) <code>AuthPrincipal</code> in the 738 * <code>Subject</code>. 739 * 740 * @supported.api 741 */ 742 public Principal getPrincipal() { 743 Set sop = getSubject().getPrincipals(); 744 if (authDebug.messageEnabled()) { 745 authDebug.message("AuthContext::getAuthPrincipal(): " + sop); 746 } 747 Iterator items = sop.iterator(); 748 if (items.hasNext()) { 749 return ((Principal) items.next()); 750 } else { 751 return null; 752 } 753 } 754 755 /** 756 * Method to get the (first) <code>AuthPrincipal</code> in the 757 * <code>Subject</code>. Returns the first <code>Principal</code>, if 758 * more than one exists. 759 * 760 * @deprecated Use getPrincipal() instead 761 */ 762 public AuthPrincipal getAuthPrincipal() { 763 authDebug.message("AuthContext::getAuthPrincipal()"); 764 765 Set sop = getSubject().getPrincipals(); 766 Iterator items = sop.iterator(); 767 if (items.hasNext()) 768 return ((AuthPrincipal) items.next()); 769 else 770 return null; 771 } 772 773 /** 774 * Method to get the set of <code>AuthPrincipal</code>s in the 775 * <code>Subject</code>. 776 */ 777 protected Set getPrincipals() { 778 authDebug.message("AuthContext::getAuthPrincipals()"); 779 return (getSubject().getPrincipals()); 780 } 781 782 /** 783 * Method to retrieve a Byte array of serializable portions of the 784 * <code>AuthContext</code>. 785 */ 786 protected byte[] toByteArray() { 787 try { 788 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 789 ObjectOutputStream bout = new ObjectOutputStream(bos); 790 791 bout.writeObject(((organizationName == null) ? " " 792 : organizationName)); 793 bout.writeInt(loginStatus); 794 bout.writeObject(loginContext.getSubject()); 795 byte[] bytestuff = bos.toByteArray(); 796 return (bytestuff); 797 } catch (IOException iox) { 798 if (authDebug.messageEnabled()) { 799 authDebug.message("AuthContext:toByteArray():IOException", iox); 800 } 801 } catch (Exception e) { 802 if (authDebug.messageEnabled()) { 803 authDebug.message("AuthContext:toByteArray():Exception", e); 804 } 805 } 806 return null; 807 } 808 809 /** 810 * Method to get organization name that was set during 811 * construction of this instance. 812 * 813 * @return organization name; <code>null</code> if it was not initialized 814 * during construction of this instance 815 * 816 * @supported.api 817 */ 818 public String getOrganizationName() { 819 if (organizationName == null) { 820 String rootSuffix = organizationName = ServiceManager.getBaseDN(); 821 if ((rootSuffix != null) && (organizationName != null)) { 822 rootSuffix = new DN(rootSuffix).toRFCString().toLowerCase(); 823 organizationName = new DN(organizationName).toRFCString() 824 .toLowerCase(); 825 } 826 } 827 return organizationName; 828 } 829 830 protected String getApplicationName() { 831 return applicationName; 832 } 833 834 /** 835 * Method to get the Single-Sign-On (SSO) Token. This 836 * token can be used as the authenticated token. 837 * 838 * @return single-sign-on token. 839 * @throws InvalidAuthContextException 840 * 841 * @supported.api 842 */ 843 public SSOToken getSSOToken() throws InvalidAuthContextException { 844 if (token != null) { 845 return (token); 846 } 847 848 token = new AuthSSOToken(this); 849 try { 850 // Set Organization 851 if (getOrganizationName() != null) { 852 token.setProperty(Constants.ORGANIZATION, 853 getOrganizationName()); 854 } 855 856 // Set Host name 857 InetAddress address = InetAddress.getLocalHost(); 858 String ipAddress = address.getHostAddress(); 859 860 861 if (authDebug.messageEnabled()) { 862 authDebug.message("Complete Host : " + address.toString()); 863 authDebug.message("getSSOToken : IP : " + ipAddress); 864 } 865 866 if (ipAddress != null) { 867 if (isEnableHostLookUp) { 868 final String strHostName = address.getHostName(); 869 if (authDebug.messageEnabled()) { 870 authDebug.message("getSSOToken : HOST Name : " + strHostName); 871 } 872 if (strHostName != null) { 873 token.setProperty("HostName", strHostName); 874 } 875 } else { 876 token.setProperty("HostName", ipAddress); 877 } 878 token.setProperty("Host", ipAddress); 879 } 880 881 // Set AuthType 882 token.setProperty("AuthType", "ldap"); 883 884 // Set Principal 885 String principal = getPrincipal().getName(); 886 if (principal != null) { 887 token.setProperty("Principal", principal); 888 // Set Universal Identifier 889 String username = principal; 890 if (DN.isDN(principal)) { 891 // Get the username 892 username = LDAPDN.explodeDN(principal, true)[0]; 893 } 894 // Since internal auth will be used during install time 895 // and during boot strap for users "dsame" and "amadmin" 896 // the IdType will be hardcoded to User 897 StringBuilder uuid = new StringBuilder(100); 898 uuid.append("id=").append(username) 899 .append(",ou=user,").append(getOrganizationName()); 900 token.setProperty(Constants.UNIVERSAL_IDENTIFIER, 901 uuid.toString()); 902 } 903 904 // Set AuthLevel 905 token.setProperty("AuthLevel", Integer.toString(0)); 906 907 //Set ContextId 908 SecureRandom secureRandom = 909 SecureRandomManager.getSecureRandom(); 910 String amCtxId = 911 Long.toHexString(secureRandom.nextLong()); 912 token.setProperty(Constants.AM_CTX_ID, amCtxId); 913 914 if (authDebug.messageEnabled()) { 915 authDebug.message("SSOToken : Organization : " 916 + token.getProperty("Organization")); 917 authDebug.message("SSOToken : Principal : " 918 + token.getProperty("Principal")); 919 authDebug.message("SSOToken : HostName : " 920 + token.getProperty("HostName")); 921 authDebug.message("SSOToken : Host : " 922 + token.getProperty("Host")); 923 authDebug.message("SSOToken : getIPAddress : " 924 + token.getIPAddress()); 925 authDebug.message("SSOToken : getHostName : " 926 + token.getHostName()); 927 authDebug.message("SSOToken : ContextId : " 928 + token.getProperty(Constants.AM_CTX_ID)); 929 } 930 931 } catch (Exception e) { 932 if (authDebug.warningEnabled()) { 933 authDebug.warning("getSSOToken: setProperty exception : ", e); 934 } 935 } 936 937 return (token); 938 } 939}
Copyright © 2010-2017, ForgeRock All Rights Reserved.