X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FLdapUserAdmin.java;h=7a617dfd6115ee3012717ad60276f040b5bb87ed;hb=8260f4470f514ea347ca53f5b4dfc632c4a4de66;hp=0cb435f073e39e25b24efde6a49ac696badd0c85;hpb=9a9418f4c0df975756de3093df71d757c72a386d;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 0cb435f07..7a617dfd6 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,68 +1,66 @@ package org.argeo.osgi.useradmin; -import java.net.URI; +import static org.argeo.osgi.useradmin.LdifName.objectClass; + import java.util.ArrayList; +import java.util.Dictionary; import java.util.Hashtable; import java.util.List; import javax.naming.Binding; import javax.naming.Context; import javax.naming.InvalidNameException; +import javax.naming.NameNotFoundException; import javax.naming.NamingEnumeration; import javax.naming.NamingException; +import javax.naming.directory.Attribute; 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 javax.transaction.TransactionManager; 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; +/** + * A user admin based on a LDAP server. Requires a {@link TransactionManager} + * and an open transaction for write access. + */ public class LdapUserAdmin extends AbstractUserDirectory { private final static Log log = LogFactory.getLog(LdapUserAdmin.class); - private String baseDn = "dc=example,dc=com"; private InitialLdapContext initialLdapContext = null; - public LdapUserAdmin(String uri) { + public LdapUserAdmin(Dictionary properties) { + super(properties); try { - setUri(new URI(uri)); Hashtable connEnv = new Hashtable(); - connEnv.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 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"); - // connEnv.put(Context.SECURITY_CREDENTIALS, "secret"); + connEnv.put("java.naming.ldap.attributes.binary", LdifName.userPassword.name()); initialLdapContext = new InitialLdapContext(connEnv, null); // StartTlsResponse tls = (StartTlsResponse) ctx // .extendedOperation(new StartTlsRequest()); // tls.negotiate(); - initialLdapContext.addToEnvironment( - Context.SECURITY_AUTHENTICATION, "simple"); - initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, - "uid=admin,ou=system"); - initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, - "secret"); - LdapContext ldapContext = (LdapContext) initialLdapContext - .lookup("uid=root,ou=users,dc=example,dc=com"); - log.debug(initialLdapContext.getAttributes( - "uid=root,ou=users,dc=example,dc=com").get("cn")); + initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); + Object principal = properties.get(Context.SECURITY_PRINCIPAL); + if (principal != null) { + initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, principal.toString()); + Object creds = properties.get(Context.SECURITY_CREDENTIALS); + if (creds != null) { + initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString()); + + } + } + // initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, + // "uid=admin,ou=system"); + // initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, + // "secret"); } catch (Exception e) { throw new UserDirectoryException("Cannot connect to LDAP", e); } @@ -77,6 +75,10 @@ public class LdapUserAdmin extends AbstractUserDirectory { } } + protected InitialLdapContext getLdapContext() { + return initialLdapContext; + } + @Override protected Boolean daoHasRole(LdapName dn) { return daoGetRole(dn) != null; @@ -85,222 +87,102 @@ public class LdapUserAdmin extends AbstractUserDirectory { @Override protected DirectoryUser daoGetRole(LdapName name) { try { - Attributes attrs = initialLdapContext.getAttributes(name); + Attributes attrs = getLdapContext().getAttributes(name); if (attrs.size() == 0) return null; LdifUser res; - if (attrs.get("objectClass").contains("groupOfNames")) + if (attrs.get(objectClass.name()).contains(getGroupObjectClass())) res = new LdifGroup(this, name, attrs); - else if (attrs.get("objectClass").contains("inetOrgPerson")) + else if (attrs.get(objectClass.name()).contains(getUserObjectClass())) res = new LdifUser(this, name, attrs); else - throw new UserDirectoryException("Unsupported LDAP type for " - + name); + throw new UserDirectoryException("Unsupported LDAP type for " + name); return res; } catch (NamingException e) { - throw new UserDirectoryException("Cannot get role for " + name, e); + return null; } } @Override protected List doGetRoles(Filter f) { - // TODO Auto-generated method stub try { String searchFilter = f != null ? f.toString() - : "(|(objectClass=inetOrgPerson)(objectClass=groupOfNames))"; + : "(|(" + objectClass + "=" + getUserObjectClass() + ")(" + objectClass + "=" + + getGroupObjectClass() + "))"; SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - String searchBase = baseDn; - NamingEnumeration results = initialLdapContext - .search(searchBase, searchFilter, searchControls); + LdapName searchBase = getBaseDn(); + NamingEnumeration results = getLdapContext().search(searchBase, searchFilter, searchControls); ArrayList res = new ArrayList(); - while (results.hasMoreElements()) { + results: while (results.hasMoreElements()) { SearchResult searchResult = results.next(); Attributes attrs = searchResult.getAttributes(); + Attribute objectClassAttr = attrs.get(objectClass.name()); + LdapName dn = toDn(searchBase, searchResult); 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()); + if (objectClassAttr.contains(getGroupObjectClass())) + role = new LdifGroup(this, dn, attrs); + else if (objectClassAttr.contains(getUserObjectClass())) + role = new LdifUser(this, dn, attrs); + else { + log.warn("Unsupported LDAP type for " + searchResult.getName()); + continue results; + } res.add(role); } return res; } catch (Exception e) { - throw new UserDirectoryException( - "Cannot get roles for filter " + f, 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); - } - + private LdapName toDn(LdapName baseDn, Binding binding) throws InvalidNameException { + return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName()); } @Override - public User getUser(String key, String value) { - if (key == null) { - List users = new ArrayList(); - for (String prop : getIndexedUserProperties()) { - User user = getUser(prop, value); - if (user != null) - users.add(user); - } - if (users.size() == 1) - return users.get(0); - else - return null; - } - + protected List getDirectGroups(LdapName dn) { + List directGroups = new ArrayList(); try { - String searchFilter = "(&(objectClass=inetOrgPerson)(" + key + "=" - + value + "))"; + String searchFilter = "(&(" + objectClass + "=" + getGroupObjectClass() + ")(" + getMemberAttributeId() + + "=" + dn + "))"; 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) - return null; - return new LdifUser(this, toDn(searchBase, searchResult), - searchResult.getAttributes()); - } catch (Exception e) { - throw new UserDirectoryException("Cannot get user with " + key - + "=" + value, e); - } - } - - private LdapName toDn(String baseDn, Binding binding) - throws InvalidNameException { - return new LdapName(binding.isRelative() ? binding.getName() + "," - + baseDn : binding.getName()); - } - - // 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() + "))"; - - SearchControls searchControls = new SearchControls(); - searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - - String searchBase = getGroupsSearchBase(); - NamingEnumeration results = initialLdapContext - .search(searchBase, searchFilter, searchControls); + LdapName searchBase = getBaseDn(); + NamingEnumeration results = getLdapContext().search(searchBase, searchFilter, searchControls); while (results.hasMoreElements()) { - SearchResult searchResult = (SearchResult) results - .nextElement(); - LdifGroup group = new LdifGroup(this, toDn(searchBase, - searchResult), searchResult.getAttributes()); - directGroups.add(group); + SearchResult searchResult = (SearchResult) results.nextElement(); + directGroups.add(toDn(searchBase, searchResult)); } return directGroups; } catch (Exception e) { - throw new ArgeoException("Cannot populate direct members of " - + user, e); + throw new UserDirectoryException("Cannot populate direct members of " + dn, e); } } - protected String getGroupsSearchBase() { - // TODO configure group search base - return baseDn; - } - @Override - protected void prepare(WorkingCopy wc) { + protected void prepare(UserDirectoryWorkingCopy wc) { try { - initialLdapContext.reconnect(initialLdapContext - .getConnectControls()); + getLdapContext().reconnect(getLdapContext().getConnectControls()); // delete for (LdapName dn : wc.getDeletedUsers().keySet()) { if (!entryExists(dn)) - throw new UserDirectoryException("User to delete no found " - + 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); + 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); + if (!wc.getNewUsers().containsKey(dn) && !entryExists(dn)) + throw new UserDirectoryException("User to modify not found " + dn); } } catch (NamingException e) { throw new UserDirectoryException("Cannot prepare LDAP", e); @@ -308,26 +190,29 @@ public class LdapUserAdmin extends AbstractUserDirectory { } private boolean entryExists(LdapName dn) throws NamingException { - return initialLdapContext.getAttributes(dn).size() != 0; + try { + return getLdapContext().getAttributes(dn).size() != 0; + } catch (NameNotFoundException e) { + return false; + } } @Override - protected void commit(WorkingCopy wc) { + protected void commit(UserDirectoryWorkingCopy wc) { try { // delete for (LdapName dn : wc.getDeletedUsers().keySet()) { - initialLdapContext.destroySubcontext(dn); + getLdapContext().destroySubcontext(dn); } // add for (LdapName dn : wc.getNewUsers().keySet()) { DirectoryUser user = wc.getNewUsers().get(dn); - initialLdapContext.createSubcontext(dn, user.getAttributes()); + getLdapContext().createSubcontext(dn, user.getAttributes()); } // modify for (LdapName dn : wc.getModifiedUsers().keySet()) { Attributes modifiedAttrs = wc.getModifiedUsers().get(dn); - initialLdapContext.modifyAttributes(dn, - DirContext.REPLACE_ATTRIBUTE, modifiedAttrs); + getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, modifiedAttrs); } } catch (NamingException e) { throw new UserDirectoryException("Cannot commit LDAP", e); @@ -335,9 +220,8 @@ public class LdapUserAdmin extends AbstractUserDirectory { } @Override - protected void rollback(WorkingCopy wc) { - // TODO Auto-generated method stub - super.rollback(wc); + protected void rollback(UserDirectoryWorkingCopy wc) { + // prepare not impacting } }