X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Fauth%2FUserAdminLoginModule.java;h=0f7f0bdeed37c6e489f67cd9a67bd4cd965d99aa;hb=ebd927da42511bb5959000c50a39974c6cfa5f49;hp=243eb0fec84e1d6288cd89b187dc63a6f980b640;hpb=a444205e81419d439635a9e0ff3382ae3f5d9947;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index 243eb0fec..0f7f0bdee 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -1,9 +1,15 @@ package org.argeo.cms.auth; import java.io.IOException; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; +import javax.naming.ldap.LdapName; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; @@ -11,13 +17,19 @@ import javax.security.auth.callback.LanguageCallback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.login.CredentialNotFoundException; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; +import javax.servlet.http.HttpServletRequest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; import org.argeo.eclipse.ui.specific.UiContext; +import org.argeo.naming.LdapAttrs; +import org.argeo.osgi.useradmin.IpaUtils; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.service.useradmin.Authorization; @@ -25,15 +37,20 @@ import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; public class UserAdminLoginModule implements LoginModule { + private final static Log log = LogFactory.getLog(UserAdminLoginModule.class); + private Subject subject; private CallbackHandler callbackHandler; private Map sharedState = null; // private boolean isAnonymous = false; + private List indexedUserProperties = Arrays + .asList(new String[] { LdapAttrs.uid.name(), LdapAttrs.mail.name(), LdapAttrs.cn.name() }); // private state private BundleContext bc; - private Authorization authorization; + // private Authorization authorization; + private User authenticatedUser = null; @SuppressWarnings("unchecked") @Override @@ -64,8 +81,9 @@ public class UserAdminLoginModule implements LoginModule { } UserAdmin userAdmin = bc.getService(bc.getServiceReference(UserAdmin.class)); if (callbackHandler == null) {// anonymous - authorization = userAdmin.getAuthorization(null); - sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, authorization); + // authorization = userAdmin.getAuthorization(null); + // sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, + // authorization); return true; } @@ -74,10 +92,13 @@ public class UserAdminLoginModule implements LoginModule { if (sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME) && sharedState.containsKey(CmsAuthUtils.SHARED_STATE_PWD)) { username = (String) sharedState.get(CmsAuthUtils.SHARED_STATE_NAME); - password = (char[]) sharedState.get(CmsAuthUtils.SHARED_STATE_NAME); - // TODO locale? + password = (char[]) sharedState.get(CmsAuthUtils.SHARED_STATE_PWD); + // // TODO locale? + // // NB: raw user name is used + // AuthenticatingUser authenticatingUser = new + // AuthenticatingUser(username, password); + // authorization = userAdmin.getAuthorization(authenticatingUser); } else { - // ask for username and password NameCallback nameCallback = new NameCallback("User"); PasswordCallback passwordCallback = new PasswordCallback("Password", false); @@ -86,9 +107,6 @@ public class UserAdminLoginModule implements LoginModule { callbackHandler.handle(new Callback[] { nameCallback, passwordCallback, langCallback }); } catch (IOException e) { throw new LoginException("Cannot handle callback: " + e.getMessage()); - // } catch (ThreadDeath e) { - // throw new ThreadDeathLoginException("Callbackhandler thread - // died", e); } catch (UnsupportedCallbackException e) { return false; } @@ -99,78 +117,134 @@ public class UserAdminLoginModule implements LoginModule { locale = Locale.getDefault(); UiContext.setLocale(locale); - // authorization = (Authorization) - // sharedState.get(CmsAuthUtils.SHARED_STATE_AUTHORIZATION); - // - // if (authorization == null) { - // create credentials username = nameCallback.getName(); if (username == null || username.trim().equals("")) { // authorization = userAdmin.getAuthorization(null); throw new CredentialNotFoundException("No credentials provided"); } - // char[] password = {}; if (passwordCallback.getPassword() != null) password = passwordCallback.getPassword(); else throw new CredentialNotFoundException("No credentials provided"); + // FIXME move Argeo specific convention from user admin to here } - // FIXME move Argeo specific convention from user admin to here - User user = userAdmin.getUser(null, username); + // User user = userAdmin.getUser(null, username); + User user = searchForUser(userAdmin, username); if (user == null) - throw new FailedLoginException("Invalid credentials"); + return true;// expect Kerberos + // throw new FailedLoginException("Invalid credentials"); if (!user.hasCredential(null, password)) throw new FailedLoginException("Invalid credentials"); + authenticatedUser = user; // return false; - // Log and monitor new login - // if (log.isDebugEnabled()) - // log.debug("Logged in to CMS with username [" + username + - // "]"); - - authorization = userAdmin.getAuthorization(user); - assert authorization != null; - - // } - // if - // (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_AUTHORIZATION)) - sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, authorization); - return authorization != null; + // authorization = userAdmin.getAuthorization(user); + // assert authorization != null; + // + // sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, + // authorization); + return true; } @Override public boolean commit() throws LoginException { - // Set kerberosPrincipals = - // subject.getPrincipals(KerberosPrincipal.class); - // if (kerberosPrincipals.size() != 0) { - // KerberosPrincipal kerberosPrincipal = - // kerberosPrincipals.iterator().next(); - // System.out.println(kerberosPrincipal); - // UserAdmin userAdmin = - // bc.getService(bc.getServiceReference(UserAdmin.class)); - // User user = userAdmin.getUser(null, kerberosPrincipal.getName()); - // Authorization authorization = userAdmin.getAuthorization(user); - // sharedState.put(SHARED_STATE_AUTHORIZATION, authorization); + // if (authorization == null) { + // return false; + // // throw new LoginException("Authorization should not be null"); + // } else { + // CmsAuthUtils.addAuthentication(subject, authorization); + // return true; // } - if (authorization == null) { - return false; - // throw new LoginException("Authorization should not be null"); + UserAdmin userAdmin = bc.getService(bc.getServiceReference(UserAdmin.class)); + Authorization authorization; + if (callbackHandler == null) {// anonymous + authorization = userAdmin.getAuthorization(null); } else { - CmsAuthUtils.addAuthentication(subject, authorization); - return true; + User authenticatingUser; + Set kerberosPrincipals = subject.getPrincipals(KerberosPrincipal.class); + if (kerberosPrincipals.isEmpty()) { + if (authenticatedUser == null) { + if(log.isTraceEnabled()) + log.trace("Neither kerberos nor user admin login succeeded. Login failed."); + return false; + } else { + authenticatingUser = authenticatedUser; + } + } else { + KerberosPrincipal kerberosPrincipal = kerberosPrincipals.iterator().next(); + LdapName dn = IpaUtils.kerberosToDn(kerberosPrincipal.getName()); + authenticatingUser = new AuthenticatingUser(dn); + if (authenticatedUser != null && !authenticatingUser.getName().equals(authenticatedUser.getName())) + throw new LoginException("Kerberos login " + authenticatingUser.getName() + + " is inconsistent with user admin login " + authenticatedUser.getName()); + } + authorization = Subject.doAs(subject, new PrivilegedAction() { + + @Override + public Authorization run() { + Authorization authorization = userAdmin.getAuthorization(authenticatingUser); + return authorization; + } + + }); + if (authorization == null) + throw new LoginException("User admin found no authorization for authenticated user "+authenticatingUser.getName()); } + // Log and monitor new login + CmsAuthUtils.addAuthorization(subject, authorization, (HttpServletRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST)); +// HttpServletRequest request = (HttpServletRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST); +// if (request != null) { +// CmsAuthUtils.registerSessionAuthorization(bc, request, subject, authorization); +// } + if (log.isDebugEnabled()) + log.debug("Logged in to CMS: " + subject); + return true; } @Override public boolean abort() throws LoginException { - authorization = null; + // authorization = null; return true; } @Override public boolean logout() throws LoginException { + if (log.isDebugEnabled()) + log.debug("Logging out from CMS... " + subject); CmsAuthUtils.cleanUp(subject); return true; } + + protected User searchForUser(UserAdmin userAdmin, String providedUsername) { + try { + // TODO check value null or empty + List collectedUsers = new ArrayList(); + // try dn + User user = null; + try { + user = (User) userAdmin.getRole(providedUsername); + if (user != null) + collectedUsers.add(user); + } catch (Exception e) { + // silent + } + // try all indexes + for (String attr : indexedUserProperties) { + user = userAdmin.getUser(attr, providedUsername); + if (user != null) + collectedUsers.add(user); + } + if (collectedUsers.size() == 1) + return collectedUsers.get(0); + else if (collectedUsers.size() > 1) + log.warn(collectedUsers.size() + " users for provided username" + providedUsername); + return null; + } catch (Exception e) { + if (log.isTraceEnabled()) + log.warn("Cannot search for user " + providedUsername, e); + return null; + } + + } }