source code fix for bug 1095 -- honor the '-l' option
[tprouty/samba.git] / source / sam / idmap_ldap.c
index 4d75feca2ca5a6d33f27d81abbf503346e83fa77..2124fb687937583fba2985b2dcdc5aeb6e80f221 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    idmap LDAP backend
@@ -7,17 +7,17 @@
    Copyright (C) Jim McDonough <jmcd@us.ibm.com>       2003
    Copyright (C) Simo Sorce            2003
    Copyright (C) Gerald Carter                 2003
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 #include "smbldap.h"
 
-#define IDMAP_GROUP_SUFFIX     "ou=idmap group"
-#define IDMAP_USER_SUFFIX      "ou=idmap people"
-
-
 struct ldap_idmap_state {
        struct smbldap_state *smbldap_state;
        TALLOC_CTX *mem_ctx;
+};
 
-       uint32 low_allocated_user_rid;
-       uint32 high_allocated_user_rid;
-       uint32 low_allocated_group_rid;
-       uint32 high_allocated_group_rid;
+static struct ldap_idmap_state ldap_state;
 
-};
+/* number tries while allocating new id */
+#define LDAP_MAX_ALLOC_ID 128
 
-#define LDAP_MAX_ALLOC_ID 128              /* number tries while allocating
-                                             new id */
 
-static struct ldap_idmap_state ldap_state;
+/***********************************************************************
+ This function cannot be called to modify a mapping, only set a new one
+***********************************************************************/
+
+static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+{
+       pstring dn;
+       pstring id_str;
+       fstring type;
+       LDAPMod **mods = NULL;
+       int rc = -1;
+       int ldap_op;
+       fstring sid_string;
+       LDAPMessage *entry = NULL;
+
+       sid_to_string( sid_string, sid );
+
+       ldap_op = LDAP_MOD_ADD;
+       pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID),
+                sid_string, lp_ldap_idmap_suffix());
+
+       if ( id_type & ID_USERID )
+               fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) );
+       else
+               fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) );
+
+       pstr_sprintf(id_str, "%lu", ((id_type & ID_USERID) ? (unsigned long)id.uid :
+                                                (unsigned long)id.gid));       
+       
+       smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY );
+
+       smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, 
+                         entry, &mods, type, id_str );
+
+       smbldap_make_mod( ldap_state.smbldap_state->ldap_struct,
+                         entry, &mods,  
+                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), 
+                         sid_string );
+
+       /* There may well be nothing at all to do */
 
-static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type);
-static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, int id_type, 
-                                          const char *ldap_dn, LDAPMessage *entry);
-static NTSTATUS ldap_idmap_close(void);
+       if (mods) {
+               smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY );
+               rc = smbldap_add(ldap_state.smbldap_state, dn, mods);
+               ldap_mods_free( mods, True );   
+       } else {
+               rc = LDAP_SUCCESS;
+       }
 
+       if (rc != LDAP_SUCCESS) {
+               char *ld_error = NULL;
+               ldap_get_option(ldap_state.smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
+                               &ld_error);
+               DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %lu [%s]\n",
+                        (ldap_op == LDAP_MOD_ADD) ? "add" : "replace",
+                        sid_string, (unsigned long)((id_type & ID_USERID) ? id.uid : id.gid), type));
+               DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", 
+                       ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+               
+       DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
+               sid_string, ((id_type & ID_USERID) ? (unsigned long)id.uid : 
+                            (unsigned long)id.gid), type));
+
+       return NT_STATUS_OK;
+}
 
 /**********************************************************************
  Even if the sambaDomain attribute in LDAP tells us that this RID is 
@@ -83,7 +136,7 @@ static BOOL sid_in_use(struct ldap_idmap_state *state,
        if (rc != LDAP_SUCCESS) {
                char *ld_error = NULL;
                ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
-               DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n", 
+               DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
                          sid_string, ld_error));
                SAFE_FREE(ld_error);
 
@@ -110,6 +163,7 @@ static BOOL sid_in_use(struct ldap_idmap_state *state,
  This also checks that this RID is actually free - in case the admin
  manually stole it :-).
 *********************************************************************/
+
 static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, 
                               int rid_type)
 {
@@ -127,11 +181,9 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
        int attempts = 0;
        char *ld_error = NULL;
 
-       while (attempts < 10) 
-       {
+       while (attempts < 10) {
                if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state, 
-                       &domain_result, get_global_sam_name(), True))) 
-               {
+                               &domain_result, get_global_sam_name(), True))) {
                        return ret;
                }
        
@@ -142,20 +194,19 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                        return ret;
                }
 
-               if ((dn = ldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) {
+               if ((dn = smbldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) {
                        DEBUG(0, ("Could not get domain info DN\n"));
                        ldap_msgfree(domain_result);
                        return ret;
                }
 
                /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and 
-                  algorithmic_rid_base.  The other two are to avoid stomping on the 
+                  algorithmic_rid_base.  The other two are to avoid stomping on the
                   different sets of algorithmic RIDs */
                
-               if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry,
+               if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
                                         get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
-                                        algorithmic_rid_base_string)) 
-               {
+                                        algorithmic_rid_base_string)) {
                        
                        alg_rid_base = (uint32)atol(algorithmic_rid_base_string);
                } else {
@@ -173,10 +224,9 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                if (alg_rid_base > BASE_RID) {
                        /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we 
                           can allocate to new users */
-                       if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry,
+                       if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
                                                 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
-                                                old_rid_string)) 
-                       {
+                                                old_rid_string)) {
                                *rid = (uint32)atol(old_rid_string);
                        } else {
                                *rid = BASE_RID;
@@ -184,6 +234,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
 
                        next_rid = *rid+1;
                        if (next_rid >= alg_rid_base) {
+                               ldap_msgfree(domain_result);
                                return NT_STATUS_UNSUCCESSFUL;
                        }
                        
@@ -199,25 +250,17 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                if (!next_rid) { /* not got one already */
                        switch (rid_type) {
                        case USER_RID_TYPE:
-                               if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry,
+                               if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
                                                         get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
-                                                        old_rid_string)) 
-                               {
-                                       
-                                       *rid = (uint32)atol(old_rid_string);
-                                       
-                               } else {
-                                       *rid = state->low_allocated_user_rid;
+                                                        old_rid_string)) {
+                                       *rid = (uint32)atol(old_rid_string);                                    
                                }
                                break;
                        case GROUP_RID_TYPE:
-                               if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, 
+                               if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry, 
                                                         get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
-                                                        old_rid_string)) 
-                               {
+                                                        old_rid_string)) {
                                        *rid = (uint32)atol(old_rid_string);
-                               } else {
-                                       *rid = state->low_allocated_group_rid;
                                }
                                break;
                        }
@@ -231,10 +274,6 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                        
                        switch (rid_type) {
                        case USER_RID_TYPE:
-                               if (next_rid > state->high_allocated_user_rid) {
-                                       return NT_STATUS_UNSUCCESSFUL;
-                               }
-                               
                                /* Try to make the modification atomically by enforcing the
                                   old value in the delete mod. */
                                smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 
@@ -243,10 +282,6 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                                break;
                                
                        case GROUP_RID_TYPE:
-                               if (next_rid > state->high_allocated_group_rid) {
-                                       return NT_STATUS_UNSUCCESSFUL;
-                               }
-                               
                                /* Try to make the modification atomically by enforcing the
                                   old value in the delete mod. */
                                smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
@@ -256,32 +291,31 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                        }
                }
 
-               if ((rc = ldap_modify_s(state->smbldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
+               if ((rc = smbldap_modify(state->smbldap_state, dn, mods)) == LDAP_SUCCESS) {
                        DOM_SID dom_sid;
                        DOM_SID sid;
                        pstring domain_sid_string;
                        int error = 0;
 
-                       if (!smbldap_get_single_attribute(state->smbldap_state->ldap_struct, domain_result,
-                               get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
-                               domain_sid_string)) 
-                       {
+                       if (!smbldap_get_single_pstring(state->smbldap_state->ldap_struct, domain_result,
+                                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
+                                       domain_sid_string)) {
                                ldap_mods_free(mods, True);
-                               ldap_memfree(dn);
+                               SAFE_FREE(dn);
                                ldap_msgfree(domain_result);
                                return ret;
                        }
 
                        if (!string_to_sid(&dom_sid, domain_sid_string)) { 
                                ldap_mods_free(mods, True);
-                               ldap_memfree(dn);
+                               SAFE_FREE(dn);
                                ldap_msgfree(domain_result);
                                return ret;
                        }
 
                        ldap_mods_free(mods, True);
                        mods = NULL;
-                       ldap_memfree(dn);
+                       SAFE_FREE(dn);
                        ldap_msgfree(domain_result);
 
                        sid_copy(&sid, &dom_sid);
@@ -306,8 +340,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                ldap_mods_free(mods, True);
                mods = NULL;
 
-               ldap_memfree(dn);
-               dn = NULL;
+               SAFE_FREE(dn);
 
                ldap_msgfree(domain_result);
                domain_result = NULL;
@@ -318,7 +351,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
                        attempts += 1;
                        
                        sleeptime %= 100;
-                       msleep(sleeptime);
+                       smb_msleep(sleeptime);
                }
        }
 
@@ -350,7 +383,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        pstring id_str, new_id_str;
        LDAPMod **mods = NULL;
        const char *type;
-       char *dn;
+       char *dn = NULL;
        char **attr_list;
        pstring filter;
        uid_t   luid, huid;
@@ -364,7 +397,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        pstr_sprintf(filter, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 
        attr_list = get_attr_list( idpool_attr_list );
-       
+
        rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
                               LDAP_SCOPE_SUBTREE, filter,
                               attr_list, 0, &result);
@@ -381,10 +414,13 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
                goto out;
        }
 
-       dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
+       dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
+       if (!dn) {
+               goto out;
+       }
        entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
 
-       if (!smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) {
+       if (!smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) {
                DEBUG(0,("ldap_allocate_id: %s attribute not found\n",
                         type));
                goto out;
@@ -420,12 +456,15 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
                 
        smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str );                 
        smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str );
-       
-       rc = ldap_modify_s(ldap_state.smbldap_state->ldap_struct, dn, mods);
 
-       ldap_memfree(dn);
+       if (mods == NULL) {
+               DEBUG(0,("ldap_allocate_id: smbldap_set_mod() failed.\n"));
+               goto out;               
+       }
+
+       rc = smbldap_modify(ldap_state.smbldap_state, dn, mods);
+
        ldap_mods_free( mods, True );
-       
        if (rc != LDAP_SUCCESS) {
                DEBUG(0,("ldap_allocate_id: Failed to allocate new %s.  ldap_modify() failed.\n",
                        type));
@@ -434,6 +473,10 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        
        ret = NT_STATUS_OK;
 out:
+       SAFE_FREE(dn);
+       if (result != NULL)
+               ldap_msgfree(result);
+
        return ret;
 }
 
@@ -445,67 +488,37 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
 {
        LDAPMessage *result = NULL;
        LDAPMessage *entry = NULL;
-       fstring id_str;
        pstring sid_str;
        pstring filter;
        pstring suffix;
        const char *type;
-       const char *obj_class;
        int rc;
        int count;
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        char **attr_list;
 
-       /* first we try for a samba user or group mapping */
-       
-       if ( id_type & ID_USERID ) {
+       if ( id_type & ID_USERID ) 
                type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
-               obj_class = LDAP_OBJ_SAMBASAMACCOUNT;
-               fstr_sprintf(id_str, "%lu", (unsigned long)id.uid );    
-               pstrcpy( suffix, lp_ldap_suffix());
-       }
-       else {
+       else 
                type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
-               obj_class = LDAP_OBJ_GROUPMAP;
-               fstr_sprintf(id_str, "%lu", (unsigned long)id.gid );    
-               pstrcpy( suffix, lp_ldap_group_suffix() );
-       }
-                
-       attr_list = get_attr_list( sidmap_attr_list );
-       pstr_sprintf(filter, "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", 
-                LDAP_OBJ_IDMAP_ENTRY, obj_class, type, id_str);
 
+       pstrcpy( suffix, lp_ldap_idmap_suffix() );
+       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
+               LDAP_OBJ_IDMAP_ENTRY, type,  
+               ((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid));
+               
+       attr_list = get_attr_list( sidmap_attr_list );
        rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
-                           filter, attr_list, 0, &result);
-       
-       if (rc != LDAP_SUCCESS) 
+               filter, attr_list, 0, &result);
+
+       if (rc != LDAP_SUCCESS) {
+               DEBUG(3,("ldap_get_isd_from_id: Failure looking up entry (%s)\n",
+                       ldap_err2string(rc) ));
                goto out;
-          
+       }
+                          
        count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
 
-       /* fall back to looking up an idmap entry if we didn't find and 
-          actual user or group */
-       
-       if (count == 0) {
-               ldap_msgfree(result);
-               result = NULL;
-               
-               pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
-                       LDAP_OBJ_IDMAP_ENTRY, type,  
-                        ((id_type & ID_USERID) ? (unsigned long)id.uid : 
-                         (unsigned long)id.gid));
-
-               pstrcpy( suffix, lp_ldap_idmap_suffix() );
-
-               rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
-                       filter, attr_list, 0, &result);
-
-               if (rc != LDAP_SUCCESS)
-                          goto out;
-                          
-               count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
-       }
-       
        if (count != 1) {
                DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %lu\n", 
                        type, ((id_type & ID_USERID) ? (unsigned long)id.uid : 
@@ -515,10 +528,10 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
        
        entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
        
-       if ( !smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) )
+       if ( !smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) )
                goto out;
           
-       if (!string_to_sid(sid, sid_str)) 
+       if (!string_to_sid(sid, sid_str))
                goto out;
 
        ret = NT_STATUS_OK;
@@ -544,99 +557,61 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
        pstring id_str;
        const char *suffix;     
        const char *type;
-       const char *obj_class;
-       const char *posix_obj_class;
        int rc;
        int count;
        char **attr_list;
        char *dn = NULL;
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
-       /* first try getting the mapping from a samba user or group */
-       
        sid_to_string(sid_str, sid);
-       if ( *id_type & ID_USERID ) {
-               type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER );
-               obj_class = LDAP_OBJ_SAMBASAMACCOUNT;
-               posix_obj_class = LDAP_OBJ_POSIXACCOUNT;
-               suffix = lp_ldap_suffix();
-               pstr_sprintf(filter, "(&(|(&(objectClass=%s)(objectClass=%s))(objectClass=%s))(%s=%s))", 
-                        obj_class, posix_obj_class, LDAP_OBJ_IDMAP_ENTRY, 
-                        get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), 
-                        sid_str);
-       }
-       else {
+
+       DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_str,
+               (*id_type & ID_GROUPID ? "group" : "user") ));
+
+       suffix = lp_ldap_idmap_suffix();
+       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 
+               LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str);
+                       
+       if ( *id_type & ID_GROUPID ) 
                type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER );
-               obj_class = LDAP_OBJ_GROUPMAP;
-               posix_obj_class = LDAP_OBJ_POSIXGROUP;
-               suffix = lp_ldap_group_suffix();
-               pstr_sprintf(filter, "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", 
-                        obj_class, LDAP_OBJ_IDMAP_ENTRY, 
-                        get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), 
-                        sid_str);
-       }
-          
+       else 
+               type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER );
+
+       /* do the search and check for errors */
+
        attr_list = get_attr_list( sidmap_attr_list );
        rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
                filter, attr_list, 0, &result);
-               
-       if (rc != LDAP_SUCCESS)
+                       
+       if (rc != LDAP_SUCCESS) {
+               DEBUG(3,("ldap_get_id_from_sid: Failure looking up idmap entry (%s)\n",
+                       ldap_err2string(rc) ));
                goto out;
+       }
+                       
+       /* check for the number of entries returned */
 
        count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
-       
-       /* fall back to looking up an idmap entry if we didn't find anything under the idmap
-          user or group suffix */
-
-       if (count == 0) {
-               ldap_msgfree(result);
-               
-               pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 
-                       LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str);
-
-               suffix = lp_ldap_idmap_suffix();
-
-               rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
-                       filter, attr_list, 0, &result);
-                       
-               if (rc != LDAP_SUCCESS)
-                       goto out;
-                       
-               count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
-       }
           
        if ( count > 1 ) {
-               DEBUG(0, ("ldap_get_id_from_sid: search %s returned more than on entry!\n",
-                       filter));
+               DEBUG(0, ("ldap_get_id_from_sid: (2nd) search %s returned [%d] entries!\n",
+                       filter, count));
                goto out;
        }
-
-       /* we might have an existing entry to work with so pull out the requested information */
-       
-       if ( count ) {
-               entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
        
-               dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
-               DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type));
-               
-               if ( smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) 
-               {
-                       if ( (*id_type & ID_USERID) )
-                               id->uid = strtoul(id_str, NULL, 10);
-                       else
-                               id->gid = strtoul(id_str, NULL, 10);
-                       
-                       ret = NT_STATUS_OK;
+       /* try to allocate a new id if we still haven't found one */
+
+       if ( !count ) {
+               int i;
+
+               if (*id_type & ID_QUERY_ONLY) {
+                       DEBUG(5,("ldap_get_id_from_sid: No matching entry found and QUERY_ONLY flag set\n"));
                        goto out;
                }
-       }
-       
-       if (!(*id_type & ID_QUERY_ONLY)) {
-               /* if entry == NULL, and we are asked to - allocate a new id */
-               int i;
+
+               DEBUG(8,("ldap_get_id_from_sid: Allocating new id\n"));
                
-               for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) 
-               {
+               for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) {
                        ret = ldap_allocate_id(id, *id_type);
                        if ( NT_STATUS_IS_OK(ret) )
                                break;
@@ -646,224 +621,51 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
                        DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n"));
                        goto out;
                }
-               
-               ret = ldap_set_mapping(sid, *id, *id_type);
-       } else {
-               /* no match, and not adding one */
-               ret = NT_STATUS_UNSUCCESSFUL;
-       }
 
-out:
-       free_attr_list( attr_list );
-       if (result)
-               ldap_msgfree(result);
-       if (dn)
-               ldap_memfree(dn);
+               DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n",
+                       (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid ));
        
-       return ret;
-}
-
-/***********************************************************************
- This function cannot be called to modify a mapping, only set a new one 
-
- This takes a possible pointer to the existing entry for the UID or SID
- involved.
-***********************************************************************/
-
-static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, 
-                                          int id_type, const char *ldap_dn, 
-                                          LDAPMessage *entry)
-{
-       pstring dn; 
-       pstring id_str;
-       fstring type;
-       LDAPMod **mods = NULL;
-       int rc = -1;
-       int ldap_op;
-       fstring sid_string;
-       char **values = NULL;
-       int i;
-
-       sid_to_string( sid_string, sid );
-
-       if (ldap_dn) {
-               DEBUG(10, ("Adding new IDMAP mapping on DN: %s", ldap_dn));
-               ldap_op = LDAP_MOD_REPLACE;
-               pstrcpy( dn, ldap_dn );
-       } else {
-               ldap_op = LDAP_MOD_ADD;
-               pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID), 
-                        sid_string, lp_ldap_idmap_suffix());
-       }
-       
-       if ( id_type & ID_USERID ) 
-               fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) );
-       else
-               fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) );
-
-       pstr_sprintf(id_str, "%lu", ((id_type & ID_USERID) ? (unsigned long)id.uid : 
-                                                (unsigned long)id.gid));       
-       
-       if (entry) 
-               values = ldap_get_values(ldap_state.smbldap_state->ldap_struct, entry, "objectClass");
-
-       if (values) {
-               BOOL found_idmap = False;
-               for (i=0; values[i]; i++) {
-                       if (StrCaseCmp(values[i], LDAP_OBJ_IDMAP_ENTRY) == 0) {
-                               found_idmap = True;
-                               break;
-                       }
-               }
-               if (!found_idmap)
-                       smbldap_set_mod( &mods, LDAP_MOD_ADD, 
-                                        "objectClass", LDAP_OBJ_IDMAP_ENTRY );
-       } else {
-               smbldap_set_mod( &mods, LDAP_MOD_ADD, 
-                                "objectClass", LDAP_OBJ_IDMAP_ENTRY );
-       }
-
-       smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, 
-                         entry, &mods, type, id_str );
-
-       smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, 
-                         entry, &mods,  
-                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), 
-                         sid_string );
+               ret = ldap_set_mapping(sid, *id, *id_type);
 
-       /* There may well be nothing at all to do */
-       if (mods) {
-               switch(ldap_op)
-               {
-               case LDAP_MOD_ADD: 
-                       smbldap_set_mod( &mods, LDAP_MOD_ADD, 
-                                        "objectClass", LDAP_OBJ_SID_ENTRY );
-                       rc = smbldap_add(ldap_state.smbldap_state, dn, mods);
-                       break;
-               case LDAP_MOD_REPLACE: 
-                       rc = smbldap_modify(ldap_state.smbldap_state, dn, mods);
-                       break;
-               }
-               
-               ldap_mods_free( mods, True );   
-       } else {
-               rc = LDAP_SUCCESS;
-       }
+               /* all done */
 
-       if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state.smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %lu [%s]\n",
-                        (ldap_op == LDAP_MOD_ADD) ? "add" : "replace",
-                        sid_string, (unsigned long)((id_type & ID_USERID) ? id.uid : id.gid), type));
-               DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
-               return NT_STATUS_UNSUCCESSFUL;
+               goto out;
        }
-               
-       DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
-               sid_string, ((id_type & ID_USERID) ? (unsigned long)id.uid : 
-                            (unsigned long)id.gid), type));
-
-       return NT_STATUS_OK;
-}
 
-/***********************************************************************
- This function cannot be called to modify a mapping, only set a new one 
-***********************************************************************/
-
-static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) 
-{
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       char *dn = NULL;
-       LDAPMessage *result = NULL;
-       LDAPMessage *entry = NULL;
-       const char *type;
-       const char *obj_class;
-       const char *posix_obj_class;
-       const char *suffix;
-       fstring sid_str;
-       fstring id_str;
-       pstring filter;
-       char **attr_list;
-       int rc;
-       int count;
+       DEBUG(10,("ldap_get_id_from_sid: success\n"));
 
-       /* try for a samba user or group mapping (looking for an entry with a SID) */
-       if ( id_type & ID_USERID ) {
-               obj_class = LDAP_OBJ_SAMBASAMACCOUNT;
-               suffix = lp_ldap_suffix();
-               type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
-               posix_obj_class = LDAP_OBJ_POSIXACCOUNT;
-               fstr_sprintf(id_str, "%lu", (unsigned long)id.uid );    
-       }
-       else {
-               obj_class = LDAP_OBJ_GROUPMAP;
-               suffix = lp_ldap_group_suffix();
-               type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
-               posix_obj_class = LDAP_OBJ_POSIXGROUP;
-               fstr_sprintf(id_str, "%lu", (unsigned long)id.gid );    
-       }
-       
-       sid_to_string(sid_str, sid);
-       pstr_sprintf(filter, 
-                "(|"
-                "(&(|(objectClass=%s)(|(objectClass=%s)(objectClass=%s)))(%s=%s))"
-                "(&(objectClass=%s)(%s=%s))"
-                ")", 
-                /* objectClasses that might contain a SID */
-                LDAP_OBJ_SID_ENTRY, LDAP_OBJ_IDMAP_ENTRY, obj_class, 
-                get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), 
-                sid_str, 
-
-                /* objectClasses that might contain a Unix UID/GID */
-                posix_obj_class, 
-                /* Unix UID/GID specifier*/
-                type, 
-                /* actual ID */
-                id_str);
-
-       attr_list = get_attr_list( sidmap_attr_list );
-       rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
-                           filter, attr_list, 0, &result);
-       free_attr_list( attr_list );
+       entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
        
-       if (rc != LDAP_SUCCESS)
+       dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
+       if (!dn)
                goto out;
 
-       count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
-       
-       /* fall back to looking up an idmap entry if we didn't find anything under the idmap
-          user or group suffix */
-
-       if (count == 1) {
-               entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
-       
-               dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
-               DEBUG(10, ("Found partial mapping entry at dn=%s, looking for %s\n", dn, type));
-
-               ret = ldap_set_mapping_internals(sid, id, id_type, dn, entry);
-
-               goto out;
-       } else if (count > 1) {
-               DEBUG(0, ("Too many entries trying to find DN to attach ldap \n"));
+       DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type));
+               
+       if ( smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) {
+               if ( (*id_type & ID_USERID) )
+                       id->uid = strtoul(id_str, NULL, 10);
+               else
+                       id->gid = strtoul(id_str, NULL, 10);
+               
+               ret = NT_STATUS_OK;
                goto out;
        }
-
-       ret = ldap_set_mapping_internals(sid, id, id_type, NULL, NULL);
-
+       
 out:
+       free_attr_list( attr_list );
        if (result)
                ldap_msgfree(result);
-       if (dn)
-               ldap_memfree(dn);
+       SAFE_FREE(dn);
        
        return ret;
 }
-/*****************************************************************************
- Initialise idmap database. 
-*****************************************************************************/
-static NTSTATUS ldap_idmap_init( char *params )
+
+/**********************************************************************
+ Verify the sambaUnixIdPool entry in the directiry.  
+**********************************************************************/
+
+static NTSTATUS verify_idpool( void )
 {
        fstring filter;
        int rc;
@@ -871,22 +673,6 @@ static NTSTATUS ldap_idmap_init( char *params )
        LDAPMessage *result = NULL;
        LDAPMod **mods = NULL;
        int count;
-       NTSTATUS nt_status;
-
-       ldap_state.mem_ctx = talloc_init("idmap_ldap");
-       if (!ldap_state.mem_ctx) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* assume location is the only parameter */
-       if (!NT_STATUS_IS_OK(nt_status = 
-                            smbldap_init(ldap_state.mem_ctx, params, 
-                                         &ldap_state.smbldap_state))) {
-               talloc_destroy(ldap_state.mem_ctx);
-               return nt_status;
-       }
-
-       /* see if the idmap suffix and sub entries exists */
        
        fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL );
        
@@ -900,6 +686,8 @@ static NTSTATUS ldap_idmap_init( char *params )
 
        count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
 
+       ldap_msgfree(result);
+
        if ( count > 1 ) {
                DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n",
                        filter, lp_ldap_idmap_suffix() ));
@@ -926,7 +714,37 @@ static NTSTATUS ldap_idmap_init( char *params )
                
                rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods);
        }
+
+       return ( rc==LDAP_SUCCESS ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+}
+
+/*****************************************************************************
+ Initialise idmap database. 
+*****************************************************************************/
+
+static NTSTATUS ldap_idmap_init( char *params )
+{
+       NTSTATUS nt_status;
+
+       ldap_state.mem_ctx = talloc_init("idmap_ldap");
+       if (!ldap_state.mem_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* assume location is the only parameter */
+       if (!NT_STATUS_IS_OK(nt_status = 
+                            smbldap_init(ldap_state.mem_ctx, params, 
+                                         &ldap_state.smbldap_state))) {
+               talloc_destroy(ldap_state.mem_ctx);
+               return nt_status;
+       }
+
+       /* see if the idmap suffix and sub entries exists */
        
+       nt_status = verify_idpool();    
+       if ( !NT_STATUS_IS_OK(nt_status) )
+               return nt_status;
+               
        return NT_STATUS_OK;
 }