package org.jboss.security;
import java.io.IOException;
import java.security.Principal;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import org.jboss.logging.Logger;
public class ClientLoginModule implements LoginModule
{
private static Logger log = Logger.getLogger(ClientLoginModule.class);
private Subject subject;
private CallbackHandler callbackHandler;
private Principal loginPrincipal;
private Object loginCredential;
private Map sharedState;
private boolean useFirstPass;
private boolean restoreLoginIdentity;
private Principal restorePrincipal;
private Object restoreCredential;
private Subject restoreSubject;
private boolean trace;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options)
{
this.trace = log.isTraceEnabled();
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
String flag = (String) options.get("multi-threaded");
if (Boolean.valueOf(flag).booleanValue() == true)
{
if( trace )
log.trace("Enabling multi-threaded mode");
SecurityAssociationActions.setServer();
}
flag = (String) options.get("restore-login-identity");
restoreLoginIdentity = Boolean.valueOf(flag).booleanValue();
String passwordStacking = (String) options.get("password-stacking");
useFirstPass = passwordStacking != null;
}
public boolean login() throws LoginException
{
if( trace )
log.trace("Begin login");
if( restoreLoginIdentity == true )
{
restorePrincipal = SecurityAssociationActions.getPrincipal();
restoreCredential = SecurityAssociationActions.getCredential();
restoreSubject = SecurityAssociationActions.getSubject();
}
if (useFirstPass == true)
{
try
{
Object name = sharedState.get("javax.security.auth.login.name");
if ((name instanceof Principal) == false)
{
String username = name != null ? name.toString() : "";
loginPrincipal = new SimplePrincipal(username);
} else
{
loginPrincipal = (Principal) name;
}
loginCredential = sharedState.get("javax.security.auth.login.password");
return true;
}
catch (Exception e)
{ log.debug("Failed to obtain shared state", e);
}
}
if (callbackHandler == null)
throw new LoginException("Error: no CallbackHandler available " +
"to garner authentication information from the user");
PasswordCallback pc = new PasswordCallback("Password: ", false);
NameCallback nc = new NameCallback("User name: ", "guest");
Callback[] callbacks = {nc, pc};
try
{
String username;
char[] password = null;
char[] tmpPassword;
callbackHandler.handle(callbacks);
username = nc.getName();
loginPrincipal = new SimplePrincipal(username);
tmpPassword = pc.getPassword();
if (tmpPassword != null)
{
password = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
pc.clearPassword();
}
loginCredential = password;
if( trace )
{
String credType = "null";
if( loginCredential != null )
credType = loginCredential.getClass().getName();
log.trace("Obtained login: "+loginPrincipal
+", credential.class: " + credType);
}
}
catch (IOException ioe)
{
LoginException ex = new LoginException(ioe.toString());
ex.initCause(ioe);
throw ex;
}
catch (UnsupportedCallbackException uce)
{
LoginException ex = new LoginException("Error: " + uce.getCallback().toString() +
", not able to use this callback for username/password");
ex.initCause(uce);
throw ex;
}
if( trace )
log.trace("End login");
return true;
}
public boolean commit() throws LoginException
{
if( trace )
log.trace("commit, subject="+subject);
SecurityAssociationActions.setPrincipalInfo(loginPrincipal, loginCredential, subject);
Set principals = subject.getPrincipals();
if (principals.contains(loginPrincipal) == false)
principals.add(loginPrincipal);
return true;
}
public boolean abort() throws LoginException
{
if( trace )
log.trace("abort");
SecurityAssociationActions.clear();
if( restoreLoginIdentity == true )
{
SecurityAssociationActions.setPrincipalInfo(restorePrincipal,
restoreCredential, restoreSubject);
}
return true;
}
public boolean logout() throws LoginException
{
if( trace )
log.trace("logout");
SecurityAssociationActions.clear();
if( restoreLoginIdentity == true )
{
SecurityAssociationActions.setPrincipalInfo(restorePrincipal,
restoreCredential, restoreSubject);
}
Set principals = subject.getPrincipals();
principals.remove(loginPrincipal);
return true;
}
}