diff options
Diffstat (limited to 'source3/sam/idmap_ldap.c')
-rw-r--r-- | source3/sam/idmap_ldap.c | 271 |
1 files changed, 8 insertions, 263 deletions
diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c index b4a8c8a752..17482a5146 100644 --- a/source3/sam/idmap_ldap.c +++ b/source3/sam/idmap_ldap.c @@ -113,260 +113,6 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) return NT_STATUS_OK; } -/********************************************************************** - Even if the sambaDomain attribute in LDAP tells us that this RID is - safe to use, always check before use. -*********************************************************************/ - -static BOOL sid_in_use(struct ldap_idmap_state *state, - const DOM_SID *sid, int *error) -{ - fstring filter; - fstring sid_string; - LDAPMessage *result = NULL; - int rc; - const char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; - - slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid)); - - rc = smbldap_search_suffix(state->smbldap_state, - filter, sid_attr, &result); - - 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", - sid_string, ld_error)); - SAFE_FREE(ld_error); - - *error = rc; - return True; - } - - if ((ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) { - DEBUG(3, ("Sid %s already in use - trying next RID\n", - sid_string)); - ldap_msgfree(result); - return True; - } - - ldap_msgfree(result); - - /* good, sid is not in use */ - return False; -} - -/********************************************************************** - Set the new nextRid attribute, and return one we can use. - - 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) -{ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - LDAPMessage *domain_result = NULL; - LDAPMessage *entry = NULL; - char *dn; - LDAPMod **mods = NULL; - fstring old_rid_string; - fstring next_rid_string; - fstring algorithmic_rid_base_string; - uint32 next_rid; - uint32 alg_rid_base; - int attempts = 0; - char *ld_error = NULL; - - while (attempts < 10) { - if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state, - &domain_result, get_global_sam_name(), True))) { - return ret; - } - - entry = ldap_first_entry(state->smbldap_state->ldap_struct, domain_result); - if (!entry) { - DEBUG(0, ("Could not get domain info entry\n")); - ldap_msgfree(domain_result); - return ret; - } - - 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 - different sets of algorithmic RIDs */ - - 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)) { - - alg_rid_base = (uint32)atol(algorithmic_rid_base_string); - } else { - alg_rid_base = algorithmic_rid_base(); - /* Try to make the modification atomically by enforcing the - old value in the delete mod. */ - slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base); - smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), - algorithmic_rid_base_string); - } - - next_rid = 0; - - 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_pstring(state->smbldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), - old_rid_string)) { - *rid = (uint32)atol(old_rid_string); - } else { - *rid = BASE_RID; - } - - next_rid = *rid+1; - if (next_rid >= alg_rid_base) { - ldap_msgfree(domain_result); - return NT_STATUS_UNSUCCESSFUL; - } - - slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); - - /* 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, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), - next_rid_string); - } - - if (!next_rid) { /* not got one already */ - switch (rid_type) { - case USER_RID_TYPE: - 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); - } - break; - case GROUP_RID_TYPE: - if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - old_rid_string)) { - *rid = (uint32)atol(old_rid_string); - } - break; - } - - /* This is the core of the whole routine. If we had - scheme-style closures, there would be a *lot* less code - duplication... */ - - next_rid = *rid+RID_MULTIPLIER; - slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); - - switch (rid_type) { - case USER_RID_TYPE: - /* 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, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - next_rid_string); - break; - - case GROUP_RID_TYPE: - /* 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, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - next_rid_string); - break; - } - } - - if ((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_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); - SAFE_FREE(dn); - ldap_msgfree(domain_result); - return ret; - } - - if (!string_to_sid(&dom_sid, domain_sid_string)) { - ldap_mods_free(mods, True); - SAFE_FREE(dn); - ldap_msgfree(domain_result); - return ret; - } - - ldap_mods_free(mods, True); - mods = NULL; - SAFE_FREE(dn); - ldap_msgfree(domain_result); - - sid_copy(&sid, &dom_sid); - sid_append_rid(&sid, *rid); - - /* check RID is not in use */ - if (sid_in_use(state, &sid, &error)) { - if (error) { - return ret; - } - continue; - } - - return NT_STATUS_OK; - } - - ld_error = NULL; - ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL")); - SAFE_FREE(ld_error); - - ldap_mods_free(mods, True); - mods = NULL; - - SAFE_FREE(dn); - - ldap_msgfree(domain_result); - domain_result = NULL; - - { - /* Sleep for a random timeout */ - unsigned sleeptime = (sys_random()*sys_getpid()*attempts); - attempts += 1; - - sleeptime %= 100; - smb_msleep(sleeptime); - } - } - - DEBUG(0, ("Failed to set new RID\n")); - return ret; -} - - -/***************************************************************************** - Allocate a new RID -*****************************************************************************/ - -static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type) -{ - return ldap_next_rid( &ldap_state, rid, rid_type ); -} - /***************************************************************************** Allocate a new uid or gid *****************************************************************************/ @@ -394,12 +140,12 @@ 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 ); + attr_list = get_attr_list( NULL, 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 ); + talloc_free( attr_list ); if (rc != LDAP_SUCCESS) { DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL)); @@ -505,7 +251,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) 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 ); + attr_list = get_attr_list( NULL, sidmap_attr_list ); rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); @@ -534,7 +280,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) ret = NT_STATUS_OK; out: - free_attr_list( attr_list ); + talloc_free( attr_list ); if (result) ldap_msgfree(result); @@ -577,7 +323,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si /* do the search and check for errors */ - attr_list = get_attr_list( sidmap_attr_list ); + attr_list = get_attr_list( NULL, sidmap_attr_list ); rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); @@ -651,7 +397,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si } out: - free_attr_list( attr_list ); + talloc_free( attr_list ); if (result) ldap_msgfree(result); SAFE_FREE(dn); @@ -674,10 +420,10 @@ static NTSTATUS verify_idpool( void ) fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL ); - attr_list = get_attr_list( idpool_attr_list ); + attr_list = get_attr_list( NULL, 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 ); + talloc_free ( attr_list ); if (rc != LDAP_SUCCESS) return NT_STATUS_UNSUCCESSFUL; @@ -776,7 +522,6 @@ static void ldap_idmap_status(void) static struct idmap_methods ldap_methods = { ldap_idmap_init, - ldap_allocate_rid, ldap_allocate_id, ldap_get_sid_from_id, ldap_get_id_from_sid, |