From cee64b535355ed14aa8c9a30f51432563391ea34 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Feb 2003 12:21:01 +0000 Subject: Kill RID-only and domain+RID madness from winbind. Now we deal with SIDs in almost all of winbind (a couple of limited exceptions remain, but I'm looking into them - they use non-winbind structs ATM). This has particular benifits in returning out-of-domain SIDs for group membership (Need to look into this a bit more) as well as general code quality. This also removes much of the complexity from the idmap interface, which now only deals with mapping IDs, not with SID->domain translations. Breifly tested, but needs more. Fixes some valgrind-found bugs from my previous commit. Winbind cache chagned to using SID strings in some places, as I could not follow exactly how to save and restore multiple packed sids properly. Andrew Bartlett (This used to be commit 9247cf08c40f016a924d600ac906cfc6a7016777) --- source3/nsswitch/winbindd.h | 28 +++--- source3/nsswitch/winbindd_ads.c | 178 ++++++++++++++++++---------------- source3/nsswitch/winbindd_cache.c | 159 +++++++++++++++++------------- source3/nsswitch/winbindd_group.c | 114 +++++++++++----------- source3/nsswitch/winbindd_idmap.c | 82 ---------------- source3/nsswitch/winbindd_idmap_tdb.c | 78 --------------- source3/nsswitch/winbindd_rpc.c | 93 ++++++++++++------ source3/nsswitch/winbindd_user.c | 56 +++++------ source3/nsswitch/winbindd_util.c | 29 +++++- 9 files changed, 377 insertions(+), 440 deletions(-) (limited to 'source3/nsswitch') diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index a498b76626..8bd8a83748 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -63,7 +63,8 @@ struct getent_state { struct getpwent_user { fstring name; /* Account name */ fstring gecos; /* User information */ - uint32 user_rid, group_rid; /* NT user and group rids */ + DOM_SID user_sid; /* NT user and primary group SIDs */ + DOM_SID group_sid; }; /* Server state structure */ @@ -81,8 +82,8 @@ extern struct winbindd_state server_state; /* Server information */ typedef struct { char *acct_name; char *full_name; - uint32 user_rid; - uint32 group_rid; /* primary group */ + DOM_SID *user_sid; /* NT user and primary group SIDs */ + DOM_SID *group_sid; } WINBIND_USERINFO; /* Structures to hold per domain information */ @@ -138,6 +139,7 @@ struct winbindd_methods { /* convert one user or group name to a sid */ NTSTATUS (*name_to_sid)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, const char *name, DOM_SID *sid, enum SID_NAME_USE *type); @@ -149,10 +151,10 @@ struct winbindd_methods { char **name, enum SID_NAME_USE *type); - /* lookup user info for a given rid */ + /* lookup user info for a given SID */ NTSTATUS (*query_user)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, + DOM_SID *user_sid, WINBIND_USERINFO *user_info); /* lookup all groups that a user is a member of. The backend @@ -160,14 +162,15 @@ struct winbindd_methods { function */ NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, - uint32 *num_groups, uint32 **user_gids); + DOM_SID *user_sid, + uint32 *num_groups, DOM_SID ***user_gids); /* find all members of the group with the specified group_rid */ NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 group_rid, uint32 *num_names, - uint32 **rid_mem, char ***names, + DOM_SID *group_sid, + uint32 *num_names, + DOM_SID ***sid_mem, char ***names, uint32 **name_types); /* return the current global sequence number */ @@ -207,13 +210,6 @@ struct idmap_methods { BOOL (*get_uid_from_sid)(DOM_SID *sid, uid_t *uid); BOOL (*get_gid_from_sid)(DOM_SID *sid, gid_t *gid); - BOOL (*get_rid_from_uid)(uid_t uid, uint32 *user_rid, - struct winbindd_domain **domain); - BOOL (*get_rid_from_gid)(gid_t gid, uint32 *group_rid, - struct winbindd_domain **domain); - BOOL (*get_uid_from_rid)(const char *dom_name, uint32 rid, uid_t *uid); - BOOL (*get_gid_from_rid)(const char *dom_name, uint32 rid, gid_t *gid); - /* Called when backend is unloaded */ BOOL (*close)(void); /* Called to dump backend status */ diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 22e4648f15..6c79e59bae 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -89,13 +89,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) return ads; } -/* useful utility */ -static void sid_from_rid(struct winbindd_domain *domain, uint32 rid, DOM_SID *sid) -{ - sid_copy(sid, &domain->sid); - sid_append_rid(sid, rid); -} - /* Query display info for a realm. This is the basic user list fn */ static NTSTATUS query_user_list(struct winbindd_domain *domain, @@ -144,7 +137,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { char *name, *gecos; DOM_SID sid; - uint32 rid, group; + DOM_SID *sid2; + DOM_SID *group_sid; + uint32 group; uint32 atype; if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) || @@ -164,15 +159,20 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, continue; } - if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { - DEBUG(1,("No rid for %s !?\n", name)); - continue; + sid2 = talloc(mem_ctx, sizeof(*sid2)); + if (!sid2) { + status = NT_STATUS_NO_MEMORY; + goto done; } + sid_copy(sid2, &sid); + + group_sid = rid_to_talloced_sid(domain, mem_ctx, group); + (*info)[i].acct_name = name; (*info)[i].full_name = gecos; - (*info)[i].user_rid = rid; - (*info)[i].group_rid = group; + (*info)[i].user_sid = sid2; + (*info)[i].group_sid = group_sid; i++; } @@ -297,6 +297,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, /* convert a single name to a sid in a domain */ static NTSTATUS name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, const char *name, DOM_SID *sid, enum SID_NAME_USE *type) @@ -329,13 +330,13 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, } -/* convert a DN to a name, rid and name type +/* convert a DN to a name, SID and name type this might become a major speed bottleneck if groups have lots of users, in which case we could cache the results */ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *dn, - char **name, uint32 *name_type, uint32 *rid) + char **name, uint32 *name_type, DOM_SID *sid) { char *exp; void *res = NULL; @@ -343,7 +344,6 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, "objectSid", "sAMAccountType", NULL}; ADS_STATUS rc; uint32 atype; - DOM_SID sid; char *escaped_dn = escape_ldap_string_alloc(dn); if (!escaped_dn) { @@ -366,8 +366,7 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, } (*name_type) = ads_atype_map(atype); - if (!ads_pull_sid(ads, res, "objectSid", &sid) || - !sid_peek_rid(&sid, rid)) { + if (!ads_pull_sid(ads, res, "objectSid", sid)) { goto failed; } @@ -382,60 +381,63 @@ failed: /* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, + DOM_SID *sid, WINBIND_USERINFO *info) { ADS_STRUCT *ads = NULL; const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "name", "objectSid", + "name", "primaryGroupID", NULL}; ADS_STATUS rc; int count; void *msg = NULL; char *exp; - DOM_SID sid; char *sidstr; + uint32 group_rid; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + DOM_SID *sid2; + fstring sid_string; DEBUG(3,("ads: query_user\n")); - sid_from_rid(domain, user_rid, &sid); - ads = ads_cached_connection(domain); if (!ads) goto done; - sidstr = sid_binstring(&sid); + sidstr = sid_binstring(sid); asprintf(&exp, "(objectSid=%s)", sidstr); rc = ads_search_retry(ads, &msg, exp, attrs); free(exp); free(sidstr); if (!ADS_ERR_OK(rc)) { - DEBUG(1,("query_user(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); + DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); goto done; } count = ads_count_replies(ads, msg); if (count != 1) { - DEBUG(1,("query_user(rid=%d): Not found\n", user_rid)); + DEBUG(1,("query_user(sid=%s): Not found\n", sid_to_string(sid_string, sid))); goto done; } info->acct_name = ads_pull_username(ads, mem_ctx, msg); info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); - if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { - DEBUG(1,("No sid for %d !?\n", user_rid)); - goto done; - } - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &info->group_rid)) { - DEBUG(1,("No primary group for %d !?\n", user_rid)); + + if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) { + DEBUG(1,("No primary group for %s !?\n", sid_to_string(sid_string, sid))); goto done; } - if (!sid_peek_check_rid(&domain->sid,&sid, &info->user_rid)) { - DEBUG(1,("No rid for %d !?\n", user_rid)); + sid2 = talloc(mem_ctx, sizeof(*sid2)); + if (!sid2) { + status = NT_STATUS_NO_MEMORY; goto done; } + sid_copy(sid2, sid); + + info->user_sid = sid2; + + info->group_sid = rid_to_talloced_sid(domain, mem_ctx, group_rid); status = NT_STATUS_OK; @@ -451,8 +453,8 @@ done: static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *user_dn, - uint32 primary_group, - uint32 *num_groups, uint32 **user_gids) + DOM_SID *primary_group, + uint32 *num_groups, DOM_SID ***user_gids) { ADS_STATUS rc; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; @@ -489,47 +491,48 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, goto done; } - (*user_gids) = (uint32 *)talloc_zero(mem_ctx, sizeof(uint32) * (count + 1)); + (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1)); (*user_gids)[0] = primary_group; *num_groups = 1; for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - uint32 rid; DOM_SID group_sid; - fstring sid_string; if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) { DEBUG(1,("No sid for this group ?!?\n")); continue; } - if (!sid_peek_check_rid(&domain->sid, &group_sid, &rid)) { - DEBUG(5,("sid for %s is out of domain or invalid\n", sid_to_string(sid_string, &group_sid))); - continue; - } - if (rid == primary_group) continue; + if (sid_equal(&group_sid, primary_group)) continue; - (*user_gids)[*num_groups] = rid; + (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); + if (!(*user_gids)[*num_groups]) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + sid_copy((*user_gids)[*num_groups], &group_sid); + (*num_groups)++; } - if (res) ads_msgfree(ads, res); - if (msg) ads_msgfree(ads, msg); - status = NT_STATUS_OK; DEBUG(3,("ads lookup_usergroups (alt) for dn=%s\n", user_dn)); done: + if (res) ads_msgfree(ads, res); + if (msg) ads_msgfree(ads, msg); + return status; } /* Lookup groups a user is a member of. */ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, - uint32 *num_groups, uint32 **user_gids) + DOM_SID *sid, + uint32 *num_groups, DOM_SID ***user_gids) { ADS_STRUCT *ads = NULL; const char *attrs[] = {"distinguishedName", NULL}; @@ -541,27 +544,26 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, char *user_dn; DOM_SID *sids; int i; - uint32 primary_group; - DOM_SID sid; + DOM_SID *primary_group; + uint32 primary_group_rid; char *sidstr; + fstring sid_string; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; DEBUG(3,("ads: lookup_usergroups\n")); *num_groups = 0; - sid_from_rid(domain, user_rid, &sid); - ads = ads_cached_connection(domain); if (!ads) goto done; - if (!(sidstr = sid_binstring(&sid))) { - DEBUG(1,("lookup_usergroups(rid=%d) sid_binstring returned NULL\n", user_rid)); + if (!(sidstr = sid_binstring(sid))) { + DEBUG(1,("lookup_usergroups(sid=%s) sid_binstring returned NULL\n", sid_to_string(sid_string, sid))); status = NT_STATUS_NO_MEMORY; goto done; } if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) { free(sidstr); - DEBUG(1,("lookup_usergroups(rid=%d) asprintf failed!\n", user_rid)); + DEBUG(1,("lookup_usergroups(sid=%s) asprintf failed!\n", sid_to_string(sid_string, sid))); status = NT_STATUS_NO_MEMORY; goto done; } @@ -571,13 +573,13 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, free(sidstr); if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); + DEBUG(1,("lookup_usergroups(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); goto done; } user_dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName"); if (!user_dn) { - DEBUG(1,("lookup_usergroups(rid=%d) ads_search did not return a a distinguishedName!\n", user_rid)); + DEBUG(1,("lookup_usergroups(sid=%s) ads_search did not return a a distinguishedName!\n", sid_to_string(sid_string, sid))); goto done; } @@ -585,15 +587,17 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups(rid=%d) ads_search tokenGroups: %s\n", user_rid, ads_errstr(rc))); + DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); goto done; } - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group)) { - DEBUG(1,("%s: No primary group for rid=%d !?\n", domain->name, user_rid)); + if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) { + DEBUG(1,("%s: No primary group for sid=%s !?\n", domain->name, sid_to_string(sid_string, sid))); goto done; } + primary_group = rid_to_talloced_sid(domain, mem_ctx, primary_group_rid); + count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); if (msg) ads_msgfree(ads, msg); @@ -602,25 +606,30 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, unless we are talking to a buggy Win2k server */ if (count == 0) { return lookup_usergroups_alt(domain, mem_ctx, user_dn, - primary_group, - num_groups, user_gids); + primary_group, + num_groups, user_gids); } - (*user_gids) = (uint32 *)talloc_zero(mem_ctx, sizeof(uint32) * (count + 1)); + (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1)); (*user_gids)[0] = primary_group; *num_groups = 1; for (i=0;isid, &sids[i-1], &rid)) continue; - if (rid == primary_group) continue; - (*user_gids)[*num_groups] = rid; + if (sid_equal(&sids[i], primary_group)) continue; + + (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); + if (!(*user_gids)[*num_groups]) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + sid_copy((*user_gids)[*num_groups], &sids[i]); (*num_groups)++; } status = NT_STATUS_OK; - DEBUG(3,("ads lookup_usergroups for rid=%d\n", user_rid)); + DEBUG(3,("ads lookup_usergroups for sid=%s\n", sid_to_string(sid_string, sid))); done: return status; } @@ -630,11 +639,10 @@ done: */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 group_rid, uint32 *num_names, - uint32 **rid_mem, char ***names, + DOM_SID *group_sid, uint32 *num_names, + DOM_SID ***sid_mem, char ***names, uint32 **name_types) { - DOM_SID group_sid; ADS_STATUS rc; int count; void *res=NULL; @@ -645,14 +653,14 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, const char *attrs[] = {"member", NULL}; char **members; int i, num_members; + fstring sid_string; *num_names = 0; ads = ads_cached_connection(domain); if (!ads) goto done; - sid_from_rid(domain, group_rid, &group_sid); - sidstr = sid_binstring(&group_sid); + sidstr = sid_binstring(group_sid); /* search for all members of the group */ asprintf(&exp, "(objectSid=%s)",sidstr); @@ -684,24 +692,30 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, for (i=0;members[i];i++) /* noop */ ; num_members = i; - (*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * num_members); - (*name_types) = talloc_zero(mem_ctx, sizeof(uint32) * num_members); - (*names) = talloc_zero(mem_ctx, sizeof(char *) * num_members); + (*sid_mem) = talloc_zero(mem_ctx, sizeof(**sid_mem) * num_members); + (*name_types) = talloc_zero(mem_ctx, sizeof(**name_types) * num_members); + (*names) = talloc_zero(mem_ctx, sizeof(**names) * num_members); for (i=0;iofs += len; } +static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid) +{ + int len; + fstring sid_string; + centry_put_string(centry, sid_to_string(sid_string, sid)); +} + /* start a centry for output. When finished, call centry_end() */ @@ -393,6 +420,7 @@ struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status /* finish a centry and write it to the tdb */ +static void centry_end(struct cache_entry *centry, const char *format, ...) PRINTF_ATTRIBUTE(2,3); static void centry_end(struct cache_entry *centry, const char *format, ...) { va_list ap; @@ -412,39 +440,30 @@ static void centry_end(struct cache_entry *centry, const char *format, ...) free(kstr); } -/* form a sid from the domain plus rid */ -static DOM_SID *form_sid(struct winbindd_domain *domain, uint32 rid) -{ - static DOM_SID sid; - sid_copy(&sid, &domain->sid); - sid_append_rid(&sid, rid); - return &sid; -} - -static void wcache_save_name_to_sid(struct winbindd_domain *domain, NTSTATUS status, - const char *name, DOM_SID *sid, enum SID_NAME_USE type) +static void wcache_save_name_to_sid(struct winbindd_domain *domain, + NTSTATUS status, + const char *name, DOM_SID *sid, + enum SID_NAME_USE type) { struct cache_entry *centry; uint32 len; fstring uname; + fstring sid_string; centry = centry_start(domain, status); if (!centry) return; - len = sid_size(sid); - centry_expand(centry, len); - centry_put_uint32(centry, type); - sid_linearize(centry->data + centry->ofs, len, sid); - centry->ofs += len; + centry_put_sid(centry, sid); fstrcpy(uname, name); strupper(uname); - centry_end(centry, "NS/%s/%s", domain->name, uname); + centry_end(centry, "NS/%s", sid_to_string(sid_string, sid)); centry_free(centry); } static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, - DOM_SID *sid, const char *name, enum SID_NAME_USE type, uint32 rid) + DOM_SID *sid, const char *name, enum SID_NAME_USE type) { struct cache_entry *centry; + fstring sid_string; centry = centry_start(domain, status); if (!centry) return; @@ -452,7 +471,7 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta centry_put_uint32(centry, type); centry_put_string(centry, name); } - centry_end(centry, "SN/%s/%d", domain->name, rid); + centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); centry_free(centry); } @@ -460,14 +479,15 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WINBIND_USERINFO *info) { struct cache_entry *centry; + fstring sid_string; centry = centry_start(domain, status); if (!centry) return; centry_put_string(centry, info->acct_name); centry_put_string(centry, info->full_name); - centry_put_uint32(centry, info->user_rid); - centry_put_uint32(centry, info->group_rid); - centry_end(centry, "U/%s/%d", domain->name, info->user_rid); + centry_put_sid(centry, info->user_sid); + centry_put_sid(centry, info->group_sid); + centry_end(centry, "U/%s", sid_to_string(sid_string, info->user_sid)); centry_free(centry); } @@ -481,7 +501,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - int i; + unsigned int i; if (!cache->tdb) goto do_query; @@ -497,8 +517,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, for (i=0; i<(*num_entries); i++) { (*info)[i].acct_name = centry_string(centry, mem_ctx); (*info)[i].full_name = centry_string(centry, mem_ctx); - (*info)[i].user_rid = centry_uint32(centry); - (*info)[i].group_rid = centry_uint32(centry); + (*info)[i].user_sid = centry_sid(centry, mem_ctx); + (*info)[i].group_sid = centry_sid(centry, mem_ctx); } do_cached: @@ -524,18 +544,18 @@ do_query: for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].full_name); - centry_put_uint32(centry, (*info)[i].user_rid); - centry_put_uint32(centry, (*info)[i].group_rid); + centry_put_sid(centry, (*info)[i].user_sid); + centry_put_sid(centry, (*info)[i].group_sid); if (cache->backend->consistent) { /* when the backend is consistent we can pre-prime some mappings */ wcache_save_name_to_sid(domain, NT_STATUS_OK, (*info)[i].acct_name, - form_sid(domain, (*info)[i].user_rid), + (*info)[i].user_sid, SID_NAME_USER); wcache_save_sid_to_name(domain, NT_STATUS_OK, - form_sid(domain, (*info)[i].user_rid), + (*info)[i].user_sid, (*info)[i].acct_name, - SID_NAME_USER, (*info)[i].user_rid); + SID_NAME_USER); wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); } } @@ -555,7 +575,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - int i; + unsigned int i; if (!cache->tdb) goto do_query; @@ -615,7 +635,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - int i; + unsigned int i; if (!cache->tdb) goto do_query; @@ -669,7 +689,7 @@ do_query: centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].acct_desc); centry_put_uint32(centry, (*info)[i].rid); - } + } centry_end(centry, "GL/%s/local", domain->name); centry_free(centry); @@ -679,6 +699,7 @@ skip_save: /* convert a single name to a sid in a domain */ static NTSTATUS name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, const char *name, DOM_SID *sid, enum SID_NAME_USE *type) @@ -687,6 +708,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, struct cache_entry *centry = NULL; NTSTATUS status; fstring uname; + DOM_SID *sid2; if (!cache->tdb) goto do_query; @@ -695,7 +717,12 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); if (!centry) goto do_query; *type = centry_uint32(centry); - sid_parse(centry->data + centry->ofs, centry->len - centry->ofs, sid); + sid2 = centry_sid(centry, mem_ctx); + if (!sid2) { + ZERO_STRUCTP(sid); + } else { + sid_copy(sid, sid2); + } status = centry->status; centry_free(centry); @@ -707,7 +734,7 @@ do_query: if (wcache_server_down(domain)) { return NT_STATUS_SERVER_DISABLED; } - status = cache->backend->name_to_sid(domain, name, sid, type); + status = cache->backend->name_to_sid(domain, mem_ctx, name, sid, type); /* and save it */ wcache_save_name_to_sid(domain, status, name, sid, *type); @@ -729,14 +756,11 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - uint32 rid = 0; - - if (!sid_peek_check_rid(&domain->sid, sid, &rid)) - return NT_STATUS_INVALID_PARAMETER; + fstring sid_string; if (!cache->tdb) goto do_query; - centry = wcache_fetch(cache, domain, "SN/%s/%d", domain->name, rid); + centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid)); if (!centry) goto do_query; if (NT_STATUS_IS_OK(centry->status)) { *type = centry_uint32(centry); @@ -756,7 +780,7 @@ do_query: /* and save it */ refresh_sequence_number(domain, True); - wcache_save_sid_to_name(domain, status, sid, *name, *type, rid); + wcache_save_sid_to_name(domain, status, sid, *name, *type); wcache_save_name_to_sid(domain, status, *name, sid, *type); return status; @@ -766,22 +790,23 @@ do_query: /* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, + DOM_SID *user_sid, WINBIND_USERINFO *info) { struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; + fstring sid_string; if (!cache->tdb) goto do_query; - centry = wcache_fetch(cache, domain, "U/%s/%d", domain->name, user_rid); + centry = wcache_fetch(cache, domain, "U/%s", sid_to_string(sid_string, user_sid)); if (!centry) goto do_query; info->acct_name = centry_string(centry, mem_ctx); info->full_name = centry_string(centry, mem_ctx); - info->user_rid = centry_uint32(centry); - info->group_rid = centry_uint32(centry); + info->user_sid = centry_sid(centry, mem_ctx); + info->group_sid = centry_sid(centry, mem_ctx); status = centry->status; centry_free(centry); return status; @@ -793,7 +818,7 @@ do_query: return NT_STATUS_SERVER_DISABLED; } - status = cache->backend->query_user(domain, mem_ctx, user_rid, info); + status = cache->backend->query_user(domain, mem_ctx, user_sid, info); /* and save it */ refresh_sequence_number(domain, True); @@ -806,17 +831,18 @@ do_query: /* Lookup groups a user is a member of. */ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, - uint32 *num_groups, uint32 **user_gids) + DOM_SID *user_sid, + uint32 *num_groups, DOM_SID ***user_gids) { struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - int i; + unsigned int i; + fstring sid_string; if (!cache->tdb) goto do_query; - centry = wcache_fetch(cache, domain, "UG/%s/%d", domain->name, user_rid); + centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid)); if (!centry) goto do_query; *num_groups = centry_uint32(centry); @@ -826,7 +852,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, (*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups)); if (! (*user_gids)) smb_panic("lookup_usergroups out of memory"); for (i=0; i<(*num_groups); i++) { - (*user_gids)[i] = centry_uint32(centry); + (*user_gids)[i] = centry_sid(centry, mem_ctx); } do_cached: @@ -841,7 +867,7 @@ do_query: if (wcache_server_down(domain)) { return NT_STATUS_SERVER_DISABLED; } - status = cache->backend->lookup_usergroups(domain, mem_ctx, user_rid, num_groups, user_gids); + status = cache->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); /* and save it */ refresh_sequence_number(domain, True); @@ -849,9 +875,9 @@ do_query: if (!centry) goto skip_save; centry_put_uint32(centry, *num_groups); for (i=0; i<(*num_groups); i++) { - centry_put_uint32(centry, (*user_gids)[i]); + centry_put_sid(centry, (*user_gids)[i]); } - centry_end(centry, "UG/%s/%d", domain->name, user_rid); + centry_end(centry, "UG/%s", sid_to_string(sid_string, user_sid)); centry_free(centry); skip_save: @@ -861,34 +887,35 @@ skip_save: static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 group_rid, uint32 *num_names, - uint32 **rid_mem, char ***names, + DOM_SID *group_sid, uint32 *num_names, + DOM_SID ***sid_mem, char ***names, uint32 **name_types) { struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - int i; + unsigned int i; + fstring sid_string; if (!cache->tdb) goto do_query; - centry = wcache_fetch(cache, domain, "GM/%s/%d", domain->name, group_rid); + centry = wcache_fetch(cache, domain, "GM/%s", sid_to_string(sid_string, group_sid)); if (!centry) goto do_query; *num_names = centry_uint32(centry); if (*num_names == 0) goto do_cached; - (*rid_mem) = talloc(mem_ctx, sizeof(**rid_mem) * (*num_names)); + (*sid_mem) = talloc(mem_ctx, sizeof(**sid_mem) * (*num_names)); (*names) = talloc(mem_ctx, sizeof(**names) * (*num_names)); (*name_types) = talloc(mem_ctx, sizeof(**name_types) * (*num_names)); - if (! (*rid_mem) || ! (*names) || ! (*name_types)) { + if (! (*sid_mem) || ! (*names) || ! (*name_types)) { smb_panic("lookup_groupmem out of memory"); } for (i=0; i<(*num_names); i++) { - (*rid_mem)[i] = centry_uint32(centry); + (*sid_mem)[i] = centry_sid(centry, mem_ctx); (*names)[i] = centry_string(centry, mem_ctx); (*name_types)[i] = centry_uint32(centry); } @@ -900,7 +927,7 @@ do_cached: do_query: (*num_names) = 0; - (*rid_mem) = NULL; + (*sid_mem) = NULL; (*names) = NULL; (*name_types) = NULL; @@ -908,8 +935,8 @@ do_query: if (wcache_server_down(domain)) { return NT_STATUS_SERVER_DISABLED; } - status = cache->backend->lookup_groupmem(domain, mem_ctx, group_rid, num_names, - rid_mem, names, name_types); + status = cache->backend->lookup_groupmem(domain, mem_ctx, group_sid, num_names, + sid_mem, names, name_types); /* and save it */ refresh_sequence_number(domain, True); @@ -917,11 +944,11 @@ do_query: if (!centry) goto skip_save; centry_put_uint32(centry, *num_names); for (i=0; i<(*num_names); i++) { - centry_put_uint32(centry, (*rid_mem)[i]); + centry_put_sid(centry, (*sid_mem)[i]); centry_put_string(centry, (*names)[i]); centry_put_uint32(centry, (*name_types)[i]); } - centry_end(centry, "GM/%s/%d", domain->name, group_rid); + centry_end(centry, "GM/%s", sid_to_string(sid_string, group_sid)); centry_free(centry); skip_save: diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 94a826fbbc..d06db5943c 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -49,43 +49,44 @@ static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name, return True; } -/* Fill in the group membership field of a NT group given by group_rid */ +/* Fill in the group membership field of a NT group given by group_sid */ static BOOL fill_grent_mem(struct winbindd_domain *domain, - uint32 group_rid, + DOM_SID *group_sid, enum SID_NAME_USE group_name_type, int *num_gr_mem, char **gr_mem, int *gr_mem_len) { - uint32 *rid_mem = NULL, num_names = 0; + DOM_SID **sid_mem = NULL; + uint32 num_names = 0; uint32 *name_types = NULL; - int buf_len, buf_ndx, i; + unsigned int buf_len, buf_ndx, i; char **names = NULL, *buf; BOOL result = False; TALLOC_CTX *mem_ctx; NTSTATUS status; + fstring sid_string; if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name))) return False; /* Initialise group membership information */ - DEBUG(10, ("group %s rid 0x%x\n", domain ? domain->name : "NULL", - group_rid)); + DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid))); *num_gr_mem = 0; if (group_name_type != SID_NAME_DOM_GRP) { - DEBUG(1, ("rid %d in domain %s isn't a domain group\n", - group_rid, domain->name)); + DEBUG(1, ("SID %s in domain %s isn't a domain group\n", + sid_to_string(sid_string, group_sid), domain->name)); goto done; } /* Lookup group members */ - status = domain->methods->lookup_groupmem(domain, mem_ctx, group_rid, &num_names, - &rid_mem, &names, &name_types); + status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names, + &sid_mem, &names, &name_types); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("could not lookup membership for group rid %d in domain %s (error: %s)\n", - group_rid, domain->name, nt_errstr(status))); + DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n", + sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status))); goto done; } @@ -94,7 +95,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, if (DEBUGLEVEL >= 10) { for (i = 0; i < num_names; i++) - DEBUG(10, ("\t%20s %x %d\n", names[i], rid_mem[i], + DEBUG(10, ("\t%20s %s %d\n", names[i], sid_to_string(sid_string, sid_mem[i]), name_types[i])); } @@ -190,7 +191,6 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) DOM_SID group_sid; struct winbindd_domain *domain; enum SID_NAME_USE name_type; - uint32 group_rid; fstring name_domain, name_group; char *tmp, *gr_mem; gid_t gid; @@ -233,10 +233,6 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - /* Fill in group structure */ - if (!sid_peek_check_rid(&domain->sid, &group_sid, &group_rid)) - return WINBINDD_ERROR; - if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) { DEBUG(1, ("error converting unix gid to sid\n")); return WINBINDD_ERROR; @@ -244,7 +240,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) if (!fill_grent(&state->response.data.gr, name_domain, name_group, gid) || - !fill_grent_mem(domain, group_rid, name_type, + !fill_grent_mem(domain, &group_sid, name_type, &state->response.data.gr.num_gr_mem, &gr_mem, &gr_mem_len)) { return WINBINDD_ERROR; @@ -269,7 +265,6 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) enum SID_NAME_USE name_type; fstring dom_name; fstring group_name; - uint32 group_rid; int gr_mem_len; char *gr_mem; @@ -284,17 +279,13 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) /* Get rid from gid */ - if (!winbindd_idmap_get_rid_from_gid(state->request.data.gid, - &group_rid, &domain)) { + if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &group_sid)) { DEBUG(1, ("could not convert gid %d to rid\n", state->request.data.gid)); return WINBINDD_ERROR; } - /* Get sid from gid */ - - sid_copy(&group_sid, &domain->sid); - sid_append_rid(&group_sid, group_rid); + /* Get name from sid */ if (!winbindd_lookup_name_by_sid(&group_sid, dom_name, group_name, &name_type)) { DEBUG(1, ("could not lookup sid\n")); @@ -310,9 +301,16 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) /* Fill in group structure */ + domain = find_domain_from_sid(&group_sid); + + if (!domain) { + DEBUG(1,("Can't find domain from sid\n")); + return WINBINDD_ERROR; + } + if (!fill_grent(&state->response.data.gr, dom_name, group_name, state->request.data.gid) || - !fill_grent_mem(domain, group_rid, name_type, + !fill_grent_mem(domain, &group_sid, name_type, &state->response.data.gr.num_gr_mem, &gr_mem, &gr_mem_len)) return WINBINDD_ERROR; @@ -544,7 +542,9 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) gid_t group_gid; int gr_mem_len; char *gr_mem, *new_gr_mem_list; - + DOM_SID group_sid; + struct winbindd_domain *domain; + /* Do we need to fetch another chunk of groups? */ tryagain: @@ -578,16 +578,25 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) name_list = ent->sam_entries; + if (!(domain = + find_domain_from_name(ent->domain_name))) { + DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name)); + result = False; + goto done; + } + /* Lookup group info */ - if (!winbindd_idmap_get_gid_from_rid( - ent->domain_name, - name_list[ent->sam_entry_index].rid, - &group_gid)) { + sid_copy(&group_sid, &domain->sid); + sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); + + if (!winbindd_idmap_get_gid_from_sid( + &group_sid, + &group_gid)) { DEBUG(1, ("could not look up gid for group %s\n", name_list[ent->sam_entry_index].acct_name)); - + ent->sam_entry_index++; goto tryagain; } @@ -608,15 +617,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) /* Fill in group membership entry */ if (result) { - struct winbindd_domain *domain; - - if (!(domain = - find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name)); - result = False; - goto done; - } - + DOM_SID member_sid; group_list[group_list_ndx].num_gr_mem = 0; gr_mem = NULL; gr_mem_len = 0; @@ -625,9 +626,11 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) if (state->request.cmd == WINBINDD_GETGRLST) { result = True; } else { + sid_copy(&member_sid, &domain->sid); + sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid); result = fill_grent_mem( domain, - name_list[ent->sam_entry_index].rid, + &member_sid, SID_NAME_DOM_GRP, &group_list[group_list_ndx].num_gr_mem, &gr_mem, &gr_mem_len); @@ -730,7 +733,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) struct winbindd_domain *domain; char *extra_data = NULL; char *ted = NULL; - int extra_data_len = 0, i; + unsigned int extra_data_len = 0, i; DEBUG(3, ("[%5d]: list groups\n", state->pid)); @@ -805,13 +808,13 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) fstring name_domain, name_user; DOM_SID user_sid; enum SID_NAME_USE name_type; - uint32 user_rid, num_groups, num_gids; + uint32 num_groups, num_gids; NTSTATUS status; - uint32 *user_gids; + DOM_SID **user_gids; struct winbindd_domain *domain; enum winbindd_result result = WINBINDD_ERROR; gid_t *gid_list; - int i; + unsigned int i; TALLOC_CTX *mem_ctx; /* Ensure null termination */ @@ -852,9 +855,9 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) goto done; } - sid_split_rid(&user_sid, &user_rid); - - status = domain->methods->lookup_usergroups(domain, mem_ctx, user_rid, &num_groups, &user_gids); + status = domain->methods->lookup_usergroups(domain, mem_ctx, + &user_sid, &num_groups, + &user_gids); if (!NT_STATUS_IS_OK(status)) goto done; /* Copy data back to client */ @@ -866,12 +869,13 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) goto done; for (i = 0; i < num_groups; i++) { - if (!winbindd_idmap_get_gid_from_rid(domain->name, - user_gids[i], - &gid_list[num_gids])) { + if (!winbindd_idmap_get_gid_from_sid( + user_gids[i], + &gid_list[num_gids])) { + fstring sid_string; - DEBUG(1, ("unable to convert group rid %d to gid\n", - user_gids[i])); + DEBUG(1, ("unable to convert group sid %s to gid\n", + sid_to_string(sid_string, user_gids[i]))); continue; } diff --git a/source3/nsswitch/winbindd_idmap.c b/source3/nsswitch/winbindd_idmap.c index 0a17fcd87f..de547cde41 100644 --- a/source3/nsswitch/winbindd_idmap.c +++ b/source3/nsswitch/winbindd_idmap.c @@ -121,48 +121,6 @@ BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid) return ret; } -/* Get UID from RID */ -BOOL winbindd_idmap_get_uid_from_rid(const char *dom_name, uint32 rid, - uid_t *uid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_uid_from_rid(dom_name, rid, uid); - } - - return ret; -} - -/* Get GID From RID */ -BOOL winbindd_idmap_get_gid_from_rid(const char *dom_name, uint32 rid, - gid_t *gid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_gid_from_rid(dom_name, rid, gid); - } - - return ret; -} - /* Get SID from UID */ BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid) { @@ -202,46 +160,6 @@ BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid) return ret; } -/* Get RID From UID */ -BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid, - struct winbindd_domain **domain) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - ret = impl->get_rid_from_uid(uid, user_rid, domain); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - - return ret; -} - -/* Get RID from GID */ -BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid, - struct winbindd_domain **domain) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - ret = impl->get_rid_from_gid(gid, group_rid, domain); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - - return ret; -} - /* Close backend */ BOOL winbindd_idmap_close(void) { diff --git a/source3/nsswitch/winbindd_idmap_tdb.c b/source3/nsswitch/winbindd_idmap_tdb.c index f27c3c1b5f..911b3b41d2 100644 --- a/source3/nsswitch/winbindd_idmap_tdb.c +++ b/source3/nsswitch/winbindd_idmap_tdb.c @@ -342,78 +342,6 @@ static BOOL tdb_get_gid_from_sid(DOM_SID * sid, gid_t * gid) return tdb_get_id_from_sid(sid, gid, True); } -/* Get a uid from a user rid */ -static BOOL tdb_get_uid_from_rid(const char *dom_name, uint32 rid, - uid_t * uid) -{ - struct winbindd_domain *domain; - DOM_SID sid; - - if (!(domain = find_domain_from_name(dom_name))) { - return False; - } - - sid_copy(&sid, &domain->sid); - sid_append_rid(&sid, rid); - - return tdb_get_id_from_sid(&sid, uid, False); -} - -/* Get a gid from a group rid */ -static BOOL tdb_get_gid_from_rid(const char *dom_name, uint32 rid, - gid_t * gid) -{ - struct winbindd_domain *domain; - DOM_SID sid; - - if (!(domain = find_domain_from_name(dom_name))) { - return False; - } - - sid_copy(&sid, &domain->sid); - sid_append_rid(&sid, rid); - - return tdb_get_id_from_sid(&sid, gid, True); -} - -/* Get a user rid from a uid */ -static BOOL tdb_get_rid_from_uid(uid_t uid, uint32 * user_rid, - struct winbindd_domain **domain) -{ - DOM_SID sid; - - if (!tdb_get_sid_from_id((int) uid, &sid, False)) { - return False; - } - - *domain = find_domain_from_sid(&sid); - if (!*domain) - return False; - - sid_split_rid(&sid, user_rid); - - return True; -} - -/* Get a group rid from a gid */ -static BOOL tdb_get_rid_from_gid(gid_t gid, uint32 * group_rid, - struct winbindd_domain **domain) -{ - DOM_SID sid; - - if (!tdb_get_sid_from_id((int) gid, &sid, True)) { - return False; - } - - *domain = find_domain_from_sid(&sid); - if (!*domain) - return False; - - sid_split_rid(&sid, group_rid); - - return True; -} - /* Close the tdb */ static BOOL tdb_idmap_close(void) { @@ -500,12 +428,6 @@ struct idmap_methods tdb_idmap_methods = { tdb_get_uid_from_sid, tdb_get_gid_from_sid, - tdb_get_rid_from_uid, - tdb_get_rid_from_gid, - - tdb_get_uid_from_rid, - tdb_get_gid_from_rid, - tdb_idmap_close, tdb_idmap_status diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 90d8e4f616..03b0a1e706 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -26,6 +26,7 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND + /* Query display info for a domain. This returns enough information plus a bit extra to give an overview of domain users for the User Manager application. */ @@ -39,7 +40,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, POLICY_HND dom_pol; BOOL got_dom_pol = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - int i, start_idx, retry; + unsigned int i, start_idx, retry; DEBUG(3,("rpc: query_user_list\n")); @@ -97,7 +98,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, (*info)[i].acct_name = talloc_strdup(mem_ctx, dom_users[j]); (*info)[i].full_name = talloc_strdup(mem_ctx, ""); - (*info)[i].user_rid = dom_rids[j]; + (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, dom_rids[j]); /* For the moment we set the primary group for every user to be the Domain Users group. There are serious problems with determining @@ -105,7 +106,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, This should really be made into a 'winbind force group' smb.conf parameter or something like that. */ - (*info)[i].group_rid = DOMAIN_GROUP_RID_USERS; + (*info)[i].user_sid + = rid_to_talloced_sid(domain, + mem_ctx, + DOMAIN_GROUP_RID_USERS); } talloc_destroy(ctx2); @@ -252,11 +256,11 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, /* convert a single name to a sid in a domain */ static NTSTATUS name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, const char *name, DOM_SID *sid, enum SID_NAME_USE *type) { - TALLOC_CTX *mem_ctx; CLI_POLICY_HND *hnd; NTSTATUS status; DOM_SID *sids = NULL; @@ -266,23 +270,16 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DEBUG(3,("rpc: name_to_sid name=%s\n", name)); - if (!(mem_ctx = talloc_init("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) { - DEBUG(0, ("talloc_init failed!\n")); - return NT_STATUS_NO_MEMORY; - } - full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name); if (!full_name) { DEBUG(0, ("talloc_asprintf failed!\n")); - talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } retry = 0; do { if (!(hnd = cm_get_lsa_handle(domain->name))) { - talloc_destroy(mem_ctx); return NT_STATUS_UNSUCCESSFUL; } @@ -297,7 +294,6 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, *type = types[0]; } - talloc_destroy(mem_ctx); return status; } @@ -345,17 +341,22 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, /* Lookup user information from a rid or username. */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, + DOM_SID *user_sid, WINBIND_USERINFO *user_info) { CLI_POLICY_HND *hnd; - NTSTATUS result; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol, user_pol; BOOL got_dom_pol = False, got_user_pol = False; SAM_USERINFO_CTR *ctr; int retry; + fstring sid_string; + uint32 user_rid; - DEBUG(3,("rpc: query_user rid=%u\n", user_rid)); + DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid))); + if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { + goto done; + } retry = 0; do { @@ -394,8 +395,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, cli_samr_close(hnd->cli, mem_ctx, &user_pol); got_user_pol = False; - user_info->user_rid = user_rid; - user_info->group_rid = ctr->info.id21->group_rid; + user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid); + user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid); user_info->acct_name = unistr2_tdup(mem_ctx, &ctr->info.id21->uni_user_name); user_info->full_name = unistr2_tdup(mem_ctx, @@ -415,8 +416,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, /* Lookup groups a user is a member of. I wish Unix had a call like this! */ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 user_rid, - uint32 *num_groups, uint32 **user_gids) + DOM_SID *user_sid, + uint32 *num_groups, DOM_SID ***user_gids) { CLI_POLICY_HND *hnd; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -424,15 +425,17 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_user_pol = False; DOM_GID *user_groups; - int i; - int retry; + unsigned int i; + unsigned int retry; + fstring sid_string; + uint32 user_rid; - DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid)); + DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid))); *num_groups = 0; /* First try cached universal groups from logon */ - *user_gids = uni_group_cache_fetch(&domain->sid, user_rid, mem_ctx, num_groups); + *user_gids = uni_group_cache_fetch(&domain->sid, user_sid, mem_ctx, num_groups); if((*num_groups > 0) && *user_gids) { return NT_STATUS_OK; } else { @@ -448,7 +451,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); + des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) @@ -456,6 +459,11 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, got_dom_pol = True; + + if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { + goto done; + } + /* Get user handle */ result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, des_access, user_rid, &user_pol); @@ -473,8 +481,13 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, goto done; (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups)); + if (!(*user_gids)) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + for (i=0;i<(*num_groups);i++) { - (*user_gids)[i] = user_groups[i].g_rid; + (*user_gids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid); } done: @@ -492,8 +505,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, /* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 group_rid, uint32 *num_names, - uint32 **rid_mem, char ***names, + DOM_SID *group_sid, uint32 *num_names, + DOM_SID ***sid_mem, char ***names, uint32 **name_types) { CLI_POLICY_HND *hnd; @@ -502,9 +515,17 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, POLICY_HND dom_pol, group_pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_group_pol = False; + uint32 *rid_mem = NULL; + uint32 group_rid; int retry; + unsigned int j; + fstring sid_string; + + DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid))); - DEBUG(10,("rpc: lookup_groupmem %s rid=%u\n", domain->name, group_rid)); + if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { + goto done; + } *num_names = 0; @@ -539,7 +560,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, group. */ result = cli_samr_query_groupmem(hnd->cli, mem_ctx, - &group_pol, num_names, rid_mem, + &group_pol, num_names, &rid_mem, name_types); if (!NT_STATUS_IS_OK(result)) @@ -554,6 +575,16 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, *names = talloc_zero(mem_ctx, *num_names * sizeof(char *)); *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); + *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *)); + + for (j=0;j<(*num_names);j++) { + (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]); + } + + if (!*names || !*name_types) { + result = NT_STATUS_NO_MEMORY; + goto done; + } for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); @@ -566,7 +597,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, result = cli_samr_lookup_rids(hnd->cli, mem_ctx, &dom_pol, 1000, /* flags */ num_lookup_rids, - &(*rid_mem)[i], + &rid_mem[i], &tmp_num_names, &tmp_names, &tmp_types); @@ -581,7 +612,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * tmp_num_names); - + total_names += tmp_num_names; } diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index 06c95224ab..ee05543d30 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -29,29 +29,30 @@ /* Fill a pwent structure with information we have obtained */ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, - uint32 user_rid, uint32 group_rid, + DOM_SID *user_sid, DOM_SID *group_sid, char *full_name, struct winbindd_pw *pw) { extern userdom_struct current_user_info; fstring output_username; pstring homedir; + fstring sid_string; if (!pw || !dom_name || !user_name) return False; /* Resolve the uid number */ - if (!winbindd_idmap_get_uid_from_rid(dom_name, user_rid, + if (!winbindd_idmap_get_uid_from_sid(user_sid, &pw->pw_uid)) { - DEBUG(1, ("error getting user id for rid %d\n", user_rid)); + DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); return False; } /* Resolve the gid number */ - if (!winbindd_idmap_get_gid_from_rid(dom_name, group_rid, + if (!winbindd_idmap_get_gid_from_sid(group_sid, &pw->pw_gid)) { - DEBUG(1, ("error getting group id for rid %d\n", group_rid)); + DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); return False; } @@ -95,7 +96,6 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) { - uint32 user_rid; WINBIND_USERINFO user_info; DOM_SID user_sid; NTSTATUS status; @@ -144,9 +144,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - sid_split_rid(&user_sid, &user_rid); - - status = domain->methods->query_user(domain, mem_ctx, user_rid, + status = domain->methods->query_user(domain, mem_ctx, &user_sid, &user_info); if (!NT_STATUS_IS_OK(status)) { @@ -158,7 +156,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) /* Now take all this information and fill in a passwd structure */ if (!winbindd_fill_pwent(name_domain, name_user, - user_rid, user_info.group_rid, + user_info.user_sid, user_info.group_sid, user_info.full_name, &state->response.data.pw)) { talloc_destroy(mem_ctx); @@ -176,7 +174,6 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) { DOM_SID user_sid; struct winbindd_domain *domain; - uint32 user_rid; fstring dom_name; fstring user_name; enum SID_NAME_USE name_type; @@ -196,18 +193,15 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Get rid from uid */ - if (!winbindd_idmap_get_rid_from_uid(state->request.data.uid, - &user_rid, &domain)) { - DEBUG(1, ("could not convert uid %d to rid\n", + if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, + &user_sid)) { + DEBUG(1, ("could not convert uid %d to SID\n", state->request.data.uid)); return WINBINDD_ERROR; } /* Get name and name type from rid */ - sid_copy(&user_sid, &domain->sid); - sid_append_rid(&user_sid, user_rid); - if (!winbindd_lookup_name_by_sid(&user_sid, dom_name, user_name, &name_type)) { fstring temp; @@ -216,6 +210,13 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } + domain = find_domain_from_sid(&user_sid); + + if (!domain) { + DEBUG(1,("Can't find domain from sid\n")); + return WINBINDD_ERROR; + } + /* Get some user info */ if (!(mem_ctx = talloc_init("winbind_getpwuid(%d)", @@ -225,7 +226,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - status = domain->methods->query_user(domain, mem_ctx, user_rid, + status = domain->methods->query_user(domain, mem_ctx, &user_sid, &user_info); if (!NT_STATUS_IS_OK(status)) { @@ -237,7 +238,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Resolve gid number */ - if (!winbindd_idmap_get_gid_from_rid(domain->name, user_info.group_rid, &gid)) { + if (!winbindd_idmap_get_gid_from_sid(user_info.group_sid, &gid)) { DEBUG(1, ("error getting group id for user %s\n", user_name)); talloc_destroy(mem_ctx); return WINBINDD_ERROR; @@ -245,7 +246,8 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Fill in password structure */ - if (!winbindd_fill_pwent(domain->name, user_name, user_rid, user_info.group_rid, + if (!winbindd_fill_pwent(domain->name, user_name, user_info.user_sid, + user_info.group_sid, user_info.full_name, &state->response.data.pw)) { talloc_destroy(mem_ctx); return WINBINDD_ERROR; @@ -332,13 +334,13 @@ static BOOL get_sam_user_entries(struct getent_state *ent) TALLOC_CTX *mem_ctx; struct winbindd_domain *domain; struct winbindd_methods *methods; - int i; + unsigned int i; if (ent->num_sam_entries) return False; if (!(mem_ctx = talloc_init("get_sam_user_entries(%s)", - ent->domain_name))) + ent->domain_name))) return False; if (!(domain = find_domain_from_name(ent->domain_name))) { @@ -393,8 +395,8 @@ static BOOL get_sam_user_entries(struct getent_state *ent) } /* User and group ids */ - name_list[ent->num_sam_entries+i].user_rid = info[i].user_rid; - name_list[ent->num_sam_entries+i].group_rid = info[i].group_rid; + sid_copy(&name_list[ent->num_sam_entries+i].user_sid, info[i].user_sid); + sid_copy(&name_list[ent->num_sam_entries+i].group_sid, info[i].group_sid); } ent->num_sam_entries += num_entries; @@ -492,8 +494,8 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state) result = winbindd_fill_pwent( ent->domain_name, name_list[ent->sam_entry_index].name, - name_list[ent->sam_entry_index].user_rid, - name_list[ent->sam_entry_index].group_rid, + &name_list[ent->sam_entry_index].user_sid, + &name_list[ent->sam_entry_index].group_sid, name_list[ent->sam_entry_index].gecos, &user_list[user_list_ndx]); @@ -540,7 +542,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) for (domain = domain_list(); domain; domain = domain->next) { NTSTATUS status; struct winbindd_methods *methods; - int i; + unsigned int i; methods = domain->methods; diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 3fa08029b6..fdbfd92b5a 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -271,14 +271,20 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, enum SID_NAME_USE *type) { NTSTATUS result; - + TALLOC_CTX *mem_ctx; /* Don't bother with machine accounts */ - + if (name[strlen(name) - 1] == '$') return False; + mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name); + if (!mem_ctx) + return False; + /* Lookup name */ - result = domain->methods->name_to_sid(domain, name, sid, type); + result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type); + + talloc_destroy(mem_ctx); /* Return rid and type if lookup successful */ if (!NT_STATUS_IS_OK(result)) { @@ -528,3 +534,20 @@ int winbindd_num_clients(void) { return _num_clients; } + +/* Help with RID -> SID conversion */ + +DOM_SID *rid_to_talloced_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 rid) +{ + DOM_SID *sid; + sid = talloc(mem_ctx, sizeof(*sid)); + if (!sid) { + smb_panic("rid_to_to_talloced_sid: talloc for DOM_SID failed!\n"); + } + sid_copy(sid, &domain->sid); + sid_append_rid(sid, rid); + return sid; +} + -- cgit