Multiple user referentials working with IPA.
[lgpl/argeo-commons.git] / org.argeo.util / src / org / argeo / util / directory / ldap / LdapDao.java
index c33b50f65fb9a1a781bb62de4535b63b25198c63..9157f23a4d8ad3033d91bd79bc6db2f24daddf4f 100644 (file)
@@ -13,22 +13,20 @@ import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
 import javax.naming.directory.SearchControls;
 import javax.naming.directory.SearchResult;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 
 import org.argeo.util.directory.HierarchyUnit;
+import org.argeo.util.naming.LdapAttrs;
 import org.argeo.util.naming.LdapObjs;
 
 /** A user admin based on a LDAP server. */
 public class LdapDao extends AbstractLdapDirectoryDao {
        private LdapConnection ldapConnection;
 
-//     public LdapUserAdmin(Dictionary<String, ?> properties) {
-//             this(properties, false);
-//     }
-
        public LdapDao(AbstractLdapDirectory directory) {
                super(directory);
        }
@@ -42,89 +40,87 @@ public class LdapDao extends AbstractLdapDirectoryDao {
                ldapConnection.destroy();
        }
 
-//     @Override
-//     protected AbstractUserDirectory scope(User user) {
-//             Dictionary<String, Object> credentials = user.getCredentials();
-//             String username = (String) credentials.get(SHARED_STATE_USERNAME);
-//             if (username == null)
-//                     username = user.getName();
-//             Dictionary<String, Object> properties = cloneProperties();
-//             properties.put(Context.SECURITY_PRINCIPAL, username.toString());
-//             Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
-//             byte[] pwd = (byte[]) pwdCred;
-//             if (pwd != null) {
-//                     char[] password = DirectoryDigestUtils.bytesToChars(pwd);
-//                     properties.put(Context.SECURITY_CREDENTIALS, new String(password));
-//             } else {
-//                     properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
-//             }
-//             return new LdapUserAdmin(properties, true);
-//     }
-
-//     protected InitialLdapContext getLdapContext() {
-//             return initialLdapContext;
-//     }
+       @Override
+       public boolean checkConnection() {
+               try {
+                       return ldapConnection.entryExists(getDirectory().getBaseDn());
+               } catch (NamingException e) {
+                       return false;
+               }
+       }
 
        @Override
-       public Boolean entryExists(LdapName dn) {
+       public boolean entryExists(LdapName dn) {
                try {
-                       return doGetEntry(dn) != null;
+                       return ldapConnection.entryExists(dn);
                } catch (NameNotFoundException e) {
                        return false;
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot check " + dn, e);
                }
        }
 
        @Override
        public LdapEntry doGetEntry(LdapName name) throws NameNotFoundException {
+//             if (!entryExists(name))
+//                     throw new NameNotFoundException(name + " was not found in " + getDirectory().getBaseDn());
                try {
                        Attributes attrs = ldapConnection.getAttributes(name);
-                       if (attrs.size() == 0)
-                               return null;
-//                     int roleType = roleType(name);
+
                        LdapEntry res;
                        Rdn technicalRdn = LdapNameUtils.getParentRdn(name);
-                       if (getDirectory().getGroupBaseRdn().equals(technicalRdn))
-                               res = newGroup(name, attrs);
-                       else if (getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
-                               res = newGroup(name, attrs);
-                       else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
-                               res = newUser(name, attrs);
-                       else
-                               res = new DefaultLdapEntry(getDirectory(), name, attrs);
-//                     if (isGroup(name))
-//                             res = newGroup(name, attrs);
-//                     else
-//                             res = newUser(name, attrs);
-//                     else
-//                             throw new IllegalArgumentException("Unsupported LDAP type for " + name);
+                       if (getDirectory().getGroupBaseRdn().equals(technicalRdn)) {
+                               if (attrs.size() == 0) {// exists but not accessible
+                                       attrs = new BasicAttributes();
+                                       attrs.put(LdapAttrs.objectClass.name(), LdapObjs.top.name());
+                                       attrs.put(LdapAttrs.objectClass.name(), getDirectory().getGroupObjectClass());
+                               }
+                               res = newGroup(name);
+                       } else if (getDirectory().getSystemRoleBaseRdn().equals(technicalRdn)) {
+                               if (attrs.size() == 0) {// exists but not accessible
+                                       attrs = new BasicAttributes();
+                                       attrs.put(LdapAttrs.objectClass.name(), LdapObjs.top.name());
+                                       attrs.put(LdapAttrs.objectClass.name(), getDirectory().getGroupObjectClass());
+                               }
+                               res = newGroup(name);
+                       } else if (getDirectory().getUserBaseRdn().equals(technicalRdn)) {
+                               if (attrs.size() == 0) {// exists but not accessible
+                                       attrs = new BasicAttributes();
+                                       attrs.put(LdapAttrs.objectClass.name(), LdapObjs.top.name());
+                                       attrs.put(LdapAttrs.objectClass.name(), getDirectory().getUserObjectClass());
+                               }
+                               res = newUser(name);
+                       } else {
+                               res = new DefaultLdapEntry(getDirectory(), name);
+                       }
                        return res;
                } catch (NameNotFoundException e) {
                        throw e;
                } catch (NamingException e) {
-                       return null;
+                       throw new IllegalStateException("Cannot retrieve entry " + name, e);
                }
        }
 
-//     protected boolean isGroup(LdapName dn) {
-//             Rdn technicalRdn = LdapNameUtils.getParentRdn(dn);
-//             if (getDirectory().getGroupBaseRdn().equals(technicalRdn)
-//                             || getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
-//                     return true;
-//             else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
-//                     return false;
-//             else
-//                     throw new IllegalArgumentException(
-//                                     "Cannot find role type, " + technicalRdn + " is not a technical RDN for " + dn);
-//     }
+       @Override
+       public Attributes doGetAttributes(LdapName name) {
+               try {
+                       Attributes attrs = ldapConnection.getAttributes(name);
+                       return attrs;
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot get attributes for " + name);
+               }
+       }
 
        @Override
        public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
                ArrayList<LdapEntry> res = new ArrayList<>();
                try {
                        String searchFilter = f != null ? f.toString()
-                                       : "(|(" + objectClass + "=" + getDirectory().getUserObjectClass() + ")(" + objectClass + "="
-                                                       + getDirectory().getGroupObjectClass() + "))";
+                                       : "(|(" + objectClass.name() + "=" + getDirectory().getUserObjectClass() + ")(" + objectClass.name()
+                                                       + "=" + getDirectory().getGroupObjectClass() + "))";
                        SearchControls searchControls = new SearchControls();
+                       // only attribute needed is objectClass
+                       searchControls.setReturningAttributes(new String[] { objectClass.name() });
                        // FIXME make one level consistent with deep
                        searchControls.setSearchScope(deep ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
 
@@ -139,10 +135,10 @@ public class LdapDao extends AbstractLdapDirectoryDao {
                                LdapEntry role;
                                if (objectClassAttr.contains(getDirectory().getGroupObjectClass())
                                                || objectClassAttr.contains(getDirectory().getGroupObjectClass().toLowerCase()))
-                                       role = newGroup(dn, attrs);
+                                       role = newGroup(dn);
                                else if (objectClassAttr.contains(getDirectory().getUserObjectClass())
                                                || objectClassAttr.contains(getDirectory().getUserObjectClass().toLowerCase()))
-                                       role = newUser(dn, attrs);
+                                       role = newUser(dn);
                                else {
 //                                     log.warn("Unsupported LDAP type for " + searchResult.getName());
                                        continue results;
@@ -217,21 +213,24 @@ public class LdapDao extends AbstractLdapDirectoryDao {
        public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
                List<HierarchyUnit> res = new ArrayList<>();
                try {
+                       String structuralFilter = functionalOnly ? ""
+                                       : "(" + getDirectory().getUserBaseRdn() + ")(" + getDirectory().getGroupBaseRdn() + ")("
+                                                       + getDirectory().getSystemRoleBaseRdn() + ")";
                        String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
-                                       + "=" + LdapObjs.organization.name() + "))";
-//                     String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
-//                                     + "=" + LdapObjs.organization.name() + ")(cn=accounts)(cn=users)(cn=groups))";
+                                       + "=" + LdapObjs.organization.name() + ")" + structuralFilter + ")";
 
                        SearchControls searchControls = new SearchControls();
                        searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+                       // no attributes needed
+                       searchControls.setReturningAttributes(new String[0]);
 
                        NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
 
                        while (results.hasMoreElements()) {
                                SearchResult searchResult = (SearchResult) results.nextElement();
                                LdapName dn = toDn(searchBase, searchResult);
-                               Attributes attrs = searchResult.getAttributes();
-                               LdapHierarchyUnit hierarchyUnit = new LdapHierarchyUnit(getDirectory(), dn, attrs);
+//                             Attributes attrs = searchResult.getAttributes();
+                               LdapHierarchyUnit hierarchyUnit = new LdapHierarchyUnit(getDirectory(), dn);
                                if (functionalOnly) {
                                        if (hierarchyUnit.isFunctional())
                                                res.add(hierarchyUnit);
@@ -252,8 +251,11 @@ public class LdapDao extends AbstractLdapDirectoryDao {
                                return getDirectory();
                        if (!dn.startsWith(getDirectory().getBaseDn()))
                                throw new IllegalArgumentException(dn + " does not start with base DN " + getDirectory().getBaseDn());
-                       Attributes attrs = ldapConnection.getAttributes(dn);
-                       return new LdapHierarchyUnit(getDirectory(), dn, attrs);
+                       if (!ldapConnection.entryExists(dn))
+                               return null;
+                       return new LdapHierarchyUnit(getDirectory(), dn);
+               } catch (NameNotFoundException e) {
+                       return null;
                } catch (NamingException e) {
                        throw new IllegalStateException("Cannot get hierarchy unit " + dn, e);
                }