package com.onaro.sanscreen.client.login;
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.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import org.jboss.security.SecurityContext;
import org.jboss.security.SecurityContextAssociation;
import org.jboss.security.SecurityContextFactory;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.callback.ObjectCallback;
/**
* This login module does much of what the ClientLoginClass does, but uses the CallbackHandler to retrieve a certificate
* which it then uses as the credential when setting the principalInfo of the onaro-login SecurityContext.
*
* @author Joshua Eisenthal Copyright 2014 NetApp
*/
public class ClientCertLoginModule implements LoginModule {
private Subject subject;
private CallbackHandler callbackHandler;
private String username;
private Object certificate;
private SimplePrincipal loginPrincipal;
@Override
public void initialize(Subject aSubject, CallbackHandler aCallbackHandler, Map sharedState, Map options) {
subject = aSubject;
callbackHandler = aCallbackHandler;
}
@Override
public boolean login() throws LoginException {
if (callbackHandler == null) {
throw new LoginException("CallbackHandler not set"); //$NON-NLS-1$
}
NameCallback nameCallback = new NameCallback("Username: "); //$NON-NLS-1$
ObjectCallback certCallback = new ObjectCallback("Certificate: "); //$NON-NLS-1$
Callback[] callbacks = {nameCallback, certCallback};
try {
callbackHandler.handle(callbacks);
} catch (IOException e) {
LoginException le = new LoginException(e.getMessage());
le.initCause(e);
throw le;
} catch (UnsupportedCallbackException e) {
LoginException le = new LoginException("CallbackHandler does not support username/certificate callbacks"); //$NON-NLS-1$
le.initCause(e);
throw le;
}
username = nameCallback.getName();
certificate = certCallback.getCredential();
return true;
}
@Override
public boolean commit() throws LoginException {
loginPrincipal = new SimplePrincipal(username);
try {
// This creates the client security context. It is somehow remotely connected to the server's
// "onaro-login" realm, and thus by specifying the principal and credential, invokes the server's
// login modules:
SecurityContext securityContext = SecurityContextFactory.createSecurityContext(loginPrincipal, certificate, subject, "CLIENT_LOGIN_MODULE"); //$NON-NLS-1$
SecurityContextAssociation.setSecurityContext(securityContext);
} catch (Exception e) {
LoginException le = new LoginException("Failed to get security context"); //$NON-NLS-1$
le.initCause(e);
throw le;
}
Set principals = subject.getPrincipals();
if (!principals.contains(loginPrincipal)) {
principals.add(loginPrincipal);
}
return true;
}
@Override
public boolean abort() throws LoginException {
return logout();
}
@Override
public boolean logout() throws LoginException {
SecurityContextAssociation.clearSecurityContext();
Set principals = subject.getPrincipals();
principals.remove(loginPrincipal);
return true;
}
}