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