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.