s3-winbind: Replace the passdb backend with a samr/lsa based backend.
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_rpc.c
blob1515cfa6e3c2ae792b4bed41d09d9a34c1e2e65b
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"
27 #include "../librpc/gen_ndr/cli_samr.h"
28 #include "rpc_client/cli_samr.h"
29 #include "../librpc/gen_ndr/cli_lsa.h"
30 #include "rpc_client/cli_lsarpc.h"
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_WINBIND
36 /* Query display info for a domain. This returns enough information plus a
37 bit extra to give an overview of domain users for the User Manager
38 application. */
39 static NTSTATUS query_user_list(struct winbindd_domain *domain,
40 TALLOC_CTX *mem_ctx,
41 uint32 *num_entries,
42 struct wbint_userinfo **info)
44 NTSTATUS result;
45 struct policy_handle dom_pol;
46 unsigned int i, start_idx;
47 uint32 loop_count;
48 struct rpc_pipe_client *cli;
50 DEBUG(3,("rpc: query_user_list\n"));
52 *num_entries = 0;
53 *info = NULL;
55 if ( !winbindd_can_contact_domain( domain ) ) {
56 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
57 domain->name));
58 return NT_STATUS_OK;
61 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
62 if (!NT_STATUS_IS_OK(result))
63 return result;
65 i = start_idx = 0;
66 loop_count = 0;
68 do {
69 uint32 num_dom_users, j;
70 uint32 max_entries, max_size;
71 uint32_t total_size, returned_size;
73 union samr_DispInfo disp_info;
75 /* this next bit is copied from net_user_list_internal() */
77 get_query_dispinfo_params(loop_count, &max_entries,
78 &max_size);
80 result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
81 &dom_pol,
83 start_idx,
84 max_entries,
85 max_size,
86 &total_size,
87 &returned_size,
88 &disp_info);
89 num_dom_users = disp_info.info1.count;
90 start_idx += disp_info.info1.count;
91 loop_count++;
93 *num_entries += num_dom_users;
95 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
96 struct wbint_userinfo,
97 *num_entries);
99 if (!(*info)) {
100 return NT_STATUS_NO_MEMORY;
103 for (j = 0; j < num_dom_users; i++, j++) {
105 uint32_t rid = disp_info.info1.entries[j].rid;
106 struct samr_DispEntryGeneral *src;
107 struct wbint_userinfo *dst;
109 src = &(disp_info.info1.entries[j]);
110 dst = &((*info)[i]);
112 dst->acct_name = talloc_strdup(
113 mem_ctx, src->account_name.string);
114 dst->full_name = talloc_strdup(
115 mem_ctx, src->full_name.string);
116 dst->homedir = NULL;
117 dst->shell = NULL;
118 sid_compose(&dst->user_sid, &domain->sid, rid);
120 /* For the moment we set the primary group for
121 every user to be the Domain Users group.
122 There are serious problems with determining
123 the actual primary group for large domains.
124 This should really be made into a 'winbind
125 force group' smb.conf parameter or
126 something like that. */
128 sid_compose(&dst->group_sid, &domain->sid,
129 DOMAIN_RID_USERS);
132 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
134 return result;
137 /* list all domain groups */
138 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
139 TALLOC_CTX *mem_ctx,
140 uint32 *num_entries,
141 struct acct_info **info)
143 struct policy_handle dom_pol;
144 NTSTATUS status;
145 uint32 start = 0;
146 struct rpc_pipe_client *cli;
148 *num_entries = 0;
149 *info = NULL;
151 DEBUG(3,("rpc: enum_dom_groups\n"));
153 if ( !winbindd_can_contact_domain( domain ) ) {
154 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
155 domain->name));
156 return NT_STATUS_OK;
159 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
160 if (!NT_STATUS_IS_OK(status))
161 return status;
163 do {
164 struct samr_SamArray *sam_array = NULL;
165 uint32 count = 0;
166 TALLOC_CTX *mem_ctx2;
167 int g;
169 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
171 /* start is updated by this call. */
172 status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2,
173 &dom_pol,
174 &start,
175 &sam_array,
176 0xFFFF, /* buffer size? */
177 &count);
179 if (!NT_STATUS_IS_OK(status) &&
180 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
181 talloc_destroy(mem_ctx2);
182 break;
185 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
186 struct acct_info,
187 (*num_entries) + count);
188 if (! *info) {
189 talloc_destroy(mem_ctx2);
190 return NT_STATUS_NO_MEMORY;
193 for (g=0; g < count; g++) {
195 fstrcpy((*info)[*num_entries + g].acct_name,
196 sam_array->entries[g].name.string);
197 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
200 (*num_entries) += count;
201 talloc_destroy(mem_ctx2);
202 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
204 return status;
207 /* List all domain groups */
209 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
210 TALLOC_CTX *mem_ctx,
211 uint32 *num_entries,
212 struct acct_info **info)
214 struct policy_handle dom_pol;
215 NTSTATUS result;
216 struct rpc_pipe_client *cli;
218 *num_entries = 0;
219 *info = NULL;
221 DEBUG(3,("rpc: enum_local_groups\n"));
223 if ( !winbindd_can_contact_domain( domain ) ) {
224 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
225 domain->name));
226 return NT_STATUS_OK;
229 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
230 if (!NT_STATUS_IS_OK(result))
231 return result;
233 do {
234 struct samr_SamArray *sam_array = NULL;
235 uint32 count = 0, start = *num_entries;
236 TALLOC_CTX *mem_ctx2;
237 int g;
239 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
241 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
242 &dom_pol,
243 &start,
244 &sam_array,
245 0xFFFF, /* buffer size? */
246 &count);
247 if (!NT_STATUS_IS_OK(result) &&
248 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
250 talloc_destroy(mem_ctx2);
251 return result;
254 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
255 struct acct_info,
256 (*num_entries) + count);
257 if (! *info) {
258 talloc_destroy(mem_ctx2);
259 return NT_STATUS_NO_MEMORY;
262 for (g=0; g < count; g++) {
264 fstrcpy((*info)[*num_entries + g].acct_name,
265 sam_array->entries[g].name.string);
266 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
269 (*num_entries) += count;
270 talloc_destroy(mem_ctx2);
272 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
274 return result;
277 /* convert a single name to a sid in a domain */
278 static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
279 TALLOC_CTX *mem_ctx,
280 const char *domain_name,
281 const char *name,
282 uint32_t flags,
283 struct dom_sid *sid,
284 enum lsa_SidType *type)
286 NTSTATUS result;
287 struct dom_sid *sids = NULL;
288 enum lsa_SidType *types = NULL;
289 char *full_name = NULL;
290 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
291 char *mapped_name = NULL;
293 if (name == NULL || *name=='\0') {
294 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
295 } else if (domain_name == NULL || *domain_name == '\0') {
296 full_name = talloc_asprintf(mem_ctx, "%s", name);
297 } else {
298 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
300 if (!full_name) {
301 DEBUG(0, ("talloc_asprintf failed!\n"));
302 return NT_STATUS_NO_MEMORY;
305 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
307 name_map_status = normalize_name_unmap(mem_ctx, full_name,
308 &mapped_name);
310 /* Reset the full_name pointer if we mapped anytthing */
312 if (NT_STATUS_IS_OK(name_map_status) ||
313 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
315 full_name = mapped_name;
318 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
319 full_name?full_name:"", domain_name ));
321 result = winbindd_lookup_names(mem_ctx, domain, 1,
322 (const char **)&full_name, NULL,
323 &sids, &types);
324 if (!NT_STATUS_IS_OK(result))
325 return result;
327 /* Return rid and type if lookup successful */
329 sid_copy(sid, &sids[0]);
330 *type = types[0];
332 return NT_STATUS_OK;
336 convert a domain SID to a user or group name
338 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
339 TALLOC_CTX *mem_ctx,
340 const struct dom_sid *sid,
341 char **domain_name,
342 char **name,
343 enum lsa_SidType *type)
345 char **domains;
346 char **names;
347 enum lsa_SidType *types = NULL;
348 NTSTATUS result;
349 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
350 char *mapped_name = NULL;
352 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
353 domain->name ));
355 result = winbindd_lookup_sids(mem_ctx,
356 domain,
358 sid,
359 &domains,
360 &names,
361 &types);
362 if (!NT_STATUS_IS_OK(result)) {
363 DEBUG(2,("msrpc_sid_to_name: failed to lookup sids: %s\n",
364 nt_errstr(result)));
365 return result;
369 *type = (enum lsa_SidType)types[0];
370 *domain_name = domains[0];
371 *name = names[0];
373 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
375 name_map_status = normalize_name_map(mem_ctx, domain, *name,
376 &mapped_name);
377 if (NT_STATUS_IS_OK(name_map_status) ||
378 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
380 *name = mapped_name;
381 DEBUG(5,("returning mapped name -- %s\n", *name));
384 return NT_STATUS_OK;
387 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
388 TALLOC_CTX *mem_ctx,
389 const struct dom_sid *sid,
390 uint32 *rids,
391 size_t num_rids,
392 char **domain_name,
393 char ***names,
394 enum lsa_SidType **types)
396 char **domains;
397 NTSTATUS result;
398 struct dom_sid *sids;
399 size_t i;
400 char **ret_names;
402 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
404 if (num_rids) {
405 sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_rids);
406 if (sids == NULL) {
407 return NT_STATUS_NO_MEMORY;
409 } else {
410 sids = NULL;
413 for (i=0; i<num_rids; i++) {
414 if (!sid_compose(&sids[i], sid, rids[i])) {
415 return NT_STATUS_INTERNAL_ERROR;
419 result = winbindd_lookup_sids(mem_ctx,
420 domain,
421 num_rids,
422 sids,
423 &domains,
424 names,
425 types);
427 if (!NT_STATUS_IS_OK(result) &&
428 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
429 return result;
432 ret_names = *names;
433 for (i=0; i<num_rids; i++) {
434 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
435 char *mapped_name = NULL;
437 if ((*types)[i] != SID_NAME_UNKNOWN) {
438 name_map_status = normalize_name_map(mem_ctx,
439 domain,
440 ret_names[i],
441 &mapped_name);
442 if (NT_STATUS_IS_OK(name_map_status) ||
443 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
445 ret_names[i] = mapped_name;
448 *domain_name = domains[i];
452 return result;
455 /* Lookup user information from a rid or username. */
456 static NTSTATUS query_user(struct winbindd_domain *domain,
457 TALLOC_CTX *mem_ctx,
458 const struct dom_sid *user_sid,
459 struct wbint_userinfo *user_info)
461 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
462 struct policy_handle dom_pol, user_pol;
463 union samr_UserInfo *info = NULL;
464 uint32 user_rid;
465 struct netr_SamInfo3 *user;
466 struct rpc_pipe_client *cli;
468 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
470 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
471 return NT_STATUS_UNSUCCESSFUL;
473 user_info->homedir = NULL;
474 user_info->shell = NULL;
475 user_info->primary_gid = (gid_t)-1;
477 /* try netsamlogon cache first */
479 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
482 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
483 sid_string_dbg(user_sid)));
485 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
486 sid_compose(&user_info->group_sid, &domain->sid,
487 user->base.primary_gid);
489 user_info->acct_name = talloc_strdup(mem_ctx,
490 user->base.account_name.string);
491 user_info->full_name = talloc_strdup(mem_ctx,
492 user->base.full_name.string);
494 TALLOC_FREE(user);
496 return NT_STATUS_OK;
499 if ( !winbindd_can_contact_domain( domain ) ) {
500 DEBUG(10,("query_user: No incoming trust for domain %s\n",
501 domain->name));
502 return NT_STATUS_OK;
505 /* no cache; hit the wire */
507 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
508 if (!NT_STATUS_IS_OK(result))
509 return result;
511 /* Get user handle */
512 result = rpccli_samr_OpenUser(cli, mem_ctx,
513 &dom_pol,
514 SEC_FLAG_MAXIMUM_ALLOWED,
515 user_rid,
516 &user_pol);
518 if (!NT_STATUS_IS_OK(result))
519 return result;
521 /* Get user info */
522 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
523 &user_pol,
524 0x15,
525 &info);
527 rpccli_samr_Close(cli, mem_ctx, &user_pol);
529 if (!NT_STATUS_IS_OK(result))
530 return result;
532 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
533 sid_compose(&user_info->group_sid, &domain->sid,
534 info->info21.primary_gid);
535 user_info->acct_name = talloc_strdup(mem_ctx,
536 info->info21.account_name.string);
537 user_info->full_name = talloc_strdup(mem_ctx,
538 info->info21.full_name.string);
539 user_info->homedir = NULL;
540 user_info->shell = NULL;
541 user_info->primary_gid = (gid_t)-1;
543 return NT_STATUS_OK;
546 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
547 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
548 TALLOC_CTX *mem_ctx,
549 const struct dom_sid *user_sid,
550 uint32 *num_groups, struct dom_sid **user_grpsids)
552 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
553 struct policy_handle dom_pol, user_pol;
554 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
555 struct samr_RidWithAttributeArray *rid_array = NULL;
556 unsigned int i;
557 uint32 user_rid;
558 struct rpc_pipe_client *cli;
560 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
562 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
563 return NT_STATUS_UNSUCCESSFUL;
565 *num_groups = 0;
566 *user_grpsids = NULL;
568 /* so lets see if we have a cached user_info_3 */
569 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
570 num_groups, user_grpsids);
572 if (NT_STATUS_IS_OK(result)) {
573 return NT_STATUS_OK;
576 if ( !winbindd_can_contact_domain( domain ) ) {
577 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
578 domain->name));
580 /* Tell the cache manager not to remember this one */
582 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
585 /* no cache; hit the wire */
587 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
588 if (!NT_STATUS_IS_OK(result))
589 return result;
591 /* Get user handle */
592 result = rpccli_samr_OpenUser(cli, mem_ctx,
593 &dom_pol,
594 des_access,
595 user_rid,
596 &user_pol);
598 if (!NT_STATUS_IS_OK(result))
599 return result;
601 /* Query user rids */
602 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
603 &user_pol,
604 &rid_array);
605 *num_groups = rid_array->count;
607 rpccli_samr_Close(cli, mem_ctx, &user_pol);
609 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
610 return result;
612 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, struct dom_sid, *num_groups);
613 if (!(*user_grpsids))
614 return NT_STATUS_NO_MEMORY;
616 for (i=0;i<(*num_groups);i++) {
617 sid_compose(&((*user_grpsids)[i]), &domain->sid,
618 rid_array->rids[i].rid);
621 return NT_STATUS_OK;
624 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
626 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
627 TALLOC_CTX *mem_ctx,
628 uint32 num_sids, const struct dom_sid *sids,
629 uint32 *num_aliases,
630 uint32 **alias_rids)
632 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
633 struct policy_handle dom_pol;
634 uint32 num_query_sids = 0;
635 int i;
636 struct rpc_pipe_client *cli;
637 struct samr_Ids alias_rids_query;
638 int rangesize = MAX_SAM_ENTRIES_W2K;
639 uint32 total_sids = 0;
640 int num_queries = 1;
642 *num_aliases = 0;
643 *alias_rids = NULL;
645 DEBUG(3,("rpc: lookup_useraliases\n"));
647 if ( !winbindd_can_contact_domain( domain ) ) {
648 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
649 domain->name));
650 return NT_STATUS_OK;
653 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
654 if (!NT_STATUS_IS_OK(result))
655 return result;
657 do {
658 /* prepare query */
659 struct lsa_SidArray sid_array;
661 ZERO_STRUCT(sid_array);
663 num_query_sids = MIN(num_sids - total_sids, rangesize);
665 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
666 num_queries, num_query_sids));
668 if (num_query_sids) {
669 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
670 if (sid_array.sids == NULL) {
671 return NT_STATUS_NO_MEMORY;
673 } else {
674 sid_array.sids = NULL;
677 for (i=0; i<num_query_sids; i++) {
678 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
679 if (!sid_array.sids[i].sid) {
680 TALLOC_FREE(sid_array.sids);
681 return NT_STATUS_NO_MEMORY;
684 sid_array.num_sids = num_query_sids;
686 /* do request */
687 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
688 &dom_pol,
689 &sid_array,
690 &alias_rids_query);
692 if (!NT_STATUS_IS_OK(result)) {
693 *num_aliases = 0;
694 *alias_rids = NULL;
695 TALLOC_FREE(sid_array.sids);
696 goto done;
699 /* process output */
701 for (i=0; i<alias_rids_query.count; i++) {
702 size_t na = *num_aliases;
703 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
704 alias_rids, &na)) {
705 return NT_STATUS_NO_MEMORY;
707 *num_aliases = na;
710 TALLOC_FREE(sid_array.sids);
712 num_queries++;
714 } while (total_sids < num_sids);
716 done:
717 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
718 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
720 return result;
724 /* Lookup group membership given a rid. */
725 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
726 TALLOC_CTX *mem_ctx,
727 const struct dom_sid *group_sid,
728 enum lsa_SidType type,
729 uint32 *num_names,
730 struct dom_sid **sid_mem, char ***names,
731 uint32 **name_types)
733 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
734 uint32 i, total_names = 0;
735 struct policy_handle dom_pol, group_pol;
736 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
737 uint32 *rid_mem = NULL;
738 uint32 group_rid;
739 unsigned int j, r;
740 struct rpc_pipe_client *cli;
741 unsigned int orig_timeout;
742 struct samr_RidTypeArray *rids = NULL;
744 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
745 sid_string_dbg(group_sid)));
747 if ( !winbindd_can_contact_domain( domain ) ) {
748 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
749 domain->name));
750 return NT_STATUS_OK;
753 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
754 return NT_STATUS_UNSUCCESSFUL;
756 *num_names = 0;
758 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
759 if (!NT_STATUS_IS_OK(result))
760 return result;
762 result = rpccli_samr_OpenGroup(cli, mem_ctx,
763 &dom_pol,
764 des_access,
765 group_rid,
766 &group_pol);
768 if (!NT_STATUS_IS_OK(result))
769 return result;
771 /* Step #1: Get a list of user rids that are the members of the
772 group. */
774 /* This call can take a long time - allow the server to time out.
775 35 seconds should do it. */
777 orig_timeout = rpccli_set_timeout(cli, 35000);
779 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
780 &group_pol,
781 &rids);
783 /* And restore our original timeout. */
784 rpccli_set_timeout(cli, orig_timeout);
786 rpccli_samr_Close(cli, mem_ctx, &group_pol);
788 if (!NT_STATUS_IS_OK(result))
789 return result;
791 if (!rids || !rids->count) {
792 names = NULL;
793 name_types = NULL;
794 sid_mem = NULL;
795 return NT_STATUS_OK;
798 *num_names = rids->count;
799 rid_mem = rids->rids;
801 /* Step #2: Convert list of rids into list of usernames. Do this
802 in bunches of ~1000 to avoid crashing NT4. It looks like there
803 is a buffer overflow or something like that lurking around
804 somewhere. */
806 #define MAX_LOOKUP_RIDS 900
808 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
809 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
810 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, *num_names);
812 for (j=0;j<(*num_names);j++)
813 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
815 if (*num_names>0 && (!*names || !*name_types))
816 return NT_STATUS_NO_MEMORY;
818 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
819 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
820 struct lsa_Strings tmp_names;
821 struct samr_Ids tmp_types;
823 /* Lookup a chunk of rids */
825 result = rpccli_samr_LookupRids(cli, mem_ctx,
826 &dom_pol,
827 num_lookup_rids,
828 &rid_mem[i],
829 &tmp_names,
830 &tmp_types);
832 /* see if we have a real error (and yes the
833 STATUS_SOME_UNMAPPED is the one returned from 2k) */
835 if (!NT_STATUS_IS_OK(result) &&
836 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
837 return result;
839 /* Copy result into array. The talloc system will take
840 care of freeing the temporary arrays later on. */
842 if (tmp_names.count != tmp_types.count) {
843 return NT_STATUS_UNSUCCESSFUL;
846 for (r=0; r<tmp_names.count; r++) {
847 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
848 continue;
850 (*names)[total_names] = fill_domain_username_talloc(
851 mem_ctx, domain->name,
852 tmp_names.names[r].string, true);
853 (*name_types)[total_names] = tmp_types.ids[r];
854 total_names += 1;
858 *num_names = total_names;
860 return NT_STATUS_OK;
863 #ifdef HAVE_LDAP
865 #include <ldap.h>
867 static int get_ldap_seq(const char *server, int port, uint32 *seq)
869 int ret = -1;
870 struct timeval to;
871 const char *attrs[] = {"highestCommittedUSN", NULL};
872 LDAPMessage *res = NULL;
873 char **values = NULL;
874 LDAP *ldp = NULL;
876 *seq = DOM_SEQUENCE_NONE;
879 * Parameterised (5) second timeout on open. This is needed as the
880 * search timeout doesn't seem to apply to doing an open as well. JRA.
883 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
884 if (ldp == NULL)
885 return -1;
887 /* Timeout if no response within 20 seconds. */
888 to.tv_sec = 10;
889 to.tv_usec = 0;
891 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
892 CONST_DISCARD(char **, attrs), 0, &to, &res))
893 goto done;
895 if (ldap_count_entries(ldp, res) != 1)
896 goto done;
898 values = ldap_get_values(ldp, res, "highestCommittedUSN");
899 if (!values || !values[0])
900 goto done;
902 *seq = atoi(values[0]);
903 ret = 0;
905 done:
907 if (values)
908 ldap_value_free(values);
909 if (res)
910 ldap_msgfree(res);
911 if (ldp)
912 ldap_unbind(ldp);
913 return ret;
916 /**********************************************************************
917 Get the sequence number for a Windows AD native mode domain using
918 LDAP queries.
919 **********************************************************************/
921 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
923 int ret = -1;
924 char addr[INET6_ADDRSTRLEN];
926 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
927 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
928 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
929 "number for Domain (%s) from DC (%s)\n",
930 domain->name, addr));
932 return ret;
935 #endif /* HAVE_LDAP */
937 /* find the sequence number for a domain */
938 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
940 TALLOC_CTX *mem_ctx;
941 union samr_DomainInfo *info = NULL;
942 NTSTATUS result;
943 struct policy_handle dom_pol;
944 bool got_seq_num = False;
945 struct rpc_pipe_client *cli;
947 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
949 if ( !winbindd_can_contact_domain( domain ) ) {
950 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
951 domain->name));
952 *seq = time(NULL);
953 return NT_STATUS_OK;
956 *seq = DOM_SEQUENCE_NONE;
958 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
959 return NT_STATUS_NO_MEMORY;
961 #ifdef HAVE_LDAP
962 if ( domain->active_directory )
964 int res;
966 DEBUG(8,("using get_ldap_seq() to retrieve the "
967 "sequence number\n"));
969 res = get_ldap_sequence_number( domain, seq );
970 if (res == 0)
972 result = NT_STATUS_OK;
973 DEBUG(10,("domain_sequence_number: LDAP for "
974 "domain %s is %u\n",
975 domain->name, *seq));
976 goto done;
979 DEBUG(10,("domain_sequence_number: failed to get LDAP "
980 "sequence number for domain %s\n",
981 domain->name ));
983 #endif /* HAVE_LDAP */
985 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
986 if (!NT_STATUS_IS_OK(result)) {
987 goto done;
990 /* Query domain info */
992 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
993 &dom_pol,
995 &info);
997 if (NT_STATUS_IS_OK(result)) {
998 *seq = info->info8.sequence_num;
999 got_seq_num = True;
1000 goto seq_num;
1003 /* retry with info-level 2 in case the dc does not support info-level 8
1004 * (like all older samba2 and samba3 dc's) - Guenther */
1006 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1007 &dom_pol,
1009 &info);
1011 if (NT_STATUS_IS_OK(result)) {
1012 *seq = info->general.sequence_num;
1013 got_seq_num = True;
1016 seq_num:
1017 if (got_seq_num) {
1018 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1019 domain->name, (unsigned)*seq));
1020 } else {
1021 DEBUG(10,("domain_sequence_number: failed to get sequence "
1022 "number (%u) for domain %s\n",
1023 (unsigned)*seq, domain->name ));
1026 done:
1028 talloc_destroy(mem_ctx);
1030 return result;
1033 /* get a list of trusted domains */
1034 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1035 TALLOC_CTX *mem_ctx,
1036 struct netr_DomainTrustList *trusts)
1038 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1039 uint32 enum_ctx = 0;
1040 struct rpc_pipe_client *cli;
1041 struct policy_handle lsa_policy;
1043 DEBUG(3,("rpc: trusted_domains\n"));
1045 ZERO_STRUCTP(trusts);
1047 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1048 if (!NT_STATUS_IS_OK(result))
1049 return result;
1051 result = STATUS_MORE_ENTRIES;
1053 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1054 uint32 start_idx;
1055 int i;
1056 struct lsa_DomainList dom_list;
1058 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1059 &lsa_policy,
1060 &enum_ctx,
1061 &dom_list,
1062 (uint32_t)-1);
1064 if (!NT_STATUS_IS_OK(result) &&
1065 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1066 break;
1068 start_idx = trusts->count;
1069 trusts->count += dom_list.count;
1071 trusts->array = talloc_realloc(
1072 mem_ctx, trusts->array, struct netr_DomainTrust,
1073 trusts->count);
1074 if (trusts->array == NULL) {
1075 return NT_STATUS_NO_MEMORY;
1078 for (i=0; i<dom_list.count; i++) {
1079 struct netr_DomainTrust *trust = &trusts->array[i];
1080 struct dom_sid *sid;
1082 ZERO_STRUCTP(trust);
1084 trust->netbios_name = talloc_move(
1085 trusts->array,
1086 &dom_list.domains[i].name.string);
1087 trust->dns_name = NULL;
1089 sid = talloc(trusts->array, struct dom_sid);
1090 if (sid == NULL) {
1091 return NT_STATUS_NO_MEMORY;
1093 sid_copy(sid, dom_list.domains[i].sid);
1094 trust->sid = sid;
1097 return result;
1100 /* find the lockout policy for a domain */
1101 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1102 TALLOC_CTX *mem_ctx,
1103 struct samr_DomInfo12 *lockout_policy)
1105 NTSTATUS result;
1106 struct rpc_pipe_client *cli;
1107 struct policy_handle dom_pol;
1108 union samr_DomainInfo *info = NULL;
1110 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1112 if ( !winbindd_can_contact_domain( domain ) ) {
1113 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1114 domain->name));
1115 return NT_STATUS_NOT_SUPPORTED;
1118 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1119 if (!NT_STATUS_IS_OK(result)) {
1120 goto done;
1123 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1124 &dom_pol,
1126 &info);
1127 if (!NT_STATUS_IS_OK(result)) {
1128 goto done;
1131 *lockout_policy = info->info12;
1133 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1134 info->info12.lockout_threshold));
1136 done:
1138 return result;
1141 /* find the password policy for a domain */
1142 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1143 TALLOC_CTX *mem_ctx,
1144 struct samr_DomInfo1 *password_policy)
1146 NTSTATUS result;
1147 struct rpc_pipe_client *cli;
1148 struct policy_handle dom_pol;
1149 union samr_DomainInfo *info = NULL;
1151 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1153 if ( !winbindd_can_contact_domain( domain ) ) {
1154 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1155 domain->name));
1156 return NT_STATUS_NOT_SUPPORTED;
1159 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1160 if (!NT_STATUS_IS_OK(result)) {
1161 goto done;
1164 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1165 &dom_pol,
1167 &info);
1168 if (!NT_STATUS_IS_OK(result)) {
1169 goto done;
1172 *password_policy = info->info1;
1174 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1175 info->info1.min_password_length));
1177 done:
1179 return result;
1182 typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
1183 TALLOC_CTX *mem_ctx,
1184 struct policy_handle *pol,
1185 int num_sids,
1186 const struct dom_sid *sids,
1187 char ***pdomains,
1188 char ***pnames,
1189 enum lsa_SidType **ptypes);
1191 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
1192 struct winbindd_domain *domain,
1193 uint32_t num_sids,
1194 const struct dom_sid *sids,
1195 char ***domains,
1196 char ***names,
1197 enum lsa_SidType **types)
1199 NTSTATUS status;
1200 struct rpc_pipe_client *cli = NULL;
1201 struct policy_handle lsa_policy;
1202 unsigned int orig_timeout;
1203 lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids;
1205 if (domain->can_do_ncacn_ip_tcp) {
1206 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1207 if (NT_STATUS_IS_OK(status)) {
1208 lookup_sids_fn = rpccli_lsa_lookup_sids3;
1209 goto lookup;
1211 domain->can_do_ncacn_ip_tcp = false;
1213 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 return status;
1219 lookup:
1221 * This call can take a long time
1222 * allow the server to time out.
1223 * 35 seconds should do it.
1225 orig_timeout = rpccli_set_timeout(cli, 35000);
1227 status = lookup_sids_fn(cli,
1228 mem_ctx,
1229 &lsa_policy,
1230 num_sids,
1231 sids,
1232 domains,
1233 names,
1234 types);
1236 /* And restore our original timeout. */
1237 rpccli_set_timeout(cli, orig_timeout);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 return status;
1243 return status;
1246 typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
1247 TALLOC_CTX *mem_ctx,
1248 struct policy_handle *pol,
1249 int num_names,
1250 const char **names,
1251 const char ***dom_names,
1252 int level,
1253 struct dom_sid **sids,
1254 enum lsa_SidType **types);
1256 NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
1257 struct winbindd_domain *domain,
1258 uint32_t num_names,
1259 const char **names,
1260 const char ***domains,
1261 struct dom_sid **sids,
1262 enum lsa_SidType **types)
1264 NTSTATUS status;
1265 struct rpc_pipe_client *cli = NULL;
1266 struct policy_handle lsa_policy;
1267 unsigned int orig_timeout = 0;
1268 lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names;
1270 if (domain->can_do_ncacn_ip_tcp) {
1271 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1272 if (NT_STATUS_IS_OK(status)) {
1273 lookup_names_fn = rpccli_lsa_lookup_names4;
1274 goto lookup;
1276 domain->can_do_ncacn_ip_tcp = false;
1278 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 return status;
1284 lookup:
1287 * This call can take a long time
1288 * allow the server to time out.
1289 * 35 seconds should do it.
1291 orig_timeout = rpccli_set_timeout(cli, 35000);
1293 status = lookup_names_fn(cli,
1294 mem_ctx,
1295 &lsa_policy,
1296 num_names,
1297 (const char **) names,
1298 domains,
1300 sids,
1301 types);
1303 /* And restore our original timeout. */
1304 rpccli_set_timeout(cli, orig_timeout);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 return status;
1310 return status;
1313 /* the rpc backend methods are exposed via this structure */
1314 struct winbindd_methods msrpc_methods = {
1315 False,
1316 query_user_list,
1317 enum_dom_groups,
1318 enum_local_groups,
1319 msrpc_name_to_sid,
1320 msrpc_sid_to_name,
1321 msrpc_rids_to_names,
1322 query_user,
1323 lookup_usergroups,
1324 msrpc_lookup_useraliases,
1325 lookup_groupmem,
1326 sequence_number,
1327 msrpc_lockout_policy,
1328 msrpc_password_policy,
1329 trusted_domains,