From b4c3087d7a41cde4a9e92736882b450e51742bf7 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 2 Sep 2015 17:16:48 +0000 Subject: [PATCH 1/1] First tests with LDAP git-svn-id: https://svn.argeo.org/commons/trunk@8360 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../argeo/osgi/useradmin/LdapUserAdmin.java | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java 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 new file mode 100644 index 000000000..0173addbb --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java @@ -0,0 +1,197 @@ +package org.argeo.osgi.useradmin; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Context; +import javax.naming.InvalidNameException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.service.useradmin.Authorization; +import org.osgi.service.useradmin.Role; +import org.osgi.service.useradmin.User; +import org.osgi.service.useradmin.UserAdmin; + +public class LdapUserAdmin implements UserAdmin { + 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 { + 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("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"); + + 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")); + } catch (Exception e) { + throw new ArgeoUserAdminException("Cannot connect to LDAP", e); + } + } + + public void destroy() { + try { + // tls.close(); + initialLdapContext.close(); + } catch (NamingException e) { + log.error("Cannot destroy LDAP user admin", e); + } + } + + @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; + } + + @Override + public Role getRole(String name) { + try { + Attributes attrs = initialLdapContext.getAttributes(name); + LdifUser res; + if (attrs.get("objectClass").contains("groupOfNames")) + res = new LdifGroup(new LdapName(name), attrs); + else if (attrs.get("objectClass").contains("inetOrgPerson")) + res = new LdifUser(new LdapName(name), attrs); + else + throw new ArgeoUserAdminException("Unsupported LDAP type for " + + name); + return res; + } catch (NamingException e) { + throw new ArgeoUserAdminException("Cannot get role for " + name, e); + } + } + + @Override + public Role[] getRoles(String filter) throws InvalidSyntaxException { + // TODO Auto-generated method stub + return null; + } + + @Override + public User getUser(String key, String value) { + if (key == null) { + List users = new ArrayList(); + for (String prop : indexedUserProperties) { + User user = getUser(prop, value); + if (user != null) + users.add(user); + } + if (users.size() == 1) + return users.get(0); + else + return null; + } + + 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) + return null; + return new LdifUser(toDn(searchBase, searchResult), + searchResult.getAttributes()); + } catch (Exception e) { + throw new ArgeoUserAdminException("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) { + + 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); + } + } + +} -- 2.39.2