this is a trick to work around the fact that posix does not supply
authorAndrew Tridgell <tridge@samba.org>
Sun, 14 Jul 2002 22:15:20 +0000 (22:15 +0000)
committerAndrew Tridgell <tridge@samba.org>
Sun, 14 Jul 2002 22:15:20 +0000 (22:15 +0000)
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)

source/nsswitch/winbind_nss.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd_dual.c
source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_nss.h
source/nsswitch/winbindd_rpc.c

index a396e5551bcb82d0886838799d581cde8c87b0ab..681bcd2bf7b46a415be11e79ee4e7f63c5662e92 100644 (file)
@@ -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) {
index 398845bdec45bc9976cd0d6e5dd28fbb403e185e..358d9add3a388c10f3de544bcbfe8f3a8e946c2d 100644 (file)
@@ -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 */
 
index d55e84ca510be73c847b20d20381c1de0fbce5e7..d32d62edaa185416c15a9fe52e624d99ed9e213b 100644 (file)
@@ -189,6 +189,7 @@ void do_dual_daemon(void)
                                break;
                                
                        case WINBINDD_GETGRENT:
+                       case WINBINDD_GETGRLST:
                                winbindd_setgrent(&state);
                                break;
                        default:
index dce75f60a3adee573f149fe58eebd229b36feef0..20563ba7bd7cf856b6a5441e798706bd37f50e31 100644 (file)
@@ -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) {
index 023d72306b7d12617b6ba2d969fc47dd7ed2c6b1..0f0e40a2ecad24f1782bf7b8d1725dfd22afdc1c 100644 (file)
@@ -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
index dbfe1deda726f163f24bee13c6466a7f92053552..2bb0e8c49f46d6661f5d0e3ad966658fbc1f9c63 100644 (file)
@@ -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;