WHATSNEW: Update release notes.
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blobaa8a5c849fb2ce6c701c00fadd346e1b4109bdb0
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Volker Lendecke 2005
9 Copyright (C) Guenther Deschner 2008 (pidl conversion)
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "winbindd.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
32 /* Query display info for a domain. This returns enough information plus a
33 bit extra to give an overview of domain users for the User Manager
34 application. */
35 static NTSTATUS query_user_list(struct winbindd_domain *domain,
36 TALLOC_CTX *mem_ctx,
37 uint32 *num_entries,
38 WINBIND_USERINFO **info)
40 NTSTATUS result;
41 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, WINBIND_USERINFO,
92 *num_entries);
94 if (!(*info)) {
95 return NT_STATUS_NO_MEMORY;
98 for (j = 0; j < num_dom_users; i++, j++) {
100 uint32_t rid = disp_info.info1.entries[j].rid;
102 (*info)[i].acct_name = talloc_strdup(mem_ctx,
103 disp_info.info1.entries[j].account_name.string);
104 (*info)[i].full_name = talloc_strdup(mem_ctx,
105 disp_info.info1.entries[j].full_name.string);
106 (*info)[i].homedir = NULL;
107 (*info)[i].shell = NULL;
108 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
110 /* For the moment we set the primary group for
111 every user to be the Domain Users group.
112 There are serious problems with determining
113 the actual primary group for large domains.
114 This should really be made into a 'winbind
115 force group' smb.conf parameter or
116 something like that. */
118 sid_compose(&(*info)[i].group_sid, &domain->sid,
119 DOMAIN_GROUP_RID_USERS);
122 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
124 return result;
127 /* list all domain groups */
128 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
129 TALLOC_CTX *mem_ctx,
130 uint32 *num_entries,
131 struct acct_info **info)
133 struct policy_handle dom_pol;
134 NTSTATUS status;
135 uint32 start = 0;
136 struct rpc_pipe_client *cli;
138 *num_entries = 0;
139 *info = NULL;
141 DEBUG(3,("rpc: enum_dom_groups\n"));
143 if ( !winbindd_can_contact_domain( domain ) ) {
144 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
145 domain->name));
146 return NT_STATUS_OK;
149 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
150 if (!NT_STATUS_IS_OK(status))
151 return status;
153 do {
154 struct samr_SamArray *sam_array = NULL;
155 uint32 count = 0;
156 TALLOC_CTX *mem_ctx2;
157 int g;
159 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
161 /* start is updated by this call. */
162 status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2,
163 &dom_pol,
164 &start,
165 &sam_array,
166 0xFFFF, /* buffer size? */
167 &count);
169 if (!NT_STATUS_IS_OK(status) &&
170 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
171 talloc_destroy(mem_ctx2);
172 break;
175 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
176 struct acct_info,
177 (*num_entries) + count);
178 if (! *info) {
179 talloc_destroy(mem_ctx2);
180 return NT_STATUS_NO_MEMORY;
183 for (g=0; g < count; g++) {
185 fstrcpy((*info)[*num_entries + g].acct_name,
186 sam_array->entries[g].name.string);
187 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
190 (*num_entries) += count;
191 talloc_destroy(mem_ctx2);
192 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
194 return NT_STATUS_OK;
197 /* List all domain groups */
199 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
200 TALLOC_CTX *mem_ctx,
201 uint32 *num_entries,
202 struct acct_info **info)
204 struct policy_handle dom_pol;
205 NTSTATUS result;
206 struct rpc_pipe_client *cli;
208 *num_entries = 0;
209 *info = NULL;
211 DEBUG(3,("rpc: enum_local_groups\n"));
213 if ( !winbindd_can_contact_domain( domain ) ) {
214 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
215 domain->name));
216 return NT_STATUS_OK;
219 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
220 if (!NT_STATUS_IS_OK(result))
221 return result;
223 do {
224 struct samr_SamArray *sam_array = NULL;
225 uint32 count = 0, start = *num_entries;
226 TALLOC_CTX *mem_ctx2;
227 int g;
229 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
231 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
232 &dom_pol,
233 &start,
234 &sam_array,
235 0xFFFF, /* buffer size? */
236 &count);
237 if (!NT_STATUS_IS_OK(result) &&
238 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
240 talloc_destroy(mem_ctx2);
241 return result;
244 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
245 struct acct_info,
246 (*num_entries) + count);
247 if (! *info) {
248 talloc_destroy(mem_ctx2);
249 return NT_STATUS_NO_MEMORY;
252 for (g=0; g < count; g++) {
254 fstrcpy((*info)[*num_entries + g].acct_name,
255 sam_array->entries[g].name.string);
256 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
259 (*num_entries) += count;
260 talloc_destroy(mem_ctx2);
262 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
264 return NT_STATUS_OK;
267 /* convert a single name to a sid in a domain */
268 static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
269 TALLOC_CTX *mem_ctx,
270 enum winbindd_cmd original_cmd,
271 const char *domain_name,
272 const char *name,
273 DOM_SID *sid,
274 enum lsa_SidType *type)
276 NTSTATUS result;
277 DOM_SID *sids = NULL;
278 enum lsa_SidType *types = NULL;
279 char *full_name = NULL;
280 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
281 char *mapped_name = NULL;
283 if (name == NULL || *name=='\0') {
284 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
285 } else if (domain_name == NULL || *domain_name == '\0') {
286 full_name = talloc_asprintf(mem_ctx, "%s", name);
287 } else {
288 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
290 if (!full_name) {
291 DEBUG(0, ("talloc_asprintf failed!\n"));
292 return NT_STATUS_NO_MEMORY;
295 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
297 name_map_status = normalize_name_unmap(mem_ctx, full_name,
298 &mapped_name);
300 /* Reset the full_name pointer if we mapped anytthing */
302 if (NT_STATUS_IS_OK(name_map_status) ||
303 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
305 full_name = mapped_name;
308 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
309 full_name?full_name:"", domain_name ));
311 result = winbindd_lookup_names(mem_ctx, domain, 1,
312 (const char **)&full_name, NULL,
313 &sids, &types);
314 if (!NT_STATUS_IS_OK(result))
315 return result;
317 /* Return rid and type if lookup successful */
319 sid_copy(sid, &sids[0]);
320 *type = types[0];
322 return NT_STATUS_OK;
326 convert a domain SID to a user or group name
328 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
329 TALLOC_CTX *mem_ctx,
330 const DOM_SID *sid,
331 char **domain_name,
332 char **name,
333 enum lsa_SidType *type)
335 char **domains;
336 char **names;
337 enum lsa_SidType *types = NULL;
338 NTSTATUS result;
339 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
340 char *mapped_name = NULL;
342 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
343 domain->name ));
345 result = winbindd_lookup_sids(mem_ctx,
346 domain,
348 sid,
349 &domains,
350 &names,
351 &types);
352 if (!NT_STATUS_IS_OK(result)) {
353 DEBUG(2,("msrpc_sid_to_name: failed to lookup sids: %s\n",
354 nt_errstr(result)));
355 return result;
359 *type = (enum lsa_SidType)types[0];
360 *domain_name = domains[0];
361 *name = names[0];
363 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
365 name_map_status = normalize_name_map(mem_ctx, domain, *name,
366 &mapped_name);
367 if (NT_STATUS_IS_OK(name_map_status) ||
368 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
370 *name = mapped_name;
371 DEBUG(5,("returning mapped name -- %s\n", *name));
374 return NT_STATUS_OK;
377 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
378 TALLOC_CTX *mem_ctx,
379 const DOM_SID *sid,
380 uint32 *rids,
381 size_t num_rids,
382 char **domain_name,
383 char ***names,
384 enum lsa_SidType **types)
386 char **domains;
387 NTSTATUS result;
388 DOM_SID *sids;
389 size_t i;
390 char **ret_names;
392 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
394 if (num_rids) {
395 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
396 if (sids == NULL) {
397 return NT_STATUS_NO_MEMORY;
399 } else {
400 sids = NULL;
403 for (i=0; i<num_rids; i++) {
404 if (!sid_compose(&sids[i], sid, rids[i])) {
405 return NT_STATUS_INTERNAL_ERROR;
409 result = winbindd_lookup_sids(mem_ctx,
410 domain,
411 num_rids,
412 sids,
413 &domains,
414 names,
415 types);
417 if (!NT_STATUS_IS_OK(result) &&
418 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
419 return result;
422 ret_names = *names;
423 for (i=0; i<num_rids; i++) {
424 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
425 char *mapped_name = NULL;
427 if ((*types)[i] != SID_NAME_UNKNOWN) {
428 name_map_status = normalize_name_map(mem_ctx,
429 domain,
430 ret_names[i],
431 &mapped_name);
432 if (NT_STATUS_IS_OK(name_map_status) ||
433 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
435 ret_names[i] = mapped_name;
438 *domain_name = domains[i];
442 return result;
445 /* Lookup user information from a rid or username. */
446 static NTSTATUS query_user(struct winbindd_domain *domain,
447 TALLOC_CTX *mem_ctx,
448 const DOM_SID *user_sid,
449 WINBIND_USERINFO *user_info)
451 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
452 struct policy_handle dom_pol, user_pol;
453 union samr_UserInfo *info = NULL;
454 uint32 user_rid;
455 struct netr_SamInfo3 *user;
456 struct rpc_pipe_client *cli;
458 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
460 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
461 return NT_STATUS_UNSUCCESSFUL;
463 user_info->homedir = NULL;
464 user_info->shell = NULL;
465 user_info->primary_gid = (gid_t)-1;
467 /* try netsamlogon cache first */
469 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
472 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
473 sid_string_dbg(user_sid)));
475 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
476 sid_compose(&user_info->group_sid, &domain->sid,
477 user->base.primary_gid);
479 user_info->acct_name = talloc_strdup(mem_ctx,
480 user->base.account_name.string);
481 user_info->full_name = talloc_strdup(mem_ctx,
482 user->base.full_name.string);
484 TALLOC_FREE(user);
486 return NT_STATUS_OK;
489 if ( !winbindd_can_contact_domain( domain ) ) {
490 DEBUG(10,("query_user: No incoming trust for domain %s\n",
491 domain->name));
492 return NT_STATUS_OK;
495 if ( !winbindd_can_contact_domain( domain ) ) {
496 DEBUG(10,("query_user: No incoming trust for domain %s\n",
497 domain->name));
498 return NT_STATUS_OK;
501 if ( !winbindd_can_contact_domain( domain ) ) {
502 DEBUG(10,("query_user: No incoming trust for domain %s\n",
503 domain->name));
504 return NT_STATUS_OK;
507 /* no cache; hit the wire */
509 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
510 if (!NT_STATUS_IS_OK(result))
511 return result;
513 /* Get user handle */
514 result = rpccli_samr_OpenUser(cli, mem_ctx,
515 &dom_pol,
516 SEC_FLAG_MAXIMUM_ALLOWED,
517 user_rid,
518 &user_pol);
520 if (!NT_STATUS_IS_OK(result))
521 return result;
523 /* Get user info */
524 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
525 &user_pol,
526 0x15,
527 &info);
529 rpccli_samr_Close(cli, mem_ctx, &user_pol);
531 if (!NT_STATUS_IS_OK(result))
532 return result;
534 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
535 sid_compose(&user_info->group_sid, &domain->sid,
536 info->info21.primary_gid);
537 user_info->acct_name = talloc_strdup(mem_ctx,
538 info->info21.account_name.string);
539 user_info->full_name = talloc_strdup(mem_ctx,
540 info->info21.full_name.string);
541 user_info->homedir = NULL;
542 user_info->shell = NULL;
543 user_info->primary_gid = (gid_t)-1;
545 return NT_STATUS_OK;
548 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
549 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
550 TALLOC_CTX *mem_ctx,
551 const DOM_SID *user_sid,
552 uint32 *num_groups, DOM_SID **user_grpsids)
554 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
555 struct policy_handle dom_pol, user_pol;
556 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
557 struct samr_RidWithAttributeArray *rid_array = NULL;
558 unsigned int i;
559 uint32 user_rid;
560 struct rpc_pipe_client *cli;
562 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
564 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
565 return NT_STATUS_UNSUCCESSFUL;
567 *num_groups = 0;
568 *user_grpsids = NULL;
570 /* so lets see if we have a cached user_info_3 */
571 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
572 num_groups, user_grpsids);
574 if (NT_STATUS_IS_OK(result)) {
575 return NT_STATUS_OK;
578 if ( !winbindd_can_contact_domain( domain ) ) {
579 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
580 domain->name));
582 /* Tell the cache manager not to remember this one */
584 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
587 /* no cache; hit the wire */
589 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
590 if (!NT_STATUS_IS_OK(result))
591 return result;
593 /* Get user handle */
594 result = rpccli_samr_OpenUser(cli, mem_ctx,
595 &dom_pol,
596 des_access,
597 user_rid,
598 &user_pol);
600 if (!NT_STATUS_IS_OK(result))
601 return result;
603 /* Query user rids */
604 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
605 &user_pol,
606 &rid_array);
607 *num_groups = rid_array->count;
609 rpccli_samr_Close(cli, mem_ctx, &user_pol);
611 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
612 return result;
614 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
615 if (!(*user_grpsids))
616 return NT_STATUS_NO_MEMORY;
618 for (i=0;i<(*num_groups);i++) {
619 sid_copy(&((*user_grpsids)[i]), &domain->sid);
620 sid_append_rid(&((*user_grpsids)[i]),
621 rid_array->rids[i].rid);
624 return NT_STATUS_OK;
627 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
629 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
630 TALLOC_CTX *mem_ctx,
631 uint32 num_sids, const DOM_SID *sids,
632 uint32 *num_aliases,
633 uint32 **alias_rids)
635 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
636 struct policy_handle dom_pol;
637 uint32 num_query_sids = 0;
638 int i;
639 struct rpc_pipe_client *cli;
640 struct samr_Ids alias_rids_query;
641 int rangesize = MAX_SAM_ENTRIES_W2K;
642 uint32 total_sids = 0;
643 int num_queries = 1;
645 *num_aliases = 0;
646 *alias_rids = NULL;
648 DEBUG(3,("rpc: lookup_useraliases\n"));
650 if ( !winbindd_can_contact_domain( domain ) ) {
651 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
652 domain->name));
653 return NT_STATUS_OK;
656 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
657 if (!NT_STATUS_IS_OK(result))
658 return result;
660 do {
661 /* prepare query */
662 struct lsa_SidArray sid_array;
664 ZERO_STRUCT(sid_array);
666 num_query_sids = MIN(num_sids - total_sids, rangesize);
668 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
669 num_queries, num_query_sids));
671 if (num_query_sids) {
672 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
673 if (sid_array.sids == NULL) {
674 return NT_STATUS_NO_MEMORY;
676 } else {
677 sid_array.sids = NULL;
680 for (i=0; i<num_query_sids; i++) {
681 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
682 if (!sid_array.sids[i].sid) {
683 TALLOC_FREE(sid_array.sids);
684 return NT_STATUS_NO_MEMORY;
687 sid_array.num_sids = num_query_sids;
689 /* do request */
690 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
691 &dom_pol,
692 &sid_array,
693 &alias_rids_query);
695 if (!NT_STATUS_IS_OK(result)) {
696 *num_aliases = 0;
697 *alias_rids = NULL;
698 TALLOC_FREE(sid_array.sids);
699 goto done;
702 /* process output */
704 for (i=0; i<alias_rids_query.count; i++) {
705 size_t na = *num_aliases;
706 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
707 alias_rids, &na)) {
708 return NT_STATUS_NO_MEMORY;
710 *num_aliases = na;
713 TALLOC_FREE(sid_array.sids);
715 num_queries++;
717 } while (total_sids < num_sids);
719 done:
720 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
721 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
723 return result;
727 /* Lookup group membership given a rid. */
728 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
729 TALLOC_CTX *mem_ctx,
730 const DOM_SID *group_sid, uint32 *num_names,
731 DOM_SID **sid_mem, char ***names,
732 uint32 **name_types)
734 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
735 uint32 i, total_names = 0;
736 struct policy_handle dom_pol, group_pol;
737 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
738 uint32 *rid_mem = NULL;
739 uint32 group_rid;
740 unsigned int j, r;
741 struct rpc_pipe_client *cli;
742 unsigned int orig_timeout;
743 struct samr_RidTypeArray *rids = NULL;
745 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
746 sid_string_dbg(group_sid)));
748 if ( !winbindd_can_contact_domain( domain ) ) {
749 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
750 domain->name));
751 return NT_STATUS_OK;
754 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
755 return NT_STATUS_UNSUCCESSFUL;
757 *num_names = 0;
759 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
760 if (!NT_STATUS_IS_OK(result))
761 return result;
763 result = rpccli_samr_OpenGroup(cli, mem_ctx,
764 &dom_pol,
765 des_access,
766 group_rid,
767 &group_pol);
769 if (!NT_STATUS_IS_OK(result))
770 return result;
772 /* Step #1: Get a list of user rids that are the members of the
773 group. */
775 /* This call can take a long time - allow the server to time out.
776 35 seconds should do it. */
778 orig_timeout = rpccli_set_timeout(cli, 35000);
780 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
781 &group_pol,
782 &rids);
784 /* And restore our original timeout. */
785 rpccli_set_timeout(cli, orig_timeout);
787 rpccli_samr_Close(cli, mem_ctx, &group_pol);
789 if (!NT_STATUS_IS_OK(result))
790 return result;
792 if (!rids || !rids->count) {
793 names = NULL;
794 name_types = NULL;
795 sid_mem = NULL;
796 return NT_STATUS_OK;
799 *num_names = rids->count;
800 rid_mem = rids->rids;
802 /* Step #2: Convert list of rids into list of usernames. Do this
803 in bunches of ~1000 to avoid crashing NT4. It looks like there
804 is a buffer overflow or something like that lurking around
805 somewhere. */
807 #define MAX_LOOKUP_RIDS 900
809 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
810 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
811 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
813 for (j=0;j<(*num_names);j++)
814 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
816 if (*num_names>0 && (!*names || !*name_types))
817 return NT_STATUS_NO_MEMORY;
819 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
820 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
821 struct lsa_Strings tmp_names;
822 struct samr_Ids tmp_types;
824 /* Lookup a chunk of rids */
826 result = rpccli_samr_LookupRids(cli, mem_ctx,
827 &dom_pol,
828 num_lookup_rids,
829 &rid_mem[i],
830 &tmp_names,
831 &tmp_types);
833 /* see if we have a real error (and yes the
834 STATUS_SOME_UNMAPPED is the one returned from 2k) */
836 if (!NT_STATUS_IS_OK(result) &&
837 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
838 return result;
840 /* Copy result into array. The talloc system will take
841 care of freeing the temporary arrays later on. */
843 if (tmp_names.count != tmp_types.count) {
844 return NT_STATUS_UNSUCCESSFUL;
847 for (r=0; r<tmp_names.count; r++) {
848 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
849 continue;
851 (*names)[total_names] = fill_domain_username_talloc(
852 mem_ctx, domain->name,
853 tmp_names.names[r].string, true);
854 (*name_types)[total_names] = tmp_types.ids[r];
855 total_names += 1;
859 *num_names = total_names;
861 return NT_STATUS_OK;
864 #ifdef HAVE_LDAP
866 #include <ldap.h>
868 static int get_ldap_seq(const char *server, int port, uint32 *seq)
870 int ret = -1;
871 struct timeval to;
872 const char *attrs[] = {"highestCommittedUSN", NULL};
873 LDAPMessage *res = NULL;
874 char **values = NULL;
875 LDAP *ldp = NULL;
877 *seq = DOM_SEQUENCE_NONE;
880 * Parameterised (5) second timeout on open. This is needed as the
881 * search timeout doesn't seem to apply to doing an open as well. JRA.
884 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
885 if (ldp == NULL)
886 return -1;
888 /* Timeout if no response within 20 seconds. */
889 to.tv_sec = 10;
890 to.tv_usec = 0;
892 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
893 CONST_DISCARD(char **, attrs), 0, &to, &res))
894 goto done;
896 if (ldap_count_entries(ldp, res) != 1)
897 goto done;
899 values = ldap_get_values(ldp, res, "highestCommittedUSN");
900 if (!values || !values[0])
901 goto done;
903 *seq = atoi(values[0]);
904 ret = 0;
906 done:
908 if (values)
909 ldap_value_free(values);
910 if (res)
911 ldap_msgfree(res);
912 if (ldp)
913 ldap_unbind(ldp);
914 return ret;
917 /**********************************************************************
918 Get the sequence number for a Windows AD native mode domain using
919 LDAP queries.
920 **********************************************************************/
922 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
924 int ret = -1;
925 char addr[INET6_ADDRSTRLEN];
927 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
928 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
929 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
930 "number for Domain (%s) from DC (%s)\n",
931 domain->name, addr));
933 return ret;
936 #endif /* HAVE_LDAP */
938 /* find the sequence number for a domain */
939 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
941 TALLOC_CTX *mem_ctx;
942 union samr_DomainInfo *info = NULL;
943 NTSTATUS result;
944 struct policy_handle dom_pol;
945 bool got_seq_num = False;
946 struct rpc_pipe_client *cli;
948 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
950 if ( !winbindd_can_contact_domain( domain ) ) {
951 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
952 domain->name));
953 *seq = time(NULL);
954 return NT_STATUS_OK;
957 *seq = DOM_SEQUENCE_NONE;
959 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
960 return NT_STATUS_NO_MEMORY;
962 #ifdef HAVE_LDAP
963 if ( domain->active_directory )
965 int res;
967 DEBUG(8,("using get_ldap_seq() to retrieve the "
968 "sequence number\n"));
970 res = get_ldap_sequence_number( domain, seq );
971 if (res == 0)
973 result = NT_STATUS_OK;
974 DEBUG(10,("domain_sequence_number: LDAP for "
975 "domain %s is %u\n",
976 domain->name, *seq));
977 goto done;
980 DEBUG(10,("domain_sequence_number: failed to get LDAP "
981 "sequence number for domain %s\n",
982 domain->name ));
984 #endif /* HAVE_LDAP */
986 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
987 if (!NT_STATUS_IS_OK(result)) {
988 goto done;
991 /* Query domain info */
993 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
994 &dom_pol,
996 &info);
998 if (NT_STATUS_IS_OK(result)) {
999 *seq = info->info8.sequence_num;
1000 got_seq_num = True;
1001 goto seq_num;
1004 /* retry with info-level 2 in case the dc does not support info-level 8
1005 * (like all older samba2 and samba3 dc's) - Guenther */
1007 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1008 &dom_pol,
1010 &info);
1012 if (NT_STATUS_IS_OK(result)) {
1013 *seq = info->general.sequence_num;
1014 got_seq_num = True;
1017 seq_num:
1018 if (got_seq_num) {
1019 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1020 domain->name, (unsigned)*seq));
1021 } else {
1022 DEBUG(10,("domain_sequence_number: failed to get sequence "
1023 "number (%u) for domain %s\n",
1024 (unsigned)*seq, domain->name ));
1027 done:
1029 talloc_destroy(mem_ctx);
1031 return result;
1034 /* get a list of trusted domains */
1035 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1036 TALLOC_CTX *mem_ctx,
1037 uint32 *num_domains,
1038 char ***names,
1039 char ***alt_names,
1040 DOM_SID **dom_sids)
1042 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1043 uint32 enum_ctx = 0;
1044 struct rpc_pipe_client *cli;
1045 struct policy_handle lsa_policy;
1047 DEBUG(3,("rpc: trusted_domains\n"));
1049 *num_domains = 0;
1050 *names = NULL;
1051 *alt_names = NULL;
1052 *dom_sids = NULL;
1054 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1055 if (!NT_STATUS_IS_OK(result))
1056 return result;
1058 result = STATUS_MORE_ENTRIES;
1060 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1061 uint32 start_idx;
1062 int i;
1063 struct lsa_DomainList dom_list;
1065 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1066 &lsa_policy,
1067 &enum_ctx,
1068 &dom_list,
1069 (uint32_t)-1);
1071 if (!NT_STATUS_IS_OK(result) &&
1072 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1073 break;
1075 start_idx = *num_domains;
1076 *num_domains += dom_list.count;
1077 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1078 char *, *num_domains);
1079 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1080 DOM_SID, *num_domains);
1081 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1082 char *, *num_domains);
1083 if ((*names == NULL) || (*dom_sids == NULL) ||
1084 (*alt_names == NULL))
1085 return NT_STATUS_NO_MEMORY;
1087 for (i=0; i<dom_list.count; i++) {
1088 (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1089 (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1090 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1093 return result;
1096 /* find the lockout policy for a domain */
1097 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1098 TALLOC_CTX *mem_ctx,
1099 struct samr_DomInfo12 *lockout_policy)
1101 NTSTATUS result;
1102 struct rpc_pipe_client *cli;
1103 struct policy_handle dom_pol;
1104 union samr_DomainInfo *info = NULL;
1106 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1108 if ( !winbindd_can_contact_domain( domain ) ) {
1109 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1110 domain->name));
1111 return NT_STATUS_NOT_SUPPORTED;
1114 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1115 if (!NT_STATUS_IS_OK(result)) {
1116 goto done;
1119 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1120 &dom_pol,
1122 &info);
1123 if (!NT_STATUS_IS_OK(result)) {
1124 goto done;
1127 *lockout_policy = info->info12;
1129 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1130 info->info12.lockout_threshold));
1132 done:
1134 return result;
1137 /* find the password policy for a domain */
1138 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1139 TALLOC_CTX *mem_ctx,
1140 struct samr_DomInfo1 *password_policy)
1142 NTSTATUS result;
1143 struct rpc_pipe_client *cli;
1144 struct policy_handle dom_pol;
1145 union samr_DomainInfo *info = NULL;
1147 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1149 if ( !winbindd_can_contact_domain( domain ) ) {
1150 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1151 domain->name));
1152 return NT_STATUS_NOT_SUPPORTED;
1155 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1156 if (!NT_STATUS_IS_OK(result)) {
1157 goto done;
1160 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1161 &dom_pol,
1163 &info);
1164 if (!NT_STATUS_IS_OK(result)) {
1165 goto done;
1168 *password_policy = info->info1;
1170 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1171 info->info1.min_password_length));
1173 done:
1175 return result;
1178 typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
1179 TALLOC_CTX *mem_ctx,
1180 struct policy_handle *pol,
1181 int num_sids,
1182 const DOM_SID *sids,
1183 char ***pdomains,
1184 char ***pnames,
1185 enum lsa_SidType **ptypes);
1187 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
1188 struct winbindd_domain *domain,
1189 uint32_t num_sids,
1190 const struct dom_sid *sids,
1191 char ***domains,
1192 char ***names,
1193 enum lsa_SidType **types)
1195 NTSTATUS status;
1196 struct rpc_pipe_client *cli = NULL;
1197 struct policy_handle lsa_policy;
1198 unsigned int orig_timeout;
1199 lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids;
1201 if (domain->can_do_ncacn_ip_tcp) {
1202 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1203 if (NT_STATUS_IS_OK(status)) {
1204 lookup_sids_fn = rpccli_lsa_lookup_sids3;
1205 goto lookup;
1207 domain->can_do_ncacn_ip_tcp = false;
1209 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 return status;
1215 lookup:
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 = lookup_sids_fn(cli,
1224 mem_ctx,
1225 &lsa_policy,
1226 num_sids,
1227 sids,
1228 domains,
1229 names,
1230 types);
1232 /* And restore our original timeout. */
1233 rpccli_set_timeout(cli, orig_timeout);
1235 if (!NT_STATUS_IS_OK(status)) {
1236 return status;
1239 return status;
1242 typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
1243 TALLOC_CTX *mem_ctx,
1244 struct policy_handle *pol,
1245 int num_names,
1246 const char **names,
1247 const char ***dom_names,
1248 int level,
1249 struct dom_sid **sids,
1250 enum lsa_SidType **types);
1252 NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
1253 struct winbindd_domain *domain,
1254 uint32_t num_names,
1255 const char **names,
1256 const char ***domains,
1257 struct dom_sid **sids,
1258 enum lsa_SidType **types)
1260 NTSTATUS status;
1261 struct rpc_pipe_client *cli = NULL;
1262 struct policy_handle lsa_policy;
1263 unsigned int orig_timeout;
1264 lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names;
1266 if (domain->can_do_ncacn_ip_tcp) {
1267 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1268 if (NT_STATUS_IS_OK(status)) {
1269 lookup_names_fn = rpccli_lsa_lookup_names4;
1270 goto lookup;
1272 domain->can_do_ncacn_ip_tcp = false;
1274 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 return status;
1280 lookup:
1283 * This call can take a long time
1284 * allow the server to time out.
1285 * 35 seconds should do it.
1287 orig_timeout = rpccli_set_timeout(cli, 35000);
1289 status = lookup_names_fn(cli,
1290 mem_ctx,
1291 &lsa_policy,
1292 num_names,
1293 (const char **) names,
1294 domains,
1296 sids,
1297 types);
1299 /* And restore our original timeout. */
1300 rpccli_set_timeout(cli, orig_timeout);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 return status;
1306 return status;
1309 /* the rpc backend methods are exposed via this structure */
1310 struct winbindd_methods msrpc_methods = {
1311 False,
1312 query_user_list,
1313 enum_dom_groups,
1314 enum_local_groups,
1315 msrpc_name_to_sid,
1316 msrpc_sid_to_name,
1317 msrpc_rids_to_names,
1318 query_user,
1319 lookup_usergroups,
1320 msrpc_lookup_useraliases,
1321 lookup_groupmem,
1322 sequence_number,
1323 msrpc_lockout_policy,
1324 msrpc_password_policy,
1325 trusted_domains,