s3-groupdb: fix enum_aliasmem in ldb branch.
[Samba.git] / source / winbindd / winbindd_rpc.c
blobf6a9c666bcf9dc4f2f8faa1762e9535e428e6204
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 POLICY_HND 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 POLICY_HND 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 POLICY_HND 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 POLICY_HND lsa_policy;
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 ws_name_return( full_name, WB_REPLACE_CHAR );
299 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
301 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
302 if (!NT_STATUS_IS_OK(result))
303 return result;
305 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
306 (const char**) &full_name, NULL, 1, &sids, &types);
308 if (!NT_STATUS_IS_OK(result))
309 return result;
311 /* Return rid and type if lookup successful */
313 sid_copy(sid, &sids[0]);
314 *type = types[0];
316 return NT_STATUS_OK;
320 convert a domain SID to a user or group name
322 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
323 TALLOC_CTX *mem_ctx,
324 const DOM_SID *sid,
325 char **domain_name,
326 char **name,
327 enum lsa_SidType *type)
329 char **domains;
330 char **names;
331 enum lsa_SidType *types = NULL;
332 NTSTATUS result;
333 struct rpc_pipe_client *cli;
334 POLICY_HND lsa_policy;
336 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
337 domain->name ));
339 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
340 if (!NT_STATUS_IS_OK(result)) {
341 DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
342 nt_errstr(result)));
343 return result;
347 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
348 1, sid, &domains, &names, &types);
349 if (!NT_STATUS_IS_OK(result)) {
350 DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n",
351 nt_errstr(result)));
352 return result;
355 *type = (enum lsa_SidType)types[0];
356 *domain_name = domains[0];
357 *name = names[0];
359 ws_name_replace( *name, WB_REPLACE_CHAR );
361 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
362 return NT_STATUS_OK;
365 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
366 TALLOC_CTX *mem_ctx,
367 const DOM_SID *sid,
368 uint32 *rids,
369 size_t num_rids,
370 char **domain_name,
371 char ***names,
372 enum lsa_SidType **types)
374 char **domains;
375 NTSTATUS result;
376 struct rpc_pipe_client *cli;
377 POLICY_HND lsa_policy;
378 DOM_SID *sids;
379 size_t i;
380 char **ret_names;
382 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
384 if (num_rids) {
385 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
386 if (sids == NULL) {
387 return NT_STATUS_NO_MEMORY;
389 } else {
390 sids = NULL;
393 for (i=0; i<num_rids; i++) {
394 if (!sid_compose(&sids[i], sid, rids[i])) {
395 return NT_STATUS_INTERNAL_ERROR;
399 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
400 if (!NT_STATUS_IS_OK(result)) {
401 return result;
404 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
405 num_rids, sids, &domains,
406 names, types);
407 if (!NT_STATUS_IS_OK(result) &&
408 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
409 return result;
412 ret_names = *names;
413 for (i=0; i<num_rids; i++) {
414 if ((*types)[i] != SID_NAME_UNKNOWN) {
415 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
416 *domain_name = domains[i];
420 return result;
423 /* Lookup user information from a rid or username. */
424 static NTSTATUS query_user(struct winbindd_domain *domain,
425 TALLOC_CTX *mem_ctx,
426 const DOM_SID *user_sid,
427 WINBIND_USERINFO *user_info)
429 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
430 POLICY_HND dom_pol, user_pol;
431 union samr_UserInfo *info = NULL;
432 uint32 user_rid;
433 struct netr_SamInfo3 *user;
434 struct rpc_pipe_client *cli;
436 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
438 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
439 return NT_STATUS_UNSUCCESSFUL;
441 user_info->homedir = NULL;
442 user_info->shell = NULL;
443 user_info->primary_gid = (gid_t)-1;
445 /* try netsamlogon cache first */
447 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
450 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
451 sid_string_dbg(user_sid)));
453 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
454 sid_compose(&user_info->group_sid, &domain->sid,
455 user->base.primary_gid);
457 user_info->acct_name = talloc_strdup(mem_ctx,
458 user->base.account_name.string);
459 user_info->full_name = talloc_strdup(mem_ctx,
460 user->base.full_name.string);
462 TALLOC_FREE(user);
464 return NT_STATUS_OK;
467 if ( !winbindd_can_contact_domain( domain ) ) {
468 DEBUG(10,("query_user: No incoming trust for domain %s\n",
469 domain->name));
470 return NT_STATUS_OK;
473 if ( !winbindd_can_contact_domain( domain ) ) {
474 DEBUG(10,("query_user: No incoming trust for domain %s\n",
475 domain->name));
476 return NT_STATUS_OK;
479 if ( !winbindd_can_contact_domain( domain ) ) {
480 DEBUG(10,("query_user: No incoming trust for domain %s\n",
481 domain->name));
482 return NT_STATUS_OK;
485 /* no cache; hit the wire */
487 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
488 if (!NT_STATUS_IS_OK(result))
489 return result;
491 /* Get user handle */
492 result = rpccli_samr_OpenUser(cli, mem_ctx,
493 &dom_pol,
494 SEC_RIGHTS_MAXIMUM_ALLOWED,
495 user_rid,
496 &user_pol);
498 if (!NT_STATUS_IS_OK(result))
499 return result;
501 /* Get user info */
502 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
503 &user_pol,
504 0x15,
505 &info);
507 rpccli_samr_Close(cli, mem_ctx, &user_pol);
509 if (!NT_STATUS_IS_OK(result))
510 return result;
512 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
513 sid_compose(&user_info->group_sid, &domain->sid,
514 info->info21.primary_gid);
515 user_info->acct_name = talloc_strdup(mem_ctx,
516 info->info21.account_name.string);
517 user_info->full_name = talloc_strdup(mem_ctx,
518 info->info21.full_name.string);
519 user_info->homedir = NULL;
520 user_info->shell = NULL;
521 user_info->primary_gid = (gid_t)-1;
523 return NT_STATUS_OK;
526 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
527 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
528 TALLOC_CTX *mem_ctx,
529 const DOM_SID *user_sid,
530 uint32 *num_groups, DOM_SID **user_grpsids)
532 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
533 POLICY_HND dom_pol, user_pol;
534 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
535 struct samr_RidWithAttributeArray *rid_array = NULL;
536 unsigned int i;
537 uint32 user_rid;
538 struct rpc_pipe_client *cli;
540 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
542 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
543 return NT_STATUS_UNSUCCESSFUL;
545 *num_groups = 0;
546 *user_grpsids = NULL;
548 /* so lets see if we have a cached user_info_3 */
549 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
550 num_groups, user_grpsids);
552 if (NT_STATUS_IS_OK(result)) {
553 return NT_STATUS_OK;
556 if ( !winbindd_can_contact_domain( domain ) ) {
557 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
558 domain->name));
560 /* Tell the cache manager not to remember this one */
562 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
565 /* no cache; hit the wire */
567 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
568 if (!NT_STATUS_IS_OK(result))
569 return result;
571 /* Get user handle */
572 result = rpccli_samr_OpenUser(cli, mem_ctx,
573 &dom_pol,
574 des_access,
575 user_rid,
576 &user_pol);
578 if (!NT_STATUS_IS_OK(result))
579 return result;
581 /* Query user rids */
582 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
583 &user_pol,
584 &rid_array);
585 *num_groups = rid_array->count;
587 rpccli_samr_Close(cli, mem_ctx, &user_pol);
589 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
590 return result;
592 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
593 if (!(*user_grpsids))
594 return NT_STATUS_NO_MEMORY;
596 for (i=0;i<(*num_groups);i++) {
597 sid_copy(&((*user_grpsids)[i]), &domain->sid);
598 sid_append_rid(&((*user_grpsids)[i]),
599 rid_array->rids[i].rid);
602 return NT_STATUS_OK;
605 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
606 TALLOC_CTX *mem_ctx,
607 uint32 num_sids, const DOM_SID *sids,
608 uint32 *num_aliases,
609 uint32 **alias_rids)
611 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
612 POLICY_HND dom_pol;
613 uint32 num_query_sids = 0;
614 int i;
615 struct rpc_pipe_client *cli;
616 struct samr_Ids alias_rids_query;
617 int rangesize = MAX_SAM_ENTRIES_W2K;
618 uint32 total_sids = 0;
619 int num_queries = 1;
621 *num_aliases = 0;
622 *alias_rids = NULL;
624 DEBUG(3,("rpc: lookup_useraliases\n"));
626 if ( !winbindd_can_contact_domain( domain ) ) {
627 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
628 domain->name));
629 return NT_STATUS_OK;
632 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
633 if (!NT_STATUS_IS_OK(result))
634 return result;
636 do {
637 /* prepare query */
638 struct lsa_SidArray sid_array;
640 ZERO_STRUCT(sid_array);
642 num_query_sids = MIN(num_sids - total_sids, rangesize);
644 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
645 num_queries, num_query_sids));
647 if (num_query_sids) {
648 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
649 if (sid_array.sids == NULL) {
650 return NT_STATUS_NO_MEMORY;
652 } else {
653 sid_array.sids = NULL;
656 for (i=0; i<num_query_sids; i++) {
657 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
658 if (!sid_array.sids[i].sid) {
659 TALLOC_FREE(sid_array.sids);
660 return NT_STATUS_NO_MEMORY;
663 sid_array.num_sids = num_query_sids;
665 /* do request */
666 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
667 &dom_pol,
668 &sid_array,
669 &alias_rids_query);
671 if (!NT_STATUS_IS_OK(result)) {
672 *num_aliases = 0;
673 *alias_rids = NULL;
674 TALLOC_FREE(sid_array.sids);
675 goto done;
678 /* process output */
680 for (i=0; i<alias_rids_query.count; i++) {
681 size_t na = *num_aliases;
682 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
683 alias_rids, &na)) {
684 return NT_STATUS_NO_MEMORY;
686 *num_aliases = na;
689 TALLOC_FREE(sid_array.sids);
691 num_queries++;
693 } while (total_sids < num_sids);
695 done:
696 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
697 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
699 return result;
703 /* Lookup group membership given a rid. */
704 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
705 TALLOC_CTX *mem_ctx,
706 const DOM_SID *group_sid, uint32 *num_names,
707 DOM_SID **sid_mem, char ***names,
708 uint32 **name_types)
710 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
711 uint32 i, total_names = 0;
712 POLICY_HND dom_pol, group_pol;
713 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
714 uint32 *rid_mem = NULL;
715 uint32 group_rid;
716 unsigned int j, r;
717 struct rpc_pipe_client *cli;
718 unsigned int orig_timeout;
719 struct samr_RidTypeArray *rids = NULL;
721 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
722 sid_string_dbg(group_sid)));
724 if ( !winbindd_can_contact_domain( domain ) ) {
725 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
726 domain->name));
727 return NT_STATUS_OK;
730 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
731 return NT_STATUS_UNSUCCESSFUL;
733 *num_names = 0;
735 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
736 if (!NT_STATUS_IS_OK(result))
737 return result;
739 result = rpccli_samr_OpenGroup(cli, mem_ctx,
740 &dom_pol,
741 des_access,
742 group_rid,
743 &group_pol);
745 if (!NT_STATUS_IS_OK(result))
746 return result;
748 /* Step #1: Get a list of user rids that are the members of the
749 group. */
751 /* This call can take a long time - allow the server to time out.
752 35 seconds should do it. */
754 orig_timeout = cli_set_timeout(cli->cli, 35000);
756 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
757 &group_pol,
758 &rids);
760 /* And restore our original timeout. */
761 cli_set_timeout(cli->cli, orig_timeout);
763 rpccli_samr_Close(cli, mem_ctx, &group_pol);
765 if (!NT_STATUS_IS_OK(result))
766 return result;
768 *num_names = rids->count;
769 rid_mem = rids->rids;
771 if (!*num_names) {
772 names = NULL;
773 name_types = NULL;
774 sid_mem = NULL;
775 return NT_STATUS_OK;
778 /* Step #2: Convert list of rids into list of usernames. Do this
779 in bunches of ~1000 to avoid crashing NT4. It looks like there
780 is a buffer overflow or something like that lurking around
781 somewhere. */
783 #define MAX_LOOKUP_RIDS 900
785 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
786 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
787 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
789 for (j=0;j<(*num_names);j++)
790 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
792 if (*num_names>0 && (!*names || !*name_types))
793 return NT_STATUS_NO_MEMORY;
795 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
796 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
797 struct lsa_Strings tmp_names;
798 struct samr_Ids tmp_types;
800 /* Lookup a chunk of rids */
802 result = rpccli_samr_LookupRids(cli, mem_ctx,
803 &dom_pol,
804 num_lookup_rids,
805 &rid_mem[i],
806 &tmp_names,
807 &tmp_types);
809 /* see if we have a real error (and yes the
810 STATUS_SOME_UNMAPPED is the one returned from 2k) */
812 if (!NT_STATUS_IS_OK(result) &&
813 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
814 return result;
816 /* Copy result into array. The talloc system will take
817 care of freeing the temporary arrays later on. */
819 if (tmp_names.count != tmp_types.count) {
820 return NT_STATUS_UNSUCCESSFUL;
823 for (r=0; r<tmp_names.count; r++) {
824 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
825 continue;
827 (*names)[total_names] = fill_domain_username_talloc(
828 mem_ctx, domain->name,
829 tmp_names.names[r].string, true);
830 (*name_types)[total_names] = tmp_types.ids[r];
831 total_names += 1;
835 *num_names = total_names;
837 return NT_STATUS_OK;
840 #ifdef HAVE_LDAP
842 #include <ldap.h>
844 static int get_ldap_seq(const char *server, int port, uint32 *seq)
846 int ret = -1;
847 struct timeval to;
848 const char *attrs[] = {"highestCommittedUSN", NULL};
849 LDAPMessage *res = NULL;
850 char **values = NULL;
851 LDAP *ldp = NULL;
853 *seq = DOM_SEQUENCE_NONE;
856 * Parameterised (5) second timeout on open. This is needed as the
857 * search timeout doesn't seem to apply to doing an open as well. JRA.
860 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
861 if (ldp == NULL)
862 return -1;
864 /* Timeout if no response within 20 seconds. */
865 to.tv_sec = 10;
866 to.tv_usec = 0;
868 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
869 CONST_DISCARD(char **, attrs), 0, &to, &res))
870 goto done;
872 if (ldap_count_entries(ldp, res) != 1)
873 goto done;
875 values = ldap_get_values(ldp, res, "highestCommittedUSN");
876 if (!values || !values[0])
877 goto done;
879 *seq = atoi(values[0]);
880 ret = 0;
882 done:
884 if (values)
885 ldap_value_free(values);
886 if (res)
887 ldap_msgfree(res);
888 if (ldp)
889 ldap_unbind(ldp);
890 return ret;
893 /**********************************************************************
894 Get the sequence number for a Windows AD native mode domain using
895 LDAP queries.
896 **********************************************************************/
898 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
900 int ret = -1;
901 char addr[INET6_ADDRSTRLEN];
903 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
904 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
905 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
906 "number for Domain (%s) from DC (%s)\n",
907 domain->name, addr));
909 return ret;
912 #endif /* HAVE_LDAP */
914 /* find the sequence number for a domain */
915 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
917 TALLOC_CTX *mem_ctx;
918 union samr_DomainInfo *info = NULL;
919 NTSTATUS result;
920 POLICY_HND dom_pol;
921 bool got_seq_num = False;
922 struct rpc_pipe_client *cli;
924 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
926 if ( !winbindd_can_contact_domain( domain ) ) {
927 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
928 domain->name));
929 *seq = time(NULL);
930 return NT_STATUS_OK;
933 *seq = DOM_SEQUENCE_NONE;
935 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
936 return NT_STATUS_NO_MEMORY;
938 #ifdef HAVE_LDAP
939 if ( domain->active_directory )
941 int res;
943 DEBUG(8,("using get_ldap_seq() to retrieve the "
944 "sequence number\n"));
946 res = get_ldap_sequence_number( domain, seq );
947 if (res == 0)
949 result = NT_STATUS_OK;
950 DEBUG(10,("domain_sequence_number: LDAP for "
951 "domain %s is %u\n",
952 domain->name, *seq));
953 goto done;
956 DEBUG(10,("domain_sequence_number: failed to get LDAP "
957 "sequence number for domain %s\n",
958 domain->name ));
960 #endif /* HAVE_LDAP */
962 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
963 if (!NT_STATUS_IS_OK(result)) {
964 goto done;
967 /* Query domain info */
969 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
970 &dom_pol,
972 &info);
974 if (NT_STATUS_IS_OK(result)) {
975 *seq = info->info8.sequence_num;
976 got_seq_num = True;
977 goto seq_num;
980 /* retry with info-level 2 in case the dc does not support info-level 8
981 * (like all older samba2 and samba3 dc's) - Guenther */
983 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
984 &dom_pol,
986 &info);
988 if (NT_STATUS_IS_OK(result)) {
989 *seq = info->info2.sequence_num;
990 got_seq_num = True;
993 seq_num:
994 if (got_seq_num) {
995 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
996 domain->name, (unsigned)*seq));
997 } else {
998 DEBUG(10,("domain_sequence_number: failed to get sequence "
999 "number (%u) for domain %s\n",
1000 (unsigned)*seq, domain->name ));
1003 done:
1005 talloc_destroy(mem_ctx);
1007 return result;
1010 /* get a list of trusted domains */
1011 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1012 TALLOC_CTX *mem_ctx,
1013 uint32 *num_domains,
1014 char ***names,
1015 char ***alt_names,
1016 DOM_SID **dom_sids)
1018 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1019 uint32 enum_ctx = 0;
1020 struct rpc_pipe_client *cli;
1021 POLICY_HND lsa_policy;
1023 DEBUG(3,("rpc: trusted_domains\n"));
1025 *num_domains = 0;
1026 *names = NULL;
1027 *alt_names = NULL;
1028 *dom_sids = NULL;
1030 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1031 if (!NT_STATUS_IS_OK(result))
1032 return result;
1034 result = STATUS_MORE_ENTRIES;
1036 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1037 uint32 start_idx;
1038 int i;
1039 struct lsa_DomainList dom_list;
1041 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1042 &lsa_policy,
1043 &enum_ctx,
1044 &dom_list,
1045 (uint32_t)-1);
1047 if (!NT_STATUS_IS_OK(result) &&
1048 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1049 break;
1051 start_idx = *num_domains;
1052 *num_domains += dom_list.count;
1053 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1054 char *, *num_domains);
1055 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1056 DOM_SID, *num_domains);
1057 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1058 char *, *num_domains);
1059 if ((*names == NULL) || (*dom_sids == NULL) ||
1060 (*alt_names == NULL))
1061 return NT_STATUS_NO_MEMORY;
1063 for (i=0; i<dom_list.count; i++) {
1064 (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1065 (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1066 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1069 return result;
1072 /* find the lockout policy for a domain */
1073 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1074 TALLOC_CTX *mem_ctx,
1075 struct samr_DomInfo12 *lockout_policy)
1077 NTSTATUS result;
1078 struct rpc_pipe_client *cli;
1079 POLICY_HND dom_pol;
1080 union samr_DomainInfo *info = NULL;
1082 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1084 if ( !winbindd_can_contact_domain( domain ) ) {
1085 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1086 domain->name));
1087 return NT_STATUS_NOT_SUPPORTED;
1090 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1091 if (!NT_STATUS_IS_OK(result)) {
1092 goto done;
1095 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1096 &dom_pol,
1098 &info);
1099 if (!NT_STATUS_IS_OK(result)) {
1100 goto done;
1103 *lockout_policy = info->info12;
1105 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1106 info->info12.lockout_threshold));
1108 done:
1110 return result;
1113 /* find the password policy for a domain */
1114 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1115 TALLOC_CTX *mem_ctx,
1116 struct samr_DomInfo1 *password_policy)
1118 NTSTATUS result;
1119 struct rpc_pipe_client *cli;
1120 POLICY_HND dom_pol;
1121 union samr_DomainInfo *info = NULL;
1123 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1125 if ( !winbindd_can_contact_domain( domain ) ) {
1126 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1127 domain->name));
1128 return NT_STATUS_NOT_SUPPORTED;
1131 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1132 if (!NT_STATUS_IS_OK(result)) {
1133 goto done;
1136 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1137 &dom_pol,
1139 &info);
1140 if (!NT_STATUS_IS_OK(result)) {
1141 goto done;
1144 *password_policy = info->info1;
1146 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1147 info->info1.min_password_length));
1149 done:
1151 return result;
1155 /* the rpc backend methods are exposed via this structure */
1156 struct winbindd_methods msrpc_methods = {
1157 False,
1158 query_user_list,
1159 enum_dom_groups,
1160 enum_local_groups,
1161 msrpc_name_to_sid,
1162 msrpc_sid_to_name,
1163 msrpc_rids_to_names,
1164 query_user,
1165 lookup_usergroups,
1166 msrpc_lookup_useraliases,
1167 lookup_groupmem,
1168 sequence_number,
1169 msrpc_lockout_policy,
1170 msrpc_password_policy,
1171 trusted_domains,