r5555: current with 3.0 tree as of r5548; getting ready for 3.0.12pre1
[Samba.git] / source / nsswitch / winbindd_rpc.c
blob42f451c50515e12a260ef93fe05e04bde9ccc38e
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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 CLI_POLICY_HND *hnd;
41 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
42 POLICY_HND dom_pol;
43 BOOL got_dom_pol = False;
44 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
45 unsigned int i, start_idx, retry;
46 uint32 loop_count;
48 DEBUG(3,("rpc: query_user_list\n"));
50 *num_entries = 0;
51 *info = NULL;
53 retry = 0;
54 do {
55 /* Get sam handle */
57 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
58 return result;
60 /* Get domain handle */
62 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
63 des_access, &domain->sid, &dom_pol);
65 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
67 if (!NT_STATUS_IS_OK(result))
68 goto done;
70 got_dom_pol = True;
72 i = start_idx = 0;
73 loop_count = 0;
75 do {
76 TALLOC_CTX *ctx2;
77 uint32 num_dom_users, j;
78 uint32 max_entries, max_size;
79 SAM_DISPINFO_CTR ctr;
80 SAM_DISPINFO_1 info1;
82 ZERO_STRUCT( ctr );
83 ZERO_STRUCT( info1 );
84 ctr.sam.info1 = &info1;
86 if (!(ctx2 = talloc_init("winbindd enum_users"))) {
87 result = NT_STATUS_NO_MEMORY;
88 goto done;
91 /* this next bit is copied from net_user_list_internal() */
93 get_query_dispinfo_params( loop_count, &max_entries, &max_size );
95 result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, &dom_pol,
96 &start_idx, 1, &num_dom_users, max_entries, max_size, &ctr);
98 loop_count++;
100 *num_entries += num_dom_users;
102 *info = TALLOC_REALLOC_ARRAY( mem_ctx, *info, WINBIND_USERINFO, *num_entries);
104 if (!(*info)) {
105 result = NT_STATUS_NO_MEMORY;
106 talloc_destroy(ctx2);
107 goto done;
110 for (j = 0; j < num_dom_users; i++, j++) {
111 fstring username, fullname;
112 uint32 rid = ctr.sam.info1->sam[j].rid_user;
114 unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
115 unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
117 (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
118 (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
119 (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, rid );
121 /* For the moment we set the primary group for
122 every user to be the Domain Users group.
123 There are serious problems with determining
124 the actual primary group for large domains.
125 This should really be made into a 'winbind
126 force group' smb.conf parameter or
127 something like that. */
129 (*info)[i].group_sid = rid_to_talloced_sid(domain,
130 mem_ctx, DOMAIN_GROUP_RID_USERS);
133 talloc_destroy(ctx2);
135 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
137 done:
139 if (got_dom_pol)
140 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
142 return result;
145 /* list all domain groups */
146 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
147 TALLOC_CTX *mem_ctx,
148 uint32 *num_entries,
149 struct acct_info **info)
151 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
152 CLI_POLICY_HND *hnd;
153 POLICY_HND dom_pol;
154 NTSTATUS status;
155 uint32 start = 0;
156 int retry;
157 NTSTATUS result;
159 *num_entries = 0;
160 *info = NULL;
162 DEBUG(3,("rpc: enum_dom_groups\n"));
164 retry = 0;
165 do {
166 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
167 return result;
169 status = cli_samr_open_domain(hnd->cli, mem_ctx,
170 &hnd->pol, des_access, &domain->sid, &dom_pol);
171 } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
173 if (!NT_STATUS_IS_OK(status))
174 return status;
176 do {
177 struct acct_info *info2 = NULL;
178 uint32 count = 0;
179 TALLOC_CTX *mem_ctx2;
181 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
183 /* start is updated by this call. */
184 status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol,
185 &start,
186 0xFFFF, /* buffer size? */
187 &info2, &count);
189 if (!NT_STATUS_IS_OK(status) &&
190 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
191 talloc_destroy(mem_ctx2);
192 break;
195 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
196 if (! *info) {
197 talloc_destroy(mem_ctx2);
198 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
199 return NT_STATUS_NO_MEMORY;
202 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
203 (*num_entries) += count;
204 talloc_destroy(mem_ctx2);
205 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
207 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
209 return status;
212 /* List all domain groups */
214 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
215 TALLOC_CTX *mem_ctx,
216 uint32 *num_entries,
217 struct acct_info **info)
219 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
220 CLI_POLICY_HND *hnd;
221 POLICY_HND dom_pol;
222 NTSTATUS result;
223 int retry;
225 *num_entries = 0;
226 *info = NULL;
228 retry = 0;
229 do {
230 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
231 return result;
233 result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol,
234 des_access, &domain->sid, &dom_pol);
235 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
237 if ( !NT_STATUS_IS_OK(result))
238 return result;
240 do {
241 struct acct_info *info2 = NULL;
242 uint32 count = 0, start = *num_entries;
243 TALLOC_CTX *mem_ctx2;
245 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
247 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
248 &start, 0xFFFF, &info2, &count);
250 if ( !NT_STATUS_IS_OK(result)
251 && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
253 talloc_destroy(mem_ctx2);
254 break;
257 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
258 if (! *info) {
259 talloc_destroy(mem_ctx2);
260 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
261 return NT_STATUS_NO_MEMORY;
264 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
265 (*num_entries) += count;
266 talloc_destroy(mem_ctx2);
267 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
269 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
271 return result;
274 /* convert a single name to a sid in a domain */
275 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
276 TALLOC_CTX *mem_ctx,
277 const char *domain_name,
278 const char *name,
279 DOM_SID *sid,
280 enum SID_NAME_USE *type)
282 CLI_POLICY_HND *hnd;
283 NTSTATUS result;
284 DOM_SID *sids = NULL;
285 uint32 *types = NULL;
286 const char *full_name;
287 int retry;
289 DEBUG(3,("rpc: name_to_sid name=%s\n", name));
291 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
293 if (!full_name) {
294 DEBUG(0, ("talloc_asprintf failed!\n"));
295 return NT_STATUS_NO_MEMORY;
298 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name ));
300 retry = 0;
301 do {
302 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
303 return result;
306 result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
307 &full_name, &sids, &types);
308 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
309 hnd && hnd->cli && hnd->cli->fd == -1);
311 /* Return rid and type if lookup successful */
313 if (NT_STATUS_IS_OK(result)) {
314 sid_copy(sid, &sids[0]);
315 *type = (enum SID_NAME_USE)types[0];
318 return result;
322 convert a domain SID to a user or group name
324 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
325 TALLOC_CTX *mem_ctx,
326 const DOM_SID *sid,
327 char **domain_name,
328 char **name,
329 enum SID_NAME_USE *type)
331 CLI_POLICY_HND *hnd;
332 char **domains;
333 char **names;
334 uint32 *types;
335 NTSTATUS result;
336 int retry;
338 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
339 domain->name ));
341 retry = 0;
342 do {
343 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
344 return result;
346 result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
347 1, sid, &domains, &names, &types);
348 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
349 hnd && hnd->cli && hnd->cli->fd == -1);
351 if (NT_STATUS_IS_OK(result)) {
352 *type = (enum SID_NAME_USE)types[0];
353 *domain_name = domains[0];
354 *name = names[0];
355 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
358 return result;
361 /* Lookup user information from a rid or username. */
362 static NTSTATUS query_user(struct winbindd_domain *domain,
363 TALLOC_CTX *mem_ctx,
364 const DOM_SID *user_sid,
365 WINBIND_USERINFO *user_info)
367 CLI_POLICY_HND *hnd = NULL;
368 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
369 POLICY_HND dom_pol, user_pol;
370 BOOL got_dom_pol = False, got_user_pol = False;
371 SAM_USERINFO_CTR *ctr;
372 int retry;
373 fstring sid_string;
374 uint32 user_rid;
375 NET_USER_INFO_3 *user;
377 DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
378 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
379 goto done;
382 /* try netsamlogon cache first */
384 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
387 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
388 sid_string_static(user_sid)));
390 user_info->user_sid = rid_to_talloced_sid( domain, mem_ctx, user_rid );
391 user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid );
393 user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
394 user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
396 SAFE_FREE(user);
398 return NT_STATUS_OK;
401 /* no cache; hit the wire */
403 retry = 0;
404 do {
405 /* Get sam handle; if we fail here there is no hope */
407 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
408 goto done;
410 /* Get domain handle */
412 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
413 SEC_RIGHTS_MAXIMUM_ALLOWED,
414 &domain->sid, &dom_pol);
415 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
416 hnd && hnd->cli && hnd->cli->fd == -1);
418 if (!NT_STATUS_IS_OK(result))
419 goto done;
421 got_dom_pol = True;
423 /* Get user handle */
424 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
425 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
427 if (!NT_STATUS_IS_OK(result))
428 goto done;
430 got_user_pol = True;
432 /* Get user info */
433 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
434 0x15, &ctr);
436 if (!NT_STATUS_IS_OK(result))
437 goto done;
439 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
440 got_user_pol = False;
442 user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
443 user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
444 user_info->acct_name = unistr2_tdup(mem_ctx,
445 &ctr->info.id21->uni_user_name);
446 user_info->full_name = unistr2_tdup(mem_ctx,
447 &ctr->info.id21->uni_full_name);
449 done:
450 /* Clean up policy handles */
451 if (got_user_pol)
452 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
454 if (got_dom_pol)
455 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
457 return result;
460 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
461 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
462 TALLOC_CTX *mem_ctx,
463 const DOM_SID *user_sid,
464 uint32 *num_groups, DOM_SID ***user_grpsids)
466 CLI_POLICY_HND *hnd;
467 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
468 POLICY_HND dom_pol, user_pol;
469 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
470 BOOL got_dom_pol = False, got_user_pol = False;
471 DOM_GID *user_groups;
472 unsigned int i;
473 unsigned int retry;
474 fstring sid_string;
475 uint32 user_rid;
476 NET_USER_INFO_3 *user;
478 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
480 *num_groups = 0;
481 *user_grpsids = NULL;
483 /* so lets see if we have a cached user_info_3 */
485 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
487 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
488 sid_string_static(user_sid)));
490 *num_groups = user->num_groups;
492 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID*, *num_groups);
493 for (i=0;i<(*num_groups);i++) {
494 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
497 SAFE_FREE(user);
499 return NT_STATUS_OK;
502 /* no cache; hit the wire */
504 retry = 0;
505 do {
506 /* Get sam handle; if we fail here there is no hope */
508 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
509 goto done;
511 /* Get domain handle */
513 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
514 des_access, &domain->sid, &dom_pol);
515 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
516 hnd && hnd->cli && hnd->cli->fd == -1);
518 if (!NT_STATUS_IS_OK(result))
519 goto done;
521 got_dom_pol = True;
524 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
525 goto done;
528 /* Get user handle */
529 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
530 des_access, user_rid, &user_pol);
532 if (!NT_STATUS_IS_OK(result))
533 goto done;
535 got_user_pol = True;
537 /* Query user rids */
538 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
539 num_groups, &user_groups);
541 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
542 goto done;
544 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID *, *num_groups);
545 if (!(*user_grpsids)) {
546 result = NT_STATUS_NO_MEMORY;
547 goto done;
550 for (i=0;i<(*num_groups);i++) {
551 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
554 done:
555 /* Clean up policy handles */
556 if (got_user_pol)
557 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
559 if (got_dom_pol)
560 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
562 return result;
565 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
566 TALLOC_CTX *mem_ctx,
567 uint32 num_sids, DOM_SID **sids,
568 uint32 *num_aliases, uint32 **alias_rids)
570 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
571 CLI_POLICY_HND *hnd;
572 BOOL got_dom_pol = False;
573 POLICY_HND dom_pol;
574 DOM_SID2 *sid2;
575 int i, retry;
577 *num_aliases = 0;
578 *alias_rids = NULL;
580 retry = 0;
581 do {
582 /* Get sam handle; if we fail here there is no hope */
584 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain,
585 &hnd)))
586 goto done;
588 /* Get domain handle */
590 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
591 SEC_RIGHTS_MAXIMUM_ALLOWED,
592 &domain->sid, &dom_pol);
593 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
594 hnd && hnd->cli && hnd->cli->fd == -1);
596 if (!NT_STATUS_IS_OK(result))
597 goto done;
599 got_dom_pol = True;
601 sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
603 if (sid2 == NULL) {
604 result = NT_STATUS_NO_MEMORY;
605 goto done;
608 for (i=0; i<num_sids; i++) {
609 sid_copy(&sid2[i].sid, sids[i]);
610 sid2[i].num_auths = sid2[i].sid.num_auths;
613 result = cli_samr_query_useraliases(hnd->cli, mem_ctx, &dom_pol,
614 num_sids, sid2,
615 num_aliases, alias_rids);
617 done:
619 if (got_dom_pol)
620 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
622 return result;
626 /* Lookup group membership given a rid. */
627 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
628 TALLOC_CTX *mem_ctx,
629 const DOM_SID *group_sid, uint32 *num_names,
630 DOM_SID ***sid_mem, char ***names,
631 uint32 **name_types)
633 CLI_POLICY_HND *hnd = NULL;
634 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
635 uint32 i, total_names = 0;
636 POLICY_HND dom_pol, group_pol;
637 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
638 BOOL got_dom_pol = False, got_group_pol = False;
639 uint32 *rid_mem = NULL;
640 uint32 group_rid;
641 int retry;
642 unsigned int j;
643 fstring sid_string;
645 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid)));
647 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
648 goto done;
651 *num_names = 0;
653 retry = 0;
654 do {
655 /* Get sam handle */
656 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
657 goto done;
659 /* Get domain handle */
661 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
662 des_access, &domain->sid, &dom_pol);
663 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
665 if (!NT_STATUS_IS_OK(result))
666 goto done;
668 got_dom_pol = True;
670 /* Get group handle */
672 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
673 des_access, group_rid, &group_pol);
675 if (!NT_STATUS_IS_OK(result))
676 goto done;
678 got_group_pol = True;
680 /* Step #1: Get a list of user rids that are the members of the
681 group. */
683 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
684 &group_pol, num_names, &rid_mem,
685 name_types);
687 if (!NT_STATUS_IS_OK(result))
688 goto done;
690 if (!*num_names) {
691 names = NULL;
692 name_types = NULL;
693 sid_mem = NULL;
694 goto done;
697 /* Step #2: Convert list of rids into list of usernames. Do this
698 in bunches of ~1000 to avoid crashing NT4. It looks like there
699 is a buffer overflow or something like that lurking around
700 somewhere. */
702 #define MAX_LOOKUP_RIDS 900
704 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
705 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
706 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID *, *num_names);
708 for (j=0;j<(*num_names);j++) {
709 (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]);
712 if (*num_names>0 && (!*names || !*name_types)) {
713 result = NT_STATUS_NO_MEMORY;
714 goto done;
717 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
718 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
719 uint32 tmp_num_names = 0;
720 char **tmp_names = NULL;
721 uint32 *tmp_types = NULL;
723 /* Lookup a chunk of rids */
725 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
726 &dom_pol,
727 num_lookup_rids,
728 &rid_mem[i],
729 &tmp_num_names,
730 &tmp_names, &tmp_types);
732 /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is
733 the one returned from 2k) */
735 if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED))
736 goto done;
738 /* Copy result into array. The talloc system will take
739 care of freeing the temporary arrays later on. */
741 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
742 tmp_num_names);
744 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
745 tmp_num_names);
747 total_names += tmp_num_names;
750 *num_names = total_names;
752 result = NT_STATUS_OK;
754 done:
755 if (got_group_pol)
756 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
758 if (got_dom_pol)
759 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
761 return result;
764 #ifdef HAVE_LDAP
766 #include <ldap.h>
768 static int get_ldap_seq(const char *server, int port, uint32 *seq)
770 int ret = -1;
771 struct timeval to;
772 const char *attrs[] = {"highestCommittedUSN", NULL};
773 LDAPMessage *res = NULL;
774 char **values = NULL;
775 LDAP *ldp = NULL;
777 *seq = DOM_SEQUENCE_NONE;
780 * Parameterised (5) second timeout on open. This is needed as the search timeout
781 * doesn't seem to apply to doing an open as well. JRA.
784 if ((ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout())) == NULL)
785 return -1;
787 /* Timeout if no response within 20 seconds. */
788 to.tv_sec = 10;
789 to.tv_usec = 0;
791 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res))
792 goto done;
794 if (ldap_count_entries(ldp, res) != 1)
795 goto done;
797 values = ldap_get_values(ldp, res, "highestCommittedUSN");
798 if (!values || !values[0])
799 goto done;
801 *seq = atoi(values[0]);
802 ret = 0;
804 done:
806 if (values)
807 ldap_value_free(values);
808 if (res)
809 ldap_msgfree(res);
810 if (ldp)
811 ldap_unbind(ldp);
812 return ret;
815 /**********************************************************************
816 Get the sequence number for a Windows AD native mode domain using
817 LDAP queries
818 **********************************************************************/
820 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
822 int ret = -1;
823 int i, port = LDAP_PORT;
824 struct ip_service *ip_list = NULL;
825 int count;
827 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
828 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
829 return False;
832 /* Finally return first DC that we can contact */
834 for (i = 0; i < count; i++) {
835 fstring ipstr;
837 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
838 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
840 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
842 if (is_zero_ip(ip_list[i].ip))
843 continue;
845 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
846 goto done;
848 /* add to failed connection cache */
849 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
852 done:
853 if ( ret == 0 ) {
854 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n",
855 domain, inet_ntoa(ip_list[i].ip), port));
858 SAFE_FREE(ip_list);
860 return ret;
863 #endif /* HAVE_LDAP */
865 /* find the sequence number for a domain */
866 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
868 TALLOC_CTX *mem_ctx;
869 CLI_POLICY_HND *hnd;
870 SAM_UNK_CTR ctr;
871 NTSTATUS result;
872 POLICY_HND dom_pol;
873 BOOL got_dom_pol = False;
874 BOOL got_seq_num = False;
875 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
876 int retry;
878 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
880 *seq = DOM_SEQUENCE_NONE;
882 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
883 return NT_STATUS_NO_MEMORY;
885 retry = 0;
886 do {
887 #ifdef HAVE_LDAP
888 if ( domain->native_mode )
890 DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
892 if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {
893 result = NT_STATUS_OK;
894 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
895 domain->name, *seq));
896 goto done;
899 DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
900 domain->name ));
902 #endif /* HAVE_LDAP */
903 /* Get sam handle */
904 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
905 goto done;
907 /* Get domain handle */
908 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
909 des_access, &domain->sid, &dom_pol);
910 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
912 if (!NT_STATUS_IS_OK(result))
913 goto done;
915 got_dom_pol = True;
917 /* Query domain info */
919 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
920 8, &ctr);
922 if (NT_STATUS_IS_OK(result)) {
923 *seq = ctr.info.inf8.seq_num.low;
924 got_seq_num = True;
925 goto seq_num;
928 /* retry with info-level 2 in case the dc does not support info-level 8
929 * (like all older samba2 and samba3 dc's - Guenther */
931 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
932 2, &ctr);
934 if (NT_STATUS_IS_OK(result)) {
935 *seq = ctr.info.inf2.seq_num.low;
936 got_seq_num = True;
939 seq_num:
940 if (got_seq_num) {
941 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
942 } else {
943 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
944 (unsigned)*seq, domain->name ));
947 done:
949 if (got_dom_pol)
950 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
952 talloc_destroy(mem_ctx);
954 return result;
957 /* get a list of trusted domains */
958 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
959 TALLOC_CTX *mem_ctx,
960 uint32 *num_domains,
961 char ***names,
962 char ***alt_names,
963 DOM_SID **dom_sids)
965 CLI_POLICY_HND *hnd;
966 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
967 uint32 enum_ctx = 0;
968 int retry;
970 DEBUG(3,("rpc: trusted_domains\n"));
972 *num_domains = 0;
973 *alt_names = NULL;
975 retry = 0;
976 do {
977 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
978 goto done;
980 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
981 &hnd->pol, &enum_ctx,
982 num_domains, names, dom_sids);
983 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
985 done:
986 return result;
989 /* find the domain sid for a domain */
990 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
992 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
993 TALLOC_CTX *mem_ctx;
994 CLI_POLICY_HND *hnd;
995 char *level5_dom;
996 DOM_SID *alloc_sid;
997 int retry;
999 DEBUG(3,("rpc: domain_sid\n"));
1001 if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
1002 return NT_STATUS_NO_MEMORY;
1004 retry = 0;
1005 do {
1006 /* Get lsa handle */
1007 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
1008 goto done;
1010 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
1011 &hnd->pol, 0x05, &level5_dom, &alloc_sid);
1012 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
1014 if (NT_STATUS_IS_OK(result)) {
1015 if (alloc_sid) {
1016 sid_copy(sid, alloc_sid);
1017 } else {
1018 result = NT_STATUS_NO_MEMORY;
1022 done:
1023 talloc_destroy(mem_ctx);
1024 return result;
1027 /* find alternate names list for the domain - none for rpc */
1028 static NTSTATUS alternate_name(struct winbindd_domain *domain)
1030 return NT_STATUS_OK;
1034 /* the rpc backend methods are exposed via this structure */
1035 struct winbindd_methods msrpc_methods = {
1036 False,
1037 query_user_list,
1038 enum_dom_groups,
1039 enum_local_groups,
1040 msrpc_name_to_sid,
1041 msrpc_sid_to_name,
1042 query_user,
1043 lookup_usergroups,
1044 msrpc_lookup_useraliases,
1045 lookup_groupmem,
1046 sequence_number,
1047 trusted_domains,
1048 domain_sid,
1049 alternate_name