| // |
| // ======================================================================== |
| // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.jaas.spi; |
| |
| import java.io.IOException; |
| import java.security.Principal; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| 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.FailedLoginException; |
| import javax.security.auth.login.LoginException; |
| import javax.security.auth.spi.LoginModule; |
| |
| import org.eclipse.jetty.jaas.JAASPrincipal; |
| import org.eclipse.jetty.jaas.JAASRole; |
| import org.eclipse.jetty.jaas.callback.ObjectCallback; |
| |
| /** |
| * AbstractLoginModule |
| * |
| * Abstract base class for all LoginModules. Subclasses should |
| * just need to implement getUserInfo method. |
| */ |
| public abstract class AbstractLoginModule implements LoginModule |
| { |
| private CallbackHandler callbackHandler; |
| |
| private boolean authState = false; |
| private boolean commitState = false; |
| private JAASUserInfo currentUser; |
| private Subject subject; |
| |
| /** |
| * JAASUserInfo |
| * |
| * This class unites the UserInfo data with jaas concepts |
| * such as Subject and Principals |
| */ |
| public class JAASUserInfo |
| { |
| private UserInfo user; |
| private Principal principal; |
| private List<JAASRole> roles; |
| |
| public JAASUserInfo (UserInfo u) |
| { |
| this.user = u; |
| this.principal = new JAASPrincipal(u.getUserName()); |
| } |
| |
| public String getUserName () |
| { |
| return this.user.getUserName(); |
| } |
| |
| public Principal getPrincipal() |
| { |
| return this.principal; |
| } |
| |
| |
| public void setJAASInfo (Subject subject) |
| { |
| subject.getPrincipals().add(this.principal); |
| subject.getPrivateCredentials().add(this.user.getCredential()); |
| subject.getPrincipals().addAll(roles); |
| } |
| |
| public void unsetJAASInfo (Subject subject) |
| { |
| subject.getPrincipals().remove(this.principal); |
| subject.getPrivateCredentials().remove(this.user.getCredential()); |
| subject.getPrincipals().removeAll(this.roles); |
| } |
| |
| public boolean checkCredential (Object suppliedCredential) |
| { |
| return this.user.checkCredential(suppliedCredential); |
| } |
| |
| public void fetchRoles() throws Exception |
| { |
| this.user.fetchRoles(); |
| this.roles = new ArrayList<JAASRole>(); |
| if (this.user.getRoleNames() != null) |
| { |
| Iterator<String> itor = this.user.getRoleNames().iterator(); |
| while (itor.hasNext()) |
| this.roles.add(new JAASRole((String)itor.next())); |
| } |
| } |
| } |
| |
| public Subject getSubject () |
| { |
| return this.subject; |
| } |
| |
| public void setSubject (Subject s) |
| { |
| this.subject = s; |
| } |
| |
| public JAASUserInfo getCurrentUser() |
| { |
| return this.currentUser; |
| } |
| |
| public void setCurrentUser (JAASUserInfo u) |
| { |
| this.currentUser = u; |
| } |
| |
| public CallbackHandler getCallbackHandler() |
| { |
| return this.callbackHandler; |
| } |
| |
| public void setCallbackHandler(CallbackHandler h) |
| { |
| this.callbackHandler = h; |
| } |
| |
| public boolean isAuthenticated() |
| { |
| return this.authState; |
| } |
| |
| public boolean isCommitted () |
| { |
| return this.commitState; |
| } |
| |
| public void setAuthenticated (boolean authState) |
| { |
| this.authState = authState; |
| } |
| |
| public void setCommitted (boolean commitState) |
| { |
| this.commitState = commitState; |
| } |
| /** |
| * @see javax.security.auth.spi.LoginModule#abort() |
| * @throws LoginException if unable to abort |
| */ |
| public boolean abort() throws LoginException |
| { |
| this.currentUser = null; |
| return (isAuthenticated() && isCommitted()); |
| } |
| |
| /** |
| * @see javax.security.auth.spi.LoginModule#commit() |
| * @return true if committed, false if not (likely not authenticated) |
| * @throws LoginException if unable to commit |
| */ |
| public boolean commit() throws LoginException |
| { |
| if (!isAuthenticated()) |
| { |
| currentUser = null; |
| setCommitted(false); |
| return false; |
| } |
| |
| setCommitted(true); |
| currentUser.setJAASInfo(subject); |
| return true; |
| } |
| |
| |
| public Callback[] configureCallbacks () |
| { |
| |
| Callback[] callbacks = new Callback[3]; |
| callbacks[0] = new NameCallback("Enter user name"); |
| callbacks[1] = new ObjectCallback(); |
| callbacks[2] = new PasswordCallback("Enter password", false); //only used if framework does not support the ObjectCallback |
| return callbacks; |
| } |
| |
| |
| public boolean isIgnored () |
| { |
| return false; |
| } |
| |
| |
| public abstract UserInfo getUserInfo (String username) throws Exception; |
| |
| |
| |
| /** |
| * @see javax.security.auth.spi.LoginModule#login() |
| * @return true if is authenticated, false otherwise |
| * @throws LoginException if unable to login |
| */ |
| public boolean login() throws LoginException |
| { |
| try |
| { |
| if (isIgnored()) |
| return false; |
| |
| if (callbackHandler == null) |
| throw new LoginException ("No callback handler"); |
| |
| Callback[] callbacks = configureCallbacks(); |
| callbackHandler.handle(callbacks); |
| |
| String webUserName = ((NameCallback)callbacks[0]).getName(); |
| Object webCredential = null; |
| |
| webCredential = ((ObjectCallback)callbacks[1]).getObject(); //first check if ObjectCallback has the credential |
| if (webCredential == null) |
| webCredential = ((PasswordCallback)callbacks[2]).getPassword(); //use standard PasswordCallback |
| |
| if ((webUserName == null) || (webCredential == null)) |
| { |
| setAuthenticated(false); |
| throw new FailedLoginException(); |
| } |
| |
| UserInfo userInfo = getUserInfo(webUserName); |
| |
| if (userInfo == null) |
| { |
| setAuthenticated(false); |
| throw new FailedLoginException(); |
| } |
| |
| currentUser = new JAASUserInfo(userInfo); |
| setAuthenticated(currentUser.checkCredential(webCredential)); |
| |
| if (isAuthenticated()) |
| { |
| currentUser.fetchRoles(); |
| return true; |
| } |
| else |
| throw new FailedLoginException(); |
| } |
| catch (IOException e) |
| { |
| throw new LoginException (e.toString()); |
| } |
| catch (UnsupportedCallbackException e) |
| { |
| throw new LoginException (e.toString()); |
| } |
| catch (Exception e) |
| { |
| if (e instanceof LoginException) |
| throw (LoginException)e; |
| throw new LoginException (e.toString()); |
| } |
| } |
| |
| /** |
| * @see javax.security.auth.spi.LoginModule#logout() |
| * @return true always |
| * @throws LoginException if unable to logout |
| */ |
| public boolean logout() throws LoginException |
| { |
| this.currentUser.unsetJAASInfo(this.subject); |
| this.currentUser = null; |
| return true; |
| } |
| |
| /** |
| * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map) |
| * @param subject the subject |
| * @param callbackHandler the callback handler |
| * @param sharedState the shared state map |
| * @param options the option map |
| */ |
| public void initialize(Subject subject, CallbackHandler callbackHandler, |
| Map<String,?> sharedState, Map<String,?> options) |
| { |
| this.callbackHandler = callbackHandler; |
| this.subject = subject; |
| } |
| |
| } |