s3:winbindd: raise the timeout for lsa_Lookup*() calls from 10 to 35 seconds.
[Samba.git] / source / winbindd / winbindd_rpc.c
blob81154df0aac266ece44f8c25130c1dfbf2d2f826
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Volker Lendecke 2005
9 Copyright (C) Guenther Deschner 2008 (pidl conversion)
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "winbindd.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
32 /* Query display info for a domain. This returns enough information plus a
33 bit extra to give an overview of domain users for the User Manager
34 application. */
35 static NTSTATUS query_user_list(struct winbindd_domain *domain,
36 TALLOC_CTX *mem_ctx,
37 uint32 *num_entries,
38 WINBIND_USERINFO **info)
40 NTSTATUS result;
41 POLICY_HND dom_pol;
42 unsigned int i, start_idx;
43 uint32 loop_count;
44 struct rpc_pipe_client *cli;
46 DEBUG(3,("rpc: query_user_list\n"));
48 *num_entries = 0;
49 *info = NULL;
51 if ( !winbindd_can_contact_domain( domain ) ) {
52 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
53 domain->name));
54 return NT_STATUS_OK;
57 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
58 if (!NT_STATUS_IS_OK(result))
59 return result;
61 i = start_idx = 0;
62 loop_count = 0;
64 do {
65 uint32 num_dom_users, j;
66 uint32 max_entries, max_size;
67 uint32_t total_size, returned_size;
69 union samr_DispInfo disp_info;
71 /* this next bit is copied from net_user_list_internal() */
73 get_query_dispinfo_params(loop_count, &max_entries,
74 &max_size);
76 result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
77 &dom_pol,
79 start_idx,
80 max_entries,
81 max_size,
82 &total_size,
83 &returned_size,
84 &disp_info);
85 num_dom_users = disp_info.info1.count;
86 start_idx += disp_info.info1.count;
87 loop_count++;
89 *num_entries += num_dom_users;
91 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
92 *num_entries);
94 if (!(*info)) {
95 return NT_STATUS_NO_MEMORY;
98 for (j = 0; j < num_dom_users; i++, j++) {
100 uint32_t rid = disp_info.info1.entries[j].rid;
102 (*info)[i].acct_name = talloc_strdup(mem_ctx,
103 disp_info.info1.entries[j].account_name.string);
104 (*info)[i].full_name = talloc_strdup(mem_ctx,
105 disp_info.info1.entries[j].full_name.string);
106 (*info)[i].homedir = NULL;
107 (*info)[i].shell = NULL;
108 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
110 /* For the moment we set the primary group for
111 every user to be the Domain Users group.
112 There are serious problems with determining
113 the actual primary group for large domains.
114 This should really be made into a 'winbind
115 force group' smb.conf parameter or
116 something like that. */
118 sid_compose(&(*info)[i].group_sid, &domain->sid,
119 DOMAIN_GROUP_RID_USERS);
122 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
124 return result;
127 /* list all domain groups */
128 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
129 TALLOC_CTX *mem_ctx,
130 uint32 *num_entries,
131 struct acct_info **info)
133 POLICY_HND dom_pol;
134 NTSTATUS status;
135 uint32 start = 0;
136 struct rpc_pipe_client *cli;
138 *num_entries = 0;
139 *info = NULL;
141 DEBUG(3,("rpc: enum_dom_groups\n"));
143 if ( !winbindd_can_contact_domain( domain ) ) {
144 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
145 domain->name));
146 return NT_STATUS_OK;
149 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
150 if (!NT_STATUS_IS_OK(status))
151 return status;
153 do {
154 struct samr_SamArray *sam_array = NULL;
155 uint32 count = 0;
156 TALLOC_CTX *mem_ctx2;
157 int g;
159 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
161 /* start is updated by this call. */
162 status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2,
163 &dom_pol,
164 &start,
165 &sam_array,
166 0xFFFF, /* buffer size? */
167 &count);
169 if (!NT_STATUS_IS_OK(status) &&
170 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
171 talloc_destroy(mem_ctx2);
172 break;
175 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
176 struct acct_info,
177 (*num_entries) + count);
178 if (! *info) {
179 talloc_destroy(mem_ctx2);
180 return NT_STATUS_NO_MEMORY;
183 for (g=0; g < count; g++) {
185 fstrcpy((*info)[*num_entries + g].acct_name,
186 sam_array->entries[g].name.string);
187 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
190 (*num_entries) += count;
191 talloc_destroy(mem_ctx2);
192 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
194 return NT_STATUS_OK;
197 /* List all domain groups */
199 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
200 TALLOC_CTX *mem_ctx,
201 uint32 *num_entries,
202 struct acct_info **info)
204 POLICY_HND dom_pol;
205 NTSTATUS result;
206 struct rpc_pipe_client *cli;
208 *num_entries = 0;
209 *info = NULL;
211 DEBUG(3,("rpc: enum_local_groups\n"));
213 if ( !winbindd_can_contact_domain( domain ) ) {
214 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
215 domain->name));
216 return NT_STATUS_OK;
219 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
220 if (!NT_STATUS_IS_OK(result))
221 return result;
223 do {
224 struct samr_SamArray *sam_array = NULL;
225 uint32 count = 0, start = *num_entries;
226 TALLOC_CTX *mem_ctx2;
227 int g;
229 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
231 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
232 &dom_pol,
233 &start,
234 &sam_array,
235 0xFFFF, /* buffer size? */
236 &count);
237 if (!NT_STATUS_IS_OK(result) &&
238 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
240 talloc_destroy(mem_ctx2);
241 return result;
244 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
245 struct acct_info,
246 (*num_entries) + count);
247 if (! *info) {
248 talloc_destroy(mem_ctx2);
249 return NT_STATUS_NO_MEMORY;
252 for (g=0; g < count; g++) {
254 fstrcpy((*info)[*num_entries + g].acct_name,
255 sam_array->entries[g].name.string);
256 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
259 (*num_entries) += count;
260 talloc_destroy(mem_ctx2);
262 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
264 return NT_STATUS_OK;
267 /* convert a single name to a sid in a domain */
268 static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
269 TALLOC_CTX *mem_ctx,
270 enum winbindd_cmd original_cmd,
271 const char *domain_name,
272 const char *name,
273 DOM_SID *sid,
274 enum lsa_SidType *type)
276 NTSTATUS result;
277 DOM_SID *sids = NULL;
278 enum lsa_SidType *types = NULL;
279 char *full_name = NULL;
280 struct rpc_pipe_client *cli;
281 POLICY_HND lsa_policy;
282 unsigned int orig_timeout;
284 if (name == NULL || *name=='\0') {
285 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
286 } else if (domain_name == NULL || *domain_name == '\0') {
287 full_name = talloc_asprintf(mem_ctx, "%s", name);
288 } else {
289 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
291 if (!full_name) {
292 DEBUG(0, ("talloc_asprintf failed!\n"));
293 return NT_STATUS_NO_MEMORY;
296 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
298 ws_name_return( full_name, WB_REPLACE_CHAR );
300 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
302 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
303 if (!NT_STATUS_IS_OK(result))
304 return result;
307 * This call can take a long time
308 * allow the server to time out.
309 * 35 seconds should do it.
311 orig_timeout = cli_set_timeout(cli->cli, 35000);
313 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
314 (const char**) &full_name, NULL, 1, &sids, &types);
316 /* And restore our original timeout. */
317 cli_set_timeout(cli->cli, orig_timeout);
319 if (!NT_STATUS_IS_OK(result))
320 return result;
322 /* Return rid and type if lookup successful */
324 sid_copy(sid, &sids[0]);
325 *type = types[0];
327 return NT_STATUS_OK;
331 convert a domain SID to a user or group name
333 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
334 TALLOC_CTX *mem_ctx,
335 const DOM_SID *sid,
336 char **domain_name,
337 char **name,
338 enum lsa_SidType *type)
340 char **domains;
341 char **names;
342 enum lsa_SidType *types = NULL;
343 NTSTATUS result;
344 struct rpc_pipe_client *cli;
345 POLICY_HND lsa_policy;
346 unsigned int orig_timeout;
348 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
349 domain->name ));
351 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
352 if (!NT_STATUS_IS_OK(result)) {
353 DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
354 nt_errstr(result)));
355 return result;
360 * This call can take a long time
361 * allow the server to time out.
362 * 35 seconds should do it.
364 orig_timeout = cli_set_timeout(cli->cli, 35000);
366 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
367 1, sid, &domains, &names, &types);
369 /* And restore our original timeout. */
370 cli_set_timeout(cli->cli, orig_timeout);
372 if (!NT_STATUS_IS_OK(result)) {
373 DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n",
374 nt_errstr(result)));
375 return result;
378 *type = (enum lsa_SidType)types[0];
379 *domain_name = domains[0];
380 *name = names[0];
382 ws_name_replace( *name, WB_REPLACE_CHAR );
384 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
385 return NT_STATUS_OK;
388 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
389 TALLOC_CTX *mem_ctx,
390 const DOM_SID *sid,
391 uint32 *rids,
392 size_t num_rids,
393 char **domain_name,
394 char ***names,
395 enum lsa_SidType **types)
397 char **domains;
398 NTSTATUS result;
399 struct rpc_pipe_client *cli;
400 POLICY_HND lsa_policy;
401 DOM_SID *sids;
402 size_t i;
403 char **ret_names;
404 unsigned int orig_timeout;
406 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
408 if (num_rids) {
409 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
410 if (sids == NULL) {
411 return NT_STATUS_NO_MEMORY;
413 } else {
414 sids = NULL;
417 for (i=0; i<num_rids; i++) {
418 if (!sid_compose(&sids[i], sid, rids[i])) {
419 return NT_STATUS_INTERNAL_ERROR;
423 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
424 if (!NT_STATUS_IS_OK(result)) {
425 return result;
429 * This call can take a long time
430 * allow the server to time out.
431 * 35 seconds should do it.
433 orig_timeout = cli_set_timeout(cli->cli, 35000);
435 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
436 num_rids, sids, &domains,
437 names, types);
439 /* And restore our original timeout. */
440 cli_set_timeout(cli->cli, orig_timeout);
442 if (!NT_STATUS_IS_OK(result) &&
443 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
444 return result;
447 ret_names = *names;
448 for (i=0; i<num_rids; i++) {
449 if ((*types)[i] != SID_NAME_UNKNOWN) {
450 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
451 *domain_name = domains[i];
455 return result;
458 /* Lookup user information from a rid or username. */
459 static NTSTATUS query_user(struct winbindd_domain *domain,
460 TALLOC_CTX *mem_ctx,
461 const DOM_SID *user_sid,
462 WINBIND_USERINFO *user_info)
464 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
465 POLICY_HND dom_pol, user_pol;
466 union samr_UserInfo *info = NULL;
467 uint32 user_rid;
468 struct netr_SamInfo3 *user;
469 struct rpc_pipe_client *cli;
471 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
473 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
474 return NT_STATUS_UNSUCCESSFUL;
476 user_info->homedir = NULL;
477 user_info->shell = NULL;
478 user_info->primary_gid = (gid_t)-1;
480 /* try netsamlogon cache first */
482 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
485 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
486 sid_string_dbg(user_sid)));
488 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
489 sid_compose(&user_info->group_sid, &domain->sid,
490 user->base.primary_gid);
492 user_info->acct_name = talloc_strdup(mem_ctx,
493 user->base.account_name.string);
494 user_info->full_name = talloc_strdup(mem_ctx,
495 user->base.full_name.string);
497 TALLOC_FREE(user);
499 return NT_STATUS_OK;
502 if ( !winbindd_can_contact_domain( domain ) ) {
503 DEBUG(10,("query_user: No incoming trust for domain %s\n",
504 domain->name));
505 return NT_STATUS_OK;
508 if ( !winbindd_can_contact_domain( domain ) ) {
509 DEBUG(10,("query_user: No incoming trust for domain %s\n",
510 domain->name));
511 return NT_STATUS_OK;
514 if ( !winbindd_can_contact_domain( domain ) ) {
515 DEBUG(10,("query_user: No incoming trust for domain %s\n",
516 domain->name));
517 return NT_STATUS_OK;
520 /* no cache; hit the wire */
522 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
523 if (!NT_STATUS_IS_OK(result))
524 return result;
526 /* Get user handle */
527 result = rpccli_samr_OpenUser(cli, mem_ctx,
528 &dom_pol,
529 SEC_RIGHTS_MAXIMUM_ALLOWED,
530 user_rid,
531 &user_pol);
533 if (!NT_STATUS_IS_OK(result))
534 return result;
536 /* Get user info */
537 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
538 &user_pol,
539 0x15,
540 &info);
542 rpccli_samr_Close(cli, mem_ctx, &user_pol);
544 if (!NT_STATUS_IS_OK(result))
545 return result;
547 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
548 sid_compose(&user_info->group_sid, &domain->sid,
549 info->info21.primary_gid);
550 user_info->acct_name = talloc_strdup(mem_ctx,
551 info->info21.account_name.string);
552 user_info->full_name = talloc_strdup(mem_ctx,
553 info->info21.full_name.string);
554 user_info->homedir = NULL;
555 user_info->shell = NULL;
556 user_info->primary_gid = (gid_t)-1;
558 return NT_STATUS_OK;
561 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
562 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
563 TALLOC_CTX *mem_ctx,
564 const DOM_SID *user_sid,
565 uint32 *num_groups, DOM_SID **user_grpsids)
567 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
568 POLICY_HND dom_pol, user_pol;
569 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
570 struct samr_RidWithAttributeArray *rid_array = NULL;
571 unsigned int i;
572 uint32 user_rid;
573 struct rpc_pipe_client *cli;
575 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
577 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
578 return NT_STATUS_UNSUCCESSFUL;
580 *num_groups = 0;
581 *user_grpsids = NULL;
583 /* so lets see if we have a cached user_info_3 */
584 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
585 num_groups, user_grpsids);
587 if (NT_STATUS_IS_OK(result)) {
588 return NT_STATUS_OK;
591 if ( !winbindd_can_contact_domain( domain ) ) {
592 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
593 domain->name));
595 /* Tell the cache manager not to remember this one */
597 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
600 /* no cache; hit the wire */
602 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
603 if (!NT_STATUS_IS_OK(result))
604 return result;
606 /* Get user handle */
607 result = rpccli_samr_OpenUser(cli, mem_ctx,
608 &dom_pol,
609 des_access,
610 user_rid,
611 &user_pol);
613 if (!NT_STATUS_IS_OK(result))
614 return result;
616 /* Query user rids */
617 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
618 &user_pol,
619 &rid_array);
620 *num_groups = rid_array->count;
622 rpccli_samr_Close(cli, mem_ctx, &user_pol);
624 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
625 return result;
627 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
628 if (!(*user_grpsids))
629 return NT_STATUS_NO_MEMORY;
631 for (i=0;i<(*num_groups);i++) {
632 sid_copy(&((*user_grpsids)[i]), &domain->sid);
633 sid_append_rid(&((*user_grpsids)[i]),
634 rid_array->rids[i].rid);
637 return NT_STATUS_OK;
640 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
641 TALLOC_CTX *mem_ctx,
642 uint32 num_sids, const DOM_SID *sids,
643 uint32 *num_aliases,
644 uint32 **alias_rids)
646 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
647 POLICY_HND dom_pol;
648 uint32 num_query_sids = 0;
649 int i;
650 struct rpc_pipe_client *cli;
651 struct samr_Ids alias_rids_query;
652 int rangesize = MAX_SAM_ENTRIES_W2K;
653 uint32 total_sids = 0;
654 int num_queries = 1;
656 *num_aliases = 0;
657 *alias_rids = NULL;
659 DEBUG(3,("rpc: lookup_useraliases\n"));
661 if ( !winbindd_can_contact_domain( domain ) ) {
662 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
663 domain->name));
664 return NT_STATUS_OK;
667 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
668 if (!NT_STATUS_IS_OK(result))
669 return result;
671 do {
672 /* prepare query */
673 struct lsa_SidArray sid_array;
675 ZERO_STRUCT(sid_array);
677 num_query_sids = MIN(num_sids - total_sids, rangesize);
679 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
680 num_queries, num_query_sids));
682 if (num_query_sids) {
683 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
684 if (sid_array.sids == NULL) {
685 return NT_STATUS_NO_MEMORY;
687 } else {
688 sid_array.sids = NULL;
691 for (i=0; i<num_query_sids; i++) {
692 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
693 if (!sid_array.sids[i].sid) {
694 TALLOC_FREE(sid_array.sids);
695 return NT_STATUS_NO_MEMORY;
698 sid_array.num_sids = num_query_sids;
700 /* do request */
701 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
702 &dom_pol,
703 &sid_array,
704 &alias_rids_query);
706 if (!NT_STATUS_IS_OK(result)) {
707 *num_aliases = 0;
708 *alias_rids = NULL;
709 TALLOC_FREE(sid_array.sids);
710 goto done;
713 /* process output */
715 for (i=0; i<alias_rids_query.count; i++) {
716 size_t na = *num_aliases;
717 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
718 alias_rids, &na)) {
719 return NT_STATUS_NO_MEMORY;
721 *num_aliases = na;
724 TALLOC_FREE(sid_array.sids);
726 num_queries++;
728 } while (total_sids < num_sids);
730 done:
731 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
732 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
734 return result;
738 /* Lookup group membership given a rid. */
739 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
740 TALLOC_CTX *mem_ctx,
741 const DOM_SID *group_sid, uint32 *num_names,
742 DOM_SID **sid_mem, char ***names,
743 uint32 **name_types)
745 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
746 uint32 i, total_names = 0;
747 POLICY_HND dom_pol, group_pol;
748 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
749 uint32 *rid_mem = NULL;
750 uint32 group_rid;
751 unsigned int j, r;
752 struct rpc_pipe_client *cli;
753 unsigned int orig_timeout;
754 struct samr_RidTypeArray *rids = NULL;
756 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
757 sid_string_dbg(group_sid)));
759 if ( !winbindd_can_contact_domain( domain ) ) {
760 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
761 domain->name));
762 return NT_STATUS_OK;
765 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
766 return NT_STATUS_UNSUCCESSFUL;
768 *num_names = 0;
770 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
771 if (!NT_STATUS_IS_OK(result))
772 return result;
774 result = rpccli_samr_OpenGroup(cli, mem_ctx,
775 &dom_pol,
776 des_access,
777 group_rid,
778 &group_pol);
780 if (!NT_STATUS_IS_OK(result))
781 return result;
783 /* Step #1: Get a list of user rids that are the members of the
784 group. */
786 /* This call can take a long time - allow the server to time out.
787 35 seconds should do it. */
789 orig_timeout = cli_set_timeout(cli->cli, 35000);
791 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
792 &group_pol,
793 &rids);
795 /* And restore our original timeout. */
796 cli_set_timeout(cli->cli, orig_timeout);
798 rpccli_samr_Close(cli, mem_ctx, &group_pol);
800 if (!NT_STATUS_IS_OK(result))
801 return result;
803 *num_names = rids->count;
804 rid_mem = rids->rids;
806 if (!*num_names) {
807 names = NULL;
808 name_types = NULL;
809 sid_mem = NULL;
810 return NT_STATUS_OK;
813 /* Step #2: Convert list of rids into list of usernames. Do this
814 in bunches of ~1000 to avoid crashing NT4. It looks like there
815 is a buffer overflow or something like that lurking around
816 somewhere. */
818 #define MAX_LOOKUP_RIDS 900
820 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
821 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
822 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
824 for (j=0;j<(*num_names);j++)
825 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
827 if (*num_names>0 && (!*names || !*name_types))
828 return NT_STATUS_NO_MEMORY;
830 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
831 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
832 struct lsa_Strings tmp_names;
833 struct samr_Ids tmp_types;
835 /* Lookup a chunk of rids */
837 result = rpccli_samr_LookupRids(cli, mem_ctx,
838 &dom_pol,
839 num_lookup_rids,
840 &rid_mem[i],
841 &tmp_names,
842 &tmp_types);
844 /* see if we have a real error (and yes the
845 STATUS_SOME_UNMAPPED is the one returned from 2k) */
847 if (!NT_STATUS_IS_OK(result) &&
848 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
849 return result;
851 /* Copy result into array. The talloc system will take
852 care of freeing the temporary arrays later on. */
854 if (tmp_names.count != tmp_types.count) {
855 return NT_STATUS_UNSUCCESSFUL;
858 for (r=0; r<tmp_names.count; r++) {
859 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
860 continue;
862 (*names)[total_names] = fill_domain_username_talloc(
863 mem_ctx, domain->name,
864 tmp_names.names[r].string, true);
865 (*name_types)[total_names] = tmp_types.ids[r];
866 total_names += 1;
870 *num_names = total_names;
872 return NT_STATUS_OK;
875 #ifdef HAVE_LDAP
877 #include <ldap.h>
879 static int get_ldap_seq(const char *server, int port, uint32 *seq)
881 int ret = -1;
882 struct timeval to;
883 const char *attrs[] = {"highestCommittedUSN", NULL};
884 LDAPMessage *res = NULL;
885 char **values = NULL;
886 LDAP *ldp = NULL;
888 *seq = DOM_SEQUENCE_NONE;
891 * Parameterised (5) second timeout on open. This is needed as the
892 * search timeout doesn't seem to apply to doing an open as well. JRA.
895 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
896 if (ldp == NULL)
897 return -1;
899 /* Timeout if no response within 20 seconds. */
900 to.tv_sec = 10;
901 to.tv_usec = 0;
903 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
904 CONST_DISCARD(char **, attrs), 0, &to, &res))
905 goto done;
907 if (ldap_count_entries(ldp, res) != 1)
908 goto done;
910 values = ldap_get_values(ldp, res, "highestCommittedUSN");
911 if (!values || !values[0])
912 goto done;
914 *seq = atoi(values[0]);
915 ret = 0;
917 done:
919 if (values)
920 ldap_value_free(values);
921 if (res)
922 ldap_msgfree(res);
923 if (ldp)
924 ldap_unbind(ldp);
925 return ret;
928 /**********************************************************************
929 Get the sequence number for a Windows AD native mode domain using
930 LDAP queries.
931 **********************************************************************/
933 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
935 int ret = -1;
936 char addr[INET6_ADDRSTRLEN];
938 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
939 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
940 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
941 "number for Domain (%s) from DC (%s)\n",
942 domain->name, addr));
944 return ret;
947 #endif /* HAVE_LDAP */
949 /* find the sequence number for a domain */
950 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
952 TALLOC_CTX *mem_ctx;
953 union samr_DomainInfo *info = NULL;
954 NTSTATUS result;
955 POLICY_HND dom_pol;
956 bool got_seq_num = False;
957 struct rpc_pipe_client *cli;
959 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
961 if ( !winbindd_can_contact_domain( domain ) ) {
962 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
963 domain->name));
964 *seq = time(NULL);
965 return NT_STATUS_OK;
968 *seq = DOM_SEQUENCE_NONE;
970 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
971 return NT_STATUS_NO_MEMORY;
973 #ifdef HAVE_LDAP
974 if ( domain->active_directory )
976 int res;
978 DEBUG(8,("using get_ldap_seq() to retrieve the "
979 "sequence number\n"));
981 res = get_ldap_sequence_number( domain, seq );
982 if (res == 0)
984 result = NT_STATUS_OK;
985 DEBUG(10,("domain_sequence_number: LDAP for "
986 "domain %s is %u\n",
987 domain->name, *seq));
988 goto done;
991 DEBUG(10,("domain_sequence_number: failed to get LDAP "
992 "sequence number for domain %s\n",
993 domain->name ));
995 #endif /* HAVE_LDAP */
997 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
998 if (!NT_STATUS_IS_OK(result)) {
999 goto done;
1002 /* Query domain info */
1004 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1005 &dom_pol,
1007 &info);
1009 if (NT_STATUS_IS_OK(result)) {
1010 *seq = info->info8.sequence_num;
1011 got_seq_num = True;
1012 goto seq_num;
1015 /* retry with info-level 2 in case the dc does not support info-level 8
1016 * (like all older samba2 and samba3 dc's) - Guenther */
1018 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1019 &dom_pol,
1021 &info);
1023 if (NT_STATUS_IS_OK(result)) {
1024 *seq = info->info2.sequence_num;
1025 got_seq_num = True;
1028 seq_num:
1029 if (got_seq_num) {
1030 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1031 domain->name, (unsigned)*seq));
1032 } else {
1033 DEBUG(10,("domain_sequence_number: failed to get sequence "
1034 "number (%u) for domain %s\n",
1035 (unsigned)*seq, domain->name ));
1038 done:
1040 talloc_destroy(mem_ctx);
1042 return result;
1045 /* get a list of trusted domains */
1046 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1047 TALLOC_CTX *mem_ctx,
1048 uint32 *num_domains,
1049 char ***names,
1050 char ***alt_names,
1051 DOM_SID **dom_sids)
1053 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1054 uint32 enum_ctx = 0;
1055 struct rpc_pipe_client *cli;
1056 POLICY_HND lsa_policy;
1058 DEBUG(3,("rpc: trusted_domains\n"));
1060 *num_domains = 0;
1061 *names = NULL;
1062 *alt_names = NULL;
1063 *dom_sids = NULL;
1065 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1066 if (!NT_STATUS_IS_OK(result))
1067 return result;
1069 result = STATUS_MORE_ENTRIES;
1071 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1072 uint32 start_idx;
1073 int i;
1074 struct lsa_DomainList dom_list;
1076 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1077 &lsa_policy,
1078 &enum_ctx,
1079 &dom_list,
1080 (uint32_t)-1);
1082 if (!NT_STATUS_IS_OK(result) &&
1083 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1084 break;
1086 start_idx = *num_domains;
1087 *num_domains += dom_list.count;
1088 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1089 char *, *num_domains);
1090 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1091 DOM_SID, *num_domains);
1092 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1093 char *, *num_domains);
1094 if ((*names == NULL) || (*dom_sids == NULL) ||
1095 (*alt_names == NULL))
1096 return NT_STATUS_NO_MEMORY;
1098 for (i=0; i<dom_list.count; i++) {
1099 (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1100 (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1101 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1104 return result;
1107 /* find the lockout policy for a domain */
1108 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1109 TALLOC_CTX *mem_ctx,
1110 struct samr_DomInfo12 *lockout_policy)
1112 NTSTATUS result;
1113 struct rpc_pipe_client *cli;
1114 POLICY_HND dom_pol;
1115 union samr_DomainInfo *info = NULL;
1117 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1119 if ( !winbindd_can_contact_domain( domain ) ) {
1120 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1121 domain->name));
1122 return NT_STATUS_NOT_SUPPORTED;
1125 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1126 if (!NT_STATUS_IS_OK(result)) {
1127 goto done;
1130 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1131 &dom_pol,
1133 &info);
1134 if (!NT_STATUS_IS_OK(result)) {
1135 goto done;
1138 *lockout_policy = info->info12;
1140 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1141 info->info12.lockout_threshold));
1143 done:
1145 return result;
1148 /* find the password policy for a domain */
1149 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1150 TALLOC_CTX *mem_ctx,
1151 struct samr_DomInfo1 *password_policy)
1153 NTSTATUS result;
1154 struct rpc_pipe_client *cli;
1155 POLICY_HND dom_pol;
1156 union samr_DomainInfo *info = NULL;
1158 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1160 if ( !winbindd_can_contact_domain( domain ) ) {
1161 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1162 domain->name));
1163 return NT_STATUS_NOT_SUPPORTED;
1166 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1167 if (!NT_STATUS_IS_OK(result)) {
1168 goto done;
1171 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1172 &dom_pol,
1174 &info);
1175 if (!NT_STATUS_IS_OK(result)) {
1176 goto done;
1179 *password_policy = info->info1;
1181 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1182 info->info1.min_password_length));
1184 done:
1186 return result;
1190 /* the rpc backend methods are exposed via this structure */
1191 struct winbindd_methods msrpc_methods = {
1192 False,
1193 query_user_list,
1194 enum_dom_groups,
1195 enum_local_groups,
1196 msrpc_name_to_sid,
1197 msrpc_sid_to_name,
1198 msrpc_rids_to_names,
1199 query_user,
1200 lookup_usergroups,
1201 msrpc_lookup_useraliases,
1202 lookup_groupmem,
1203 sequence_number,
1204 msrpc_lockout_policy,
1205 msrpc_password_policy,
1206 trusted_domains,