r6303: Setting up for 3.0.15pre1
[Samba.git] / source / nsswitch / winbindd_rpc.c
blob1dfa810a8d3869e1f30718761ef8ee6e3d16310a
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=*)",
792 CONST_DISCARD(char **, &attrs[0]), 0, &to, &res))
793 goto done;
795 if (ldap_count_entries(ldp, res) != 1)
796 goto done;
798 values = ldap_get_values(ldp, res, "highestCommittedUSN");
799 if (!values || !values[0])
800 goto done;
802 *seq = atoi(values[0]);
803 ret = 0;
805 done:
807 if (values)
808 ldap_value_free(values);
809 if (res)
810 ldap_msgfree(res);
811 if (ldp)
812 ldap_unbind(ldp);
813 return ret;
816 /**********************************************************************
817 Get the sequence number for a Windows AD native mode domain using
818 LDAP queries
819 **********************************************************************/
821 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
823 int ret = -1;
824 int i, port = LDAP_PORT;
825 struct ip_service *ip_list = NULL;
826 int count;
828 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
829 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
830 return False;
833 /* Finally return first DC that we can contact */
835 for (i = 0; i < count; i++) {
836 fstring ipstr;
838 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
839 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
841 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
843 if (is_zero_ip(ip_list[i].ip))
844 continue;
846 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
847 goto done;
849 /* add to failed connection cache */
850 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
853 done:
854 if ( ret == 0 ) {
855 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n",
856 domain, inet_ntoa(ip_list[i].ip), port));
859 SAFE_FREE(ip_list);
861 return ret;
864 #endif /* HAVE_LDAP */
866 /* find the sequence number for a domain */
867 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
869 TALLOC_CTX *mem_ctx;
870 CLI_POLICY_HND *hnd;
871 SAM_UNK_CTR ctr;
872 NTSTATUS result;
873 POLICY_HND dom_pol;
874 BOOL got_dom_pol = False;
875 BOOL got_seq_num = False;
876 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
877 int retry;
879 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
881 *seq = DOM_SEQUENCE_NONE;
883 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
884 return NT_STATUS_NO_MEMORY;
886 retry = 0;
887 do {
888 #ifdef HAVE_LDAP
889 if ( domain->native_mode )
891 DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
893 if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {
894 result = NT_STATUS_OK;
895 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
896 domain->name, *seq));
897 goto done;
900 DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
901 domain->name ));
903 #endif /* HAVE_LDAP */
904 /* Get sam handle */
905 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
906 goto done;
908 /* Get domain handle */
909 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
910 des_access, &domain->sid, &dom_pol);
911 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
913 if (!NT_STATUS_IS_OK(result))
914 goto done;
916 got_dom_pol = True;
918 /* Query domain info */
920 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
921 8, &ctr);
923 if (NT_STATUS_IS_OK(result)) {
924 *seq = ctr.info.inf8.seq_num.low;
925 got_seq_num = True;
926 goto seq_num;
929 /* retry with info-level 2 in case the dc does not support info-level 8
930 * (like all older samba2 and samba3 dc's - Guenther */
932 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
933 2, &ctr);
935 if (NT_STATUS_IS_OK(result)) {
936 *seq = ctr.info.inf2.seq_num.low;
937 got_seq_num = True;
940 seq_num:
941 if (got_seq_num) {
942 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
943 } else {
944 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
945 (unsigned)*seq, domain->name ));
948 done:
950 if (got_dom_pol)
951 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
953 talloc_destroy(mem_ctx);
955 return result;
958 /* get a list of trusted domains */
959 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
960 TALLOC_CTX *mem_ctx,
961 uint32 *num_domains,
962 char ***names,
963 char ***alt_names,
964 DOM_SID **dom_sids)
966 CLI_POLICY_HND *hnd;
967 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
968 uint32 enum_ctx = 0;
969 int retry;
971 DEBUG(3,("rpc: trusted_domains\n"));
973 *num_domains = 0;
974 *names = NULL;
975 *alt_names = NULL;
976 *dom_sids = NULL;
978 retry = 0;
979 do {
980 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
981 goto done;
983 result = STATUS_MORE_ENTRIES;
985 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
986 uint32 start_idx, num;
987 char **tmp_names;
988 DOM_SID *tmp_sids;
989 int i;
991 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
992 &hnd->pol, &enum_ctx,
993 &num, &tmp_names,
994 &tmp_sids);
996 if (!NT_STATUS_IS_OK(result) &&
997 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
998 break;
1000 start_idx = *num_domains;
1001 *num_domains += num;
1002 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1003 char *, *num_domains);
1004 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1005 DOM_SID,
1006 *num_domains);
1007 if ((*names == NULL) || (*dom_sids == NULL))
1008 return NT_STATUS_NO_MEMORY;
1010 for (i=0; i<num; i++) {
1011 (*names)[start_idx+i] = tmp_names[i];
1012 (*dom_sids)[start_idx+i] = tmp_sids[i];
1015 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
1017 done:
1018 return result;
1021 /* find the domain sid for a domain */
1022 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
1024 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1025 TALLOC_CTX *mem_ctx;
1026 CLI_POLICY_HND *hnd;
1027 char *level5_dom;
1028 DOM_SID *alloc_sid;
1029 int retry;
1031 DEBUG(3,("rpc: domain_sid\n"));
1033 if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
1034 return NT_STATUS_NO_MEMORY;
1036 retry = 0;
1037 do {
1038 /* Get lsa handle */
1039 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
1040 goto done;
1042 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
1043 &hnd->pol, 0x05, &level5_dom, &alloc_sid);
1044 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
1046 if (NT_STATUS_IS_OK(result)) {
1047 if (alloc_sid) {
1048 sid_copy(sid, alloc_sid);
1049 } else {
1050 result = NT_STATUS_NO_MEMORY;
1054 done:
1055 talloc_destroy(mem_ctx);
1056 return result;
1059 /* find alternate names list for the domain - none for rpc */
1060 static NTSTATUS alternate_name(struct winbindd_domain *domain)
1062 return NT_STATUS_OK;
1066 /* the rpc backend methods are exposed via this structure */
1067 struct winbindd_methods msrpc_methods = {
1068 False,
1069 query_user_list,
1070 enum_dom_groups,
1071 enum_local_groups,
1072 msrpc_name_to_sid,
1073 msrpc_sid_to_name,
1074 query_user,
1075 lookup_usergroups,
1076 msrpc_lookup_useraliases,
1077 lookup_groupmem,
1078 sequence_number,
1079 trusted_domains,
1080 domain_sid,
1081 alternate_name