diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/smbldap.h | 6 | ||||
-rw-r--r-- | source3/lib/smbldap.c | 38 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 2 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 780 | ||||
-rw-r--r-- | source3/sam/idmap_ldap.c | 855 | ||||
-rw-r--r-- | source3/sam/idmap_util.c | 7 | ||||
-rw-r--r-- | source3/smbd/server.c | 20 | ||||
-rw-r--r-- | source3/utils/pdbedit.c | 6 |
8 files changed, 724 insertions, 990 deletions
diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index 5f3606aa32..589d01aa6d 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -37,6 +37,7 @@ #define LDAP_OBJ_DOMINFO "sambaDomain" #define LDAP_OBJ_IDPOOL "sambaUnixIdPool" #define LDAP_OBJ_IDMAP_ENTRY "sambaIdmapEntry" +#define LDAP_OBJ_SID_ENTRY "sambaSidEntry" #define LDAP_OBJ_ACCOUNT "account" #define LDAP_OBJ_POSIXACCOUNT "posixAccount" @@ -85,7 +86,8 @@ #define LDAP_ATTR_GROUP_SID 30 #define LDAP_ATTR_GROUP_TYPE 31 #define LDAP_ATTR_SID 32 - +#define LDAP_ATTR_ALGORITHMIC_RID_BASE 33 +#define LDAP_ATTR_NEXT_RID 34 typedef struct _attrib_map_entry { int attrib; @@ -113,6 +115,8 @@ void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, con void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, LDAPMod ***mods, const char *attribute, const char *newval); +BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, + const char *attribute, pstring value); /** * Struct to keep the state for all the ldap stuff diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 8401787317..f65860d1b8 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -102,9 +102,11 @@ ATTRIB_MAP_ENTRY attrib_map_v30[] = { ATTRIB_MAP_ENTRY dominfo_attr_list[] = { { LDAP_ATTR_DOMAIN, "sambaDomainName" }, + { LDAP_ATTR_NEXT_RID, "sambaNextRid" }, { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, { LDAP_ATTR_DOM_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"}, { LDAP_ATTR_LIST_END, NULL }, }; @@ -271,6 +273,40 @@ BOOL fetch_ldap_pw(char **dn, char** pw) return True; } +/******************************************************************* +search an attribute and return the first value found. +******************************************************************/ + BOOL smbldap_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, ("smbldap_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, ("smbldap_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, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value)); +#endif + return True; +} + /************************************************************************ Routine to manage the LDAPMod structure array manage memory used by the array, by each struct, and values @@ -819,7 +855,7 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state) return NT_STATUS_OK; } -static int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts) +int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts) { int rc; 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) diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c index b31ce18925..2dccaf04f7 100644 --- a/source3/sam/idmap_ldap.c +++ b/source3/sam/idmap_ldap.c @@ -39,463 +39,23 @@ struct ldap_idmap_state { - LDAP *ldap_struct; - time_t last_ping; - char *uri; - char *bind_dn; - char *bind_secret; - unsigned int num_failures; - struct ldap_idmap_state *prev, *next; + struct smbldap_state *smbldap_state; + TALLOC_CTX *mem_ctx; + + /* struct ldap_idmap_state *prev, *next; */ }; -#define LDAP_IDMAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ #define LDAP_MAX_ALLOC_ID 128 /* number tries while allocating new id */ static struct ldap_idmap_state ldap_state; -static int ldap_idmap_connect_system(struct ldap_idmap_state *state); 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); -/******************************************************************* - open a connection to the ldap server. -******************************************************************/ -static int ldap_idmap_open_connection(struct ldap_idmap_state *state) -{ - int rc = LDAP_SUCCESS; - int version; - BOOL ldap_v3 = False; - -#ifdef HAVE_LDAP_INITIALIZE - DEBUG(10, ("ldap_idmap_open_connection: %s\n", state->uri)); - - if ((rc = ldap_initialize(&state->ldap_struct, state->uri)) - != LDAP_SUCCESS) { - DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); - return rc; - } -#else - /* Parse the string manually */ - { - int port = 0; - fstring protocol; - fstring host; - const char *p = state->uri; - SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, "URL:", 4 ) == 0 ) { - p += 4; - } - - sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); - - if (port == 0) { - if (strequal(protocol, "ldap")) { - port = LDAP_PORT; - } else if (strequal(protocol, "ldaps")) { - port = LDAPS_PORT; - } else { - DEBUG(0, ("unrecognised protocol (%s)!\n", - protocol)); - } - } - - if ((state->ldap_struct = ldap_init(host, port)) == NULL) { - DEBUG(0, ("ldap_init failed !\n")); - return LDAP_OPERATIONS_ERROR; - } - - if (strequal(protocol, "ldaps")) { -#ifdef LDAP_OPT_X_TLS - int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (state->ldap_struct, - LDAP_OPT_X_TLS, &tls) != - LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); - } - - DEBUG(3,("LDAPS option set...!\n")); -#else - DEBUG(0,("ldap_idmap_open_connection: Secure " - "connection not supported by LDAP client " - "libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - } -#endif - - if (ldap_get_option(state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, - &version) == LDAP_OPT_SUCCESS) { - if (version != LDAP_VERSION3) { - version = LDAP_VERSION3; - if (ldap_set_option(state->ldap_struct, - LDAP_OPT_PROTOCOL_VERSION, - &version) == LDAP_OPT_SUCCESS) { - ldap_v3 = True; - } - } else { - ldap_v3 = True; - } - } - - if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { -#ifdef LDAP_OPT_X_TLS - if (ldap_v3) { - if ((rc = ldap_start_tls_s(state->ldap_struct, NULL, - NULL)) != LDAP_SUCCESS) { - DEBUG(0,("Failed to issue the StartTLS " - "instruction: %s\n", - ldap_err2string(rc))); - return rc; - } - DEBUG (3, ("StartTLS issued: using a TLS " - "connection\n")); - } else { - - DEBUG(0, ("Need LDAPv3 for Start TLS\n")); - return LDAP_OPERATIONS_ERROR; - } -#else - DEBUG(0,("ldap_idmap_open_connection: StartTLS not supported by " - "LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - - DEBUG(2, ("ldap_idmap_open_connection: connection opened\n")); - return rc; -} - -/********************************************************************** -Connect to LDAP server -*********************************************************************/ -static int ldap_idmap_open(struct ldap_idmap_state *state) -{ - int rc; - SMB_ASSERT(state); - -#ifndef NO_LDAP_SECURITY - if (geteuid() != 0) { - DEBUG(0, - ("ldap_idmap_open: cannot access LDAP when not root\n")); - return LDAP_INSUFFICIENT_ACCESS; - } -#endif - - if ((state->ldap_struct != NULL) && - ((state->last_ping + LDAP_IDMAP_DONT_PING_TIME)<time(NULL))) { - struct sockaddr_un addr; - socklen_t len = sizeof(addr); - int sd; - - if (!ldap_get_option(state->ldap_struct, LDAP_OPT_DESC, &sd)&& - getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { - /* the other end has died. reopen. */ - ldap_unbind_ext(state->ldap_struct, NULL, NULL); - state->ldap_struct = NULL; - state->last_ping = (time_t)0; - } else { - state->last_ping = time(NULL); - } - } - - if (state->ldap_struct != NULL) { - DEBUG(5,("ldap_idmap_open: already connected to the LDAP " - "server\n")); - return LDAP_SUCCESS; - } - - if ((rc = ldap_idmap_open_connection(state))) { - return rc; - } - - if ((rc = ldap_idmap_connect_system(state))) { - ldap_unbind_ext(state->ldap_struct, NULL, NULL); - state->ldap_struct = NULL; - return rc; - } - - - state->last_ping = time(NULL); - DEBUG(4,("The LDAP server is succesful connected\n")); - - return LDAP_SUCCESS; -} - -/******************************************************************* -******************************************************************/ - -static int ldap_idmap_retry_open(struct ldap_idmap_state *state, int *attempts) -{ - int rc; - - SMB_ASSERT(state && attempts); - - if (*attempts != 0) { - unsigned int sleep_time; - uint8 rand_byte = 128; /* a reasonable place to start */ - - generate_random_buffer(&rand_byte, 1, False); - - sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; - /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds - on average. - */ - DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", - sleep_time)); - msleep(sleep_time); - } - (*attempts)++; - - if ((rc = ldap_idmap_open(state))) { - DEBUG(1,("Connection to LDAP Server failed for the %d try!\n", - *attempts)); - return rc; - } - - return LDAP_SUCCESS; -} - -/******************************************************************* - a rebind function for authenticated referrals - This version takes a void* that we can shove useful stuff in :-) -******************************************************************/ - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -#else -static int rebindproc_with_state (LDAP * ld, char **whop, char **credp, - int *methodp, int freeit, void *arg) -{ - struct ldap_idmap_state *state = arg; - - /** @TODO Should we be doing something to check what servers we rebind - to? Could we get a referral to a machine that we don't want to - give our username and password to? */ - - if (freeit) { - SAFE_FREE(*whop); - memset(*credp, '\0', strlen(*credp)); - SAFE_FREE(*credp); - } else { - DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", - state->bind_dn)); - - *whop = strdup(state->bind_dn); - if (!*whop) { - return LDAP_NO_MEMORY; - } - *credp = strdup(state->bind_secret); - if (!*credp) { - SAFE_FREE(*whop); - return LDAP_NO_MEMORY; - } - *methodp = LDAP_AUTH_SIMPLE; - } - return 0; -} -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - a rebind function for authenticated referrals - This version takes a void* that we can shove useful stuff in :-) - and actually does the connection. -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -static int rebindproc_connect_with_state (LDAP *ldap_struct, - LDAP_CONST char *url, - ber_tag_t request, - ber_int_t msgid, void *arg) -{ - struct ldap_idmap_state *state = arg; - int rc; - DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", - state->bind_dn)); - - /** @TODO Should we be doing something to check what servers we rebind - to? Could we get a referral to a machine that we don't want to - give our username and password to? */ - - rc = ldap_simple_bind_s(ldap_struct, state->bind_dn, - state->bind_secret); - - return rc; -} -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - Add a rebind function for authenticated referrals -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -#else -# if LDAP_SET_REBIND_PROC_ARGS == 2 -static int rebindproc (LDAP *ldap_struct, char **whop, char **credp, - int *method, int freeit ) -{ - return rebindproc_with_state(ldap_struct, whop, credp, - method, freeit, &ldap_state); - -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - a rebind function for authenticated referrals - this also does the connection, but no void*. -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 -static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request, - ber_int_t msgid) -{ - return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, - msgid, &ldap_state); -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - connect to the ldap server under system privilege. -******************************************************************/ -static int ldap_idmap_connect_system(struct ldap_idmap_state *state) -{ - int rc; - char *ldap_dn; - char *ldap_secret; - - /* get the password */ - if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) - { - DEBUG(0, ("ldap_idmap_connect_system: Failed to retrieve " - "password from secrets.tdb\n")); - return LDAP_INVALID_CREDENTIALS; - } - - state->bind_dn = ldap_dn; - state->bind_secret = ldap_secret; - - /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite - (OpenLDAP) doesnt' seem to support it */ - - DEBUG(10,("ldap_idmap_connect_system: Binding to ldap server %s as " - "\"%s\"\n", state->uri, ldap_dn)); - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(state->ldap_struct, &rebindproc_connect); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(state->ldap_struct, - &rebindproc_connect_with_state, (void *)state); -# endif -#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(state->ldap_struct, &rebindproc); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(state->ldap_struct, &rebindproc_with_state, - (void *)state); -# endif -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - - rc = ldap_simple_bind_s(state->ldap_struct, ldap_dn, ldap_secret); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(state->num_failures ? 2 : 0, - ("failed to bind to server with dn= %s Error: " - "%s\n\t%s\n", - ldap_dn ? ld_error : "(unknown)", - ldap_err2string(rc), ld_error)); - SAFE_FREE(ld_error); - state->num_failures++; - return rc; - } - - state->num_failures = 0; - - DEBUG(3, ("ldap_idmap_connect_system: succesful connection to the " - "LDAP server\n")); - return rc; -} - -/***************************************************************************** - wrapper around ldap_search() -*****************************************************************************/ - -static int ldap_idmap_search(struct ldap_idmap_state *state, - const char *base, int scope, const char *filter, - char *attrs[], int attrsonly, - LDAPMessage **res) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_filter; - - SMB_ASSERT(state); - - if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - if ((rc = ldap_idmap_retry_open(state, &attempts)) != - LDAP_SUCCESS) continue; - - rc = ldap_search_s(state->ldap_struct, base, scope, - utf8_filter, (char**)attrs, attrsonly, res); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("ldap_idmap_search: LDAP server is down!\n")); - ldap_idmap_close(); - } - - SAFE_FREE(utf8_filter); - return rc; -} - -/*********************************************************************** - search an attribute and return the first value found. -***********************************************************************/ - -static BOOL ldap_idmap_attribute (struct ldap_idmap_state *state, - LDAPMessage * entry, - const char *attribute, pstring value) -{ - char **values; - value[0] = '\0'; - - if ( !entry ) - return False; - - if ((values = ldap_get_values (state->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, ("ldap_idmap_attribute: string conversion of [%s] = " - "[%s] failed!\n", attribute, values[0])); - ldap_value_free(values); - return False; - } - ldap_value_free(values); - - return True; -} - /***************************************************************************** Allocate a new uid or gid *****************************************************************************/ @@ -505,8 +65,8 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; int rc = LDAP_SERVER_DOWN; int count = 0; - LDAPMessage *result = 0; - LDAPMessage *entry = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; pstring id_str, new_id_str; LDAPMod **mods = NULL; const char *type; @@ -525,7 +85,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) attr_list = get_attr_list( idpool_attr_list ); - rc = ldap_idmap_search(&ldap_state, lp_ldap_idmap_suffix(), + rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); free_attr_list( attr_list ); @@ -535,16 +95,16 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) goto out; } - count = ldap_count_entries(ldap_state.ldap_struct, result); + 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 = ldap_get_dn(ldap_state.ldap_struct, result); - entry = ldap_first_entry(ldap_state.ldap_struct, result); + dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) { + 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; @@ -578,7 +138,7 @@ 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.ldap_struct, dn, mods); + rc = ldap_modify_s(ldap_state.smbldap_state->ldap_struct, dn, mods); ldap_memfree(dn); ldap_mods_free( mods, True ); @@ -600,12 +160,14 @@ out: static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) { - LDAPMessage *result = 0; - LDAPMessage *entry = 0; + 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; @@ -615,49 +177,48 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) if ( id_type & ID_USERID ) { type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); - snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", - LDAP_OBJ_SAMBASAMACCOUNT, type, id.uid ); + obj_class = LDAP_OBJ_SAMBASAMACCOUNT; + snprintf(id_str, sizeof(id_str), "%u", id.uid ); pstrcpy( suffix, lp_ldap_suffix()); } else { type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); - snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", - LDAP_OBJ_GROUPMAP, type, id.gid ); + obj_class = LDAP_OBJ_GROUPMAP; + snprintf(id_str, sizeof(id_str), "%u", id.gid ); pstrcpy( suffix, lp_ldap_group_suffix() ); } attr_list = get_attr_list( sidmap_attr_list ); - rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE, - filter, attr_list, 0, &result); + snprintf(filter, sizeof(filter), "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", + LDAP_OBJ_IDMAP_ENTRY, obj_class, type, id_str); + + 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.ldap_struct, result); + 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; + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", LDAP_OBJ_IDMAP_ENTRY, type, ((id_type & ID_USERID) ? id.uid : id.gid)); -#if 0 /* commented out for now -- jerry */ - if ( id_type & ID_USERID ) - snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_USER_SUFFIX, lp_ldap_idmap_suffix() ); - else - snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_GROUP_SUFFIX, lp_ldap_idmap_suffix() ); -#else pstrcpy( suffix, lp_ldap_idmap_suffix() ); -#endif - rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE, + 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.ldap_struct, result); + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); } if (count != 1) { @@ -666,9 +227,9 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) goto out; } - entry = ldap_first_entry(ldap_state.ldap_struct, result); + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - if ( !ldap_idmap_attribute(&ldap_state, entry, LDAP_ATTRIBUTE_SID, sid_str) ) + if ( !smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) ) goto out; if (!string_to_sid(sid, sid_str)) @@ -678,6 +239,9 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) out: free_attr_list( attr_list ); + if (result) + ldap_msgfree(result); + return ret; } @@ -687,68 +251,74 @@ out: static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) { - LDAPMessage *result = 0; - LDAPMessage *entry = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; pstring sid_str; pstring filter; pstring id_str; - pstring suffix; + 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( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); + type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ); obj_class = LDAP_OBJ_SAMBASAMACCOUNT; - pstrcpy( suffix, lp_ldap_suffix() ); + posix_obj_class = LDAP_OBJ_POSIXACCOUNT; + suffix = lp_ldap_suffix(); + snprintf(filter, sizeof(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 { - type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); + type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ); obj_class = LDAP_OBJ_GROUPMAP; - pstrcpy( suffix, lp_ldap_group_suffix() ); - } + posix_obj_class = LDAP_OBJ_POSIXGROUP; + suffix = lp_ldap_group_suffix(); + snprintf(filter, sizeof(filter), + "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", + obj_class, LDAP_OBJ_IDMAP_ENTRY, + get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), + sid_str); + } - sid_to_string(sid_str, sid); - snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%s))", obj_class, - LDAP_ATTRIBUTE_SID, sid_str); - attr_list = get_attr_list( sidmap_attr_list ); - rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE, + 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.ldap_struct, result); + 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 */ + /* 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); + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str); -#if 0 /* commented out for now -- jerry */ - if ( *id_type & ID_USERID ) - snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_USER_SUFFIX, lp_ldap_idmap_suffix() ); - else - snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_GROUP_SUFFIX, lp_ldap_idmap_suffix() ); -#else - pstrcpy( suffix, lp_ldap_idmap_suffix() ); -#endif + suffix = lp_ldap_idmap_suffix(); - rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE, + 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.ldap_struct, result); + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); } if ( count > 1 ) { @@ -759,15 +329,28 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si /* we might have an existing entry to work with so pull out the requested information */ - if ( count ) - entry = ldap_first_entry(ldap_state.ldap_struct, result); + if ( count ) { + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - /* if entry == NULL, then we will default to allocating a new id */ + 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; + goto out; + } + } - if ( !ldap_idmap_attribute(&ldap_state, entry, type, id_str) ) - { + if (!(*id_type & ID_QUERY_ONLY)) { + /* if entry == NULL, and we are asked to - allocate a new id */ int i; - + for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) { ret = ldap_allocate_id(id, *id_type); @@ -781,115 +364,236 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si } ret = ldap_set_mapping(sid, *id, *id_type); - - } - else - { - if ( (*id_type & ID_USERID) ) - id->uid = strtoul(id_str, NULL, 10); - else - id->gid = strtoul(id_str, NULL, 10); - - ret = NT_STATUS_OK; + } 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); 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(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) { - pstring dn, sid_str, id_str; + char *dn = NULL; + pstring id_str; fstring type; LDAPMod **mods = NULL; - int rc; - int attempts = 0; + int rc = -1; + int ldap_op; + fstring sid_string; + + 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; + dn = strdup(ldap_dn); + } else { + ldap_op = LDAP_MOD_ADD; + asprintf(&dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID), + sid_string, lp_ldap_idmap_suffix()); + } + + if (!dn) { + DEBUG(0, ("ldap_set_mapping_internals: out of memory allocating DN!\n")); + return NT_STATUS_NO_MEMORY; + } if ( id_type & ID_USERID ) - fstrcpy( type, get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) ); + fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) ); else - fstrcpy( type, get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ) ); - -#if 0 - snprintf(dn, sizeof(dn), "%s=%u,%s,%s", type, - ((id_type & ID_USERID) ? id.uid : id.gid), - ((id_type & ID_USERID) ? IDMAP_USER_SUFFIX : IDMAP_GROUP_SUFFIX ), - lp_ldap_idmap_suffix()); -#else - snprintf(dn, sizeof(dn), "%s=%u,%s", type, - ((id_type & ID_USERID) ? id.uid : id.gid), - lp_ldap_idmap_suffix()); -#endif + fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) ); snprintf(id_str, sizeof(id_str), "%u", ((id_type & ID_USERID) ? id.uid : id.gid)); - sid_to_string( sid_str, sid ); - smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY ); - smbldap_set_mod( &mods, LDAP_MOD_ADD, type, id_str ); smbldap_set_mod( &mods, LDAP_MOD_ADD, - get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), sid_str ); + "objectClass", LDAP_OBJ_IDMAP_ENTRY ); + + smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, + entry, &mods, type, id_str ); - do { - if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_add_s(ldap_state.ldap_struct, dn, mods); - } while ((rc == LDAP_SERVER_DOWN) && (attempts <= 8)); + smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, + entry, &mods, + get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), + sid_string ); + + 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 ); if (rc != LDAP_SUCCESS) { - DEBUG(0,("ldap_set_mapping: Failed to create mapping from %s to %d [%s]\n", - sid_str, ((id_type & ID_USERID) ? id.uid : id.gid), type)); + 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 create mapping from %s to %u [%s]\n", + sid_string, (unsigned int)((id_type & ID_USERID) ? id.uid : id.gid), type)); + DEBUG(0, ("ldap_set_mapping_internals: Error was: %s\n", ld_error ? ld_error : "(NULL)")); return NT_STATUS_UNSUCCESSFUL; } DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %d [%s]\n", - sid_str, ((id_type & ID_USERID) ? id.uid : id.gid), type)); + sid_string, ((id_type & ID_USERID) ? id.uid : 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; + + /* 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; + snprintf(id_str, sizeof(id_str), "%u", 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; + snprintf(id_str, sizeof(id_str), "%u", id.gid ); + } + + sid_to_string(sid_str, sid); + snprintf(filter, sizeof(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 ); + + if (rc != LDAP_SUCCESS) + 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")); + goto out; + } + + ret = ldap_set_mapping_internals(sid, id, id_type, NULL, NULL); + +out: + if (result) + ldap_msgfree(result); + if (dn) + ldap_memfree(dn); + + return ret; +} /***************************************************************************** Initialise idmap database. *****************************************************************************/ static NTSTATUS ldap_idmap_init( char *params ) { fstring filter; -#if 0 - pstring dn; -#endif int rc; char **attr_list; LDAPMessage *result = NULL; LDAPMod **mods = NULL; int count; + NTSTATUS nt_status; - /* parse out the server (assuming only parameter is a URI) */ + 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; + } - if ( params ) - ldap_state.uri = smb_xstrdup( params ); - else - ldap_state.uri = smb_xstrdup( "ldap://localhost/" ); - /* see if the idmap suffix and sub entries exists */ snprintf( filter, sizeof(filter), "(objectclass=%s)", LDAP_OBJ_IDPOOL ); attr_list = get_attr_list( idpool_attr_list ); - rc = ldap_idmap_search(&ldap_state, lp_ldap_idmap_suffix(), + 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) return NT_STATUS_UNSUCCESSFUL; - count = ldap_count_entries(ldap_state.ldap_struct, result); + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); if ( count > 1 ) { DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n", @@ -900,7 +604,6 @@ static NTSTATUS ldap_idmap_init( char *params ) uid_t luid, huid; gid_t lgid, hgid; fstring uid_str, gid_str; - int attempts = 0; if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) { DEBUG(0,("ldap_idmap_init: idmap uid/gid parameters not specified\n")); @@ -916,34 +619,9 @@ static NTSTATUS ldap_idmap_init( char *params ) smbldap_set_mod( &mods, LDAP_MOD_ADD, get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str ); - do { - if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_modify_s(ldap_state.ldap_struct, lp_ldap_idmap_suffix(), mods); - } while ((rc == LDAP_SERVER_DOWN) && (attempts <= 8)); + rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods); } - /* we have the initial entry now; let's create the sub entries */ - /* if they already exist then this will fail, but we don't care */ - -#if 0 /* commenting out for now, but I will come back to this --jerry */ - - mods = NULL; - snprintf( dn, sizeof(dn), "%s,%s", IDMAP_USER_SUFFIX, lp_ldap_idmap_suffix() ); - smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_OU ); - smbldap_set_mod( &mods, LDAP_MOD_ADD, "ou", "idmap people" ); - ldap_add_s(ldap_state.ldap_struct, dn, mods); - ldap_mods_free( mods, True ); - - mods = NULL; - snprintf( dn, sizeof(dn), "%s,%s", IDMAP_GROUP_SUFFIX, lp_ldap_idmap_suffix() ); - smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_OU ); - smbldap_set_mod( &mods, LDAP_MOD_ADD, "ou", "idmap group" ); - ldap_add_s(ldap_state.ldap_struct, dn, mods); - ldap_mods_free( mods, True ); -#endif - return NT_STATUS_OK; } @@ -953,14 +631,9 @@ static NTSTATUS ldap_idmap_init( char *params ) static NTSTATUS ldap_idmap_close(void) { - if (ldap_state.ldap_struct != NULL) { - ldap_unbind_ext(ldap_state.ldap_struct, NULL, NULL); - ldap_state.ldap_struct = NULL; - } - SAFE_FREE( ldap_state.uri ); - SAFE_FREE( ldap_state.bind_dn ); - SAFE_FREE( ldap_state.bind_secret ); + smbldap_free_struct(&(ldap_state).smbldap_state); + talloc_destroy(ldap_state.mem_ctx); DEBUG(5,("The connection to the LDAP server was closed\n")); /* maybe free the results here --metze */ diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c index 095f5f0874..ffc3db2a0a 100644 --- a/source3/sam/idmap_util.c +++ b/source3/sam/idmap_util.c @@ -132,7 +132,6 @@ BOOL idmap_get_free_ugid_range(uint32 *low, uint32 *high) *THE CANONICAL* convert uid_t to SID function. check idmap if uid is in idmap range, otherwise falls back to the legacy algorithmic mapping. - A special cache is used for uids that maps to Wellknown SIDs Returns SID pointer. *****************************************************************/ @@ -204,7 +203,6 @@ NTSTATUS gid_to_sid(DOM_SID *sid, gid_t gid) *THE CANONICAL* convert SID to uid function. if it is a foreign sid or it is in idmap rid range check idmap, otherwise falls back to the legacy algorithmic mapping. - A special cache is used for uids that maps to Wellknown SIDs Returns True if this name is a user sid and the conversion was done correctly, False if not. *****************************************************************/ @@ -351,6 +349,7 @@ BOOL idmap_init_wellknown_sids(void) int num_entries=0; DOM_SID sid; unid_t id; + fstring sid_string; if (!(guest_account && *guest_account)) { DEBUG(1, ("NULL guest account!?!?\n")); @@ -368,6 +367,8 @@ BOOL idmap_init_wellknown_sids(void) sid_append_rid(&sid, DOMAIN_USER_RID_GUEST); if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_USERID))) { + DEBUG(0, ("Failed to setup UID mapping for GUEST (%s) to (%u)\n", + sid_to_string(sid_string, &sid), (unsigned int)id.uid)); passwd_free(&pass); return False; } @@ -378,6 +379,8 @@ BOOL idmap_init_wellknown_sids(void) sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, DOMAIN_GROUP_RID_GUESTS); if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_GROUPID))) { + DEBUG(0, ("Failed to setup GID mapping for Group DOMAIN GUESTS (%s) to (%u)\n", + sid_to_string(sid_string, &sid), (unsigned int)id.gid)); passwd_free(&pass); return False; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e2fe2ac819..6f549aab1c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -842,9 +842,19 @@ void build_options(BOOL screen); if (!init_registry()) exit(1); + /* Initialise the password backed before idmap and the global_sam_sid + to ensure that we fetch from ldap before we make a domain sid up */ + if(!initialize_password_db(False)) exit(1); + if(!get_global_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); + exit(1); + } + + static_init_auth; + { const char *idmap_back = lp_idmap_backend(); @@ -852,8 +862,10 @@ void build_options(BOOL screen); exit(1); } - if (!idmap_init_wellknown_sids()) + if (!idmap_init_wellknown_sids()) { + DEBUG(0,("ERROR: Samba failed to initialize it's 'well known' SID -> ID mapping tables.\n")); exit(1); + } static_init_rpc; @@ -862,12 +874,6 @@ void build_options(BOOL screen); /* possibly reload the services file. */ reload_services(True); - if(!get_global_sam_sid()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); - exit(1); - } - - if (!init_account_policy()) { DEBUG(0,("Could not open account policy tdb.\n")); exit(1); diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 3fa2751347..5b702f7591 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -606,6 +606,12 @@ int main (int argc, char **argv) exit(1); } + /* Initialise the password backed before idmap and the global_sam_sid + to ensure that we fetch from ldap before we make a domain sid up */ + + if(!initialize_password_db(False)) + exit(1); + if (!init_names()) exit(1); |