X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=security%2Fruntime%2Forg.argeo.security.core%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fsecurity%2Fldap%2FArgeoSecurityDaoLdap.java;h=bf4beb0e8bfa00299bfdbf83528245ca564018bf;hb=136dab5338b5f731b285d17c804861bd5e5a9b5c;hp=350050bbcb5e30786cdebc7f747b0067e00dbd8e;hpb=490d9907457c43acfa965e7979ce5974bc1ba6ca;p=lgpl%2Fargeo-commons.git diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java index 350050bbc..bf4beb0e8 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java @@ -18,8 +18,13 @@ package org.argeo.security.ldap; import static org.argeo.security.core.ArgeoUserDetails.createSimpleArgeoUser; -import java.util.ArrayList; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Collections; import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; import javax.naming.Name; import javax.naming.NamingException; @@ -36,7 +41,6 @@ import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.core.support.BaseLdapPathContextSource; -import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper; import org.springframework.security.ldap.LdapAuthoritiesPopulator; @@ -44,6 +48,8 @@ import org.springframework.security.ldap.LdapUsernameToDnMapper; import org.springframework.security.ldap.LdapUtils; import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator; import org.springframework.security.ldap.search.FilterBasedLdapUserSearch; +import org.springframework.security.providers.UsernamePasswordAuthenticationToken; +import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsManager; import org.springframework.security.userdetails.UserDetailsService; @@ -74,6 +80,19 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean private LdapUserDetailsService ldapUserDetailsService; private List userNatureMappers; + private LdapShaPasswordEncoder ldapShaPasswordEncoder = new LdapShaPasswordEncoder(); + private Random random; + + public ArgeoSecurityDaoLdap(BaseLdapPathContextSource contextSource) { + this.contextSource = contextSource; + ldapTemplate = new LdapTemplate(this.contextSource); + try { + random = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + random = new Random(System.currentTimeMillis()); + } + } + public void afterPropertiesSet() throws Exception { if (usernameMapper == null) usernameMapper = new DefaultLdapUsernameToDnMapper(userBase, @@ -113,38 +132,31 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean } } - public ArgeoSecurityDaoLdap(BaseLdapPathContextSource contextSource) { - this.contextSource = contextSource; - ldapTemplate = new LdapTemplate(this.contextSource); - } - - public void create(ArgeoUser user) { + public synchronized void createUser(ArgeoUser user) { userDetailsManager.createUser(new ArgeoUserDetails(user)); } - public ArgeoUser getUser(String uname) { + public synchronized ArgeoUser getUser(String uname) { SimpleArgeoUser user = createSimpleArgeoUser(getDetails(uname)); user.setPassword(null); return user; } - public ArgeoUser getUserWithPassword(String uname) { + public synchronized ArgeoUser getUserWithPassword(String uname) { return createSimpleArgeoUser(getDetails(uname)); } - public ArgeoUser getCurrentUser() { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - ArgeoUser argeoUser = ArgeoUserDetails.asArgeoUser(authentication); - if (argeoUser == null) - return null; - if (argeoUser.getRoles().contains(defaultRole)) - argeoUser.getRoles().remove(defaultRole); - return argeoUser; - } + // public ArgeoUser getCurrentUser() { + // ArgeoUser argeoUser = ArgeoUserDetails.securityContextUser(); + // if (argeoUser == null) + // return null; + // if (argeoUser.getRoles().contains(defaultRole)) + // argeoUser.getRoles().remove(defaultRole); + // return argeoUser; + // } @SuppressWarnings("unchecked") - public List listUsers() { + public synchronized Set listUsers() { List usernames = (List) ldapTemplate.listBindings( new DistinguishedName(userBase), new ContextMapper() { public Object mapFromContext(Object ctxArg) { @@ -153,35 +165,63 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean } }); - List lst = new ArrayList(); + TreeSet lst = new TreeSet(); for (String username : usernames) { lst.add(createSimpleArgeoUser(getDetails(username))); } - return lst; + return Collections.unmodifiableSortedSet(lst); } @SuppressWarnings("unchecked") - public List listEditableRoles() { - return (List) ldapTemplate.listBindings(groupBase, - new ContextMapper() { + public Set listEditableRoles() { + return Collections.unmodifiableSortedSet(new TreeSet( + ldapTemplate.listBindings(groupBase, new ContextMapper() { public Object mapFromContext(Object ctxArg) { String groupName = ((DirContextAdapter) ctxArg) .getStringAttribute(groupRoleAttributeName); String roleName = convertGroupToRole(groupName); return roleName; } + }))); + } + + @SuppressWarnings("unchecked") + public Set listUsersInRole(String role) { + return (Set) ldapTemplate.lookup( + buildGroupDn(convertRoleToGroup(role)), new ContextMapper() { + public Object mapFromContext(Object ctxArg) { + DirContextAdapter ctx = (DirContextAdapter) ctxArg; + String[] userDns = ctx + .getStringAttributes(groupMemberAttributeName); + TreeSet set = new TreeSet(); + for (String userDn : userDns) { + DistinguishedName dn = new DistinguishedName(userDn); + String username = dn + .getValue(usernameAttributeName); + set.add(createSimpleArgeoUser(getDetails(username))); + } + return Collections.unmodifiableSortedSet(set); + } }); } - public void update(ArgeoUser user) { + public synchronized void updateUser(ArgeoUser user) { + ArgeoUserDetails argeoUserDetails = new ArgeoUserDetails(user); userDetailsManager.updateUser(new ArgeoUserDetails(user)); + // refresh logged in user + if (ArgeoUserDetails.securityContextUser().getUsername() + .equals(argeoUserDetails.getUsername())) { + SecurityContextHolder.getContext().setAuthentication( + new UsernamePasswordAuthenticationToken(argeoUserDetails, + null, argeoUserDetails.getAuthorities())); + } } - public void delete(String username) { + public synchronized void deleteUser(String username) { userDetailsManager.deleteUser(username); } - public Boolean userExists(String username) { + public synchronized Boolean userExists(String username) { return userDetailsManager.userExists(username); } @@ -191,8 +231,8 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean .executeReadWrite(new ContextExecutor() { public Object executeWithContext(DirContext ctx) throws NamingException { - return LdapUtils.getFullDn(usernameMapper - .buildDn(superuserName), ctx); + return LdapUtils.getFullDn( + usernameMapper.buildDn(superuserName), ctx); } }); @@ -202,8 +242,8 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean context.setAttributeValue("cn", group); // Add superuser because cannot create empty group - context.setAttributeValue(groupMemberAttributeName, superuserDn - .toString()); + context.setAttributeValue(groupMemberAttributeName, + superuserDn.toString()); ldapTemplate.bind(groupDn, context, null); } @@ -214,6 +254,18 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean ldapTemplate.unbind(dn); } + public Boolean isPasswordValid(String encoded, String raw) { + return ldapShaPasswordEncoder.isPasswordValid(encoded, raw, null); + } + + public String encodePassword(String raw) { + byte[] salt = null; + // TODO: check that Linux auth supports SSHA + // byte[] salt = new byte[16]; + // random.nextBytes(salt); + return ldapShaPasswordEncoder.encodePassword(raw, salt); + } + protected String convertRoleToGroup(String role) { String group = role; if (group.startsWith(rolePrefix)) {