s3-winbind: Use rpc_query_user_list in msrpc.
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_msrpc.c
blob26f3e86236e96ff117914b7b667fa3627c0ee665
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 "winbindd_rpc.h"
29 #include "../librpc/gen_ndr/cli_samr.h"
30 #include "rpc_client/cli_samr.h"
31 #include "../librpc/gen_ndr/cli_lsa.h"
32 #include "rpc_client/cli_lsarpc.h"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_WINBIND
38 /* Query display info for a domain. This returns enough information plus a
39 bit extra to give an overview of domain users for the User Manager
40 application. */
41 static NTSTATUS msrpc_query_user_list(struct winbindd_domain *domain,
42 TALLOC_CTX *mem_ctx,
43 uint32_t *pnum_info,
44 struct wbint_userinfo **pinfo)
46 struct rpc_pipe_client *samr_pipe = NULL;
47 struct policy_handle dom_pol;
48 struct wbint_userinfo *info = NULL;
49 uint32_t num_info = 0;
50 TALLOC_CTX *tmp_ctx;
51 NTSTATUS status;
53 DEBUG(3,("rpc_query_user_list\n"));
55 if (pnum_info) {
56 *pnum_info = 0;
59 tmp_ctx = talloc_stackframe();
60 if (tmp_ctx == NULL) {
61 return NT_STATUS_NO_MEMORY;
64 if ( !winbindd_can_contact_domain( domain ) ) {
65 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
66 domain->name));
67 status = NT_STATUS_OK;
68 goto done;
71 status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
72 if (!NT_STATUS_IS_OK(status)) {
73 goto done;
76 status = rpc_query_user_list(tmp_ctx,
77 samr_pipe,
78 &dom_pol,
79 &domain->sid,
80 &num_info,
81 &info);
82 if (!NT_STATUS_IS_OK(status)) {
83 goto done;
86 if (pnum_info) {
87 *pnum_info = num_info;
90 if (pinfo) {
91 *pinfo = talloc_move(mem_ctx, &info);
94 done:
95 TALLOC_FREE(tmp_ctx);
96 return status;
99 /* list all domain groups */
100 static NTSTATUS msrpc_enum_dom_groups(struct winbindd_domain *domain,
101 TALLOC_CTX *mem_ctx,
102 uint32_t *pnum_info,
103 struct acct_info **pinfo)
105 struct rpc_pipe_client *samr_pipe;
106 struct policy_handle dom_pol;
107 struct acct_info *info = NULL;
108 uint32_t num_info = 0;
109 TALLOC_CTX *tmp_ctx;
110 NTSTATUS status;
112 DEBUG(3,("msrpc_enum_dom_groups\n"));
114 if (pnum_info) {
115 *pnum_info = 0;
118 tmp_ctx = talloc_stackframe();
119 if (tmp_ctx == NULL) {
120 return NT_STATUS_NO_MEMORY;
123 if ( !winbindd_can_contact_domain( domain ) ) {
124 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
125 domain->name));
126 status = NT_STATUS_OK;
127 goto done;
130 status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
131 if (!NT_STATUS_IS_OK(status)) {
132 goto done;
135 status = rpc_enum_dom_groups(tmp_ctx,
136 samr_pipe,
137 &dom_pol,
138 &num_info,
139 &info);
140 if (!NT_STATUS_IS_OK(status)) {
141 goto done;
144 if (pnum_info) {
145 *pnum_info = num_info;
148 if (pinfo) {
149 *pinfo = talloc_move(mem_ctx, &info);
152 done:
153 TALLOC_FREE(tmp_ctx);
154 return status;
157 /* List all domain groups */
159 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
160 TALLOC_CTX *mem_ctx,
161 uint32 *num_entries,
162 struct acct_info **info)
164 struct policy_handle dom_pol;
165 NTSTATUS result;
166 struct rpc_pipe_client *cli;
168 *num_entries = 0;
169 *info = NULL;
171 DEBUG(3,("rpc: enum_local_groups\n"));
173 if ( !winbindd_can_contact_domain( domain ) ) {
174 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
175 domain->name));
176 return NT_STATUS_OK;
179 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
180 if (!NT_STATUS_IS_OK(result))
181 return result;
183 do {
184 struct samr_SamArray *sam_array = NULL;
185 uint32 count = 0, start = *num_entries;
186 TALLOC_CTX *mem_ctx2;
187 int g;
189 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
191 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
192 &dom_pol,
193 &start,
194 &sam_array,
195 0xFFFF, /* buffer size? */
196 &count);
197 if (!NT_STATUS_IS_OK(result) &&
198 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
200 talloc_destroy(mem_ctx2);
201 return result;
204 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
205 struct acct_info,
206 (*num_entries) + count);
207 if (! *info) {
208 talloc_destroy(mem_ctx2);
209 return NT_STATUS_NO_MEMORY;
212 for (g=0; g < count; g++) {
214 fstrcpy((*info)[*num_entries + g].acct_name,
215 sam_array->entries[g].name.string);
216 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
219 (*num_entries) += count;
220 talloc_destroy(mem_ctx2);
222 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
224 return result;
227 /* convert a single name to a sid in a domain */
228 static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
229 TALLOC_CTX *mem_ctx,
230 const char *domain_name,
231 const char *name,
232 uint32_t flags,
233 struct dom_sid *sid,
234 enum lsa_SidType *type)
236 NTSTATUS result;
237 struct dom_sid *sids = NULL;
238 enum lsa_SidType *types = NULL;
239 char *full_name = NULL;
240 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
241 char *mapped_name = NULL;
243 if (name == NULL || *name=='\0') {
244 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
245 } else if (domain_name == NULL || *domain_name == '\0') {
246 full_name = talloc_asprintf(mem_ctx, "%s", name);
247 } else {
248 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
250 if (!full_name) {
251 DEBUG(0, ("talloc_asprintf failed!\n"));
252 return NT_STATUS_NO_MEMORY;
255 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
257 name_map_status = normalize_name_unmap(mem_ctx, full_name,
258 &mapped_name);
260 /* Reset the full_name pointer if we mapped anytthing */
262 if (NT_STATUS_IS_OK(name_map_status) ||
263 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
265 full_name = mapped_name;
268 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
269 full_name?full_name:"", domain_name ));
271 result = winbindd_lookup_names(mem_ctx, domain, 1,
272 (const char **)&full_name, NULL,
273 &sids, &types);
274 if (!NT_STATUS_IS_OK(result))
275 return result;
277 /* Return rid and type if lookup successful */
279 sid_copy(sid, &sids[0]);
280 *type = types[0];
282 return NT_STATUS_OK;
286 convert a domain SID to a user or group name
288 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
289 TALLOC_CTX *mem_ctx,
290 const struct dom_sid *sid,
291 char **domain_name,
292 char **name,
293 enum lsa_SidType *type)
295 char **domains;
296 char **names;
297 enum lsa_SidType *types = NULL;
298 NTSTATUS result;
299 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
300 char *mapped_name = NULL;
302 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
303 domain->name ));
305 result = winbindd_lookup_sids(mem_ctx,
306 domain,
308 sid,
309 &domains,
310 &names,
311 &types);
312 if (!NT_STATUS_IS_OK(result)) {
313 DEBUG(2,("msrpc_sid_to_name: failed to lookup sids: %s\n",
314 nt_errstr(result)));
315 return result;
319 *type = (enum lsa_SidType)types[0];
320 *domain_name = domains[0];
321 *name = names[0];
323 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
325 name_map_status = normalize_name_map(mem_ctx, domain, *name,
326 &mapped_name);
327 if (NT_STATUS_IS_OK(name_map_status) ||
328 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
330 *name = mapped_name;
331 DEBUG(5,("returning mapped name -- %s\n", *name));
334 return NT_STATUS_OK;
337 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
338 TALLOC_CTX *mem_ctx,
339 const struct dom_sid *sid,
340 uint32 *rids,
341 size_t num_rids,
342 char **domain_name,
343 char ***names,
344 enum lsa_SidType **types)
346 char **domains;
347 NTSTATUS result;
348 struct dom_sid *sids;
349 size_t i;
350 char **ret_names;
352 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
354 if (num_rids) {
355 sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_rids);
356 if (sids == NULL) {
357 return NT_STATUS_NO_MEMORY;
359 } else {
360 sids = NULL;
363 for (i=0; i<num_rids; i++) {
364 if (!sid_compose(&sids[i], sid, rids[i])) {
365 return NT_STATUS_INTERNAL_ERROR;
369 result = winbindd_lookup_sids(mem_ctx,
370 domain,
371 num_rids,
372 sids,
373 &domains,
374 names,
375 types);
377 if (!NT_STATUS_IS_OK(result) &&
378 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
379 return result;
382 ret_names = *names;
383 for (i=0; i<num_rids; i++) {
384 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
385 char *mapped_name = NULL;
387 if ((*types)[i] != SID_NAME_UNKNOWN) {
388 name_map_status = normalize_name_map(mem_ctx,
389 domain,
390 ret_names[i],
391 &mapped_name);
392 if (NT_STATUS_IS_OK(name_map_status) ||
393 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
395 ret_names[i] = mapped_name;
398 *domain_name = domains[i];
402 return result;
405 /* Lookup user information from a rid or username. */
406 static NTSTATUS query_user(struct winbindd_domain *domain,
407 TALLOC_CTX *mem_ctx,
408 const struct dom_sid *user_sid,
409 struct wbint_userinfo *user_info)
411 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
412 struct policy_handle dom_pol, user_pol;
413 union samr_UserInfo *info = NULL;
414 uint32 user_rid;
415 struct netr_SamInfo3 *user;
416 struct rpc_pipe_client *cli;
418 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
420 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
421 return NT_STATUS_UNSUCCESSFUL;
423 user_info->homedir = NULL;
424 user_info->shell = NULL;
425 user_info->primary_gid = (gid_t)-1;
427 /* try netsamlogon cache first */
429 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
432 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
433 sid_string_dbg(user_sid)));
435 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
436 sid_compose(&user_info->group_sid, &domain->sid,
437 user->base.primary_gid);
439 user_info->acct_name = talloc_strdup(mem_ctx,
440 user->base.account_name.string);
441 user_info->full_name = talloc_strdup(mem_ctx,
442 user->base.full_name.string);
444 TALLOC_FREE(user);
446 return NT_STATUS_OK;
449 if ( !winbindd_can_contact_domain( domain ) ) {
450 DEBUG(10,("query_user: No incoming trust for domain %s\n",
451 domain->name));
452 return NT_STATUS_OK;
455 /* no cache; hit the wire */
457 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
458 if (!NT_STATUS_IS_OK(result))
459 return result;
461 /* Get user handle */
462 result = rpccli_samr_OpenUser(cli, mem_ctx,
463 &dom_pol,
464 SEC_FLAG_MAXIMUM_ALLOWED,
465 user_rid,
466 &user_pol);
468 if (!NT_STATUS_IS_OK(result))
469 return result;
471 /* Get user info */
472 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
473 &user_pol,
474 0x15,
475 &info);
477 rpccli_samr_Close(cli, mem_ctx, &user_pol);
479 if (!NT_STATUS_IS_OK(result))
480 return result;
482 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
483 sid_compose(&user_info->group_sid, &domain->sid,
484 info->info21.primary_gid);
485 user_info->acct_name = talloc_strdup(mem_ctx,
486 info->info21.account_name.string);
487 user_info->full_name = talloc_strdup(mem_ctx,
488 info->info21.full_name.string);
489 user_info->homedir = NULL;
490 user_info->shell = NULL;
491 user_info->primary_gid = (gid_t)-1;
493 return NT_STATUS_OK;
496 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
497 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
498 TALLOC_CTX *mem_ctx,
499 const struct dom_sid *user_sid,
500 uint32 *num_groups, struct dom_sid **user_grpsids)
502 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
503 struct policy_handle dom_pol, user_pol;
504 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
505 struct samr_RidWithAttributeArray *rid_array = NULL;
506 unsigned int i;
507 uint32 user_rid;
508 struct rpc_pipe_client *cli;
510 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
512 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
513 return NT_STATUS_UNSUCCESSFUL;
515 *num_groups = 0;
516 *user_grpsids = NULL;
518 /* so lets see if we have a cached user_info_3 */
519 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
520 num_groups, user_grpsids);
522 if (NT_STATUS_IS_OK(result)) {
523 return NT_STATUS_OK;
526 if ( !winbindd_can_contact_domain( domain ) ) {
527 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
528 domain->name));
530 /* Tell the cache manager not to remember this one */
532 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
535 /* no cache; hit the wire */
537 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
538 if (!NT_STATUS_IS_OK(result))
539 return result;
541 /* Get user handle */
542 result = rpccli_samr_OpenUser(cli, mem_ctx,
543 &dom_pol,
544 des_access,
545 user_rid,
546 &user_pol);
548 if (!NT_STATUS_IS_OK(result))
549 return result;
551 /* Query user rids */
552 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
553 &user_pol,
554 &rid_array);
555 *num_groups = rid_array->count;
557 rpccli_samr_Close(cli, mem_ctx, &user_pol);
559 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
560 return result;
562 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, struct dom_sid, *num_groups);
563 if (!(*user_grpsids))
564 return NT_STATUS_NO_MEMORY;
566 for (i=0;i<(*num_groups);i++) {
567 sid_compose(&((*user_grpsids)[i]), &domain->sid,
568 rid_array->rids[i].rid);
571 return NT_STATUS_OK;
574 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
576 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
577 TALLOC_CTX *mem_ctx,
578 uint32 num_sids, const struct dom_sid *sids,
579 uint32 *num_aliases,
580 uint32 **alias_rids)
582 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
583 struct policy_handle dom_pol;
584 uint32 num_query_sids = 0;
585 int i;
586 struct rpc_pipe_client *cli;
587 struct samr_Ids alias_rids_query;
588 int rangesize = MAX_SAM_ENTRIES_W2K;
589 uint32 total_sids = 0;
590 int num_queries = 1;
592 *num_aliases = 0;
593 *alias_rids = NULL;
595 DEBUG(3,("rpc: lookup_useraliases\n"));
597 if ( !winbindd_can_contact_domain( domain ) ) {
598 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
599 domain->name));
600 return NT_STATUS_OK;
603 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
604 if (!NT_STATUS_IS_OK(result))
605 return result;
607 do {
608 /* prepare query */
609 struct lsa_SidArray sid_array;
611 ZERO_STRUCT(sid_array);
613 num_query_sids = MIN(num_sids - total_sids, rangesize);
615 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
616 num_queries, num_query_sids));
618 if (num_query_sids) {
619 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
620 if (sid_array.sids == NULL) {
621 return NT_STATUS_NO_MEMORY;
623 } else {
624 sid_array.sids = NULL;
627 for (i=0; i<num_query_sids; i++) {
628 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
629 if (!sid_array.sids[i].sid) {
630 TALLOC_FREE(sid_array.sids);
631 return NT_STATUS_NO_MEMORY;
634 sid_array.num_sids = num_query_sids;
636 /* do request */
637 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
638 &dom_pol,
639 &sid_array,
640 &alias_rids_query);
642 if (!NT_STATUS_IS_OK(result)) {
643 *num_aliases = 0;
644 *alias_rids = NULL;
645 TALLOC_FREE(sid_array.sids);
646 goto done;
649 /* process output */
651 for (i=0; i<alias_rids_query.count; i++) {
652 size_t na = *num_aliases;
653 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
654 alias_rids, &na)) {
655 return NT_STATUS_NO_MEMORY;
657 *num_aliases = na;
660 TALLOC_FREE(sid_array.sids);
662 num_queries++;
664 } while (total_sids < num_sids);
666 done:
667 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
668 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
670 return result;
674 /* Lookup group membership given a rid. */
675 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
676 TALLOC_CTX *mem_ctx,
677 const struct dom_sid *group_sid,
678 enum lsa_SidType type,
679 uint32 *num_names,
680 struct dom_sid **sid_mem, char ***names,
681 uint32 **name_types)
683 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
684 uint32 i, total_names = 0;
685 struct policy_handle dom_pol, group_pol;
686 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
687 uint32 *rid_mem = NULL;
688 uint32 group_rid;
689 unsigned int j, r;
690 struct rpc_pipe_client *cli;
691 unsigned int orig_timeout;
692 struct samr_RidTypeArray *rids = NULL;
694 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
695 sid_string_dbg(group_sid)));
697 if ( !winbindd_can_contact_domain( domain ) ) {
698 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
699 domain->name));
700 return NT_STATUS_OK;
703 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
704 return NT_STATUS_UNSUCCESSFUL;
706 *num_names = 0;
708 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
709 if (!NT_STATUS_IS_OK(result))
710 return result;
712 result = rpccli_samr_OpenGroup(cli, mem_ctx,
713 &dom_pol,
714 des_access,
715 group_rid,
716 &group_pol);
718 if (!NT_STATUS_IS_OK(result))
719 return result;
721 /* Step #1: Get a list of user rids that are the members of the
722 group. */
724 /* This call can take a long time - allow the server to time out.
725 35 seconds should do it. */
727 orig_timeout = rpccli_set_timeout(cli, 35000);
729 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
730 &group_pol,
731 &rids);
733 /* And restore our original timeout. */
734 rpccli_set_timeout(cli, orig_timeout);
736 rpccli_samr_Close(cli, mem_ctx, &group_pol);
738 if (!NT_STATUS_IS_OK(result))
739 return result;
741 if (!rids || !rids->count) {
742 names = NULL;
743 name_types = NULL;
744 sid_mem = NULL;
745 return NT_STATUS_OK;
748 *num_names = rids->count;
749 rid_mem = rids->rids;
751 /* Step #2: Convert list of rids into list of usernames. Do this
752 in bunches of ~1000 to avoid crashing NT4. It looks like there
753 is a buffer overflow or something like that lurking around
754 somewhere. */
756 #define MAX_LOOKUP_RIDS 900
758 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
759 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
760 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, *num_names);
762 for (j=0;j<(*num_names);j++)
763 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
765 if (*num_names>0 && (!*names || !*name_types))
766 return NT_STATUS_NO_MEMORY;
768 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
769 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
770 struct lsa_Strings tmp_names;
771 struct samr_Ids tmp_types;
773 /* Lookup a chunk of rids */
775 result = rpccli_samr_LookupRids(cli, mem_ctx,
776 &dom_pol,
777 num_lookup_rids,
778 &rid_mem[i],
779 &tmp_names,
780 &tmp_types);
782 /* see if we have a real error (and yes the
783 STATUS_SOME_UNMAPPED is the one returned from 2k) */
785 if (!NT_STATUS_IS_OK(result) &&
786 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
787 return result;
789 /* Copy result into array. The talloc system will take
790 care of freeing the temporary arrays later on. */
792 if (tmp_names.count != tmp_types.count) {
793 return NT_STATUS_UNSUCCESSFUL;
796 for (r=0; r<tmp_names.count; r++) {
797 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
798 continue;
800 (*names)[total_names] = fill_domain_username_talloc(
801 mem_ctx, domain->name,
802 tmp_names.names[r].string, true);
803 (*name_types)[total_names] = tmp_types.ids[r];
804 total_names += 1;
808 *num_names = total_names;
810 return NT_STATUS_OK;
813 #ifdef HAVE_LDAP
815 #include <ldap.h>
817 static int get_ldap_seq(const char *server, int port, uint32 *seq)
819 int ret = -1;
820 struct timeval to;
821 const char *attrs[] = {"highestCommittedUSN", NULL};
822 LDAPMessage *res = NULL;
823 char **values = NULL;
824 LDAP *ldp = NULL;
826 *seq = DOM_SEQUENCE_NONE;
829 * Parameterised (5) second timeout on open. This is needed as the
830 * search timeout doesn't seem to apply to doing an open as well. JRA.
833 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
834 if (ldp == NULL)
835 return -1;
837 /* Timeout if no response within 20 seconds. */
838 to.tv_sec = 10;
839 to.tv_usec = 0;
841 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
842 CONST_DISCARD(char **, attrs), 0, &to, &res))
843 goto done;
845 if (ldap_count_entries(ldp, res) != 1)
846 goto done;
848 values = ldap_get_values(ldp, res, "highestCommittedUSN");
849 if (!values || !values[0])
850 goto done;
852 *seq = atoi(values[0]);
853 ret = 0;
855 done:
857 if (values)
858 ldap_value_free(values);
859 if (res)
860 ldap_msgfree(res);
861 if (ldp)
862 ldap_unbind(ldp);
863 return ret;
866 /**********************************************************************
867 Get the sequence number for a Windows AD native mode domain using
868 LDAP queries.
869 **********************************************************************/
871 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
873 int ret = -1;
874 char addr[INET6_ADDRSTRLEN];
876 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
877 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
878 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
879 "number for Domain (%s) from DC (%s)\n",
880 domain->name, addr));
882 return ret;
885 #endif /* HAVE_LDAP */
887 /* find the sequence number for a domain */
888 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
890 TALLOC_CTX *mem_ctx;
891 union samr_DomainInfo *info = NULL;
892 NTSTATUS result;
893 struct policy_handle dom_pol;
894 bool got_seq_num = False;
895 struct rpc_pipe_client *cli;
897 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
899 if ( !winbindd_can_contact_domain( domain ) ) {
900 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
901 domain->name));
902 *seq = time(NULL);
903 return NT_STATUS_OK;
906 *seq = DOM_SEQUENCE_NONE;
908 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
909 return NT_STATUS_NO_MEMORY;
911 #ifdef HAVE_LDAP
912 if ( domain->active_directory )
914 int res;
916 DEBUG(8,("using get_ldap_seq() to retrieve the "
917 "sequence number\n"));
919 res = get_ldap_sequence_number( domain, seq );
920 if (res == 0)
922 result = NT_STATUS_OK;
923 DEBUG(10,("domain_sequence_number: LDAP for "
924 "domain %s is %u\n",
925 domain->name, *seq));
926 goto done;
929 DEBUG(10,("domain_sequence_number: failed to get LDAP "
930 "sequence number for domain %s\n",
931 domain->name ));
933 #endif /* HAVE_LDAP */
935 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
936 if (!NT_STATUS_IS_OK(result)) {
937 goto done;
940 /* Query domain info */
942 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
943 &dom_pol,
945 &info);
947 if (NT_STATUS_IS_OK(result)) {
948 *seq = info->info8.sequence_num;
949 got_seq_num = True;
950 goto seq_num;
953 /* retry with info-level 2 in case the dc does not support info-level 8
954 * (like all older samba2 and samba3 dc's) - Guenther */
956 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
957 &dom_pol,
959 &info);
961 if (NT_STATUS_IS_OK(result)) {
962 *seq = info->general.sequence_num;
963 got_seq_num = True;
966 seq_num:
967 if (got_seq_num) {
968 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
969 domain->name, (unsigned)*seq));
970 } else {
971 DEBUG(10,("domain_sequence_number: failed to get sequence "
972 "number (%u) for domain %s\n",
973 (unsigned)*seq, domain->name ));
976 done:
978 talloc_destroy(mem_ctx);
980 return result;
983 /* get a list of trusted domains */
984 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
985 TALLOC_CTX *mem_ctx,
986 struct netr_DomainTrustList *trusts)
988 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
989 uint32 enum_ctx = 0;
990 struct rpc_pipe_client *cli;
991 struct policy_handle lsa_policy;
993 DEBUG(3,("rpc: trusted_domains\n"));
995 ZERO_STRUCTP(trusts);
997 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
998 if (!NT_STATUS_IS_OK(result))
999 return result;
1001 result = STATUS_MORE_ENTRIES;
1003 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1004 uint32 start_idx;
1005 int i;
1006 struct lsa_DomainList dom_list;
1008 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1009 &lsa_policy,
1010 &enum_ctx,
1011 &dom_list,
1012 (uint32_t)-1);
1014 if (!NT_STATUS_IS_OK(result) &&
1015 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1016 break;
1018 start_idx = trusts->count;
1019 trusts->count += dom_list.count;
1021 trusts->array = talloc_realloc(
1022 mem_ctx, trusts->array, struct netr_DomainTrust,
1023 trusts->count);
1024 if (trusts->array == NULL) {
1025 return NT_STATUS_NO_MEMORY;
1028 for (i=0; i<dom_list.count; i++) {
1029 struct netr_DomainTrust *trust = &trusts->array[i];
1030 struct dom_sid *sid;
1032 ZERO_STRUCTP(trust);
1034 trust->netbios_name = talloc_move(
1035 trusts->array,
1036 &dom_list.domains[i].name.string);
1037 trust->dns_name = NULL;
1039 sid = talloc(trusts->array, struct dom_sid);
1040 if (sid == NULL) {
1041 return NT_STATUS_NO_MEMORY;
1043 sid_copy(sid, dom_list.domains[i].sid);
1044 trust->sid = sid;
1047 return result;
1050 /* find the lockout policy for a domain */
1051 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1052 TALLOC_CTX *mem_ctx,
1053 struct samr_DomInfo12 *lockout_policy)
1055 NTSTATUS result;
1056 struct rpc_pipe_client *cli;
1057 struct policy_handle dom_pol;
1058 union samr_DomainInfo *info = NULL;
1060 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1062 if ( !winbindd_can_contact_domain( domain ) ) {
1063 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1064 domain->name));
1065 return NT_STATUS_NOT_SUPPORTED;
1068 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1069 if (!NT_STATUS_IS_OK(result)) {
1070 goto done;
1073 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1074 &dom_pol,
1076 &info);
1077 if (!NT_STATUS_IS_OK(result)) {
1078 goto done;
1081 *lockout_policy = info->info12;
1083 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1084 info->info12.lockout_threshold));
1086 done:
1088 return result;
1091 /* find the password policy for a domain */
1092 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1093 TALLOC_CTX *mem_ctx,
1094 struct samr_DomInfo1 *password_policy)
1096 NTSTATUS result;
1097 struct rpc_pipe_client *cli;
1098 struct policy_handle dom_pol;
1099 union samr_DomainInfo *info = NULL;
1101 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1103 if ( !winbindd_can_contact_domain( domain ) ) {
1104 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1105 domain->name));
1106 return NT_STATUS_NOT_SUPPORTED;
1109 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1110 if (!NT_STATUS_IS_OK(result)) {
1111 goto done;
1114 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1115 &dom_pol,
1117 &info);
1118 if (!NT_STATUS_IS_OK(result)) {
1119 goto done;
1122 *password_policy = info->info1;
1124 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1125 info->info1.min_password_length));
1127 done:
1129 return result;
1132 typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
1133 TALLOC_CTX *mem_ctx,
1134 struct policy_handle *pol,
1135 int num_sids,
1136 const struct dom_sid *sids,
1137 char ***pdomains,
1138 char ***pnames,
1139 enum lsa_SidType **ptypes);
1141 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
1142 struct winbindd_domain *domain,
1143 uint32_t num_sids,
1144 const struct dom_sid *sids,
1145 char ***domains,
1146 char ***names,
1147 enum lsa_SidType **types)
1149 NTSTATUS status;
1150 struct rpc_pipe_client *cli = NULL;
1151 struct policy_handle lsa_policy;
1152 unsigned int orig_timeout;
1153 lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids;
1155 if (domain->can_do_ncacn_ip_tcp) {
1156 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1157 if (NT_STATUS_IS_OK(status)) {
1158 lookup_sids_fn = rpccli_lsa_lookup_sids3;
1159 goto lookup;
1161 domain->can_do_ncacn_ip_tcp = false;
1163 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 return status;
1169 lookup:
1171 * This call can take a long time
1172 * allow the server to time out.
1173 * 35 seconds should do it.
1175 orig_timeout = rpccli_set_timeout(cli, 35000);
1177 status = lookup_sids_fn(cli,
1178 mem_ctx,
1179 &lsa_policy,
1180 num_sids,
1181 sids,
1182 domains,
1183 names,
1184 types);
1186 /* And restore our original timeout. */
1187 rpccli_set_timeout(cli, orig_timeout);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 return status;
1193 return status;
1196 typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
1197 TALLOC_CTX *mem_ctx,
1198 struct policy_handle *pol,
1199 int num_names,
1200 const char **names,
1201 const char ***dom_names,
1202 int level,
1203 struct dom_sid **sids,
1204 enum lsa_SidType **types);
1206 NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
1207 struct winbindd_domain *domain,
1208 uint32_t num_names,
1209 const char **names,
1210 const char ***domains,
1211 struct dom_sid **sids,
1212 enum lsa_SidType **types)
1214 NTSTATUS status;
1215 struct rpc_pipe_client *cli = NULL;
1216 struct policy_handle lsa_policy;
1217 unsigned int orig_timeout = 0;
1218 lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names;
1220 if (domain->can_do_ncacn_ip_tcp) {
1221 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1222 if (NT_STATUS_IS_OK(status)) {
1223 lookup_names_fn = rpccli_lsa_lookup_names4;
1224 goto lookup;
1226 domain->can_do_ncacn_ip_tcp = false;
1228 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 return status;
1234 lookup:
1237 * This call can take a long time
1238 * allow the server to time out.
1239 * 35 seconds should do it.
1241 orig_timeout = rpccli_set_timeout(cli, 35000);
1243 status = lookup_names_fn(cli,
1244 mem_ctx,
1245 &lsa_policy,
1246 num_names,
1247 (const char **) names,
1248 domains,
1250 sids,
1251 types);
1253 /* And restore our original timeout. */
1254 rpccli_set_timeout(cli, orig_timeout);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 return status;
1260 return status;
1263 /* the rpc backend methods are exposed via this structure */
1264 struct winbindd_methods msrpc_methods = {
1265 False,
1266 msrpc_query_user_list,
1267 msrpc_enum_dom_groups,
1268 enum_local_groups,
1269 msrpc_name_to_sid,
1270 msrpc_sid_to_name,
1271 msrpc_rids_to_names,
1272 query_user,
1273 lookup_usergroups,
1274 msrpc_lookup_useraliases,
1275 lookup_groupmem,
1276 sequence_number,
1277 msrpc_lockout_policy,
1278 msrpc_password_policy,
1279 trusted_domains,