s3/packaging: pam_winbind has been moved to section 8.
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_rpc.c
blob50ccbae6b226315d04ebcad3cafdfd0ee0017d6c
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 struct rpc_pipe_client *cli;
281 struct policy_handle lsa_policy;
282 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
283 char *mapped_name = NULL;
285 if (name == NULL || *name=='\0') {
286 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
287 } else if (domain_name == NULL || *domain_name == '\0') {
288 full_name = talloc_asprintf(mem_ctx, "%s", name);
289 } else {
290 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
292 if (!full_name) {
293 DEBUG(0, ("talloc_asprintf failed!\n"));
294 return NT_STATUS_NO_MEMORY;
297 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
299 name_map_status = normalize_name_unmap(mem_ctx, full_name,
300 &mapped_name);
302 /* Reset the full_name pointer if we mapped anytthing */
304 if (NT_STATUS_IS_OK(name_map_status) ||
305 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
307 full_name = mapped_name;
310 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
311 full_name?full_name:"", domain_name ));
313 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
314 if (!NT_STATUS_IS_OK(result))
315 return result;
317 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
318 (const char**) &full_name, NULL, 1, &sids, &types);
320 if (!NT_STATUS_IS_OK(result))
321 return result;
323 /* Return rid and type if lookup successful */
325 sid_copy(sid, &sids[0]);
326 *type = types[0];
328 return NT_STATUS_OK;
332 convert a domain SID to a user or group name
334 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
335 TALLOC_CTX *mem_ctx,
336 const DOM_SID *sid,
337 char **domain_name,
338 char **name,
339 enum lsa_SidType *type)
341 char **domains;
342 char **names;
343 enum lsa_SidType *types = NULL;
344 NTSTATUS result;
345 struct rpc_pipe_client *cli;
346 struct policy_handle lsa_policy;
347 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
348 char *mapped_name = NULL;
350 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
351 domain->name ));
353 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
354 if (!NT_STATUS_IS_OK(result)) {
355 DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
356 nt_errstr(result)));
357 return result;
361 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
362 1, sid, &domains, &names, &types);
363 if (!NT_STATUS_IS_OK(result)) {
364 DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n",
365 nt_errstr(result)));
366 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 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 rpc_pipe_client *cli;
399 struct policy_handle lsa_policy;
400 DOM_SID *sids;
401 size_t i;
402 char **ret_names;
404 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
406 if (num_rids) {
407 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
408 if (sids == NULL) {
409 return NT_STATUS_NO_MEMORY;
411 } else {
412 sids = NULL;
415 for (i=0; i<num_rids; i++) {
416 if (!sid_compose(&sids[i], sid, rids[i])) {
417 return NT_STATUS_INTERNAL_ERROR;
421 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
422 if (!NT_STATUS_IS_OK(result)) {
423 return result;
426 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
427 num_rids, sids, &domains,
428 names, types);
429 if (!NT_STATUS_IS_OK(result) &&
430 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
431 return result;
434 ret_names = *names;
435 for (i=0; i<num_rids; i++) {
436 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
437 char *mapped_name = NULL;
439 if ((*types)[i] != SID_NAME_UNKNOWN) {
440 name_map_status = normalize_name_map(mem_ctx,
441 domain,
442 ret_names[i],
443 &mapped_name);
444 if (NT_STATUS_IS_OK(name_map_status) ||
445 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
447 ret_names[i] = mapped_name;
450 *domain_name = domains[i];
454 return result;
457 /* Lookup user information from a rid or username. */
458 static NTSTATUS query_user(struct winbindd_domain *domain,
459 TALLOC_CTX *mem_ctx,
460 const DOM_SID *user_sid,
461 WINBIND_USERINFO *user_info)
463 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
464 struct policy_handle dom_pol, user_pol;
465 union samr_UserInfo *info = NULL;
466 uint32 user_rid;
467 struct netr_SamInfo3 *user;
468 struct rpc_pipe_client *cli;
470 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
472 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
473 return NT_STATUS_UNSUCCESSFUL;
475 user_info->homedir = NULL;
476 user_info->shell = NULL;
477 user_info->primary_gid = (gid_t)-1;
479 /* try netsamlogon cache first */
481 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
484 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
485 sid_string_dbg(user_sid)));
487 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
488 sid_compose(&user_info->group_sid, &domain->sid,
489 user->base.primary_gid);
491 user_info->acct_name = talloc_strdup(mem_ctx,
492 user->base.account_name.string);
493 user_info->full_name = talloc_strdup(mem_ctx,
494 user->base.full_name.string);
496 TALLOC_FREE(user);
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 if ( !winbindd_can_contact_domain( domain ) ) {
508 DEBUG(10,("query_user: No incoming trust for domain %s\n",
509 domain->name));
510 return NT_STATUS_OK;
513 if ( !winbindd_can_contact_domain( domain ) ) {
514 DEBUG(10,("query_user: No incoming trust for domain %s\n",
515 domain->name));
516 return NT_STATUS_OK;
519 /* no cache; hit the wire */
521 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
522 if (!NT_STATUS_IS_OK(result))
523 return result;
525 /* Get user handle */
526 result = rpccli_samr_OpenUser(cli, mem_ctx,
527 &dom_pol,
528 SEC_FLAG_MAXIMUM_ALLOWED,
529 user_rid,
530 &user_pol);
532 if (!NT_STATUS_IS_OK(result))
533 return result;
535 /* Get user info */
536 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
537 &user_pol,
538 0x15,
539 &info);
541 rpccli_samr_Close(cli, mem_ctx, &user_pol);
543 if (!NT_STATUS_IS_OK(result))
544 return result;
546 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
547 sid_compose(&user_info->group_sid, &domain->sid,
548 info->info21.primary_gid);
549 user_info->acct_name = talloc_strdup(mem_ctx,
550 info->info21.account_name.string);
551 user_info->full_name = talloc_strdup(mem_ctx,
552 info->info21.full_name.string);
553 user_info->homedir = NULL;
554 user_info->shell = NULL;
555 user_info->primary_gid = (gid_t)-1;
557 return NT_STATUS_OK;
560 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
561 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
562 TALLOC_CTX *mem_ctx,
563 const DOM_SID *user_sid,
564 uint32 *num_groups, DOM_SID **user_grpsids)
566 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
567 struct policy_handle dom_pol, user_pol;
568 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
569 struct samr_RidWithAttributeArray *rid_array = NULL;
570 unsigned int i;
571 uint32 user_rid;
572 struct rpc_pipe_client *cli;
574 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
576 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
577 return NT_STATUS_UNSUCCESSFUL;
579 *num_groups = 0;
580 *user_grpsids = NULL;
582 /* so lets see if we have a cached user_info_3 */
583 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
584 num_groups, user_grpsids);
586 if (NT_STATUS_IS_OK(result)) {
587 return NT_STATUS_OK;
590 if ( !winbindd_can_contact_domain( domain ) ) {
591 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
592 domain->name));
594 /* Tell the cache manager not to remember this one */
596 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
599 /* no cache; hit the wire */
601 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
602 if (!NT_STATUS_IS_OK(result))
603 return result;
605 /* Get user handle */
606 result = rpccli_samr_OpenUser(cli, mem_ctx,
607 &dom_pol,
608 des_access,
609 user_rid,
610 &user_pol);
612 if (!NT_STATUS_IS_OK(result))
613 return result;
615 /* Query user rids */
616 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
617 &user_pol,
618 &rid_array);
619 *num_groups = rid_array->count;
621 rpccli_samr_Close(cli, mem_ctx, &user_pol);
623 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
624 return result;
626 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
627 if (!(*user_grpsids))
628 return NT_STATUS_NO_MEMORY;
630 for (i=0;i<(*num_groups);i++) {
631 sid_copy(&((*user_grpsids)[i]), &domain->sid);
632 sid_append_rid(&((*user_grpsids)[i]),
633 rid_array->rids[i].rid);
636 return NT_STATUS_OK;
639 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
641 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
642 TALLOC_CTX *mem_ctx,
643 uint32 num_sids, const DOM_SID *sids,
644 uint32 *num_aliases,
645 uint32 **alias_rids)
647 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
648 struct policy_handle dom_pol;
649 uint32 num_query_sids = 0;
650 int i;
651 struct rpc_pipe_client *cli;
652 struct samr_Ids alias_rids_query;
653 int rangesize = MAX_SAM_ENTRIES_W2K;
654 uint32 total_sids = 0;
655 int num_queries = 1;
657 *num_aliases = 0;
658 *alias_rids = NULL;
660 DEBUG(3,("rpc: lookup_useraliases\n"));
662 if ( !winbindd_can_contact_domain( domain ) ) {
663 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
664 domain->name));
665 return NT_STATUS_OK;
668 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
669 if (!NT_STATUS_IS_OK(result))
670 return result;
672 do {
673 /* prepare query */
674 struct lsa_SidArray sid_array;
676 ZERO_STRUCT(sid_array);
678 num_query_sids = MIN(num_sids - total_sids, rangesize);
680 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
681 num_queries, num_query_sids));
683 if (num_query_sids) {
684 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
685 if (sid_array.sids == NULL) {
686 return NT_STATUS_NO_MEMORY;
688 } else {
689 sid_array.sids = NULL;
692 for (i=0; i<num_query_sids; i++) {
693 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
694 if (!sid_array.sids[i].sid) {
695 TALLOC_FREE(sid_array.sids);
696 return NT_STATUS_NO_MEMORY;
699 sid_array.num_sids = num_query_sids;
701 /* do request */
702 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
703 &dom_pol,
704 &sid_array,
705 &alias_rids_query);
707 if (!NT_STATUS_IS_OK(result)) {
708 *num_aliases = 0;
709 *alias_rids = NULL;
710 TALLOC_FREE(sid_array.sids);
711 goto done;
714 /* process output */
716 for (i=0; i<alias_rids_query.count; i++) {
717 size_t na = *num_aliases;
718 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
719 alias_rids, &na)) {
720 return NT_STATUS_NO_MEMORY;
722 *num_aliases = na;
725 TALLOC_FREE(sid_array.sids);
727 num_queries++;
729 } while (total_sids < num_sids);
731 done:
732 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
733 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
735 return result;
739 /* Lookup group membership given a rid. */
740 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
741 TALLOC_CTX *mem_ctx,
742 const DOM_SID *group_sid, uint32 *num_names,
743 DOM_SID **sid_mem, char ***names,
744 uint32 **name_types)
746 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
747 uint32 i, total_names = 0;
748 struct policy_handle dom_pol, group_pol;
749 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
750 uint32 *rid_mem = NULL;
751 uint32 group_rid;
752 unsigned int j, r;
753 struct rpc_pipe_client *cli;
754 unsigned int orig_timeout;
755 struct samr_RidTypeArray *rids = NULL;
757 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
758 sid_string_dbg(group_sid)));
760 if ( !winbindd_can_contact_domain( domain ) ) {
761 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
762 domain->name));
763 return NT_STATUS_OK;
766 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
767 return NT_STATUS_UNSUCCESSFUL;
769 *num_names = 0;
771 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
772 if (!NT_STATUS_IS_OK(result))
773 return result;
775 result = rpccli_samr_OpenGroup(cli, mem_ctx,
776 &dom_pol,
777 des_access,
778 group_rid,
779 &group_pol);
781 if (!NT_STATUS_IS_OK(result))
782 return result;
784 /* Step #1: Get a list of user rids that are the members of the
785 group. */
787 /* This call can take a long time - allow the server to time out.
788 35 seconds should do it. */
790 orig_timeout = rpccli_set_timeout(cli, 35000);
792 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
793 &group_pol,
794 &rids);
796 /* And restore our original timeout. */
797 rpccli_set_timeout(cli, orig_timeout);
799 rpccli_samr_Close(cli, mem_ctx, &group_pol);
801 if (!NT_STATUS_IS_OK(result))
802 return result;
804 *num_names = rids->count;
805 rid_mem = rids->rids;
807 if (!*num_names) {
808 names = NULL;
809 name_types = NULL;
810 sid_mem = NULL;
811 return NT_STATUS_OK;
814 /* Step #2: Convert list of rids into list of usernames. Do this
815 in bunches of ~1000 to avoid crashing NT4. It looks like there
816 is a buffer overflow or something like that lurking around
817 somewhere. */
819 #define MAX_LOOKUP_RIDS 900
821 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
822 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
823 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
825 for (j=0;j<(*num_names);j++)
826 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
828 if (*num_names>0 && (!*names || !*name_types))
829 return NT_STATUS_NO_MEMORY;
831 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
832 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
833 struct lsa_Strings tmp_names;
834 struct samr_Ids tmp_types;
836 /* Lookup a chunk of rids */
838 result = rpccli_samr_LookupRids(cli, mem_ctx,
839 &dom_pol,
840 num_lookup_rids,
841 &rid_mem[i],
842 &tmp_names,
843 &tmp_types);
845 /* see if we have a real error (and yes the
846 STATUS_SOME_UNMAPPED is the one returned from 2k) */
848 if (!NT_STATUS_IS_OK(result) &&
849 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
850 return result;
852 /* Copy result into array. The talloc system will take
853 care of freeing the temporary arrays later on. */
855 if (tmp_names.count != tmp_types.count) {
856 return NT_STATUS_UNSUCCESSFUL;
859 for (r=0; r<tmp_names.count; r++) {
860 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
861 continue;
863 (*names)[total_names] = fill_domain_username_talloc(
864 mem_ctx, domain->name,
865 tmp_names.names[r].string, true);
866 (*name_types)[total_names] = tmp_types.ids[r];
867 total_names += 1;
871 *num_names = total_names;
873 return NT_STATUS_OK;
876 #ifdef HAVE_LDAP
878 #include <ldap.h>
880 static int get_ldap_seq(const char *server, int port, uint32 *seq)
882 int ret = -1;
883 struct timeval to;
884 const char *attrs[] = {"highestCommittedUSN", NULL};
885 LDAPMessage *res = NULL;
886 char **values = NULL;
887 LDAP *ldp = NULL;
889 *seq = DOM_SEQUENCE_NONE;
892 * Parameterised (5) second timeout on open. This is needed as the
893 * search timeout doesn't seem to apply to doing an open as well. JRA.
896 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
897 if (ldp == NULL)
898 return -1;
900 /* Timeout if no response within 20 seconds. */
901 to.tv_sec = 10;
902 to.tv_usec = 0;
904 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
905 CONST_DISCARD(char **, attrs), 0, &to, &res))
906 goto done;
908 if (ldap_count_entries(ldp, res) != 1)
909 goto done;
911 values = ldap_get_values(ldp, res, "highestCommittedUSN");
912 if (!values || !values[0])
913 goto done;
915 *seq = atoi(values[0]);
916 ret = 0;
918 done:
920 if (values)
921 ldap_value_free(values);
922 if (res)
923 ldap_msgfree(res);
924 if (ldp)
925 ldap_unbind(ldp);
926 return ret;
929 /**********************************************************************
930 Get the sequence number for a Windows AD native mode domain using
931 LDAP queries.
932 **********************************************************************/
934 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
936 int ret = -1;
937 char addr[INET6_ADDRSTRLEN];
939 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
940 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
941 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
942 "number for Domain (%s) from DC (%s)\n",
943 domain->name, addr));
945 return ret;
948 #endif /* HAVE_LDAP */
950 /* find the sequence number for a domain */
951 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
953 TALLOC_CTX *mem_ctx;
954 union samr_DomainInfo *info = NULL;
955 NTSTATUS result;
956 struct policy_handle dom_pol;
957 bool got_seq_num = False;
958 struct rpc_pipe_client *cli;
960 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
962 if ( !winbindd_can_contact_domain( domain ) ) {
963 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
964 domain->name));
965 *seq = time(NULL);
966 return NT_STATUS_OK;
969 *seq = DOM_SEQUENCE_NONE;
971 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
972 return NT_STATUS_NO_MEMORY;
974 #ifdef HAVE_LDAP
975 if ( domain->active_directory )
977 int res;
979 DEBUG(8,("using get_ldap_seq() to retrieve the "
980 "sequence number\n"));
982 res = get_ldap_sequence_number( domain, seq );
983 if (res == 0)
985 result = NT_STATUS_OK;
986 DEBUG(10,("domain_sequence_number: LDAP for "
987 "domain %s is %u\n",
988 domain->name, *seq));
989 goto done;
992 DEBUG(10,("domain_sequence_number: failed to get LDAP "
993 "sequence number for domain %s\n",
994 domain->name ));
996 #endif /* HAVE_LDAP */
998 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
999 if (!NT_STATUS_IS_OK(result)) {
1000 goto done;
1003 /* Query domain info */
1005 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1006 &dom_pol,
1008 &info);
1010 if (NT_STATUS_IS_OK(result)) {
1011 *seq = info->info8.sequence_num;
1012 got_seq_num = True;
1013 goto seq_num;
1016 /* retry with info-level 2 in case the dc does not support info-level 8
1017 * (like all older samba2 and samba3 dc's) - Guenther */
1019 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1020 &dom_pol,
1022 &info);
1024 if (NT_STATUS_IS_OK(result)) {
1025 *seq = info->general.sequence_num;
1026 got_seq_num = True;
1029 seq_num:
1030 if (got_seq_num) {
1031 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1032 domain->name, (unsigned)*seq));
1033 } else {
1034 DEBUG(10,("domain_sequence_number: failed to get sequence "
1035 "number (%u) for domain %s\n",
1036 (unsigned)*seq, domain->name ));
1039 done:
1041 talloc_destroy(mem_ctx);
1043 return result;
1046 /* get a list of trusted domains */
1047 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1048 TALLOC_CTX *mem_ctx,
1049 uint32 *num_domains,
1050 char ***names,
1051 char ***alt_names,
1052 DOM_SID **dom_sids)
1054 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1055 uint32 enum_ctx = 0;
1056 struct rpc_pipe_client *cli;
1057 struct policy_handle lsa_policy;
1059 DEBUG(3,("rpc: trusted_domains\n"));
1061 *num_domains = 0;
1062 *names = NULL;
1063 *alt_names = NULL;
1064 *dom_sids = NULL;
1066 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1067 if (!NT_STATUS_IS_OK(result))
1068 return result;
1070 result = STATUS_MORE_ENTRIES;
1072 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1073 uint32 start_idx;
1074 int i;
1075 struct lsa_DomainList dom_list;
1077 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1078 &lsa_policy,
1079 &enum_ctx,
1080 &dom_list,
1081 (uint32_t)-1);
1083 if (!NT_STATUS_IS_OK(result) &&
1084 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1085 break;
1087 start_idx = *num_domains;
1088 *num_domains += dom_list.count;
1089 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1090 char *, *num_domains);
1091 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1092 DOM_SID, *num_domains);
1093 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1094 char *, *num_domains);
1095 if ((*names == NULL) || (*dom_sids == NULL) ||
1096 (*alt_names == NULL))
1097 return NT_STATUS_NO_MEMORY;
1099 for (i=0; i<dom_list.count; i++) {
1100 (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1101 (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1102 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1105 return result;
1108 /* find the lockout policy for a domain */
1109 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1110 TALLOC_CTX *mem_ctx,
1111 struct samr_DomInfo12 *lockout_policy)
1113 NTSTATUS result;
1114 struct rpc_pipe_client *cli;
1115 struct policy_handle dom_pol;
1116 union samr_DomainInfo *info = NULL;
1118 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1120 if ( !winbindd_can_contact_domain( domain ) ) {
1121 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1122 domain->name));
1123 return NT_STATUS_NOT_SUPPORTED;
1126 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1127 if (!NT_STATUS_IS_OK(result)) {
1128 goto done;
1131 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1132 &dom_pol,
1134 &info);
1135 if (!NT_STATUS_IS_OK(result)) {
1136 goto done;
1139 *lockout_policy = info->info12;
1141 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1142 info->info12.lockout_threshold));
1144 done:
1146 return result;
1149 /* find the password policy for a domain */
1150 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1151 TALLOC_CTX *mem_ctx,
1152 struct samr_DomInfo1 *password_policy)
1154 NTSTATUS result;
1155 struct rpc_pipe_client *cli;
1156 struct policy_handle dom_pol;
1157 union samr_DomainInfo *info = NULL;
1159 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1161 if ( !winbindd_can_contact_domain( domain ) ) {
1162 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1163 domain->name));
1164 return NT_STATUS_NOT_SUPPORTED;
1167 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1168 if (!NT_STATUS_IS_OK(result)) {
1169 goto done;
1172 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1173 &dom_pol,
1175 &info);
1176 if (!NT_STATUS_IS_OK(result)) {
1177 goto done;
1180 *password_policy = info->info1;
1182 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1183 info->info1.min_password_length));
1185 done:
1187 return result;
1191 /* the rpc backend methods are exposed via this structure */
1192 struct winbindd_methods msrpc_methods = {
1193 False,
1194 query_user_list,
1195 enum_dom_groups,
1196 enum_local_groups,
1197 msrpc_name_to_sid,
1198 msrpc_sid_to_name,
1199 msrpc_rids_to_names,
1200 query_user,
1201 lookup_usergroups,
1202 msrpc_lookup_useraliases,
1203 lookup_groupmem,
1204 sequence_number,
1205 msrpc_lockout_policy,
1206 msrpc_password_policy,
1207 trusted_domains,