s3-winbindd: add and use winbindd_lookup_sids().
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blob259ebc77c07542625b6f8620335ae533a3913257
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 struct wbint_userinfo **info)
40 NTSTATUS result;
41 struct policy_handle 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,
92 struct wbint_userinfo,
93 *num_entries);
95 if (!(*info)) {
96 return NT_STATUS_NO_MEMORY;
99 for (j = 0; j < num_dom_users; i++, j++) {
101 uint32_t rid = disp_info.info1.entries[j].rid;
103 (*info)[i].acct_name = talloc_strdup(mem_ctx,
104 disp_info.info1.entries[j].account_name.string);
105 (*info)[i].full_name = talloc_strdup(mem_ctx,
106 disp_info.info1.entries[j].full_name.string);
107 (*info)[i].homedir = NULL;
108 (*info)[i].shell = NULL;
109 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
111 /* For the moment we set the primary group for
112 every user to be the Domain Users group.
113 There are serious problems with determining
114 the actual primary group for large domains.
115 This should really be made into a 'winbind
116 force group' smb.conf parameter or
117 something like that. */
119 sid_compose(&(*info)[i].group_sid, &domain->sid,
120 DOMAIN_GROUP_RID_USERS);
123 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
125 return result;
128 /* list all domain groups */
129 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
130 TALLOC_CTX *mem_ctx,
131 uint32 *num_entries,
132 struct acct_info **info)
134 struct policy_handle dom_pol;
135 NTSTATUS status;
136 uint32 start = 0;
137 struct rpc_pipe_client *cli;
139 *num_entries = 0;
140 *info = NULL;
142 DEBUG(3,("rpc: enum_dom_groups\n"));
144 if ( !winbindd_can_contact_domain( domain ) ) {
145 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
146 domain->name));
147 return NT_STATUS_OK;
150 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
151 if (!NT_STATUS_IS_OK(status))
152 return status;
154 do {
155 struct samr_SamArray *sam_array = NULL;
156 uint32 count = 0;
157 TALLOC_CTX *mem_ctx2;
158 int g;
160 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
162 /* start is updated by this call. */
163 status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2,
164 &dom_pol,
165 &start,
166 &sam_array,
167 0xFFFF, /* buffer size? */
168 &count);
170 if (!NT_STATUS_IS_OK(status) &&
171 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
172 talloc_destroy(mem_ctx2);
173 break;
176 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
177 struct acct_info,
178 (*num_entries) + count);
179 if (! *info) {
180 talloc_destroy(mem_ctx2);
181 return NT_STATUS_NO_MEMORY;
184 for (g=0; g < count; g++) {
186 fstrcpy((*info)[*num_entries + g].acct_name,
187 sam_array->entries[g].name.string);
188 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
191 (*num_entries) += count;
192 talloc_destroy(mem_ctx2);
193 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
195 return NT_STATUS_OK;
198 /* List all domain groups */
200 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
201 TALLOC_CTX *mem_ctx,
202 uint32 *num_entries,
203 struct acct_info **info)
205 struct policy_handle dom_pol;
206 NTSTATUS result;
207 struct rpc_pipe_client *cli;
209 *num_entries = 0;
210 *info = NULL;
212 DEBUG(3,("rpc: enum_local_groups\n"));
214 if ( !winbindd_can_contact_domain( domain ) ) {
215 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
216 domain->name));
217 return NT_STATUS_OK;
220 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
221 if (!NT_STATUS_IS_OK(result))
222 return result;
224 do {
225 struct samr_SamArray *sam_array = NULL;
226 uint32 count = 0, start = *num_entries;
227 TALLOC_CTX *mem_ctx2;
228 int g;
230 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
232 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
233 &dom_pol,
234 &start,
235 &sam_array,
236 0xFFFF, /* buffer size? */
237 &count);
238 if (!NT_STATUS_IS_OK(result) &&
239 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
241 talloc_destroy(mem_ctx2);
242 return result;
245 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
246 struct acct_info,
247 (*num_entries) + count);
248 if (! *info) {
249 talloc_destroy(mem_ctx2);
250 return NT_STATUS_NO_MEMORY;
253 for (g=0; g < count; g++) {
255 fstrcpy((*info)[*num_entries + g].acct_name,
256 sam_array->entries[g].name.string);
257 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
260 (*num_entries) += count;
261 talloc_destroy(mem_ctx2);
263 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
265 return NT_STATUS_OK;
268 /* convert a single name to a sid in a domain */
269 static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
270 TALLOC_CTX *mem_ctx,
271 const char *domain_name,
272 const char *name,
273 uint32_t flags,
274 DOM_SID *sid,
275 enum lsa_SidType *type)
277 NTSTATUS result;
278 DOM_SID *sids = NULL;
279 enum lsa_SidType *types = NULL;
280 char *full_name = NULL;
281 struct rpc_pipe_client *cli;
282 struct policy_handle lsa_policy;
283 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
284 char *mapped_name = NULL;
285 unsigned int orig_timeout;
287 if (name == NULL || *name=='\0') {
288 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
289 } else if (domain_name == NULL || *domain_name == '\0') {
290 full_name = talloc_asprintf(mem_ctx, "%s", name);
291 } else {
292 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
294 if (!full_name) {
295 DEBUG(0, ("talloc_asprintf failed!\n"));
296 return NT_STATUS_NO_MEMORY;
299 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
301 name_map_status = normalize_name_unmap(mem_ctx, full_name,
302 &mapped_name);
304 /* Reset the full_name pointer if we mapped anytthing */
306 if (NT_STATUS_IS_OK(name_map_status) ||
307 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
309 full_name = mapped_name;
312 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
313 full_name?full_name:"", domain_name ));
315 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
316 if (!NT_STATUS_IS_OK(result))
317 return result;
320 * This call can take a long time
321 * allow the server to time out.
322 * 35 seconds should do it.
324 orig_timeout = rpccli_set_timeout(cli, 35000);
326 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
327 (const char**) &full_name, NULL, 1, &sids, &types);
329 /* And restore our original timeout. */
330 rpccli_set_timeout(cli, orig_timeout);
332 if (!NT_STATUS_IS_OK(result))
333 return result;
335 /* Return rid and type if lookup successful */
337 sid_copy(sid, &sids[0]);
338 *type = types[0];
340 return NT_STATUS_OK;
344 convert a domain SID to a user or group name
346 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
347 TALLOC_CTX *mem_ctx,
348 const DOM_SID *sid,
349 char **domain_name,
350 char **name,
351 enum lsa_SidType *type)
353 char **domains;
354 char **names;
355 enum lsa_SidType *types = NULL;
356 NTSTATUS result;
357 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
358 char *mapped_name = NULL;
360 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
361 domain->name ));
363 result = winbindd_lookup_sids(mem_ctx,
364 domain,
366 sid,
367 &domains,
368 &names,
369 &types);
370 if (!NT_STATUS_IS_OK(result)) {
371 DEBUG(2,("msrpc_sid_to_name: failed to lookup sids: %s\n",
372 nt_errstr(result)));
373 return result;
377 *type = (enum lsa_SidType)types[0];
378 *domain_name = domains[0];
379 *name = names[0];
381 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
383 name_map_status = normalize_name_map(mem_ctx, domain, *name,
384 &mapped_name);
385 if (NT_STATUS_IS_OK(name_map_status) ||
386 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
388 *name = mapped_name;
389 DEBUG(5,("returning mapped name -- %s\n", *name));
392 return NT_STATUS_OK;
395 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
396 TALLOC_CTX *mem_ctx,
397 const DOM_SID *sid,
398 uint32 *rids,
399 size_t num_rids,
400 char **domain_name,
401 char ***names,
402 enum lsa_SidType **types)
404 char **domains;
405 NTSTATUS result;
406 DOM_SID *sids;
407 size_t i;
408 char **ret_names;
410 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
412 if (num_rids) {
413 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
414 if (sids == NULL) {
415 return NT_STATUS_NO_MEMORY;
417 } else {
418 sids = NULL;
421 for (i=0; i<num_rids; i++) {
422 if (!sid_compose(&sids[i], sid, rids[i])) {
423 return NT_STATUS_INTERNAL_ERROR;
427 result = winbindd_lookup_sids(mem_ctx,
428 domain,
429 num_rids,
430 sids,
431 &domains,
432 names,
433 types);
435 if (!NT_STATUS_IS_OK(result) &&
436 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
437 return result;
440 ret_names = *names;
441 for (i=0; i<num_rids; i++) {
442 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
443 char *mapped_name = NULL;
445 if ((*types)[i] != SID_NAME_UNKNOWN) {
446 name_map_status = normalize_name_map(mem_ctx,
447 domain,
448 ret_names[i],
449 &mapped_name);
450 if (NT_STATUS_IS_OK(name_map_status) ||
451 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
453 ret_names[i] = mapped_name;
456 *domain_name = domains[i];
460 return result;
463 /* Lookup user information from a rid or username. */
464 static NTSTATUS query_user(struct winbindd_domain *domain,
465 TALLOC_CTX *mem_ctx,
466 const DOM_SID *user_sid,
467 struct wbint_userinfo *user_info)
469 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
470 struct policy_handle dom_pol, user_pol;
471 union samr_UserInfo *info = NULL;
472 uint32 user_rid;
473 struct netr_SamInfo3 *user;
474 struct rpc_pipe_client *cli;
476 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
478 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
479 return NT_STATUS_UNSUCCESSFUL;
481 user_info->homedir = NULL;
482 user_info->shell = NULL;
483 user_info->primary_gid = (gid_t)-1;
485 /* try netsamlogon cache first */
487 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
490 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
491 sid_string_dbg(user_sid)));
493 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
494 sid_compose(&user_info->group_sid, &domain->sid,
495 user->base.primary_gid);
497 user_info->acct_name = talloc_strdup(mem_ctx,
498 user->base.account_name.string);
499 user_info->full_name = talloc_strdup(mem_ctx,
500 user->base.full_name.string);
502 TALLOC_FREE(user);
504 return NT_STATUS_OK;
507 if ( !winbindd_can_contact_domain( domain ) ) {
508 DEBUG(10,("query_user: No incoming trust for domain %s\n",
509 domain->name));
510 return NT_STATUS_OK;
513 if ( !winbindd_can_contact_domain( domain ) ) {
514 DEBUG(10,("query_user: No incoming trust for domain %s\n",
515 domain->name));
516 return NT_STATUS_OK;
519 if ( !winbindd_can_contact_domain( domain ) ) {
520 DEBUG(10,("query_user: No incoming trust for domain %s\n",
521 domain->name));
522 return NT_STATUS_OK;
525 /* no cache; hit the wire */
527 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
528 if (!NT_STATUS_IS_OK(result))
529 return result;
531 /* Get user handle */
532 result = rpccli_samr_OpenUser(cli, mem_ctx,
533 &dom_pol,
534 SEC_FLAG_MAXIMUM_ALLOWED,
535 user_rid,
536 &user_pol);
538 if (!NT_STATUS_IS_OK(result))
539 return result;
541 /* Get user info */
542 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
543 &user_pol,
544 0x15,
545 &info);
547 rpccli_samr_Close(cli, mem_ctx, &user_pol);
549 if (!NT_STATUS_IS_OK(result))
550 return result;
552 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
553 sid_compose(&user_info->group_sid, &domain->sid,
554 info->info21.primary_gid);
555 user_info->acct_name = talloc_strdup(mem_ctx,
556 info->info21.account_name.string);
557 user_info->full_name = talloc_strdup(mem_ctx,
558 info->info21.full_name.string);
559 user_info->homedir = NULL;
560 user_info->shell = NULL;
561 user_info->primary_gid = (gid_t)-1;
563 return NT_STATUS_OK;
566 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
567 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
568 TALLOC_CTX *mem_ctx,
569 const DOM_SID *user_sid,
570 uint32 *num_groups, DOM_SID **user_grpsids)
572 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
573 struct policy_handle dom_pol, user_pol;
574 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
575 struct samr_RidWithAttributeArray *rid_array = NULL;
576 unsigned int i;
577 uint32 user_rid;
578 struct rpc_pipe_client *cli;
580 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
582 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
583 return NT_STATUS_UNSUCCESSFUL;
585 *num_groups = 0;
586 *user_grpsids = NULL;
588 /* so lets see if we have a cached user_info_3 */
589 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
590 num_groups, user_grpsids);
592 if (NT_STATUS_IS_OK(result)) {
593 return NT_STATUS_OK;
596 if ( !winbindd_can_contact_domain( domain ) ) {
597 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
598 domain->name));
600 /* Tell the cache manager not to remember this one */
602 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
605 /* no cache; hit the wire */
607 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
608 if (!NT_STATUS_IS_OK(result))
609 return result;
611 /* Get user handle */
612 result = rpccli_samr_OpenUser(cli, mem_ctx,
613 &dom_pol,
614 des_access,
615 user_rid,
616 &user_pol);
618 if (!NT_STATUS_IS_OK(result))
619 return result;
621 /* Query user rids */
622 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
623 &user_pol,
624 &rid_array);
625 *num_groups = rid_array->count;
627 rpccli_samr_Close(cli, mem_ctx, &user_pol);
629 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
630 return result;
632 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
633 if (!(*user_grpsids))
634 return NT_STATUS_NO_MEMORY;
636 for (i=0;i<(*num_groups);i++) {
637 sid_copy(&((*user_grpsids)[i]), &domain->sid);
638 sid_append_rid(&((*user_grpsids)[i]),
639 rid_array->rids[i].rid);
642 return NT_STATUS_OK;
645 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
647 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
648 TALLOC_CTX *mem_ctx,
649 uint32 num_sids, const DOM_SID *sids,
650 uint32 *num_aliases,
651 uint32 **alias_rids)
653 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
654 struct policy_handle dom_pol;
655 uint32 num_query_sids = 0;
656 int i;
657 struct rpc_pipe_client *cli;
658 struct samr_Ids alias_rids_query;
659 int rangesize = MAX_SAM_ENTRIES_W2K;
660 uint32 total_sids = 0;
661 int num_queries = 1;
663 *num_aliases = 0;
664 *alias_rids = NULL;
666 DEBUG(3,("rpc: lookup_useraliases\n"));
668 if ( !winbindd_can_contact_domain( domain ) ) {
669 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
670 domain->name));
671 return NT_STATUS_OK;
674 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
675 if (!NT_STATUS_IS_OK(result))
676 return result;
678 do {
679 /* prepare query */
680 struct lsa_SidArray sid_array;
682 ZERO_STRUCT(sid_array);
684 num_query_sids = MIN(num_sids - total_sids, rangesize);
686 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
687 num_queries, num_query_sids));
689 if (num_query_sids) {
690 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
691 if (sid_array.sids == NULL) {
692 return NT_STATUS_NO_MEMORY;
694 } else {
695 sid_array.sids = NULL;
698 for (i=0; i<num_query_sids; i++) {
699 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
700 if (!sid_array.sids[i].sid) {
701 TALLOC_FREE(sid_array.sids);
702 return NT_STATUS_NO_MEMORY;
705 sid_array.num_sids = num_query_sids;
707 /* do request */
708 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
709 &dom_pol,
710 &sid_array,
711 &alias_rids_query);
713 if (!NT_STATUS_IS_OK(result)) {
714 *num_aliases = 0;
715 *alias_rids = NULL;
716 TALLOC_FREE(sid_array.sids);
717 goto done;
720 /* process output */
722 for (i=0; i<alias_rids_query.count; i++) {
723 size_t na = *num_aliases;
724 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
725 alias_rids, &na)) {
726 return NT_STATUS_NO_MEMORY;
728 *num_aliases = na;
731 TALLOC_FREE(sid_array.sids);
733 num_queries++;
735 } while (total_sids < num_sids);
737 done:
738 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
739 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
741 return result;
745 /* Lookup group membership given a rid. */
746 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
747 TALLOC_CTX *mem_ctx,
748 const DOM_SID *group_sid,
749 enum lsa_SidType type,
750 uint32 *num_names,
751 DOM_SID **sid_mem, char ***names,
752 uint32 **name_types)
754 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
755 uint32 i, total_names = 0;
756 struct policy_handle dom_pol, group_pol;
757 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
758 uint32 *rid_mem = NULL;
759 uint32 group_rid;
760 unsigned int j, r;
761 struct rpc_pipe_client *cli;
762 unsigned int orig_timeout;
763 struct samr_RidTypeArray *rids = NULL;
765 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
766 sid_string_dbg(group_sid)));
768 if ( !winbindd_can_contact_domain( domain ) ) {
769 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
770 domain->name));
771 return NT_STATUS_OK;
774 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
775 return NT_STATUS_UNSUCCESSFUL;
777 *num_names = 0;
779 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
780 if (!NT_STATUS_IS_OK(result))
781 return result;
783 result = rpccli_samr_OpenGroup(cli, mem_ctx,
784 &dom_pol,
785 des_access,
786 group_rid,
787 &group_pol);
789 if (!NT_STATUS_IS_OK(result))
790 return result;
792 /* Step #1: Get a list of user rids that are the members of the
793 group. */
795 /* This call can take a long time - allow the server to time out.
796 35 seconds should do it. */
798 orig_timeout = rpccli_set_timeout(cli, 35000);
800 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
801 &group_pol,
802 &rids);
804 /* And restore our original timeout. */
805 rpccli_set_timeout(cli, orig_timeout);
807 rpccli_samr_Close(cli, mem_ctx, &group_pol);
809 if (!NT_STATUS_IS_OK(result))
810 return result;
812 *num_names = rids->count;
813 rid_mem = rids->rids;
815 if (!*num_names) {
816 names = NULL;
817 name_types = NULL;
818 sid_mem = NULL;
819 return NT_STATUS_OK;
822 /* Step #2: Convert list of rids into list of usernames. Do this
823 in bunches of ~1000 to avoid crashing NT4. It looks like there
824 is a buffer overflow or something like that lurking around
825 somewhere. */
827 #define MAX_LOOKUP_RIDS 900
829 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
830 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
831 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
833 for (j=0;j<(*num_names);j++)
834 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
836 if (*num_names>0 && (!*names || !*name_types))
837 return NT_STATUS_NO_MEMORY;
839 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
840 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
841 struct lsa_Strings tmp_names;
842 struct samr_Ids tmp_types;
844 /* Lookup a chunk of rids */
846 result = rpccli_samr_LookupRids(cli, mem_ctx,
847 &dom_pol,
848 num_lookup_rids,
849 &rid_mem[i],
850 &tmp_names,
851 &tmp_types);
853 /* see if we have a real error (and yes the
854 STATUS_SOME_UNMAPPED is the one returned from 2k) */
856 if (!NT_STATUS_IS_OK(result) &&
857 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
858 return result;
860 /* Copy result into array. The talloc system will take
861 care of freeing the temporary arrays later on. */
863 if (tmp_names.count != tmp_types.count) {
864 return NT_STATUS_UNSUCCESSFUL;
867 for (r=0; r<tmp_names.count; r++) {
868 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
869 continue;
871 (*names)[total_names] = fill_domain_username_talloc(
872 mem_ctx, domain->name,
873 tmp_names.names[r].string, true);
874 (*name_types)[total_names] = tmp_types.ids[r];
875 total_names += 1;
879 *num_names = total_names;
881 return NT_STATUS_OK;
884 #ifdef HAVE_LDAP
886 #include <ldap.h>
888 static int get_ldap_seq(const char *server, int port, uint32 *seq)
890 int ret = -1;
891 struct timeval to;
892 const char *attrs[] = {"highestCommittedUSN", NULL};
893 LDAPMessage *res = NULL;
894 char **values = NULL;
895 LDAP *ldp = NULL;
897 *seq = DOM_SEQUENCE_NONE;
900 * Parameterised (5) second timeout on open. This is needed as the
901 * search timeout doesn't seem to apply to doing an open as well. JRA.
904 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
905 if (ldp == NULL)
906 return -1;
908 /* Timeout if no response within 20 seconds. */
909 to.tv_sec = 10;
910 to.tv_usec = 0;
912 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
913 CONST_DISCARD(char **, attrs), 0, &to, &res))
914 goto done;
916 if (ldap_count_entries(ldp, res) != 1)
917 goto done;
919 values = ldap_get_values(ldp, res, "highestCommittedUSN");
920 if (!values || !values[0])
921 goto done;
923 *seq = atoi(values[0]);
924 ret = 0;
926 done:
928 if (values)
929 ldap_value_free(values);
930 if (res)
931 ldap_msgfree(res);
932 if (ldp)
933 ldap_unbind(ldp);
934 return ret;
937 /**********************************************************************
938 Get the sequence number for a Windows AD native mode domain using
939 LDAP queries.
940 **********************************************************************/
942 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
944 int ret = -1;
945 char addr[INET6_ADDRSTRLEN];
947 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
948 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
949 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
950 "number for Domain (%s) from DC (%s)\n",
951 domain->name, addr));
953 return ret;
956 #endif /* HAVE_LDAP */
958 /* find the sequence number for a domain */
959 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
961 TALLOC_CTX *mem_ctx;
962 union samr_DomainInfo *info = NULL;
963 NTSTATUS result;
964 struct policy_handle dom_pol;
965 bool got_seq_num = False;
966 struct rpc_pipe_client *cli;
968 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
970 if ( !winbindd_can_contact_domain( domain ) ) {
971 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
972 domain->name));
973 *seq = time(NULL);
974 return NT_STATUS_OK;
977 *seq = DOM_SEQUENCE_NONE;
979 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
980 return NT_STATUS_NO_MEMORY;
982 #ifdef HAVE_LDAP
983 if ( domain->active_directory )
985 int res;
987 DEBUG(8,("using get_ldap_seq() to retrieve the "
988 "sequence number\n"));
990 res = get_ldap_sequence_number( domain, seq );
991 if (res == 0)
993 result = NT_STATUS_OK;
994 DEBUG(10,("domain_sequence_number: LDAP for "
995 "domain %s is %u\n",
996 domain->name, *seq));
997 goto done;
1000 DEBUG(10,("domain_sequence_number: failed to get LDAP "
1001 "sequence number for domain %s\n",
1002 domain->name ));
1004 #endif /* HAVE_LDAP */
1006 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1007 if (!NT_STATUS_IS_OK(result)) {
1008 goto done;
1011 /* Query domain info */
1013 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1014 &dom_pol,
1016 &info);
1018 if (NT_STATUS_IS_OK(result)) {
1019 *seq = info->info8.sequence_num;
1020 got_seq_num = True;
1021 goto seq_num;
1024 /* retry with info-level 2 in case the dc does not support info-level 8
1025 * (like all older samba2 and samba3 dc's) - Guenther */
1027 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1028 &dom_pol,
1030 &info);
1032 if (NT_STATUS_IS_OK(result)) {
1033 *seq = info->general.sequence_num;
1034 got_seq_num = True;
1037 seq_num:
1038 if (got_seq_num) {
1039 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1040 domain->name, (unsigned)*seq));
1041 } else {
1042 DEBUG(10,("domain_sequence_number: failed to get sequence "
1043 "number (%u) for domain %s\n",
1044 (unsigned)*seq, domain->name ));
1047 done:
1049 talloc_destroy(mem_ctx);
1051 return result;
1054 /* get a list of trusted domains */
1055 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1056 TALLOC_CTX *mem_ctx,
1057 uint32 *num_domains,
1058 char ***names,
1059 char ***alt_names,
1060 DOM_SID **dom_sids)
1062 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1063 uint32 enum_ctx = 0;
1064 struct rpc_pipe_client *cli;
1065 struct policy_handle lsa_policy;
1067 DEBUG(3,("rpc: trusted_domains\n"));
1069 *num_domains = 0;
1070 *names = NULL;
1071 *alt_names = NULL;
1072 *dom_sids = NULL;
1074 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1075 if (!NT_STATUS_IS_OK(result))
1076 return result;
1078 result = STATUS_MORE_ENTRIES;
1080 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1081 uint32 start_idx;
1082 int i;
1083 struct lsa_DomainList dom_list;
1085 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1086 &lsa_policy,
1087 &enum_ctx,
1088 &dom_list,
1089 (uint32_t)-1);
1091 if (!NT_STATUS_IS_OK(result) &&
1092 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1093 break;
1095 start_idx = *num_domains;
1096 *num_domains += dom_list.count;
1097 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1098 char *, *num_domains);
1099 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1100 DOM_SID, *num_domains);
1101 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1102 char *, *num_domains);
1103 if ((*names == NULL) || (*dom_sids == NULL) ||
1104 (*alt_names == NULL))
1105 return NT_STATUS_NO_MEMORY;
1107 for (i=0; i<dom_list.count; i++) {
1108 (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1109 (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1110 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1113 return result;
1116 /* find the lockout policy for a domain */
1117 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1118 TALLOC_CTX *mem_ctx,
1119 struct samr_DomInfo12 *lockout_policy)
1121 NTSTATUS result;
1122 struct rpc_pipe_client *cli;
1123 struct policy_handle dom_pol;
1124 union samr_DomainInfo *info = NULL;
1126 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1128 if ( !winbindd_can_contact_domain( domain ) ) {
1129 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1130 domain->name));
1131 return NT_STATUS_NOT_SUPPORTED;
1134 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1135 if (!NT_STATUS_IS_OK(result)) {
1136 goto done;
1139 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1140 &dom_pol,
1142 &info);
1143 if (!NT_STATUS_IS_OK(result)) {
1144 goto done;
1147 *lockout_policy = info->info12;
1149 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1150 info->info12.lockout_threshold));
1152 done:
1154 return result;
1157 /* find the password policy for a domain */
1158 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1159 TALLOC_CTX *mem_ctx,
1160 struct samr_DomInfo1 *password_policy)
1162 NTSTATUS result;
1163 struct rpc_pipe_client *cli;
1164 struct policy_handle dom_pol;
1165 union samr_DomainInfo *info = NULL;
1167 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1169 if ( !winbindd_can_contact_domain( domain ) ) {
1170 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1171 domain->name));
1172 return NT_STATUS_NOT_SUPPORTED;
1175 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1176 if (!NT_STATUS_IS_OK(result)) {
1177 goto done;
1180 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1181 &dom_pol,
1183 &info);
1184 if (!NT_STATUS_IS_OK(result)) {
1185 goto done;
1188 *password_policy = info->info1;
1190 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1191 info->info1.min_password_length));
1193 done:
1195 return result;
1198 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
1199 struct winbindd_domain *domain,
1200 uint32_t num_sids,
1201 const struct dom_sid *sids,
1202 char ***domains,
1203 char ***names,
1204 enum lsa_SidType **types)
1206 NTSTATUS status;
1207 struct rpc_pipe_client *cli = NULL;
1208 struct policy_handle lsa_policy;
1209 unsigned int orig_timeout;
1211 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 return status;
1217 * This call can take a long time
1218 * allow the server to time out.
1219 * 35 seconds should do it.
1221 orig_timeout = rpccli_set_timeout(cli, 35000);
1223 status = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
1224 num_sids, sids, domains,
1225 names, types);
1227 /* And restore our original timeout. */
1228 rpccli_set_timeout(cli, orig_timeout);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 return status;
1234 return status;
1238 /* the rpc backend methods are exposed via this structure */
1239 struct winbindd_methods msrpc_methods = {
1240 False,
1241 query_user_list,
1242 enum_dom_groups,
1243 enum_local_groups,
1244 msrpc_name_to_sid,
1245 msrpc_sid_to_name,
1246 msrpc_rids_to_names,
1247 query_user,
1248 lookup_usergroups,
1249 msrpc_lookup_useraliases,
1250 lookup_groupmem,
1251 sequence_number,
1252 msrpc_lockout_policy,
1253 msrpc_password_policy,
1254 trusted_domains,