From 13157d1494b99bf85632120c27286ba4d877a68f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 14 Jul 2002 22:15:20 +0000 Subject: [PATCH] this is a trick to work around the fact that posix does not supply a getgr*() function that lists groups without numerating all the group members. Instead of definiing a new nss method (which might cause problems) I added an environment variable WINBIND_GETGRLST that tells winbind not to fill in the group members in a gergrent() request. This can speed up group listing by a factor of 20 or more (on my test system with 50000 groups it reduces the time from an hour to 2 minutes) (This used to be commit e3f73256d31ab9914daae49f41e984a534996870) --- source3/nsswitch/winbind_nss.c | 14 +++++++++++++- source3/nsswitch/winbindd.c | 1 + source3/nsswitch/winbindd_dual.c | 1 + source3/nsswitch/winbindd_group.c | 23 +++++++++++++++-------- source3/nsswitch/winbindd_nss.h | 3 +++ source3/nsswitch/winbindd_rpc.c | 20 ++++++++++++++++++++ 6 files changed, 53 insertions(+), 9 deletions(-) diff --git a/source3/nsswitch/winbind_nss.c b/source3/nsswitch/winbind_nss.c index a396e5551bc..681bcd2bf7b 100644 --- a/source3/nsswitch/winbind_nss.c +++ b/source3/nsswitch/winbind_nss.c @@ -238,6 +238,7 @@ winbind_callback(nsd_file_t **rqp, int fd) free_response(&response); return(do_list(1,rq)); case WINBINDD_GETGRENT: + case WINBINDD_GETGRLST: nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - %d GETGRENT responses\n", response.data.num_entries); @@ -1060,6 +1061,7 @@ _nss_winbind_getgrent_r(struct group *result, NSS_STATUS ret; static struct winbindd_request request; static int called_again; + enum winbindd_cmd cmd; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrent\n", getpid()); @@ -1083,7 +1085,17 @@ _nss_winbind_getgrent_r(struct group *result, request.data.num_entries = MAX_GETGRENT_USERS; - ret = winbindd_request(WINBINDD_GETGRENT, &request, + /* this is a hack to work around the fact that posix doesn't + define a 'list groups' call and listing all group members can + be *very* expensive. We use an environment variable to give + us a saner call (tridge) */ + if (getenv("WINBIND_GETGRLST")) { + cmd = WINBINDD_GETGRLST; + } else { + cmd = WINBINDD_GETGRENT; + } + + ret = winbindd_request(cmd, &request, &getgrent_response); if (ret == NSS_STATUS_SUCCESS) { diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 398845bdec4..358d9add3a3 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -223,6 +223,7 @@ static struct dispatch_table dispatch_table[] = { { WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" }, { WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" }, { WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" }, + { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" }, /* PAM auth functions */ diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index d55e84ca510..d32d62edaa1 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -189,6 +189,7 @@ void do_dual_daemon(void) break; case WINBINDD_GETGRENT: + case WINBINDD_GETGRLST: winbindd_setgrent(&state); break; default: diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index dce75f60a3a..20563ba7bd7 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -75,7 +75,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, *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", + DEBUG(1, ("rid %d in domain %s isn't a domain group\n", group_rid, domain->name)); goto done; } @@ -580,14 +580,21 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) goto done; } - /* Get group membership */ + group_list[group_list_ndx].num_gr_mem = 0; + gr_mem = NULL; + gr_mem_len = 0; - result = fill_grent_mem( - domain, - name_list[ent->sam_entry_index].rid, - SID_NAME_DOM_GRP, - &group_list[group_list_ndx].num_gr_mem, - &gr_mem, &gr_mem_len); + /* Get group membership */ + if (state->request.cmd == WINBINDD_GETGRLST) { + result = True; + } else { + result = fill_grent_mem( + domain, + name_list[ent->sam_entry_index].rid, + SID_NAME_DOM_GRP, + &group_list[group_list_ndx].num_gr_mem, + &gr_mem, &gr_mem_len); + } } if (result) { diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index 023d72306b7..0f0e40a2eca 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -99,6 +99,9 @@ enum winbindd_cmd { WINBINDD_WINS_BYIP, WINBINDD_WINS_BYNAME, + /* this is like GETGRENT but gives an empty group list */ + WINBINDD_GETGRLST, + /* Placeholder for end of cmd list */ WINBINDD_NUM_CMDS diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index dbfe1deda72..2bb0e8c49f4 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -41,6 +41,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; int i; + DEBUG(3,("rpc: query_user_list\n")); + *num_entries = 0; *info = NULL; @@ -133,6 +135,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, *num_entries = 0; *info = NULL; + DEBUG(3,("rpc: enum_dom_groups\n")); + if (!(hnd = cm_get_sam_handle(domain->name))) { return NT_STATUS_UNSUCCESSFUL; } @@ -192,6 +196,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, uint32 *types = NULL; const char *full_name; + DEBUG(3,("rpc: name_to_sid name=%s\n", name)); + if (!(mem_ctx = talloc_init_named("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) { DEBUG(0, ("talloc_init failed!\n")); return NT_STATUS_NO_MEMORY; @@ -239,6 +245,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, uint32 *types; NTSTATUS status; + DEBUG(3,("rpc: sid_to_name\n")); + if (!(hnd = cm_get_lsa_handle(domain->name))) return NT_STATUS_UNSUCCESSFUL; @@ -271,6 +279,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, BOOL got_dom_pol = False, got_user_pol = False; SAM_USERINFO_CTR *ctr; + DEBUG(3,("rpc: query_user rid=%u\n", user_rid)); + /* Get sam handle */ if (!(hnd = cm_get_sam_handle(domain->name))) goto done; @@ -336,6 +346,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, DOM_GID *user_groups; int i; + DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid)); + *num_groups = 0; /* First try cached universal groups from logon */ @@ -407,6 +419,8 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_group_pol = False; + DEBUG(3,("rpc: lookup_groupmem rid=%u\n", group_rid)); + *num_names = 0; /* Get sam handle */ @@ -509,6 +523,8 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) BOOL got_dom_pol = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + DEBUG(3,("rpc: sequence_number\n")); + *seq = DOM_SEQUENCE_NONE; if (!(mem_ctx = talloc_init_named("sequence_number[rpc]"))) @@ -566,6 +582,8 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, uint32 enum_ctx = 0; uint32 pref_num_domains = 5; + DEBUG(3,("rpc: trusted_domains\n")); + *num_domains = 0; if (!(hnd = cm_get_lsa_handle(lp_workgroup()))) @@ -586,6 +604,8 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) CLI_POLICY_HND *hnd; fstring level5_dom; + DEBUG(3,("rpc: domain_sid\n")); + if (!(mem_ctx = talloc_init_named("domain_sid[rpc]"))) return NT_STATUS_NO_MEMORY;