Index: lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java =================================================================== diff -u -r484bbdf5dec3610769320731a88eeeeabcf1ee39 -rd69d6409d2853f6a13a2de63e0044e6e7d1ec01c --- lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java (.../UniversalLoginModule.java) (revision 484bbdf5dec3610769320731a88eeeeabcf1ee39) +++ lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java (.../UniversalLoginModule.java) (revision d69d6409d2853f6a13a2de63e0044e6e7d1ec01c) @@ -70,251 +70,264 @@ import org.springframework.web.context.support.WebApplicationContextUtils; public class UniversalLoginModule extends UsernamePasswordLoginModule { - - private static Logger log = Logger.getLogger(UniversalLoginModule.class); - public UniversalLoginModule() { - } + private static Logger log = Logger.getLogger(UniversalLoginModule.class); - protected String dsJndiName; - protected String rolesQuery; - protected String principalsQuery; + public UniversalLoginModule() { + } - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { - super.initialize(subject, callbackHandler, sharedState, options); - dsJndiName = (String)options.get("dsJndiName"); - principalsQuery = (String)options.get("principalsQuery"); - rolesQuery = (String)options.get("rolesQuery"); - } + protected String dsJndiName; - protected boolean validatePassword(String inputPassword, - String expectedPassword) { - boolean isValid = false; - if (inputPassword != null) { - // empty password not allowed - if (inputPassword.length() == 0) - return false; + protected String rolesQuery; - try { - String username = getUsername(); - log.debug("===> authenticating user: " + username); - - WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(HttpSessionManager.getInstance().getServletContext()); - UserManagementService service = (UserManagementService) ctx.getBean("userManagementService"); - User user = service.getUserByLogin(username); - - // LDAP user provisioning - if (user == null) { - // provision a new user by checking ldap server - if (Configuration.getAsBoolean(ConfigurationKeys.LDAP_PROVISIONING_ENABLED)) { - LdapService ldapService; - try { - ldapService = (LdapService) ctx.getBean("ldapService"); - } catch (NoSuchBeanDefinitionException e) { - // LDEV-1937 - log.error("NoSuchBeanDefinitionException while getting ldapService bean, will try another method...", e); - ApplicationContext context = new ClassPathXmlApplicationContext("org/lamsfoundation/lams/usermanagement/ldapContext.xml"); - ldapService = (LdapService) context.getBean("ldapService"); - } - log.debug("===> LDAP provisioning is enabled, checking username against LDAP server..."); - LDAPAuthenticator ldap = new LDAPAuthenticator(); - isValid = ldap.authenticate(username, inputPassword); - if (isValid) { // create a new user - log.info("===> Creating new user for LDAP username: " + username); - if (ldapService.createLDAPUser(ldap.getAttrs())) { - user = service.getUserByLogin(username); - if (!ldapService.addLDAPUser(ldap.getAttrs(), user.getUserId())) { - log.error("===> Couldn't add LDAP user: "+username+" to organisation."); - } - } else { - log.error("===> Couldn't create new user for LDAP username: "+username); - return false; - } - } else { // didn't authenticate successfully with ldap - return false; - } - } else { - return false; - } - } - - // allow sysadmin to login as another user; in this case, the LAMS shared session - // will be present, allowing the following check to work - if (service.isUserSysAdmin()) { - isValid = true; - } - - // perform password checking according to user's authentication method - if (!isValid) { - String type = user.getAuthenticationMethod().getAuthenticationMethodType().getDescription(); - log.debug("===> authentication type: " + type); - if (AuthenticationMethodType.LDAP.equals(type)) { - LDAPAuthenticator authenticator = new LDAPAuthenticator(); - isValid = authenticator.authenticate(username,inputPassword); - // if ldap user profile has updated, udpate user object for dto below - user = service.getUserByLogin(username); - } else if (AuthenticationMethodType.LAMS.equals(type)) { - DatabaseAuthenticator authenticator = new DatabaseAuthenticator(dsJndiName, principalsQuery); - // if the password is not encrypted when sent from the jsp (e.g. when it is passed - // unencrypted to say, ldap) then encrypt it here when authenticating against local db - if (!Configuration.getAsBoolean(ConfigurationKeys.LDAP_ENCRYPT_PASSWORD_FROM_BROWSER)) { - // try the passed in password first, LoginRequestServlet always passes in encrypted - // passwords - isValid = authenticator.authenticate(username,inputPassword); - if (!isValid) { - inputPassword = HashUtil.sha1(inputPassword); - } - isValid = authenticator.authenticate(username,inputPassword); - } else { - isValid = authenticator.authenticate(username,inputPassword); - } - } else if (AuthenticationMethodType.WEB_AUTH.equals(type)) { - WebAuthAuthenticator authenticator = new WebAuthAuthenticator(); - isValid = authenticator.authenticate(username,inputPassword); - } else { - log.error("===> Unexpected authentication type: "+type); - return false; - } - } - - // disabled users can't login; - // check after authentication to give non-db authentication methods - // a chance to update disabled flag - if (user.getDisabledFlag()) { - log.debug("===> user is disabled."); - return false; - } - - //if login is valid, register userDTO into session. - if(isValid){ - HttpSession sharedsession = SessionManager.getSession(); - sharedsession.setAttribute(AttributeNames.USER,user.getUserDTO()); - } - } catch (Exception e) { - e.printStackTrace(); - log.error("===> exception: " + e,e); - } - } - return isValid; - } + protected String principalsQuery; - /** - * According to Lams's security policy, all the authorization - * must be done locally, in other word, through Lams database - * or other "local"(logically) data resource. - * - @return Group[] containing the sets of roles - */ - protected Group[] getRoleSets() throws LoginException { - String username = getUsername(); - Connection conn = null; - HashMap setsMap = new HashMap(); - PreparedStatement ps = null; - ResultSet rs = null; + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { + super.initialize(subject, callbackHandler, sharedState, options); + dsJndiName = (String) options.get("dsJndiName"); + principalsQuery = (String) options.get("principalsQuery"); + rolesQuery = (String) options.get("rolesQuery"); + } - try { + protected boolean validatePassword(String inputPassword, String expectedPassword) { + boolean isValid = false; + if (inputPassword != null) { + // empty password not allowed + if (inputPassword.length() == 0) + return false; - InitialContext ctx = new InitialContext(); - DataSource ds = (DataSource) ctx.lookup(this.dsJndiName); + try { + String username = getUsername(); + log.debug("===> authenticating user: " + username); - //log.debug("===> getRoleSets() called: " + dsJndiName + ": " + rolesQuery); - conn = ds.getConnection(); - // Get the user role names - ps = conn.prepareStatement(this.rolesQuery); + WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(HttpSessionManager + .getInstance().getServletContext()); + UserManagementService service = (UserManagementService) ctx.getBean("userManagementService"); + User user = service.getUserByLogin(username); + + // LDAP user provisioning + if (user == null) { + // provision a new user by checking ldap server + if (Configuration.getAsBoolean(ConfigurationKeys.LDAP_PROVISIONING_ENABLED)) { + LdapService ldapService; try { - ps.setString(1, username); - } catch (ArrayIndexOutOfBoundsException ignore) { - // The query may not have any parameters so just try it + ldapService = (LdapService) ctx.getBean("ldapService"); + } catch (NoSuchBeanDefinitionException e) { + // LDEV-1937 + log.error("NoSuchBeanDefinitionException while getting ldapService bean, will try another method...", + e); + ApplicationContext context = new ClassPathXmlApplicationContext( + "org/lamsfoundation/lams/usermanagement/ldapContext.xml"); + ldapService = (LdapService) context.getBean("ldapService"); } - rs = ps.executeQuery(); - if (rs.next() == false) { - if (getUnauthenticatedIdentity() == null) - throw new FailedLoginException("No matching username found in Roles"); - /* We are running with an unauthenticatedIdentity so create an - empty Roles set and return. - */ - Group[] roleSets = { new SimpleGroup("Roles") }; - return roleSets; + log.debug("===> LDAP provisioning is enabled, checking username against LDAP server..."); + LDAPAuthenticator ldap = new LDAPAuthenticator(); + isValid = ldap.authenticate(username, inputPassword); + if (isValid) { // create a new user + log.info("===> Creating new user for LDAP username: " + username); + if (ldapService.createLDAPUser(ldap.getAttrs())) { + user = service.getUserByLogin(username); + if (!ldapService.addLDAPUser(ldap.getAttrs(), user.getUserId())) { + log.error("===> Couldn't add LDAP user: " + username + " to organisation."); + } + } else { + log.error("===> Couldn't create new user for LDAP username: " + username); + return false; + } + } else { // didn't authenticate successfully with ldap + return false; } + } else { + return false; + } + } - ArrayList groupMembers = new ArrayList(); - do { - String name = rs.getString(1); - String groupName = rs.getString(2); - if (groupName == null || groupName.length() == 0) - groupName = "Roles"; - Group group = (Group) setsMap.get(groupName); - if (group == null) { - group = new SimpleGroup(groupName); - setsMap.put(groupName, group); - } + // allow sysadmin to login as another user; in this case, the + // LAMS shared session + // will be present, allowing the following check to work + if (service.isUserSysAdmin()) { + isValid = true; + } - try { - Principal p; - // Assign minimal role if user has none - if (name==null) { - name = Role.LEARNER; - log.info("===> Found no roles"); - } - p = super.createIdentity(name); - if (!groupMembers.contains(name)) { - log.info("===> Assign user to role " + p.getName()); - group.addMember(p); - groupMembers.add(name); - } - if (name.equals(Role.SYSADMIN) || name.equals(Role.AUTHOR_ADMIN)) { - p = super.createIdentity(Role.AUTHOR); - log.info("===> Found "+name); - if (!groupMembers.contains(Role.AUTHOR)) { - log.info("===> Assign user to role "+Role.AUTHOR); - group.addMember(p); - groupMembers.add(Role.AUTHOR); - } - } - } catch (Exception e) { - log.debug("===> Failed to create principal: " + name, e); - } - } while (rs.next()); - } catch (NamingException ex) { - throw new LoginException(ex.toString(true)); - } catch (SQLException ex) { - super.log.error("SQL failure", ex); - throw new LoginException(ex.toString()); - } finally { - if (rs != null) { - try { - rs.close(); - } catch (SQLException e) { - } + // perform password checking according to user's authentication + // method + if (!isValid) { + String type = user.getAuthenticationMethod().getAuthenticationMethodType().getDescription(); + log.debug("===> authentication type: " + type); + if (AuthenticationMethodType.LDAP.equals(type)) { + LDAPAuthenticator authenticator = new LDAPAuthenticator(); + isValid = authenticator.authenticate(username, inputPassword); + // if ldap user profile has updated, udpate user object + // for dto below + user = service.getUserByLogin(username); + } else if (AuthenticationMethodType.LAMS.equals(type)) { + DatabaseAuthenticator authenticator = new DatabaseAuthenticator(dsJndiName, principalsQuery); + // if the password is not encrypted when sent from the + // jsp (e.g. when it is passed + // unencrypted to say, ldap) then encrypt it here when + // authenticating against local db + if (!Configuration.getAsBoolean(ConfigurationKeys.LDAP_ENCRYPT_PASSWORD_FROM_BROWSER)) { + // try the passed in password first, + // LoginRequestServlet always passes in encrypted + // passwords + isValid = authenticator.authenticate(username, inputPassword); + if (!isValid) { + inputPassword = HashUtil.sha1(inputPassword); + } + isValid = authenticator.authenticate(username, inputPassword); + } else { + isValid = authenticator.authenticate(username, inputPassword); } - if (ps != null) { - try { - ps.close(); - } catch (SQLException e) { - } - } - if (conn != null) { - try { - conn.close(); - } catch (Exception ex) { - } - } + } else if (AuthenticationMethodType.WEB_AUTH.equals(type)) { + WebAuthAuthenticator authenticator = new WebAuthAuthenticator(); + isValid = authenticator.authenticate(username, inputPassword); + } else { + log.error("===> Unexpected authentication type: " + type); + return false; + } } - Group[] roleSets = new Group[setsMap.size()]; - setsMap.values().toArray(roleSets); - return roleSets; + // disabled users can't login; + // check after authentication to give non-db authentication + // methods + // a chance to update disabled flag + if (user.getDisabledFlag()) { + log.debug("===> user is disabled."); + return false; + } + + // if login is valid, register userDTO into session. + if (isValid) { + HttpSession sharedsession = SessionManager.getSession(); + sharedsession.setAttribute(AttributeNames.USER, user.getUserDTO()); + } + } catch (Exception e) { + e.printStackTrace(); + log.error("===> exception: " + e, e); + } } + return isValid; + } - /** - * Overriden to return an empty password string as typically one cannot - * obtain a user's password. We also override the validatePassword so - * this is ok. - * @return and empty password String - */ - protected String getUsersPassword() throws LoginException { - return ""; + /** + * According to Lams's security policy, all the authorization must be done + * locally, in other word, through Lams database or other "local"(logically) + * data resource. + * + * @return Group[] containing the sets of roles + */ + protected Group[] getRoleSets() throws LoginException { + String username = getUsername(); + Connection conn = null; + HashMap setsMap = new HashMap(); + PreparedStatement ps = null; + ResultSet rs = null; + + try { + + InitialContext ctx = new InitialContext(); + DataSource ds = (DataSource) ctx.lookup(this.dsJndiName); + + // log.debug("===> getRoleSets() called: " + dsJndiName + ": " + + // rolesQuery); + conn = ds.getConnection(); + // Get the user role names + ps = conn.prepareStatement(this.rolesQuery); + try { + ps.setString(1, username); + } catch (ArrayIndexOutOfBoundsException ignore) { + // The query may not have any parameters so just try it + } + rs = ps.executeQuery(); + if (rs.next() == false) { + if (getUnauthenticatedIdentity() == null) + throw new FailedLoginException("No matching username found in Roles"); + /* + * We are running with an unauthenticatedIdentity so create an + * empty Roles set and return. + */ + Group[] roleSets = { new SimpleGroup("Roles") }; + return roleSets; + } + + ArrayList groupMembers = new ArrayList(); + do { + String name = rs.getString(1); + String groupName = rs.getString(2); + if (groupName == null || groupName.length() == 0) + groupName = "Roles"; + Group group = (Group) setsMap.get(groupName); + if (group == null) { + group = new SimpleGroup(groupName); + setsMap.put(groupName, group); + } + + try { + Principal p; + // Assign minimal role if user has none + if (name == null) { + name = Role.LEARNER; + log.info("===> Found no roles"); + } + p = super.createIdentity(name); + if (!groupMembers.contains(name)) { + log.info("===> Assign user to role " + p.getName()); + group.addMember(p); + groupMembers.add(name); + } + if (name.equals(Role.SYSADMIN) || name.equals(Role.AUTHOR_ADMIN)) { + p = super.createIdentity(Role.AUTHOR); + log.info("===> Found " + name); + if (!groupMembers.contains(Role.AUTHOR)) { + log.info("===> Assign user to role " + Role.AUTHOR); + group.addMember(p); + groupMembers.add(Role.AUTHOR); + } + } + } catch (Exception e) { + log.debug("===> Failed to create principal: " + name, e); + } + } while (rs.next()); + } catch (NamingException ex) { + throw new LoginException(ex.toString(true)); + } catch (SQLException ex) { + super.log.error("SQL failure", ex); + throw new LoginException(ex.toString()); + } finally { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + } + } + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + } + } + if (conn != null) { + try { + conn.close(); + } catch (Exception ex) { + } + } } + Group[] roleSets = new Group[setsMap.size()]; + setsMap.values().toArray(roleSets); + return roleSets; + } + + /** + * Overriden to return an empty password string as typically one cannot + * obtain a user's password. We also override the validatePassword so this + * is ok. + * + * @return and empty password String + */ + protected String getUsersPassword() throws LoginException { + return ""; + } + } \ No newline at end of file