/* * @(#)SolarisLoginModule.java 1.10 04/05/18 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package com.sun.security.auth.module; import java.util.*; import java.io.IOException; import javax.security.auth.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; import javax.security.auth.spi.*; import com.sun.security.auth.SolarisPrincipal; import com.sun.security.auth.SolarisNumericUserPrincipal; import com.sun.security.auth.SolarisNumericGroupPrincipal; /** *
 This LoginModule imports a user's Solaris
 * Principal information (SolarisPrincipal,
 * SolarisNumericUserPrincipal,
 * and SolarisNumericGroupPrincipal)
 * and associates them with the current Subject.
 *
 * 
 This LoginModule recognizes the debug option.
 * If set to true in the login Configuration,
 * debug messages will be output to the output stream, System.out.
 * @deprecated  As of JDK1.4, replaced by 
 * com.sun.security.auth.module.UnixLoginModule.
 *             This LoginModule is entirely deprecated and
 *             is here to allow for a smooth transition to the new
 *             UnixLoginModule.
 *
 * @version 1.19, 01/11/00
 */
@Deprecated
public class SolarisLoginModule implements LoginModule {
    // initial state
    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map sharedState;
    private Map options;
    // configurable option
    private boolean debug = true;
    // SolarisSystem to retrieve underlying system info
    private SolarisSystem ss;
    // the authentication status
    private boolean succeeded = false;
    private boolean commitSucceeded = false;
    // Underlying system info
    private SolarisPrincipal userPrincipal;
    private SolarisNumericUserPrincipal UIDPrincipal;
    private SolarisNumericGroupPrincipal GIDPrincipal;
    private LinkedList supplementaryGroups = new LinkedList();
    /**
     * Initialize this LoginModule.
     *
     * 
     *
     * @param subject the Subject to be authenticated. 
     *
     * @param callbackHandler a CallbackHandler for communicating
     *			with the end user (prompting for usernames and
     *			passwords, for example). 
     *
     * @param sharedState shared LoginModule state. 
     *
     * @param options options specified in the login
     *			  The implementation of this method attempts to retrieve the user's
     * Solaris  
     *
     * @exception FailedLoginException if attempts to retrieve the underlying
     *		system information fail.
     *
     * @return true in all cases (this   This method is called if the LoginContext's
     * overall authentication succeeded
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * succeeded).
     *
     *   If this LoginModule's own authentication attempt
     * succeeded (the importing of the Solaris authentication information
     * succeeded), then this method associates the Solaris Principals
     * with the  
     *
     * @exception LoginException if the commit fails
     *
     * @return true if this LoginModule's own login and commit attempts
     *		succeeded, or false otherwise.
     */
    public boolean commit() throws LoginException {
	if (succeeded == false) {
	    if (debug) {
		System.out.println("\t\t[SolarisLoginModule]: " +
		    "did not add any Principals to Subject " +
		    "because own authentication failed.");
	    }
	    return false;
	} 
	if (subject.isReadOnly()) {
	    throw new LoginException ("Subject is Readonly");
	}
	if (!subject.getPrincipals().contains(userPrincipal))
	    subject.getPrincipals().add(userPrincipal);
	if (!subject.getPrincipals().contains(UIDPrincipal))
	    subject.getPrincipals().add(UIDPrincipal);
	if (!subject.getPrincipals().contains(GIDPrincipal))
	    subject.getPrincipals().add(GIDPrincipal);
	for (int i = 0; i < supplementaryGroups.size(); i++) {
	    if (!subject.getPrincipals().contains
		((SolarisNumericGroupPrincipal)supplementaryGroups.get(i)))
		subject.getPrincipals().add((SolarisNumericGroupPrincipal)
					    supplementaryGroups.get(i));
	}
	
	if (debug) {
	    System.out.println("\t\t[SolarisLoginModule]: " +
			       "added SolarisPrincipal,");
	    System.out.println("\t\t\t\tSolarisNumericUserPrincipal,");
	    System.out.println("\t\t\t\tSolarisNumericGroupPrincipal(s),");
	    System.out.println("\t\t\t to Subject");
	}
	
	commitSucceeded = true;
	return true;
    }
    /**
     * Abort the authentication (second phase).
     *
     *   This method is called if the LoginContext's
     * overall authentication failed.
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * did not succeed).
     *
     *   This method cleans up any state that was originally saved
     * as part of the authentication attempt from the  
     *
     * @exception LoginException if the abort fails
     *
     * @return false if this LoginModule's own login and/or commit attempts
     *		failed, and true otherwise.
     */
    public boolean abort() throws LoginException {
	if (debug) {
	    System.out.println("\t\t[SolarisLoginModule]: " +
		"aborted authentication attempt");
	}
	if (succeeded == false) {
	    return false;
	} else if (succeeded == true && commitSucceeded == false) {
	    // Clean out state
	    succeeded = false;
	    ss = null;
	    userPrincipal = null;
	    UIDPrincipal = null;
	    GIDPrincipal = null;
	    supplementaryGroups = new LinkedList();
	} else {
	    // overall authentication succeeded and commit succeeded,
	    // but someone else's commit failed
	    logout();
	}
	return true;
    }
    /**
     * Logout the user
     *
     *   This method removes the Principals associated
     * with the  
     *
     * @exception LoginException if the logout fails
     *
     * @return true in all cases (this Configuration for this particular
     *			LoginModule.
     */
    public void initialize(Subject subject, CallbackHandler callbackHandler,
			   MapSubject information by making a native Solaris
     * system call.
     *
     * LoginModule
     *		should not be ignored).
     */
    public boolean login() throws LoginException {
	long[] solarisGroups = null;
	ss = new SolarisSystem();
	if (ss == null) {
	    succeeded = false;
	    throw new FailedLoginException
				("Failed in attempt to import " +
				"the underlying system identity information");
	} else {
	    userPrincipal = new SolarisPrincipal(ss.getUsername());
	    UIDPrincipal = new SolarisNumericUserPrincipal(ss.getUid());
	    GIDPrincipal = new SolarisNumericGroupPrincipal(ss.getGid(), true);
	    if (ss.getGroups() != null && ss.getGroups().length > 0)
		solarisGroups = ss.getGroups();
		for (int i = 0; i < solarisGroups.length; i++) {
		    SolarisNumericGroupPrincipal ngp =
			new SolarisNumericGroupPrincipal
			(solarisGroups[i], false);
		    if (!ngp.getName().equals(GIDPrincipal.getName()))
			supplementaryGroups.add(ngp);
		}
	    if (debug) {
		System.out.println("\t\t[SolarisLoginModule]: " +
			"succeeded importing info: ");
		System.out.println("\t\t\tuid = " + ss.getUid());
		System.out.println("\t\t\tgid = " + ss.getGid());
		solarisGroups = ss.getGroups();
		for (int i = 0; i < solarisGroups.length; i++) {
		    System.out.println("\t\t\tsupp gid = " + solarisGroups[i]);
		}
	    }
	    succeeded = true;
	    return true;
	}
    }
    /**
     * Commit the authentication (second phase).
     *
     * Subject currently tied to the 
     * LoginModule.  If this LoginModule's
     * authentication attempted failed, then this method removes
     * any state that was originally saved.
     *
     * login
     * and commit methods.
     *
     * Subject.
     *
     * LoginModule
     *		should not be ignored).
     */
    public boolean logout() throws LoginException {
	if (debug) {
	    System.out.println("\t\t[SolarisLoginModule]: " +
		"Entering logout");
	}
	if (subject.isReadOnly()) {
	    throw new LoginException ("Subject is Readonly");
	}
	// remove the added Principals from the Subject
	subject.getPrincipals().remove(userPrincipal);
	subject.getPrincipals().remove(UIDPrincipal);
	subject.getPrincipals().remove(GIDPrincipal);
	for (int i = 0; i < supplementaryGroups.size(); i++) {
	    subject.getPrincipals().remove
		    ((SolarisNumericGroupPrincipal)supplementaryGroups.get(i));
	}
	// clean out state
	ss = null;
	succeeded = false;
	commitSucceeded = false;
	userPrincipal = null;
	UIDPrincipal = null;
	GIDPrincipal = null;
	supplementaryGroups = new LinkedList();
	if (debug) {
	    System.out.println("\t\t[SolarisLoginModule]: " +
		"logged out Subject");
	}
	return true;
    }
}