diff options
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/passdb.c | 2 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 780 |
2 files changed, 394 insertions, 388 deletions
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index ece4a1e057..54a852601a 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -581,7 +581,7 @@ BOOL pdb_gethexpwd(const char *p, unsigned char *pwd) return (True); } -static int algorithmic_rid_base(void) +int algorithmic_rid_base(void) { static int rid_offset = 0; diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index ec164a7e7b..6911cea369 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -216,8 +216,6 @@ static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, pstring filter; int rc; - /* check if the user rid exists, if not, try searching on the uid */ - snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid, get_objclass_filter(ldap_state->schema_ver)); @@ -237,8 +235,6 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, int rc; fstring sid_string; - /* check if the user rid exsists, if not, try searching on the uid */ - snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)", get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), sid_to_string(sid_string, sid), @@ -250,40 +246,6 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, } /******************************************************************* -search an attribute and return the first value found. -******************************************************************/ -static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - const char *attribute, pstring value) -{ - char **values; - - if ( !attribute ) - return False; - - value[0] = '\0'; - - if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { - DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute)); - - return False; - } - - if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) - { - DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n", - attribute, values[0])); - ldap_value_free(values); - return False; - } - - ldap_value_free(values); -#ifdef DEBUG_PASSWORDS - DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value)); -#endif - return True; -} - -/******************************************************************* Delete complete object or objectclass and attrs from object found in search_result depending on lp_ldap_delete_dn ******************************************************************/ @@ -368,167 +330,6 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, } /********************************************************************** -Search for the domain info entry -*********************************************************************/ -static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state, - LDAPMessage ** result) -{ - pstring filter; - int rc; - char **attr_list; - - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", - LDAP_OBJ_DOMINFO, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name); - - DEBUG(2, ("Searching for:[%s]\n", filter)); - - - attr_list = get_attr_list( dominfo_attr_list ); - rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, - attr_list , result); - free_attr_list( attr_list ); - - if (rc != LDAP_SUCCESS) { - DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc))); - DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - } - - return rc; -} - -/********************************************************************** - If this entry is is the 'allocated' range, extract the RID and return - it, so we can find the 'next' rid to allocate. - - Do this, no matter what type of object holds the RID - be it a user, - group or somthing else. -*********************************************************************/ -static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type) -{ - pstring sid_string; - DOM_SID dom_sid; - uint32 rid; - - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - LDAP_ATTRIBUTE_SID, sid_string)) - { - return 0; - } - - if (!string_to_sid(&dom_sid, sid_string)) { - return 0; - } - - if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) { - /* not our domain, so we don't care */ - return 0; - } - - switch (rid_type) { - case USER_RID_TYPE: - if (rid >= ldap_state->low_allocated_user_rid && - rid <= ldap_state->high_allocated_user_rid) { - return rid; - } - break; - case GROUP_RID_TYPE: - if (rid >= ldap_state->low_allocated_group_rid && - rid <= ldap_state->high_allocated_group_rid) { - return rid; - } - break; - } - return 0; -} - - -/********************************************************************** -Connect to LDAP server and find the next available 'allocated' RID. - -The search is done 'per type' as we allocate seperate pools for the -EVEN and ODD (user and group) RIDs. - -This is only done once, so that we can fill out the sambaDomain. -*********************************************************************/ -static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type) -{ - int rc; - LDAPMessage *result; - LDAPMessage *entry; - uint32 top_rid = 0; - uint32 next_rid; - uint32 count; - uint32 rid; - char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; - fstring filter; - - snprintf( filter, sizeof(filter)-1, "(%s=*)", LDAP_ATTRIBUTE_SID ); - - DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter)); - - rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, - sid_attr, &result); - - if (rc != LDAP_SUCCESS) { - DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc))); - DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - - result = NULL; - return 0; - } - - count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); - DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count)); - - if (count == 0) { - DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc))); - DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - } else { - entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,result); - - top_rid = entry_to_rid(ldap_state, entry, rid_type); - - while ((entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, entry))) { - - rid = entry_to_rid(ldap_state, entry, rid_type); - if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) { - top_rid = rid; - } - } - } - - switch (rid_type) { - case USER_RID_TYPE: - if (top_rid < ldap_state->low_allocated_user_rid) { - return ldap_state->low_allocated_user_rid; - } - break; - case GROUP_RID_TYPE: - if (top_rid < ldap_state->low_allocated_group_rid) - return ldap_state->low_allocated_group_rid; - break; - } - - next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER; - - switch (rid_type) { - case USER_RID_TYPE: - if (next_rid > ldap_state->high_allocated_user_rid) { - return 0; - } - break; - case GROUP_RID_TYPE: - if (next_rid > ldap_state->high_allocated_group_rid) { - return 0; - } - break; - } - return next_rid; -} - -/********************************************************************** Add the sambaDomain to LDAP, so we don't have to search for this stuff again. This is a once-add operation for now. @@ -536,7 +337,8 @@ static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int *********************************************************************/ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) { - pstring tmp; + fstring sid_string; + fstring algorithmic_rid_base_string; pstring filter, dn; LDAPMod **mods = NULL; int rc; @@ -545,22 +347,9 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) int num_result; char **attr_list; - uint32 next_allocated_user_rid; - uint32 next_allocated_group_rid; - - next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE); - if (!next_allocated_user_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE); - if (!next_allocated_group_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name, LDAP_OBJ_DOMINFO); + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + ldap_state->domain_name, LDAP_OBJ_DOMINFO); attr_list = get_attr_list( dominfo_attr_list ); rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, @@ -582,6 +371,7 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) /* Check if we need to add an entry */ DEBUG(3,("Adding new domain\n")); ldap_op = LDAP_MOD_ADD; + snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), ldap_state->domain_name, lp_ldap_suffix()); @@ -592,15 +382,15 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), ldap_state->domain_name); - sid_to_string(tmp, &ldap_state->domain_sid); - smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), tmp); - - snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid); - smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), tmp); + /* If we don't have an entry, then ask secrets.tdb for what it thinks. + It may choose to make it up */ - snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid); - smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), tmp); + sid_to_string(sid_string, get_global_sam_sid()); + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string); + slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base()); + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), + algorithmic_rid_base_string); smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); switch(ldap_op) @@ -637,7 +427,59 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) } /********************************************************************** - Even if the sambaAccount attribute in LDAP tells us that this RID is +Search for the domain info entry +*********************************************************************/ +static NTSTATUS ldapsam_search_domain_info(struct ldapsam_privates *ldap_state, + LDAPMessage ** result, BOOL try_add) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + pstring filter; + int rc; + char **attr_list; + int count; + + snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", + LDAP_OBJ_DOMINFO, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + ldap_state->domain_name); + + DEBUG(2, ("Searching for:[%s]\n", filter)); + + + attr_list = get_attr_list( dominfo_attr_list ); + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, + attr_list , result); + free_attr_list( attr_list ); + + if (rc != LDAP_SUCCESS) { + DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc))); + DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter)); + } else if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, *result) < 1) { + DEBUG(3, ("Got no domain info entries for domain %s\n", + ldap_state->domain_name)); + ldap_msgfree(*result); + *result = NULL; + if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) { + return ldapsam_search_domain_info(ldap_state, result, False); + } else { + DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret))); + return ret; + } + } else if ((count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, *result)) > 1) { + DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n", + count, ldap_state->domain_name)); + ldap_msgfree(*result); + *result = NULL; + return ret; + } else { + return NT_STATUS_OK; + } + + return ret; +} + +/********************************************************************** + 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 ldapsam_privates *ldap_state, @@ -689,15 +531,17 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; int rc; - LDAPMessage *result = NULL; + LDAPMessage *domain_result = NULL; LDAPMessage *entry = NULL; char *dn; LDAPMod **mods = NULL; - int count; 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; if ( ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT ) { DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n", @@ -707,100 +551,129 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri while (attempts < 10) { - char *ld_error; - if (ldapsam_search_domain_info(ldap_state, &result)) { - return ret; - } - - if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) < 1) { - DEBUG(3, ("Got no domain info entries for domain %s\n", - ldap_state->domain_name)); - ldap_msgfree(result); - if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) { - continue; - } else { - DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret))); - return ret; - } - } - - if ((count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result)) > 1) { - DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n", - count, ldap_state->domain_name)); - ldap_msgfree(result); + if (!NT_STATUS_IS_OK(ret = ldapsam_search_domain_info(ldap_state, &domain_result, True))) { return ret; } - - entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, domain_result); if (!entry) { - ldap_msgfree(result); + DEBUG(0, ("Could not get domain info entry\n")); + ldap_msgfree(domain_result); return ret; } if ((dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry)) == NULL) { DEBUG(0, ("Could not get domain info DN\n")); - ldap_msgfree(result); + ldap_msgfree(domain_result); return ret; } - /* yes, we keep 2 seperate counters, to avoid stomping on the two + /* 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 */ - - switch (rid_type) { - case USER_RID_TYPE: - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - old_rid_string)) - { - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } - break; - case GROUP_RID_TYPE: - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - old_rid_string)) - { - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } - break; + + if (smbldap_get_single_attribute(ldap_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(ldap_state->smbldap_state->ldap_struct, entry, &mods, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), + algorithmic_rid_base_string); } - /* This is the core of the whole routine. If we had - scheme-style closures, there would be a *lot* less code - duplication... */ - *rid = (uint32)atol(old_rid_string); - next_rid = *rid+RID_MULTIPLIER; + next_rid = 0; - slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_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(ldap_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; + } - switch (rid_type) { - case USER_RID_TYPE: - if (next_rid > ldap_state->high_allocated_user_rid) { + next_rid = *rid+1; + if (next_rid >= alg_rid_base) { 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(ldap_state->smbldap_state->ldap_struct, entry, &mods, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - next_rid_string); - break; + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), + next_rid_string); + } - case GROUP_RID_TYPE: - if (next_rid > ldap_state->high_allocated_group_rid) { - return NT_STATUS_UNSUCCESSFUL; + if (!next_rid) { /* not got one already */ + switch (rid_type) { + case USER_RID_TYPE: + if (smbldap_get_single_attribute(ldap_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 = ldap_state->low_allocated_user_rid; + } + break; + case GROUP_RID_TYPE: + if (smbldap_get_single_attribute(ldap_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); + } else { + *rid = ldap_state->low_allocated_group_rid; + } + break; } + + /* This is the core of the whole routine. If we had + scheme-style closures, there would be a *lot* less code + duplication... */ - /* Try to make the modification atomically by enforcing the - old value in the delete mod. */ - smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - next_rid_string); - break; + next_rid = *rid+RID_MULTIPLIER; + slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); + + switch (rid_type) { + case USER_RID_TYPE: + if (next_rid > ldap_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(ldap_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: + if (next_rid > ldap_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(ldap_state->smbldap_state->ldap_struct, entry, &mods, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), + next_rid_string); + break; + } } if ((rc = ldap_modify_s(ldap_state->smbldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) { @@ -809,27 +682,27 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri pstring domain_sid_string; int error = 0; - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, result, + if (!smbldap_get_single_attribute(ldap_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); - ldap_msgfree(result); + ldap_msgfree(domain_result); return ret; } if (!string_to_sid(&dom_sid, domain_sid_string)) { ldap_mods_free(mods, True); ldap_memfree(dn); - ldap_msgfree(result); + ldap_msgfree(domain_result); return ret; } ldap_mods_free(mods, True); mods = NULL; ldap_memfree(dn); - ldap_msgfree(result); + ldap_msgfree(domain_result); sid_copy(&sid, &dom_sid); sid_append_rid(&sid, *rid); @@ -845,8 +718,9 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri return NT_STATUS_OK; } + ld_error = NULL; ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(2, ("Failed to modify rid: %s\n", ld_error)); + DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL")); SAFE_FREE(ld_error); ldap_mods_free(mods, True); @@ -855,8 +729,8 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri ldap_memfree(dn); dn = NULL; - ldap_msgfree(result); - result = NULL; + ldap_msgfree(domain_result); + domain_result = NULL; { /* Sleep for a random timeout */ @@ -905,13 +779,13 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, } ldap_value_free(ldap_values); - if ( !get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) ) { return False; } - if ( !get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) ) { return False; @@ -989,7 +863,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, return False; } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) { + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) { DEBUG(1, ("No uid attribute found for this user!\n")); return False; } @@ -1009,13 +883,13 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) { - if (get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) { pdb_set_user_sid_from_string(sampass, temp, PDB_SET); } - if (get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) { pdb_set_group_sid_from_string(sampass, temp, PDB_SET); @@ -1029,14 +903,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } else { - if (get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) { user_rid = (uint32)atol(temp); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) { pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); @@ -1083,7 +957,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) { /* leave as default */ @@ -1092,7 +966,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) { /* leave as default */ @@ -1101,7 +975,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logon_time(sampass, logon_time, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) { /* leave as default */ @@ -1110,7 +984,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logoff_time(sampass, logoff_time, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) { /* leave as default */ @@ -1119,7 +993,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) { /* leave as default */ @@ -1128,7 +1002,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp)) { /* leave as default */ @@ -1143,10 +1017,10 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, * that fits your needs; using cn then displayName rather than 'userFullName' */ - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) { - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) { /* leave as default */ @@ -1157,7 +1031,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_fullname(sampass, fullname, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) { pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -1169,7 +1043,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_dir_drive(sampass, dir_drive, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) { pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -1181,7 +1055,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_homedir(sampass, homedir, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) { pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -1193,7 +1067,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logon_script(sampass, logon_script, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) { pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -1205,7 +1079,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_profile_path(sampass, profile_path, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc)) { /* leave as default */ @@ -1213,7 +1087,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_acct_desc(sampass, acct_desc, PDB_SET); } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) { /* leave as default */; @@ -1227,7 +1101,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, hours_len = 21; memset(hours, 0xff, hours_len); - if (!get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) { /* leave as default */ @@ -1239,7 +1113,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smblmpwd); } - if (!get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) { /* leave as default */ @@ -1251,7 +1125,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smbntpwd); } - if (!get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) { acct_ctrl |= ACB_NORMAL; @@ -1346,10 +1220,10 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) { + if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) { DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, user_sid), - sid_to_string(dom_sid_string, get_global_sam_sid()))); + sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; } slprintf(temp, sizeof(temp) - 1, "%i", rid); @@ -1382,10 +1256,10 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - if (!sid_peek_check_rid(get_global_sam_sid(), group_sid, &rid)) { + if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) { DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, group_sid), - sid_to_string(dom_sid_string, get_global_sam_sid()))); + sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; } @@ -1637,48 +1511,59 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT return ret; } -/********************************************************************** -Get SAM_ACCOUNT entry from LDAP by SID -*********************************************************************/ -static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) +static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, + const DOM_SID *sid, LDAPMessage **result) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; - LDAPMessage *result; - LDAPMessage *entry; - fstring sid_string; - int count; - int rc; + int rc = -1; char ** attr_list; - switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBASAMACCOUNT: attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_sid(ldap_state, sid, &result, attr_list); + rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list); free_attr_list( attr_list ); if ( rc != LDAP_SUCCESS ) - return NT_STATUS_NO_SUCH_USER; + return rc; break; case SCHEMAVER_SAMBAACCOUNT: { uint32 rid; - if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) { - return NT_STATUS_NO_SUCH_USER; + if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) { + return rc; } attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_rid(ldap_state, rid, &result, attr_list ); + rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list ); free_attr_list( attr_list ); if ( rc != LDAP_SUCCESS ) - return NT_STATUS_NO_SUCH_USER; + return rc; } break; } - + return rc; +} + +/********************************************************************** +Get SAM_ACCOUNT entry from LDAP by SID +*********************************************************************/ +static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; + LDAPMessage *result; + LDAPMessage *entry; + int count; + int rc; + fstring sid_string; + + rc = ldapsam_get_ldap_user_by_sid(ldap_state, + sid, &result); + if (rc != LDAP_SUCCESS) + return NT_STATUS_NO_SUCH_USER; + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) @@ -1737,7 +1622,9 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, switch(ldap_op) { case LDAP_MOD_ADD: - smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_ACCOUNT); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + "objectclass", + LDAP_OBJ_ACCOUNT); rc = smbldap_add(ldap_state->smbldap_state, dn, mods); break; @@ -1746,7 +1633,8 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, dn ,mods); break; default: - DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); + DEBUG(0,("Wrong LDAP operation type: %d!\n", + ldap_op)); return NT_STATUS_INVALID_PARAMETER; } @@ -1979,7 +1867,9 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO char **attr_list; char *escape_user; const char *username = pdb_get_username(newpwd); + const DOM_SID *sid = pdb_get_user_sid(newpwd); pstring filter; + fstring sid_string; if (!username || !*username) { DEBUG(0, ("Cannot add user without a username!\n")); @@ -1987,8 +1877,8 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO } /* free this list after the second search or in case we exit on failure */ - attr_list = get_userattr_list(ldap_state->schema_ver); + rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list); if (rc != LDAP_SUCCESS) { @@ -2004,9 +1894,24 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO return NT_STATUS_UNSUCCESSFUL; } ldap_msgfree(result); + result = NULL; + + if (element_is_set_or_changed(newpwd, PDB_USERSID)) { + rc = ldapsam_get_ldap_user_by_sid(ldap_state, + sid, &result); + if (rc == LDAP_SUCCESS) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) { + DEBUG(0,("SID '%s' already in the base, with samba attributes\n", + sid_to_string(sid_string, sid))); + free_attr_list( attr_list ); + return NT_STATUS_UNSUCCESSFUL; + } + ldap_msgfree(result); + } + } /* does the entry already exist but without a samba rttibutes? - we don't really care what attributes are returned here */ + we need to return the samba attributes here */ escape_user = escape_ldap_string_alloc( username ); pstrcpy( filter, lp_ldap_filter() ); @@ -2015,15 +1920,16 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr_list, &result); - free_attr_list( attr_list ); - - if ( rc != LDAP_SUCCESS ) + if ( rc != LDAP_SUCCESS ) { + free_attr_list( attr_list ); return NT_STATUS_UNSUCCESSFUL; + } num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (num_result > 1) { DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + free_attr_list( attr_list ); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -2038,15 +1944,57 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); slprintf (dn, sizeof (dn) - 1, "%s", tmp); ldap_memfree (tmp); - } else { + + } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) { + + /* There might be a SID for this account already - say an idmap entry */ + + snprintf(filter, sizeof(filter)-1, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + sid_to_string(sid_string, sid), + LDAP_OBJ_IDMAP_ENTRY, + LDAP_OBJ_SID_ENTRY); + + rc = smbldap_search_suffix(ldap_state->smbldap_state, + filter, attr_list, &result); + free_attr_list( attr_list ); + + if ( rc != LDAP_SUCCESS ) { + free_attr_list( attr_list ); + return NT_STATUS_UNSUCCESSFUL; + } + + num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); + + if (num_result > 1) { + DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + free_attr_list( attr_list ); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Check if we need to update an existing entry */ + if (num_result == 1) { + char *tmp; + + DEBUG(3,("User exists without samba attributes: adding them\n")); + ldap_op = LDAP_MOD_REPLACE; + entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); + tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); + slprintf (dn, sizeof (dn) - 1, "%s", tmp); + ldap_memfree (tmp); + } + } + + if (num_result == 0) { /* Check if we need to add an entry */ DEBUG(3,("Adding new user\n")); ldap_op = LDAP_MOD_ADD; if (username[strlen(username)-1] == '$') { - slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ()); - } else { - slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ()); - } + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ()); + } else { + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ()); + } } if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, @@ -2090,21 +2038,6 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO } /********************************************************************** - Housekeeping - *********************************************************************/ - -static void free_private_data(void **vp) -{ - struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp; - - smbldap_free_struct(&(*ldap_state)->smbldap_state); - - *ldap_state = NULL; - - /* No need to free any further, as it is talloc()ed */ -} - -/********************************************************************** *********************************************************************/ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state, @@ -2154,7 +2087,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, return False; } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -2165,7 +2098,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, map->gid = (gid_t)atol(temp); - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -2174,7 +2107,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, } string_to_sid(&map->sid, temp); - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -2189,11 +2122,11 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, return False; } - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) { temp[0] = '\0'; - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) { DEBUG(0, ("Attributes cn not found either " @@ -2203,7 +2136,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, } fstrcpy(map->nt_name, temp); - if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) { temp[0] = '\0'; @@ -2333,13 +2266,18 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, const char *name) { pstring filter; + char *escape_name = escape_ldap_string_alloc(name); - /* TODO: Escaping of name? */ + if (!escape_name) { + return NT_STATUS_NO_MEMORY; + } snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))", LDAP_OBJ_GROUPMAP, - get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), name, - get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), name); + get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name, + get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name); + + SAFE_FREE(escape_name); return ldapsam_getgroup(methods, filter, map); } @@ -2651,6 +2589,21 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, } /********************************************************************** + Housekeeping + *********************************************************************/ + +static void free_private_data(void **vp) +{ + struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp; + + smbldap_free_struct(&(*ldap_state)->smbldap_state); + + *ldap_state = NULL; + + /* No need to free any further, as it is talloc()ed */ +} + +/********************************************************************** Intitalise the parts of the pdb_context that are common to all pdb_ldap modes *********************************************************************/ @@ -2700,8 +2653,6 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** return NT_STATUS_NO_MEMORY; } - sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); - (*pdb_method)->private_data = ldap_state; (*pdb_method)->free_private_data = free_private_data; @@ -2743,6 +2694,8 @@ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS ** ldap_state = (*pdb_method)->private_data; ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT; + sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); + return NT_STATUS_OK; } @@ -2754,8 +2707,15 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met { NTSTATUS nt_status; struct ldapsam_privates *ldap_state; + uint32 alg_rid_base; + pstring alg_rid_base_string; uint32 low_idmap_uid, high_idmap_uid; uint32 low_idmap_gid, high_idmap_gid; + LDAPMessage *result; + LDAPMessage *entry; + DOM_SID ldap_domain_sid; + DOM_SID secrets_domain_sid; + pstring domain_sid_string; if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) { return nt_status; @@ -2767,6 +2727,52 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT; ldap_state->permit_non_unix_accounts = False; + /* Try to setup the Domain Name, Domain SID, algorithmic rid base */ + + if (!NT_STATUS_IS_OK(nt_status = ldapsam_search_domain_info(ldap_state, &result, True))) { + DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n")); + DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, and will risk BDCs having inconsistant SIDs\n")); + sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); + return NT_STATUS_OK; + } + + /* Given that the above might fail, everything below this must be optional */ + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + if (!entry) { + DEBUG(0, ("Could not get domain info entry\n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + domain_sid_string)) + { + BOOL found_sid; + string_to_sid(&ldap_domain_sid, domain_sid_string); + found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid); + if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) { + /* reset secrets.tdb sid */ + secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid); + } + sid_copy(&ldap_state->domain_sid, &ldap_domain_sid); + } + + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE), + alg_rid_base_string)) + { + alg_rid_base = (uint32)atol(alg_rid_base_string); + if (alg_rid_base != algorithmic_rid_base()) { + DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n" + "database was initialised. Aborting. \n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + } + ldap_msgfree(result); + /* check for non-unix account ranges */ if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid) |