From a3ddfa5069c9df07626135aa5fd2ec411c41943f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 5 Jul 2003 09:46:12 +0000 Subject: Fixes to our LDAP/vampire codepaths: - Try better to add the appropriate mapping between UID and SIDs, based on Get_Pwnam() - Look for previous users (lookup by SID) and correctly modify the existing entry in that case - Map the root user to the Admin SID as a 'well known user' - Save the LDAPMessage result on the SAM_ACCOUNT for use in the next 'update' call on that user. This means that VL's very nice work on atomic LDAP updates now really gets used properly! - This also means that we know the right DN to update, without the extra round-trips to the server. Andrew Bartlett (This used to be commit c7118cb31dac24db3b762fe68ce655b17ea102e0) --- source3/include/passdb.h | 3 ++ source3/lib/smbldap.c | 4 ++ source3/passdb/passdb.c | 4 ++ source3/passdb/pdb_get_set.c | 30 +++++++++++++++ source3/passdb/pdb_ldap.c | 38 +++++++++++++------ source3/sam/idmap_util.c | 11 ++++++ source3/utils/net_rpc_samsync.c | 81 ++++++++++++++++++++++------------------- 7 files changed, 123 insertions(+), 48 deletions(-) (limited to 'source3') diff --git a/source3/include/passdb.h b/source3/include/passdb.h index aeddcbcb3a..bf2fd6f6ce 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -61,6 +61,7 @@ enum pdb_elements { PDB_UNKNOWN6, PDB_LMPASSWD, PDB_NTPASSWD, + PDB_BACKEND_PRIVATE_DATA, /* this must be the last element */ PDB_COUNT @@ -137,6 +138,8 @@ typedef struct sam_passwd uint32 unknown_5; /* 0x0002 0000 */ uint32 unknown_6; /* 0x0000 04ec */ + void *backend_private_data; + void (*backend_private_data_free_fn)(void **); } private; /* Lets see if the remaining code can get the hint that you diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index f65860d1b8..e0c6aab617 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -107,6 +107,7 @@ ATTRIB_MAP_ENTRY dominfo_attr_list[] = { { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, { LDAP_ATTR_DOM_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL }, }; @@ -119,6 +120,7 @@ ATTRIB_MAP_ENTRY groupmap_attr_list[] = { { LDAP_ATTR_DESC, "description" }, { LDAP_ATTR_DISPLAY_NAME, "displayName" }, { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL } }; @@ -135,6 +137,7 @@ ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { ATTRIB_MAP_ENTRY idpool_attr_list[] = { { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL } }; @@ -142,6 +145,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { { LDAP_ATTR_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL } }; diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 54a852601a..de919ef6f9 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -347,6 +347,10 @@ static void pdb_free_sam_contents(SAM_ACCOUNT *user) data_blob_clear_free(&(user->private.nt_pw)); if (user->private.plaintext_pw!=NULL) memset(user->private.plaintext_pw,'\0',strlen(user->private.plaintext_pw)); + + if (user->private.backend_private_data && user->private.backend_private_data_free_fn) { + user->private.backend_private_data_free_fn(&user->private.backend_private_data); + } } diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index c95719451a..e0b9f0e0ec 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -330,6 +330,14 @@ uint32 pdb_get_unknown_6 (const SAM_ACCOUNT *sampass) return (-1); } +void *pdb_get_backend_private_data (const SAM_ACCOUNT *sampass, const struct pdb_methods *my_methods) +{ + if (sampass && my_methods == sampass->methods) + return sampass->private.backend_private_data; + else + return NULL; +} + /********************************************************************* Collection of set...() functions for SAM_ACCOUNT. ********************************************************************/ @@ -1011,6 +1019,28 @@ BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_sta return pdb_set_init_flags(sampass, PDB_HOURS, flag); } +BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data, + void (*free_fn)(void **), + const struct pdb_methods *my_methods, + enum pdb_value_state flag) +{ + if (!sampass) + return False; + + /* does this backend 'own' this SAM_ACCOUNT? */ + if (my_methods != sampass->methods) + return False; + + if (sampass->private.backend_private_data && sampass->private.backend_private_data_free_fn) { + sampass->private.backend_private_data_free_fn(&sampass->private.backend_private_data); + } + + sampass->private.backend_private_data = private_data; + sampass->private.backend_private_data_free_fn = free_fn; + + return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag); +} + /* Helpful interfaces to the above */ diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 6911cea369..140b87afb9 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -107,6 +107,16 @@ struct ldapsam_privates { }; +/********************************************************************** + Free a LDAPMessage (one is stored on the SAM_ACCOUNT) + **********************************************************************/ + +static void private_data_free_fn(void **result) +{ + ldap_memfree(*result); + *result = NULL; +} + /********************************************************************** get the attribute name given a user schame version **********************************************************************/ @@ -1503,7 +1513,9 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } - ldap_msgfree(result); + pdb_set_backend_private_data(user, result, + private_data_free_fn, + my_methods, PDB_CHANGED); ret = NT_STATUS_OK; } else { ldap_msgfree(result); @@ -1591,9 +1603,13 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } + pdb_set_backend_private_data(user, result, + private_data_free_fn, + my_methods, PDB_CHANGED); ret = NT_STATUS_OK; + } else { + ldap_msgfree(result); } - ldap_msgfree(result); return ret; } @@ -1789,15 +1805,18 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A LDAPMod **mods; char **attr_list; - attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list ); - free_attr_list( attr_list ); - if (rc != LDAP_SUCCESS) - return NT_STATUS_UNSUCCESSFUL; + result = pdb_get_backend_private_data(newpwd, my_methods); + if (!result) { + attr_list = get_userattr_list(ldap_state->schema_ver); + rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list ); + free_attr_list( attr_list ); + if (rc != LDAP_SUCCESS) + return NT_STATUS_UNSUCCESSFUL; + pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED); + } if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) { DEBUG(0, ("No user to modify!\n")); - ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -1807,12 +1826,9 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, element_is_changed)) { DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n")); - ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - ldap_msgfree(result); - if (mods == NULL) { DEBUG(4,("mods is empty: nothing to update for user: %s\n", pdb_get_username(newpwd))); diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c index 3125c647d6..8c66ef9ab0 100644 --- a/source3/sam/idmap_util.c +++ b/source3/sam/idmap_util.c @@ -402,5 +402,16 @@ BOOL idmap_init_wellknown_sids(void) SAFE_FREE(map); } + /* Fill in the SID for the administrator account. */ + id.uid = 0; + sid_copy(&sid, get_global_sam_sid()); + sid_append_rid(&sid, DOMAIN_USER_RID_ADMIN); + + if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_USERID))) { + DEBUG(0, ("Failed to setup UID mapping for ADMINISTRATOR (%s) to (%u)\n", + sid_to_string(sid_string, &sid), (unsigned int)id.uid)); + return False; + } + return True; } diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index ada2d274ba..881ea96db6 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -409,10 +409,11 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) SAM_ACCOUNT *sam_account=NULL; GROUP_MAP map; struct group *grp; - DOM_SID sid; + DOM_SID user_sid; + DOM_SID group_sid; struct passwd *passwd; unid_t id; - int u_type; + int u_type = ID_USERID | ID_QUERY_ONLY; fstrcpy(account, unistr2_static(&delta->uni_acct_name)); d_printf("Creating account: %s\n", account); @@ -444,55 +445,56 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) passwd = Get_Pwnam(account); } } + + sid_copy(&user_sid, get_global_sam_sid()); + sid_append_rid(&user_sid, delta->user_rid); - sam_account_from_delta(sam_account, delta); - if (!pdb_add_sam_account(sam_account)) { - DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n", - account)); + if (!pdb_getsampwsid(sam_account, &user_sid)) { + sam_account_from_delta(sam_account, delta); + if (!pdb_add_sam_account(sam_account)) { + DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n", + account)); + return NT_STATUS_ACCESS_DENIED; + } + } else { + sam_account_from_delta(sam_account, delta); if (!pdb_update_sam_account(sam_account)) { DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n", account)); pdb_free_sam(&sam_account); - return NT_STATUS_OK; -/* return NT_STATUS_ACCESS_DENIED; */ + return NT_STATUS_ACCESS_DENIED; } } - sid = *pdb_get_group_sid(sam_account); + group_sid = *pdb_get_group_sid(sam_account); - if (!pdb_getgrsid(&map, sid)) { + if (!pdb_getgrsid(&map, group_sid)) { DEBUG(0, ("Primary group of %s has no mapping!\n", pdb_get_username(sam_account))); - pdb_free_sam(&sam_account); - return NT_STATUS_NO_SUCH_GROUP; - } - + } else { + if (map.gid != passwd->pw_gid) { + if (!(grp = getgrgid(map.gid))) { + DEBUG(0, ("Could not find unix group %d for user %s (group SID=%s)\n", + map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid))); + } else { + smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account)); + } + } + } + if (!passwd) { + DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n", pdb_get_username(sam_account))); /* if no unix user, changing the mapping won't help */ - pdb_free_sam(&sam_account); - return NT_STATUS_OK; - } - - if (map.gid != passwd->pw_gid) { - if (!(grp = getgrgid(map.gid))) { - DEBUG(0, ("Could not find unix group %d for user %s (group SID=%s)\n", - map.gid, pdb_get_username(sam_account), sid_string_static(&sid))); - pdb_free_sam(&sam_account); - return NT_STATUS_NO_SUCH_GROUP; + } else { + nt_ret = idmap_get_id_from_sid(&id, &u_type, pdb_get_user_sid(sam_account)); + if (NT_STATUS_IS_OK(nt_ret) && (u_type == ID_USERID) && (id.uid == passwd->pw_uid)) { + + } else { + /* set mapping */ + + id.uid = passwd->pw_uid; + nt_ret = idmap_set_mapping(pdb_get_user_sid(sam_account), id, ID_USERID); } - - smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account)); - } - - nt_ret = idmap_get_id_from_sid(&id, &u_type, pdb_get_user_sid(sam_account)); - if (!NT_STATUS_IS_OK(nt_ret)) { - pdb_free_sam(&sam_account); - return nt_ret; - } - - if ((u_type != ID_USERID) || (id.uid != passwd->pw_uid)) { - id.uid = passwd->pw_uid; - nt_ret = idmap_set_mapping(pdb_get_user_sid(sam_account), id, ID_USERID); } pdb_free_sam(&sam_account); @@ -980,6 +982,11 @@ int rpc_vampire(int argc, const char **argv) ZERO_STRUCT(ret_creds); + if (!idmap_init(lp_idmap_backend())) { + d_printf("Could not init idmap\n"); + return -1; + } + /* Connect to remote machine */ if (!(cli = net_make_ipc_connection(NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC))) { -- cgit