X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FLdapUserAdmin.java;h=0cb435f073e39e25b24efde6a49ac696badd0c85;hb=9a9418f4c0df975756de3093df71d757c72a386d;hp=0173addbba8cc3f0b24d7a38630979552ec7070d;hpb=b4c3087d7a41cde4a9e92736882b450e51742bf7;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java index 0173addbb..0cb435f07 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java @@ -1,7 +1,7 @@ package org.argeo.osgi.useradmin; +import java.net.URI; import java.util.ArrayList; -import java.util.Arrays; import java.util.Hashtable; import java.util.List; @@ -11,36 +11,39 @@ import javax.naming.InvalidNameException; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import javax.naming.ldap.LdapName; +import javax.transaction.xa.XAException; +import javax.transaction.xa.Xid; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; +import org.osgi.framework.Filter; import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.useradmin.Authorization; +import org.osgi.service.useradmin.Group; import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -public class LdapUserAdmin implements UserAdmin { +public class LdapUserAdmin extends AbstractUserDirectory { private final static Log log = LogFactory.getLog(LdapUserAdmin.class); - private List indexedUserProperties = Arrays.asList(new String[] { - "uid", "mail", "cn" }); - private String baseDn = "dc=example,dc=com"; private InitialLdapContext initialLdapContext = null; public LdapUserAdmin(String uri) { try { + setUri(new URI(uri)); Hashtable connEnv = new Hashtable(); connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - connEnv.put(Context.PROVIDER_URL, "ldap://localhost:10389/"); + connEnv.put(Context.PROVIDER_URL, getUri().toString()); connEnv.put("java.naming.ldap.attributes.binary", "userPassword"); // connEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); // connEnv.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system"); @@ -61,7 +64,7 @@ public class LdapUserAdmin implements UserAdmin { log.debug(initialLdapContext.getAttributes( "uid=root,ou=users,dc=example,dc=com").get("cn")); } catch (Exception e) { - throw new ArgeoUserAdminException("Cannot connect to LDAP", e); + throw new UserDirectoryException("Cannot connect to LDAP", e); } } @@ -75,46 +78,102 @@ public class LdapUserAdmin implements UserAdmin { } @Override - public Role createRole(String name, int type) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean removeRole(String name) { - // TODO Auto-generated method stub - return false; + protected Boolean daoHasRole(LdapName dn) { + return daoGetRole(dn) != null; } @Override - public Role getRole(String name) { + protected DirectoryUser daoGetRole(LdapName name) { try { Attributes attrs = initialLdapContext.getAttributes(name); + if (attrs.size() == 0) + return null; LdifUser res; if (attrs.get("objectClass").contains("groupOfNames")) - res = new LdifGroup(new LdapName(name), attrs); + res = new LdifGroup(this, name, attrs); else if (attrs.get("objectClass").contains("inetOrgPerson")) - res = new LdifUser(new LdapName(name), attrs); + res = new LdifUser(this, name, attrs); else - throw new ArgeoUserAdminException("Unsupported LDAP type for " + throw new UserDirectoryException("Unsupported LDAP type for " + name); return res; } catch (NamingException e) { - throw new ArgeoUserAdminException("Cannot get role for " + name, e); + throw new UserDirectoryException("Cannot get role for " + name, e); } } @Override - public Role[] getRoles(String filter) throws InvalidSyntaxException { + protected List doGetRoles(Filter f) { // TODO Auto-generated method stub - return null; + try { + String searchFilter = f != null ? f.toString() + : "(|(objectClass=inetOrgPerson)(objectClass=groupOfNames))"; + SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + String searchBase = baseDn; + NamingEnumeration results = initialLdapContext + .search(searchBase, searchFilter, searchControls); + + ArrayList res = new ArrayList(); + while (results.hasMoreElements()) { + SearchResult searchResult = results.next(); + Attributes attrs = searchResult.getAttributes(); + LdifUser role; + if (attrs.get("objectClass").contains("groupOfNames")) + role = new LdifGroup(this, toDn(searchBase, searchResult), + attrs); + else if (attrs.get("objectClass").contains("inetOrgPerson")) + role = new LdifUser(this, toDn(searchBase, searchResult), + attrs); + else + throw new UserDirectoryException( + "Unsupported LDAP type for " + + searchResult.getName()); + res.add(role); + } + return res; + } catch (Exception e) { + throw new UserDirectoryException( + "Cannot get roles for filter " + f, e); + } + } + + @Override + protected void doGetUser(String key, String value, + List collectedUsers) { + try { + String searchFilter = "(&(objectClass=inetOrgPerson)(" + key + "=" + + value + "))"; + + SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + String searchBase = baseDn; + NamingEnumeration results = initialLdapContext + .search(searchBase, searchFilter, searchControls); + + SearchResult searchResult = null; + if (results.hasMoreElements()) { + searchResult = (SearchResult) results.nextElement(); + if (results.hasMoreElements()) + searchResult = null; + } + if (searchResult != null) + collectedUsers.add(new LdifUser(this, toDn(searchBase, + searchResult), searchResult.getAttributes())); + } catch (Exception e) { + throw new UserDirectoryException("Cannot get user with " + key + + "=" + value, e); + } + } @Override public User getUser(String key, String value) { if (key == null) { List users = new ArrayList(); - for (String prop : indexedUserProperties) { + for (String prop : getIndexedUserProperties()) { User user = getUser(prop, value); if (user != null) users.add(user); @@ -144,29 +203,52 @@ public class LdapUserAdmin implements UserAdmin { } if (searchResult == null) return null; - return new LdifUser(toDn(searchBase, searchResult), + return new LdifUser(this, toDn(searchBase, searchResult), searchResult.getAttributes()); } catch (Exception e) { - throw new ArgeoUserAdminException("Cannot get user with " + key + throw new UserDirectoryException("Cannot get user with " + key + "=" + value, e); } } - @Override - public Authorization getAuthorization(User user) { - LdifUser u = (LdifUser) user; - populateDirectMemberOf(u); - return new LdifAuthorization(u); - } - private LdapName toDn(String baseDn, Binding binding) throws InvalidNameException { return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName()); } - void populateDirectMemberOf(LdifUser user) { + // void populateDirectMemberOf(LdifUser user) { + // + // try { + // String searchFilter = "(&(objectClass=groupOfNames)(member=" + // + user.getName() + "))"; + // + // SearchControls searchControls = new SearchControls(); + // searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + // + // String searchBase = "ou=node"; + // NamingEnumeration results = initialLdapContext + // .search(searchBase, searchFilter, searchControls); + // + // // TODO synchro + // //user.directMemberOf.clear(); + // while (results.hasMoreElements()) { + // SearchResult searchResult = (SearchResult) results + // .nextElement(); + // LdifGroup group = new LdifGroup(toDn(searchBase, searchResult), + // searchResult.getAttributes()); + // populateDirectMemberOf(group); + // //user.directMemberOf.add(group); + // } + // } catch (Exception e) { + // throw new ArgeoException("Cannot populate direct members of " + // + user, e); + // } + // } + @Override + protected List getDirectGroups(User user) { + List directGroups = new ArrayList(); try { String searchFilter = "(&(objectClass=groupOfNames)(member=" + user.getName() + "))"; @@ -174,24 +256,88 @@ public class LdapUserAdmin implements UserAdmin { SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - String searchBase = "ou=node"; + String searchBase = getGroupsSearchBase(); NamingEnumeration results = initialLdapContext .search(searchBase, searchFilter, searchControls); - // TODO synchro - user.directMemberOf.clear(); while (results.hasMoreElements()) { SearchResult searchResult = (SearchResult) results .nextElement(); - LdifGroup group = new LdifGroup(toDn(searchBase, searchResult), - searchResult.getAttributes()); - populateDirectMemberOf(group); - user.directMemberOf.add(group); + LdifGroup group = new LdifGroup(this, toDn(searchBase, + searchResult), searchResult.getAttributes()); + directGroups.add(group); } + return directGroups; } catch (Exception e) { throw new ArgeoException("Cannot populate direct members of " + user, e); } } + protected String getGroupsSearchBase() { + // TODO configure group search base + return baseDn; + } + + @Override + protected void prepare(WorkingCopy wc) { + try { + initialLdapContext.reconnect(initialLdapContext + .getConnectControls()); + // delete + for (LdapName dn : wc.getDeletedUsers().keySet()) { + if (!entryExists(dn)) + throw new UserDirectoryException("User to delete no found " + + dn); + } + // add + for (LdapName dn : wc.getNewUsers().keySet()) { + if (!entryExists(dn)) + throw new UserDirectoryException("User to create found " + + dn); + } + // modify + for (LdapName dn : wc.getModifiedUsers().keySet()) { + if (!entryExists(dn)) + throw new UserDirectoryException("User to modify no found " + + dn); + } + } catch (NamingException e) { + throw new UserDirectoryException("Cannot prepare LDAP", e); + } + } + + private boolean entryExists(LdapName dn) throws NamingException { + return initialLdapContext.getAttributes(dn).size() != 0; + } + + @Override + protected void commit(WorkingCopy wc) { + try { + // delete + for (LdapName dn : wc.getDeletedUsers().keySet()) { + initialLdapContext.destroySubcontext(dn); + } + // add + for (LdapName dn : wc.getNewUsers().keySet()) { + DirectoryUser user = wc.getNewUsers().get(dn); + initialLdapContext.createSubcontext(dn, user.getAttributes()); + } + // modify + for (LdapName dn : wc.getModifiedUsers().keySet()) { + Attributes modifiedAttrs = wc.getModifiedUsers().get(dn); + initialLdapContext.modifyAttributes(dn, + DirContext.REPLACE_ATTRIBUTE, modifiedAttrs); + } + } catch (NamingException e) { + throw new UserDirectoryException("Cannot commit LDAP", e); + } + } + + @Override + protected void rollback(WorkingCopy wc) { + // TODO Auto-generated method stub + super.rollback(wc); + } + }