diff options
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 15 | ||||
-rw-r--r-- | source3/rpc_client/cli_samr.c | 37 | ||||
-rw-r--r-- | source3/rpc_parse/parse_samr.c | 4 | ||||
-rw-r--r-- | source3/rpcclient/cmd_samr.c | 28 | ||||
-rw-r--r-- | source3/utils/net_rpc.c | 11 |
5 files changed, 78 insertions, 17 deletions
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index edeacdec6d..b260e55c86 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -39,7 +39,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; + int i, loop_count = 0; DEBUG(3,("rpc: query_user_list\n")); @@ -65,7 +65,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, do { SAM_DISPINFO_CTR ctr; SAM_DISPINFO_1 info1; - uint32 count = 0, start=i; + uint32 count = 0, start=i, max_entries, max_size; int j; TALLOC_CTX *ctx2; @@ -77,10 +77,15 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, goto done; } + get_query_dispinfo_params( + loop_count, &max_entries, &max_size); + /* Query display info level 1 */ - result = cli_samr_query_dispinfo(hnd->cli, ctx2, - &dom_pol, &start, 1, - &count, 0xFFFF, &ctr); + result = cli_samr_query_dispinfo( + hnd->cli, ctx2, &dom_pol, &start, 1, &count, + max_entries, max_size, &ctr); + + loop_count++; if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) break; diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index d101b8fe21..f0035ca22e 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -961,12 +961,45 @@ NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } +/* This function returns the bizzare set of (max_entries, max_size) required + for the QueryDisplayInfo RPC to actually work against a domain controller + with large (10k and higher) numbers of users. These values were + obtained by inspection using ethereal and NT4 running User Manager. */ + +void get_query_dispinfo_params(int loop_count, uint32 *max_entries, + uint32 *max_size) +{ + switch(loop_count) { + case 0: + *max_entries = 512; + *max_size = 16383; + break; + case 1: + *max_entries = 1024; + *max_size = 32766; + break; + case 2: + *max_entries = 2048; + *max_size = 65532; + break; + case 3: + *max_entries = 4096; + *max_size = 131064; + break; + default: /* loop_count >= 4 */ + *max_entries = 4096; + *max_size = 131071; + break; + } +} + /* Query display info */ NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *domain_pol, uint32 *start_idx, uint16 switch_value, uint32 *num_entries, - uint32 max_entries, SAM_DISPINFO_CTR *ctr) + uint32 max_entries, uint32 max_size, + SAM_DISPINFO_CTR *ctr) { prs_struct qbuf, rbuf; SAMR_Q_QUERY_DISPINFO q; @@ -984,7 +1017,7 @@ NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Marshall data and send request */ init_samr_q_query_dispinfo(&q, domain_pol, switch_value, - *start_idx, max_entries); + *start_idx, max_entries, max_size); if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) { diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 918cdbcd1d..d031d13955 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -1448,7 +1448,7 @@ inits a SAMR_Q_QUERY_DISPINFO structure. void init_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO * q_e, POLICY_HND *pol, uint16 switch_level, uint32 start_idx, - uint32 max_entries) + uint32 max_entries, uint32 max_size) { DEBUG(5, ("init_samr_q_query_dispinfo\n")); @@ -1458,7 +1458,7 @@ void init_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO * q_e, POLICY_HND *pol, q_e->start_idx = start_idx; q_e->max_entries = max_entries; - q_e->max_size = 0xffff; /* Not especially useful */ + q_e->max_size = max_size; } /******************************************************************* diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index fbc4d49819..9e8d105c46 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -863,7 +863,7 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 start_idx=0, max_entries=250, num_entries, i; + uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; uint32 info_level = 1; SAM_DISPINFO_CTR ctr; @@ -872,9 +872,11 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, SAM_DISPINFO_3 info3; SAM_DISPINFO_4 info4; SAM_DISPINFO_5 info5; + int loop_count = 0; + BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */ if (argc > 5) { - printf("Usage: %s [info level] [start index] [max entries] [access mask]\n", argv[0]); + printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]); return NT_STATUS_OK; } @@ -884,11 +886,18 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, if (argc >= 3) sscanf(argv[2], "%i", &start_idx); - if (argc >= 4) + if (argc >= 4) { sscanf(argv[3], "%i", &max_entries); + got_params = True; + } + + if (argc >= 5) { + sscanf(argv[4], "%i", &max_size); + got_params = True; + } - if (argc >= 5) - sscanf(argv[4], "%x", &access_mask); + if (argc >= 6) + sscanf(argv[5], "%x", &access_mask); /* Get sam policy handle */ @@ -938,9 +947,16 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, while(1) { + if (!got_params) + get_query_dispinfo_params( + loop_count, &max_entries, &max_size); + result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, &start_idx, info_level, - &num_entries, max_entries, &ctr); + &num_entries, max_entries, + max_size, &ctr); + + loop_count++; if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) break; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 60adcfdf6e..922fc027e6 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -779,7 +779,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 start_idx=0, max_entries=250, num_entries, i; + uint32 start_idx=0, num_entries, i, loop_count = 0; SAM_DISPINFO_CTR ctr; SAM_DISPINFO_1 info1; @@ -809,9 +809,16 @@ rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, "\n-----------------------------\n"); do { fstring user, desc; + uint32 max_entries, max_size; + + get_query_dispinfo_params( + loop_count, &max_entries, &max_size); + result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, &start_idx, 1, &num_entries, - max_entries, &ctr); + max_entries, max_size, &ctr); + loop_count++; + for (i = 0; i < num_entries; i++) { unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1); if (opt_long_list_entries) |