From de744cb970f5e3afb174a2d923d4e7d11b266173 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Dec 2001 12:31:43 +0000 Subject: The beginnings of alternative backends for winbindd This just splits off the dispinfo call behind a methods structure. I'll split off a few more functions soon, then we will be ready for LDAP replacement methods (This used to be commit 0216b0fca115c903ec31ed21427a83c62077dc95) --- source3/include/config.h.in | 2 +- source3/lib/util_unistr.c | 17 ++++++++ source3/nsswitch/winbindd.h | 24 ++++++++++- source3/nsswitch/winbindd_cm.c | 2 +- source3/nsswitch/winbindd_proto.h | 4 +- source3/nsswitch/winbindd_user.c | 83 +++++++++++++++------------------------ source3/nsswitch/winbindd_util.c | 47 +++++++++++++++++----- 7 files changed, 112 insertions(+), 67 deletions(-) (limited to 'source3') diff --git a/source3/include/config.h.in b/source3/include/config.h.in index 930eee6084..635c634e11 100644 --- a/source3/include/config.h.in +++ b/source3/include/config.h.in @@ -1,4 +1,4 @@ -/* include/config.h.in. Generated automatically from configure.in by autoheader. */ +/* include/config.h.in. Generated automatically from configure.in by autoheader 2.13. */ /* Define if on AIX 3. System headers sometimes define this. diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index d2d23dafa5..fc29ca8dc2 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -164,6 +164,23 @@ void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen) } +/******************************************************************* + duplicate a UNISTR2 string into a null terminated char* + using a talloc context +********************************************************************/ +char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str) +{ + char *s; + int maxlen = (str->uni_str_len+1)*4; + if (!str->buffer) return NULL; + s = (char *)talloc(ctx, maxlen); /* convervative */ + if (!s) return NULL; + pull_ucs2(NULL, s, str->buffer, maxlen, str->uni_str_len*2, + STR_NOALIGN); + return s; +} + + /******************************************************************* Return a number stored in a buffer ********************************************************************/ diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 1380d5cc88..c4a7c82bc6 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -77,11 +77,33 @@ struct winbindd_state { extern struct winbindd_state server_state; /* Server information */ -/* Structures to hold per domain information */ +typedef struct { + char *acct_name; + char *full_name; + uint32 user_rid; + uint32 group_rid; /* primary group */ +} WINBIND_DISPINFO; + +/* per-domain methods. This is how LDAP vs RPC is selected + This will eventually be the sole entry point to all the methods, + I'm just starting small + */ +struct winbindd_methods { + NTSTATUS (*query_dispinfo)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *start_ndx, uint32 *num_entries, + WINBIND_DISPINFO **info); + +}; + +/* Structures to hold per domain information */ struct winbindd_domain { fstring name; /* Domain name */ DOM_SID sid; /* SID for this domain */ + struct winbindd_methods *methods; /* lookup methods for + this domain (LDAP or + RPC) */ struct winbindd_domain *prev, *next; /* Linked list info */ }; diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index f11d86d4c1..987b28e09c 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -73,7 +73,7 @@ struct winbindd_cm_conn { POLICY_HND pol; }; -struct winbindd_cm_conn *cm_conns = NULL; +static struct winbindd_cm_conn *cm_conns = NULL; /* Get a domain controller name. Cache positive and negative lookups so we don't go to the network too often when something is badly broken. */ diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h index 7c3326ce36..fc8377697a 100644 --- a/source3/nsswitch/winbindd_proto.h +++ b/source3/nsswitch/winbindd_proto.h @@ -152,8 +152,8 @@ void free_getent_state(struct getent_state *state); BOOL winbindd_param_init(void); NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 *start_ndx, uint16 info_level, - uint32 *num_entries, SAM_DISPINFO_CTR *ctr); + uint32 *start_ndx, uint32 *num_entries, + WINBIND_DISPINFO **info); BOOL check_domain_env(char *domain_env, char *domain); void parse_domain_user(char *domuser, fstring domain, fstring user); #endif /* _PROTO_H_ */ diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index 853350fd19..2cc64cb565 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -377,12 +377,11 @@ static BOOL get_sam_user_entries(struct getent_state *ent) { NTSTATUS status; uint32 num_entries; - SAM_DISPINFO_1 info1; - SAM_DISPINFO_CTR ctr; + WINBIND_DISPINFO *info; struct getpwent_user *name_list = NULL; - uint32 group_rid; BOOL result = False; TALLOC_CTX *mem_ctx; + struct winbindd_methods *methods; if (ent->got_all_sam_entries) return False; @@ -390,10 +389,7 @@ static BOOL get_sam_user_entries(struct getent_state *ent) if (!(mem_ctx = talloc_init())) return False; - ZERO_STRUCT(info1); - ZERO_STRUCT(ctr); - - ctr.sam.info1 = &info1; + methods = ent->domain->methods; #if 0 /* Look in cache for entries, else get them direct */ @@ -406,14 +402,6 @@ static BOOL get_sam_user_entries(struct getent_state *ent) } #endif - /* For the moment we set the primary group for every user to be the - Domain Users group. There are serious problems with determining - the actual primary group for large domains. This should really - be made into a 'winbind force group' smb.conf parameter or - something like that. */ - - group_rid = DOMAIN_GROUP_RID_USERS; - /* Free any existing user info */ SAFE_FREE(ent->sam_entries); @@ -426,9 +414,9 @@ static BOOL get_sam_user_entries(struct getent_state *ent) num_entries = 0; - status = winbindd_query_dispinfo(ent->domain, mem_ctx, - &ent->dispinfo_ndx, 1, - &num_entries, &ctr); + status = methods->query_dispinfo(ent->domain, mem_ctx, + &ent->dispinfo_ndx, + &num_entries, &info); if (num_entries) { struct getpwent_user *tnl; @@ -447,26 +435,23 @@ static BOOL get_sam_user_entries(struct getent_state *ent) } for (i = 0; i < num_entries; i++) { - /* Store account name and gecos */ - - unistr2_to_ascii( - name_list[ent->num_sam_entries + i].name, - &info1.str[i].uni_acct_name, - sizeof(fstring)); - - unistr2_to_ascii( - name_list[ent->num_sam_entries + i].gecos, - &info1.str[i].uni_full_name, - sizeof(fstring)); + if (!info[i].acct_name) { + fstrcpy(name_list[ent->num_sam_entries + i].name, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].name, + info[i].acct_name); + } + if (!info[i].full_name) { + fstrcpy(name_list[ent->num_sam_entries + i].gecos, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].gecos, + info[i].full_name); + } /* User and group ids */ - - name_list[ent->num_sam_entries + i].user_rid = - info1.sam[i].rid_user; - - name_list[ent->num_sam_entries + i]. - group_rid = group_rid; + 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; } ent->num_sam_entries += num_entries; @@ -615,8 +600,7 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state) enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) { struct winbindd_domain *domain; - SAM_DISPINFO_CTR ctr; - SAM_DISPINFO_1 info1; + WINBIND_DISPINFO *info; uint32 num_entries = 0, total_entries = 0; char *ted, *extra_data = NULL; int extra_data_len = 0; @@ -630,14 +614,13 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) /* Enumerate over trusted domains */ - ctr.sam.info1 = &info1; - if (domain_list == NULL) get_domain_info(); for (domain = domain_list; domain; domain = domain->next) { NTSTATUS status; uint32 start_ndx = 0; + struct winbindd_methods *methods; /* Skip domains other than WINBINDD_DOMAIN environment variable */ @@ -646,20 +629,20 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) !check_domain_env(state->request.domain, domain->name)) continue; + methods = domain->methods; + /* Query display info */ do { int i; - status = winbindd_query_dispinfo( - domain, mem_ctx, &start_ndx, - 1, &num_entries, &ctr); + status = methods->query_dispinfo(domain, mem_ctx, &start_ndx, + &num_entries, &info); if (num_entries == 0) continue; /* Allocate some memory for extra data */ - total_entries += num_entries; ted = Realloc(extra_data, sizeof(fstring) * @@ -675,26 +658,22 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) /* Pack user list into extra data fields */ for (i = 0; i < num_entries; i++) { - UNISTR2 *uni_acct_name; fstring acct_name, name; - /* Convert unistring to ascii */ - - uni_acct_name = &ctr.sam.info1->str[i]. - uni_acct_name; - unistr2_to_ascii(acct_name, uni_acct_name, - sizeof(acct_name) - 1); + if (!info[i].acct_name) { + fstrcpy(acct_name, ""); + } else { + fstrcpy(acct_name, info[i].acct_name); + } slprintf(name, sizeof(name) - 1, "%s%s%s", domain->name, lp_winbind_separator(), acct_name); /* Append to extra data */ - memcpy(&extra_data[extra_data_len], name, strlen(name)); extra_data_len += strlen(name); - extra_data[extra_data_len++] = ','; } } while (NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES)); diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 777b3cdac2..41eb8b9d28 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -40,9 +40,12 @@ static const fstring name_deadbeef = ""; /* Globals for domain list stuff */ - struct winbindd_domain *domain_list = NULL; +static struct winbindd_methods msrpc_methods = { + winbindd_query_dispinfo +}; + /* Given a domain name, return the struct winbindd domain info for it if it is actually working. */ @@ -89,7 +92,8 @@ struct winbindd_domain *find_domain_from_sid(DOM_SID *sid) /* Add a trusted domain to our list of domains */ static struct winbindd_domain *add_trusted_domain(char *domain_name, - DOM_SID *domain_sid) + DOM_SID *domain_sid, + struct winbindd_methods *methods) { struct winbindd_domain *domain, *tmp; @@ -112,7 +116,8 @@ static struct winbindd_domain *add_trusted_domain(char *domain_name, ZERO_STRUCTP(domain); fstrcpy(domain->name, domain_name); sid_copy(&domain->sid, domain_sid); - + domain->methods = methods; + /* Link to domain list */ DLIST_ADD(domain_list, domain); @@ -150,7 +155,7 @@ BOOL get_domain_info(void) if (!NT_STATUS_IS_OK(result)) goto done; - add_trusted_domain(lp_workgroup(), &domain_sid); + add_trusted_domain(lp_workgroup(), &domain_sid, &msrpc_methods); /* Enumerate list of trusted domains */ @@ -166,7 +171,7 @@ BOOL get_domain_info(void) /* Add each domain to the trusted domain list */ for(i = 0; i < num_doms; i++) - add_trusted_domain(domains[i], &sids[i]); + add_trusted_domain(domains[i], &sids[i], &msrpc_methods); rv = True; @@ -790,14 +795,17 @@ BOOL winbindd_param_init(void) NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32 *start_ndx, uint16 info_level, - uint32 *num_entries, SAM_DISPINFO_CTR *ctr) + uint32 *start_ndx, uint32 *num_entries, + WINBIND_DISPINFO **info) { CLI_POLICY_HND *hnd; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol; BOOL got_dom_pol = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + SAM_DISPINFO_CTR ctr; + SAM_DISPINFO_1 info1; + int i; /* Get sam handle */ @@ -814,11 +822,30 @@ NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain, got_dom_pol = True; - /* Query display info */ + ctr.sam.info1 = &info1; + /* Query display info level 1 */ result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, - &dom_pol, start_ndx, info_level, - num_entries, 0xffff, ctr); + &dom_pol, start_ndx, 1, + num_entries, 0xffff, &ctr); + + /* now map the result into the WINBIND_DISPINFO structure */ + (*info) = (WINBIND_DISPINFO *)talloc(mem_ctx, (*num_entries)*sizeof(WINBIND_DISPINFO)); + if (!(*info)) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0;i<*num_entries;i++) { + (*info)[i].acct_name = unistr2_tdup(mem_ctx, &info1.str[i].uni_acct_name); + (*info)[i].full_name = unistr2_tdup(mem_ctx, &info1.str[i].uni_full_name); + (*info)[i].user_rid = info1.sam[i].rid_user; + /* For the moment we set the primary group for every user to be the + Domain Users group. There are serious problems with determining + the actual primary group for large domains. 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; + } done: -- cgit