FileDocCategorySizeDatePackage
ClientCertificateLoginModule.javaAPI DocGlassfish v2 API12024Fri May 04 22:35:26 BST 2007com.sun.enterprise.security.auth.login

ClientCertificateLoginModule

public class ClientCertificateLoginModule extends Object implements LoginModule

This LoginModule authenticates users with X509 certificates.

If testUser successfully authenticates itself, a PrincipalImpl with the testUser's username is added to the 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.

author
Harpreet Singh (harpreet.singh@sun.com)

Fields Summary
private static Logger
_logger
private static com.sun.enterprise.util.LocalStringManagerImpl
localStrings
private static KeyStore
ks
private Subject
subject
private CallbackHandler
callbackHandler
private Map
sharedState
private Map
options
private boolean
debug
private boolean
succeeded
private boolean
commitSucceeded
private String
alias
private X509Certificate
certificate
private com.sun.enterprise.deployment.PrincipalImpl
userPrincipal
Constructors Summary
Methods Summary
public booleanabort()

This method is called if the LoginContext's overall authentication failed. (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules did not succeed).

If this LoginModule's own authentication attempt succeeded (checked by retrieving the private state saved by the login and commit methods), then this method cleans up any state that was originally saved.

exception
LoginException if the abort fails.
return
false if this LoginModule's own login and/or commit attempts failed, and true otherwise.

	if (succeeded == false) {
	    return false;
	} else if (succeeded == true && commitSucceeded == false) {
	    // login succeeded but overall authentication failed
	    succeeded = false;
	    alias = null;
	    userPrincipal = null;
	} else {
	    // overall authentication succeeded and commit succeeded,
	    // but someone else's commit failed
	    logout();
	}
	return true;
    
public booleancommit()

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 (checked by retrieving the private state saved by the login method), then this method associates a PrincipalImpl with the Subject located in the LoginModule. If this LoginModule's own authentication attempted failed, then this method removes any state that was originally saved.

exception
LoginException if the commit fails.
return
true if this LoginModule's own login and commit attempts succeeded, or false otherwise.

	if (succeeded == false) {
	    return false;
	} else {
	    // add a Principal (authenticated identity)
	    // to the Subject

	    // assume the user we authenticated is the PrincipalImpl
	    userPrincipal = new PrincipalImpl(alias);
	    if (!subject.getPrincipals().contains(userPrincipal)){
		subject.getPrincipals().add(userPrincipal);
            }

	    if (debug) {
                if(_logger.isLoggable(Level.FINE)){
                    _logger.log(Level.FINE,"\t\t[ClientCertificateLoginModule] " +
                                "added PrincipalImpl to Subject");
                }
	    }
            Ssl ssl = new Ssl();
            ssl.setCertNickname(this.alias);
            SSLUtils.setAppclientSsl(ssl);
	    String realm = LoginContextDriver.CERT_REALMNAME;
	    X509Certificate[] certChain = new X509Certificate[1];
	    certChain[0] = certificate;
	    X509CertificateCredential pc = 
		new X509CertificateCredential(certChain, alias, realm);
	    if(!subject.getPrivateCredentials().contains(pc)) {
		subject.getPrivateCredentials().add(pc);
            }

	    commitSucceeded = true;
	    return true;
	}
    
private voidinit()
Initialize the key store.

	try {
	    if(ks == null) {
	        SSLUtils.initStoresAtStartup();
	    }

	} catch(Exception e) {
	    _logger.log(Level.SEVERE,"java_security.initkeystore_exception",e);
	}
    
public voidinitialize(javax.security.auth.Subject subject, javax.security.auth.callback.CallbackHandler callbackHandler, java.util.Map sharedState, java.util.Map options)
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 Configuration for this particular LoginModule.


                      			       			                			   			     
         
			    
 

	this.subject = subject;
	this.callbackHandler = callbackHandler;
	this.sharedState = sharedState;
	this.options = options;

	// initialize any configured options
	debug = "true".equalsIgnoreCase((String)options.get("debug"));

	init();
    
public booleanlogin()
Authenticate the user by prompting for a username and password.

return
true in all cases since this LoginModule should not be ignored.
exception
FailedLoginException if the authentication fails.

exception
LoginException if this LoginModule is unable to perform the authentication.


	// prompt for a username and password
	if (callbackHandler == null){
	    throw new LoginException("Error: no CallbackHandler available " +
			"to garner authentication information from the user");
        }

	try {
	    String[] as = new String[ks.size()];
	    String[] aliasString = new String[ks.size()];
	    Enumeration aliases = ks.aliases();
	    for(int i = 0; i < ks.size(); i++) {
	        aliasString[i] = (String) aliases.nextElement();
	        as[i] = ((X509Certificate)ks.getCertificate(aliasString[i])).getSubjectDN().getName();
	    }

	    Callback[] callbacks = new Callback[1];
	    callbacks[0] = new ChoiceCallback(localStrings.getLocalString("login.certificate", "Choose from list of certificates: "),  as, 0, false);
 
	    callbackHandler.handle(callbacks);
	    String[] choices = ((ChoiceCallback)callbacks[0]).getChoices();
	    int[] idx = ((ChoiceCallback)callbacks[0]).getSelectedIndexes();
	    if (choices == null) {
		// figure out
	    }
	    if (idx == null) {
		throw new LoginException ("No certificate selected!");
	    } else if (idx[0] == -1){
		throw new LoginException ("Incorrect keystore password");
	    }
	    // print debugging information
	    if (debug) {
                if(_logger.isLoggable(Level.FINE)){
                    _logger.log(Level.FINE,"\t\t[ClientCertificateLoginModule] " +
                                "user entered certificate: ");
                    for (int i = 0; i < idx.length; i++){
                        _logger.log(Level.FINE,aliasString[idx[i]]);
                    }
                }
	    }
            
	    // the authenticate method previously picked out the
	    // wrong alias.
	    // since we allow only 1 choice the first element in idx 
	    // idx[0] should have the selected index.
	    this.alias  = aliasString[idx[0]];
	    certificate = (X509Certificate) ks.getCertificate(alias);
	    // the authenticate should always return a true.
	    if (debug){
                if(_logger.isLoggable(Level.FINE)){
                    _logger.log(Level.FINE,"\t\t[ClientCertificateLoginModule] " +
                            "authentication succeeded");
                }
	    }
	    succeeded = true;
	    return true;
	} catch (java.io.IOException ioe) {
	    throw new LoginException(ioe.toString());
	} catch (UnsupportedCallbackException uce) {
	    throw new LoginException("Error: " + uce.getCallback().toString() +
		" not available to garner authentication information " +
		"from the user");
	} catch (Exception e) {
	    throw new LoginException(e.toString());
	}
    
public booleanlogout()
Logout the user.

This method removes the PrincipalImpl that was added by the commit method.

exception
LoginException if the logout fails.
return
true in all cases since this LoginModule should not be ignored.

	// unset the alias
        SSLUtils.setAppclientSsl(null);
    
	subject.getPrincipals().remove(userPrincipal);
	succeeded = false;
	succeeded = commitSucceeded;
	alias = null;
	userPrincipal = null;
	return true;
    
public static voidsetKeyStore(java.security.KeyStore keyStore)

	ks = keyStore;