diff -ru source/sam.orig/idmap.c source/sam/idmap.c --- source/sam.orig/idmap.c Wed Mar 24 22:33:34 2004 +++ source/sam/idmap.c Wed Mar 24 22:21:45 2004 @@ -253,17 +253,60 @@ } /************************************************************************** + Returns true if the specified ID exists in idmap or the local system. +**************************************************************************/ + +BOOL idmap_id_exists(unid_t id, int id_type) +{ + DOM_SID sid; + BOOL exists; + unsigned long ul_id = (unsigned long) ((id_type & ID_USERID) ? id.uid : id.gid); + + DEBUG(1,("idmap_id_exists: Checking if %s %u exists.\n", + ((id_type & ID_USERID) ? "uid" : "gid"), ul_id)); + + sid.sid_rev_num = 0; + + exists = NT_STATUS_IS_OK(idmap_get_sid_from_id(&sid, id, id_type)) + || sid.sid_rev_num; + + if (exists) { + DEBUG(1,("idmap_id_exists: %s %u exists in idmap mapping.\n", + ((id_type & ID_USERID) ? "uid" : "gid"), ul_id)); + } + else { + exists = (((id_type & ID_TYPEMASK) == ID_USERID) + ? getpwuid(id.uid) != NULL + : getgrgid(id.gid) != NULL); + + if (exists) { + DEBUG(1,("idmap_id_exists: %s %u exists in local filesystem.\n", + ((id_type & ID_USERID) ? "uid" : "gid"), ul_id)); + } + } + + return exists; +} + +/************************************************************************** Alloocate a new UNIX uid/gid **************************************************************************/ NTSTATUS idmap_allocate_id(unid_t *id, int id_type) { - /* we have to allocate from the authoritative backend */ - - if ( remote_map ) - return remote_map->allocate_id( id, id_type ); + NTSTATUS status; + + /* loop to find an unused id in the idmap range */ + do { + /* we have to allocate from the authoritative backend */ + if ( remote_map ) + status = remote_map->allocate_id( id, id_type ); + else + status = cache_map->allocate_id( id, id_type ); + + } while (NT_STATUS_IS_OK(status) && idmap_id_exists(*id, id_type)); - return cache_map->allocate_id( id, id_type ); + return status; } /************************************************************************** diff -ru source/sam.orig/idmap_ldap.c source/sam/idmap_ldap.c --- source/sam.orig/idmap_ldap.c Wed Mar 24 22:33:34 2004 +++ source/sam/idmap_ldap.c Wed Mar 24 22:21:45 2004 @@ -398,81 +398,88 @@ 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); - free_attr_list( attr_list ); - - if (rc != LDAP_SUCCESS) { - DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL)); - goto out; - } - - count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); - if (count != 1) { - DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL)); - goto out; - } - - 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)) { - DEBUG(0,("ldap_allocate_id: %s attribute not found\n", - type)); - goto out; - } - - /* this must succeed or else we wouldn't have initialized */ + do + { + result = NULL; + mods = NULL; + rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) { + DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL)); + goto out; + } - lp_idmap_uid( &luid, &huid); - lp_idmap_gid( &lgid, &hgid); - - /* make sure we still have room to grow */ + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); + if (count != 1) { + DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL)); + goto out; + } - if (id_type & ID_USERID) { - id->uid = strtoul(id_str, NULL, 10); - if (id->uid > huid ) { - DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n", - (unsigned long)huid)); + dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + if (!dn) { goto out; } - } - else { - id->gid = strtoul(id_str, NULL, 10); - if (id->gid > hgid ) { - DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n", - (unsigned long)hgid)); + 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)) { + DEBUG(0,("ldap_allocate_id: %s attribute not found\n", + type)); goto out; } - } - pstr_sprintf(new_id_str, "%lu", - ((id_type & ID_USERID) ? (unsigned long)id->uid : - (unsigned long)id->gid) + 1); + /* this must succeed or else we wouldn't have initialized */ + + lp_idmap_uid( &luid, &huid); + lp_idmap_gid( &lgid, &hgid); + + /* make sure we still have room to grow */ + + if (id_type & ID_USERID) { + id->uid = strtoul(id_str, NULL, 10); + if (id->uid > huid ) { + DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n", + (unsigned long)huid)); + goto out; + } + } + else { + id->gid = strtoul(id_str, NULL, 10); + if (id->gid > hgid ) { + DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n", + (unsigned long)hgid)); + goto out; + } + } + + pstr_sprintf(new_id_str, "%lu", + ((id_type & ID_USERID) ? (unsigned long)id->uid : + (unsigned long)id->gid) + 1); - smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str ); - smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str ); + smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str ); + smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str ); - if (mods == NULL) { - DEBUG(0,("ldap_allocate_id: smbldap_set_mod() failed.\n")); - goto out; - } + if (mods == NULL) { + DEBUG(0,("ldap_allocate_id: smbldap_set_mod() failed.\n")); + goto out; + } - rc = smbldap_modify(ldap_state.smbldap_state, dn, mods); + 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)); - goto out; - } + ldap_mods_free( mods, True ); + if (rc != LDAP_SUCCESS) { + DEBUG(0,("ldap_allocate_id: Failed to allocate new %s. ldap_modify() failed.\n", + type)); + goto out; + } + /* repeat if the id collides with an existing global or local id */ + } while (idmap_id_exists(*id, id_type)); + ret = NT_STATUS_OK; out: + free_attr_list( attr_list ); SAFE_FREE(dn); if (result != NULL) ldap_msgfree(result); @@ -523,7 +530,7 @@ 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", + DEBUG(1,("ldap_get_sid_from_id: mapping not found for %s: %lu\n", type, ((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid))); goto out; diff -ru source/sam.orig/idmap_tdb.c source/sam/idmap_tdb.c --- source/sam.orig/idmap_tdb.c Wed Mar 24 22:33:34 2004 +++ source/sam/idmap_tdb.c Wed Mar 24 22:21:45 2004 @@ -95,64 +95,71 @@ /* Get current high water mark */ switch (id_type & ID_TYPEMASK) { case ID_USERID: - - if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { - return NT_STATUS_INTERNAL_DB_ERROR; - } - - /* check it is in the range */ - if (hwm > idmap_state.uid_high) { - DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", - (unsigned long)idmap_state.uid_high)); - return NT_STATUS_UNSUCCESSFUL; - } - - /* fetch a new id and increment it */ - ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, (unsigned int *)&hwm, 1); - if (!ret) { - DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); - return NT_STATUS_UNSUCCESSFUL; - } - - /* recheck it is in the range */ - if (hwm > idmap_state.uid_high) { - DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", - (unsigned long)idmap_state.uid_high)); - return NT_STATUS_UNSUCCESSFUL; - } + do + { + if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + /* check it is in the range */ + if (hwm > idmap_state.uid_high) { + DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", + (unsigned long)idmap_state.uid_high)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* fetch a new id and increment it */ + ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, (unsigned int *)&hwm, 1); + if (!ret) { + DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* recheck it is in the range */ + if (hwm > idmap_state.uid_high) { + DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", + (unsigned long)idmap_state.uid_high)); + return NT_STATUS_UNSUCCESSFUL; + } + (*id).uid = hwm; + /* repeat if the id collides with an existing global or local id */ + } while (idmap_id_exists(*id, id_type)); - (*id).uid = hwm; DEBUG(10,("db_allocate_id: ID_USERID (*id).uid = %d\n", (unsigned int)hwm)); break; case ID_GROUPID: - if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) { - return NT_STATUS_INTERNAL_DB_ERROR; - } - - /* check it is in the range */ - if (hwm > idmap_state.gid_high) { - DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", - (unsigned long)idmap_state.gid_high)); - return NT_STATUS_UNSUCCESSFUL; - } - - /* fetch a new id and increment it */ - ret = tdb_change_uint32_atomic(idmap_tdb, HWM_GROUP, (unsigned int *)&hwm, 1); - - if (!ret) { - DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); - return NT_STATUS_UNSUCCESSFUL; - } - - /* recheck it is in the range */ - if (hwm > idmap_state.gid_high) { - DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", - (unsigned long)idmap_state.gid_high)); - return NT_STATUS_UNSUCCESSFUL; - } - - (*id).gid = hwm; + do + { + if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + /* check it is in the range */ + if (hwm > idmap_state.gid_high) { + DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", + (unsigned long)idmap_state.gid_high)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* fetch a new id and increment it */ + ret = tdb_change_uint32_atomic(idmap_tdb, HWM_GROUP, (unsigned int *)&hwm, 1); + + if (!ret) { + DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* recheck it is in the range */ + if (hwm > idmap_state.gid_high) { + DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", + (unsigned long)idmap_state.gid_high)); + return NT_STATUS_UNSUCCESSFUL; + } + (*id).gid = hwm; + /* repeat if the id collides with an existing global or local id */ + } while (idmap_id_exists(*id, id_type)); + DEBUG(10,("db_allocate_id: ID_GROUPID (*id).gid = %d\n", (unsigned int)hwm)); break;