package org.dcache.gplazma.plugins; 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.TextOutputCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import java.security.Principal; import java.util.Properties; import java.util.Set; import org.dcache.auth.PasswordCredential; import org.dcache.gplazma.AuthenticationException; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.getFirst; import static org.dcache.gplazma.util.Preconditions.checkAuthentication; /** * A {@link GPlazmaAuthenticationPlugin} implementation which verifies * user/pasword credentials using JAAS, the Jave Authentication and * Authorization Services. * * A valid JAAS setup for password authentication has to be in place. */ public class JaasPlugin implements GPlazmaAuthenticationPlugin { private static final String NAME = "gplazma.jaas.name"; private final String _name; public JaasPlugin(Properties properties) { String name = properties.getProperty(NAME); checkArgument(name != null, "Undefined property: " + NAME); _name = name; } @Override public void authenticate(Set<Object> publicCredentials, Set<Object> privateCredentials, Set<Principal> identifiedPrincipals) throws AuthenticationException { PasswordCredential password = getFirst(filter(privateCredentials, PasswordCredential.class), null); checkAuthentication(password != null, "no login name"); try { LoginContext loginContext = new LoginContext(_name, new PasswordCallbackHandler(password)); loginContext.login(); identifiedPrincipals.addAll(loginContext.getSubject().getPrincipals()); tryToLogout(loginContext); } catch (LoginException e) { throw new AuthenticationException(e.getMessage(), e); } } private static void tryToLogout(LoginContext loginContext) { if (loginContext == null) { return; } try { loginContext.logout(); } catch (LoginException e) { // ignored } } private static class PasswordCallbackHandler implements CallbackHandler { private final String _userName; private final char _password[]; public PasswordCallbackHandler(PasswordCredential credential) { _userName = credential.getUsername(); _password = credential.getPassword().toCharArray(); } @Override public void handle(Callback callbacks[]) throws UnsupportedCallbackException { for (Callback callback: callbacks) { if (callback instanceof NameCallback) { ((NameCallback) callback).setName(_userName); } else if (callback instanceof PasswordCallback) { ((PasswordCallback) callback).setPassword(_password); } else if (callback instanceof TextOutputCallback) { // do nothing } else { throw new UnsupportedCallbackException(callback, "Unrecognized Callback"); } } } } }