Implement 389 DS's PBKDF2_SHA256 password scheme.
[lgpl/argeo-commons.git] / org.argeo.enterprise / src / org / argeo / osgi / useradmin / LdapUserAdmin.java
index 000cfab0c623e26aae86f5ffd81cc2bb6ae50e7c..22c178ef473916f6597ab471d8f69dd7dbb36b7a 100644 (file)
@@ -22,10 +22,9 @@ import javax.naming.ldap.InitialLdapContext;
 import javax.naming.ldap.LdapName;
 import javax.transaction.TransactionManager;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.argeo.naming.LdapAttrs;
 import org.osgi.framework.Filter;
+import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
 
 /**
@@ -33,12 +32,13 @@ import org.osgi.service.useradmin.User;
  * and an open transaction for write access.
  */
 public class LdapUserAdmin extends AbstractUserDirectory {
-       private final static Log log = LogFactory.getLog(LdapUserAdmin.class);
-
        private InitialLdapContext initialLdapContext = null;
 
+//     private LdapName adminUserDn = null;
+//     private LdifUser adminUser = null;
+
        public LdapUserAdmin(Dictionary<String, ?> properties) {
-               super(properties);
+               super(null, properties);
                try {
                        Hashtable<String, Object> connEnv = new Hashtable<String, Object>();
                        connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
@@ -49,20 +49,24 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                        // StartTlsResponse tls = (StartTlsResponse) ctx
                        // .extendedOperation(new StartTlsRequest());
                        // tls.negotiate();
-                       initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
+                       Object securityAuthentication = properties.get(Context.SECURITY_AUTHENTICATION);
+                       if (securityAuthentication != null)
+                               initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, securityAuthentication);
+                       else
+                               initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
                        Object principal = properties.get(Context.SECURITY_PRINCIPAL);
                        if (principal != null) {
                                initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, principal.toString());
+//                             adminUserDn = new LdapName(principal.toString());
+//                             BasicAttributes adminUserAttrs = new BasicAttributes();
+//                             adminUser = new LdifUser(this, adminUserDn, adminUserAttrs);
                                Object creds = properties.get(Context.SECURITY_CREDENTIALS);
                                if (creds != null) {
                                        initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString());
-
+//                                     adminUserAttrs.put(LdapAttrs.userPassword.name(), adminUser.hash(creds.toString().toCharArray()));
                                }
+//                             adminUserAttrs.put(LdapAttrs.memberOf.name(), "cn=admin,ou=roles,ou=node");
                        }
-                       // 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);
                }
@@ -73,22 +77,26 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                        // tls.close();
                        initialLdapContext.close();
                } catch (NamingException e) {
-                       log.error("Cannot destroy LDAP user admin", e);
+                       e.printStackTrace();
                }
        }
-       
-       
 
-       @SuppressWarnings("unchecked")
        @Override
        protected AbstractUserDirectory scope(User user) {
                Dictionary<String, Object> credentials = user.getCredentials();
-               // FIXME use arrays
-               Object usernameObj =    credentials.get(SHARED_STATE_USERNAME);
-               Object passwordObj =    credentials.get(SHARED_STATE_PASSWORD);
+               String username = (String) credentials.get(SHARED_STATE_USERNAME);
+               if (username == null)
+                       username = user.getName();
                Dictionary<String, Object> properties = cloneProperties();
-               properties.put(Context.SECURITY_PRINCIPAL, usernameObj.toString());
-               properties.put(Context.SECURITY_CREDENTIALS, passwordObj.toString());
+               properties.put(Context.SECURITY_PRINCIPAL, username.toString());
+               Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
+               byte[] pwd = (byte[]) pwdCred;
+               if (pwd != null) {
+                       char[] password = DigestUtils.bytesToChars(pwd);
+                       properties.put(Context.SECURITY_CREDENTIALS, new String(password));
+               } else {
+                       properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
+               }
                return new LdapUserAdmin(properties);
        }
 
@@ -98,23 +106,33 @@ public class LdapUserAdmin extends AbstractUserDirectory {
 
        @Override
        protected Boolean daoHasRole(LdapName dn) {
-               return daoGetRole(dn) != null;
+               try {
+                       return daoGetRole(dn) != null;
+               } catch (NameNotFoundException e) {
+                       return false;
+               }
        }
 
        @Override
-       protected DirectoryUser daoGetRole(LdapName name) {
+       protected DirectoryUser daoGetRole(LdapName name) throws NameNotFoundException {
                try {
                        Attributes attrs = getLdapContext().getAttributes(name);
                        if (attrs.size() == 0)
                                return null;
+                       int roleType = roleType(name);
                        LdifUser res;
-                       if (attrs.get(objectClass.name()).contains(getGroupObjectClass()))
+                       if (roleType == Role.GROUP)
                                res = new LdifGroup(this, name, attrs);
-                       else if (attrs.get(objectClass.name()).contains(getUserObjectClass()))
+                       else if (roleType == Role.USER)
                                res = new LdifUser(this, name, attrs);
                        else
                                throw new UserDirectoryException("Unsupported LDAP type for " + name);
                        return res;
+               } catch (NameNotFoundException e) {
+//                     if (adminUserDn != null && adminUserDn.equals(name)) {
+//                             return adminUser;
+//                     }
+                       throw e;
                } catch (NamingException e) {
                        return null;
                }
@@ -122,6 +140,7 @@ public class LdapUserAdmin extends AbstractUserDirectory {
 
        @Override
        protected List<DirectoryUser> doGetRoles(Filter f) {
+               ArrayList<DirectoryUser> res = new ArrayList<DirectoryUser>();
                try {
                        String searchFilter = f != null ? f.toString()
                                        : "(|(" + objectClass + "=" + getUserObjectClass() + ")(" + objectClass + "="
@@ -132,24 +151,27 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                        LdapName searchBase = getBaseDn();
                        NamingEnumeration<SearchResult> results = getLdapContext().search(searchBase, searchFilter, searchControls);
 
-                       ArrayList<DirectoryUser> res = new ArrayList<DirectoryUser>();
                        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 (objectClassAttr.contains(getGroupObjectClass()))
+                               if (objectClassAttr.contains(getGroupObjectClass())
+                                               || objectClassAttr.contains(getGroupObjectClass().toLowerCase()))
                                        role = new LdifGroup(this, dn, attrs);
-                               else if (objectClassAttr.contains(getUserObjectClass()))
+                               else if (objectClassAttr.contains(getUserObjectClass())
+                                               || objectClassAttr.contains(getUserObjectClass().toLowerCase()))
                                        role = new LdifUser(this, dn, attrs);
                                else {
-                                       log.warn("Unsupported LDAP type for " + searchResult.getName());
+//                                     log.warn("Unsupported LDAP type for " + searchResult.getName());
                                        continue results;
                                }
                                res.add(role);
                        }
                        return res;
+//             } catch (NameNotFoundException e) {
+//                     return res;
                } catch (Exception e) {
                        throw new UserDirectoryException("Cannot get roles for filter " + f, e);
                }