r294: checking in volker's winbindd patches; tested on domain members (Samba and...
[Samba.git] / source / nsswitch / winbindd_rpc.c
blob76688449209d9dd2ae0ee6eb7abba1a329836240
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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
25 #include "winbindd.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_WINBIND
31 /* Query display info for a domain. This returns enough information plus a
32 bit extra to give an overview of domain users for the User Manager
33 application. */
34 static NTSTATUS query_user_list(struct winbindd_domain *domain,
35 TALLOC_CTX *mem_ctx,
36 uint32 *num_entries,
37 WINBIND_USERINFO **info)
39 CLI_POLICY_HND *hnd;
40 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
41 POLICY_HND dom_pol;
42 BOOL got_dom_pol = False;
43 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
44 unsigned int i, start_idx, retry;
45 uint32 loop_count;
47 DEBUG(3,("rpc: query_user_list\n"));
49 *num_entries = 0;
50 *info = NULL;
52 retry = 0;
53 do {
54 /* Get sam handle */
56 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
57 return result;
59 /* Get domain handle */
61 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
62 des_access, &domain->sid, &dom_pol);
64 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
66 if (!NT_STATUS_IS_OK(result))
67 goto done;
69 got_dom_pol = True;
71 i = start_idx = 0;
72 loop_count = 0;
74 do {
75 TALLOC_CTX *ctx2;
76 uint32 num_dom_users, j;
77 uint32 max_entries, max_size;
78 SAM_DISPINFO_CTR ctr;
79 SAM_DISPINFO_1 info1;
81 ZERO_STRUCT( ctr );
82 ZERO_STRUCT( info1 );
83 ctr.sam.info1 = &info1;
85 if (!(ctx2 = talloc_init("winbindd enum_users"))) {
86 result = NT_STATUS_NO_MEMORY;
87 goto done;
90 /* this next bit is copied from net_user_list_internal() */
92 get_query_dispinfo_params( loop_count, &max_entries, &max_size );
94 result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, &dom_pol,
95 &start_idx, 1, &num_dom_users, max_entries, max_size, &ctr);
97 loop_count++;
99 *num_entries += num_dom_users;
101 *info = talloc_realloc( mem_ctx, *info,
102 (*num_entries) * sizeof(WINBIND_USERINFO));
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(mem_ctx, *info,
196 sizeof(**info) * ((*num_entries) + count));
197 if (! *info) {
198 talloc_destroy(mem_ctx2);
199 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
200 return NT_STATUS_NO_MEMORY;
203 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
204 (*num_entries) += count;
205 talloc_destroy(mem_ctx2);
206 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
208 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
210 return status;
213 /* List all domain groups */
215 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
216 TALLOC_CTX *mem_ctx,
217 uint32 *num_entries,
218 struct acct_info **info)
220 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
221 CLI_POLICY_HND *hnd;
222 POLICY_HND dom_pol;
223 NTSTATUS result;
224 int retry;
226 *num_entries = 0;
227 *info = NULL;
229 retry = 0;
230 do {
231 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
232 return result;
234 result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol,
235 des_access, &domain->sid, &dom_pol);
236 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
238 if ( !NT_STATUS_IS_OK(result))
239 return result;
241 do {
242 struct acct_info *info2 = NULL;
243 uint32 count = 0, start = *num_entries;
244 TALLOC_CTX *mem_ctx2;
246 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
248 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
249 &start, 0xFFFF, &info2, &count);
251 if ( !NT_STATUS_IS_OK(result)
252 && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
254 talloc_destroy(mem_ctx2);
255 break;
258 (*info) = talloc_realloc(mem_ctx, *info,
259 sizeof(**info) * ((*num_entries) + count));
260 if (! *info) {
261 talloc_destroy(mem_ctx2);
262 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
263 return NT_STATUS_NO_MEMORY;
266 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
267 (*num_entries) += count;
268 talloc_destroy(mem_ctx2);
269 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
271 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
273 return result;
276 /* convert a single name to a sid in a domain */
277 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
278 TALLOC_CTX *mem_ctx,
279 const char *domain_name,
280 const char *name,
281 DOM_SID *sid,
282 enum SID_NAME_USE *type)
284 CLI_POLICY_HND *hnd;
285 NTSTATUS result;
286 DOM_SID *sids = NULL;
287 uint32 *types = NULL;
288 const char *full_name;
289 int retry;
291 DEBUG(3,("rpc: name_to_sid name=%s\n", name));
293 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
295 if (!full_name) {
296 DEBUG(0, ("talloc_asprintf failed!\n"));
297 return NT_STATUS_NO_MEMORY;
300 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name ));
302 retry = 0;
303 do {
304 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
305 return result;
308 result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
309 &full_name, &sids, &types);
310 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
311 hnd && hnd->cli && hnd->cli->fd == -1);
313 /* Return rid and type if lookup successful */
315 if (NT_STATUS_IS_OK(result)) {
316 sid_copy(sid, &sids[0]);
317 *type = (enum SID_NAME_USE)types[0];
320 return result;
324 convert a domain SID to a user or group name
326 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
327 TALLOC_CTX *mem_ctx,
328 const DOM_SID *sid,
329 char **domain_name,
330 char **name,
331 enum SID_NAME_USE *type)
333 CLI_POLICY_HND *hnd;
334 char **domains;
335 char **names;
336 uint32 *types;
337 NTSTATUS result;
338 int retry;
340 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
341 domain->name ));
343 retry = 0;
344 do {
345 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
346 return result;
348 result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
349 1, sid, &domains, &names, &types);
350 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
351 hnd && hnd->cli && hnd->cli->fd == -1);
353 if (NT_STATUS_IS_OK(result)) {
354 *type = (enum SID_NAME_USE)types[0];
355 *domain_name = domains[0];
356 *name = names[0];
357 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
360 return result;
363 /* Lookup user information from a rid or username. */
364 static NTSTATUS query_user(struct winbindd_domain *domain,
365 TALLOC_CTX *mem_ctx,
366 const DOM_SID *user_sid,
367 WINBIND_USERINFO *user_info)
369 CLI_POLICY_HND *hnd = NULL;
370 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
371 POLICY_HND dom_pol, user_pol;
372 BOOL got_dom_pol = False, got_user_pol = False;
373 SAM_USERINFO_CTR *ctr;
374 int retry;
375 fstring sid_string;
376 uint32 user_rid;
377 NET_USER_INFO_3 *user;
379 DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
380 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
381 goto done;
384 /* try netsamlogon cache first */
386 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
389 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
390 sid_string_static(user_sid)));
392 user_info->user_sid = rid_to_talloced_sid( domain, mem_ctx, user_rid );
393 user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid );
395 user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
396 user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
398 SAFE_FREE(user);
400 return NT_STATUS_OK;
403 /* no cache; hit the wire */
405 retry = 0;
406 do {
407 /* Get sam handle; if we fail here there is no hope */
409 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
410 goto done;
412 /* Get domain handle */
414 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
415 SEC_RIGHTS_MAXIMUM_ALLOWED,
416 &domain->sid, &dom_pol);
417 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
418 hnd && hnd->cli && hnd->cli->fd == -1);
420 if (!NT_STATUS_IS_OK(result))
421 goto done;
423 got_dom_pol = True;
425 /* Get user handle */
426 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
427 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
429 if (!NT_STATUS_IS_OK(result))
430 goto done;
432 got_user_pol = True;
434 /* Get user info */
435 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
436 0x15, &ctr);
438 if (!NT_STATUS_IS_OK(result))
439 goto done;
441 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
442 got_user_pol = False;
444 user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
445 user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
446 user_info->acct_name = unistr2_tdup(mem_ctx,
447 &ctr->info.id21->uni_user_name);
448 user_info->full_name = unistr2_tdup(mem_ctx,
449 &ctr->info.id21->uni_full_name);
451 done:
452 /* Clean up policy handles */
453 if (got_user_pol)
454 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
456 if (got_dom_pol)
457 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
459 return result;
462 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
463 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
464 TALLOC_CTX *mem_ctx,
465 const DOM_SID *user_sid,
466 uint32 *num_groups, DOM_SID ***user_grpsids)
468 CLI_POLICY_HND *hnd;
469 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
470 POLICY_HND dom_pol, user_pol;
471 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
472 BOOL got_dom_pol = False, got_user_pol = False;
473 DOM_GID *user_groups;
474 unsigned int i;
475 unsigned int retry;
476 fstring sid_string;
477 uint32 user_rid;
478 NET_USER_INFO_3 *user;
480 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
482 *num_groups = 0;
483 *user_grpsids = NULL;
485 /* so lets see if we have a cached user_info_3 */
487 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
489 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
490 sid_string_static(user_sid)));
492 *num_groups = user->num_groups;
494 (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
495 for (i=0;i<(*num_groups);i++) {
496 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
499 SAFE_FREE(user);
501 return NT_STATUS_OK;
504 /* no cache; hit the wire */
506 retry = 0;
507 do {
508 /* Get sam handle; if we fail here there is no hope */
510 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
511 goto done;
513 /* Get domain handle */
515 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
516 des_access, &domain->sid, &dom_pol);
517 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
518 hnd && hnd->cli && hnd->cli->fd == -1);
520 if (!NT_STATUS_IS_OK(result))
521 goto done;
523 got_dom_pol = True;
526 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
527 goto done;
530 /* Get user handle */
531 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
532 des_access, user_rid, &user_pol);
534 if (!NT_STATUS_IS_OK(result))
535 goto done;
537 got_user_pol = True;
539 /* Query user rids */
540 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
541 num_groups, &user_groups);
543 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
544 goto done;
546 (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
547 if (!(*user_grpsids)) {
548 result = NT_STATUS_NO_MEMORY;
549 goto done;
552 for (i=0;i<(*num_groups);i++) {
553 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
556 done:
557 /* Clean up policy handles */
558 if (got_user_pol)
559 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
561 if (got_dom_pol)
562 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
564 return result;
568 /* Lookup group membership given a rid. */
569 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
570 TALLOC_CTX *mem_ctx,
571 const DOM_SID *group_sid, uint32 *num_names,
572 DOM_SID ***sid_mem, char ***names,
573 uint32 **name_types)
575 CLI_POLICY_HND *hnd = NULL;
576 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
577 uint32 i, total_names = 0;
578 POLICY_HND dom_pol, group_pol;
579 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
580 BOOL got_dom_pol = False, got_group_pol = False;
581 uint32 *rid_mem = NULL;
582 uint32 group_rid;
583 int retry;
584 unsigned int j;
585 fstring sid_string;
587 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid)));
589 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
590 goto done;
593 *num_names = 0;
595 retry = 0;
596 do {
597 /* Get sam handle */
598 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
599 goto done;
601 /* Get domain handle */
603 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
604 des_access, &domain->sid, &dom_pol);
605 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
607 if (!NT_STATUS_IS_OK(result))
608 goto done;
610 got_dom_pol = True;
612 /* Get group handle */
614 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
615 des_access, group_rid, &group_pol);
617 if (!NT_STATUS_IS_OK(result))
618 goto done;
620 got_group_pol = True;
622 /* Step #1: Get a list of user rids that are the members of the
623 group. */
625 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
626 &group_pol, num_names, &rid_mem,
627 name_types);
629 if (!NT_STATUS_IS_OK(result))
630 goto done;
632 if (!*num_names) {
633 names = NULL;
634 name_types = NULL;
635 sid_mem = NULL;
636 goto done;
639 /* Step #2: Convert list of rids into list of usernames. Do this
640 in bunches of ~1000 to avoid crashing NT4. It looks like there
641 is a buffer overflow or something like that lurking around
642 somewhere. */
644 #define MAX_LOOKUP_RIDS 900
646 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *));
647 *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32));
648 *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *));
650 for (j=0;j<(*num_names);j++) {
651 (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]);
654 if (*num_names>0 && (!*names || !*name_types)) {
655 result = NT_STATUS_NO_MEMORY;
656 goto done;
659 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
660 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
661 uint32 tmp_num_names = 0;
662 char **tmp_names = NULL;
663 uint32 *tmp_types = NULL;
665 /* Lookup a chunk of rids */
667 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
668 &dom_pol, 1000, /* flags */
669 num_lookup_rids,
670 &rid_mem[i],
671 &tmp_num_names,
672 &tmp_names, &tmp_types);
674 /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is
675 the one returned from 2k) */
677 if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED))
678 goto done;
680 /* Copy result into array. The talloc system will take
681 care of freeing the temporary arrays later on. */
683 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
684 tmp_num_names);
686 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
687 tmp_num_names);
689 total_names += tmp_num_names;
692 *num_names = total_names;
694 result = NT_STATUS_OK;
696 done:
697 if (got_group_pol)
698 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
700 if (got_dom_pol)
701 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
703 return result;
706 #ifdef HAVE_LDAP
708 #include <ldap.h>
710 static SIG_ATOMIC_T gotalarm;
712 /***************************************************************
713 Signal function to tell us we timed out.
714 ****************************************************************/
716 static void gotalarm_sig(void)
718 gotalarm = 1;
721 static LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
723 LDAP *ldp = NULL;
725 /* Setup timeout */
726 gotalarm = 0;
727 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
728 alarm(to);
729 /* End setup timeout. */
731 ldp = ldap_open(server, port);
733 /* Teardown timeout. */
734 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
735 alarm(0);
737 return ldp;
740 static int get_ldap_seq(const char *server, int port, uint32 *seq)
742 int ret = -1;
743 struct timeval to;
744 char *attrs[] = {"highestCommittedUSN", NULL};
745 LDAPMessage *res = NULL;
746 char **values = NULL;
747 LDAP *ldp = NULL;
749 *seq = DOM_SEQUENCE_NONE;
752 * 10 second timeout on open. This is needed as the search timeout
753 * doesn't seem to apply to doing an open as well. JRA.
756 if ((ldp = ldap_open_with_timeout(server, port, 10)) == NULL)
757 return -1;
759 /* Timeout if no response within 20 seconds. */
760 to.tv_sec = 10;
761 to.tv_usec = 0;
763 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res))
764 goto done;
766 if (ldap_count_entries(ldp, res) != 1)
767 goto done;
769 values = ldap_get_values(ldp, res, "highestCommittedUSN");
770 if (!values || !values[0])
771 goto done;
773 *seq = atoi(values[0]);
774 ret = 0;
776 done:
778 if (values)
779 ldap_value_free(values);
780 if (res)
781 ldap_msgfree(res);
782 if (ldp)
783 ldap_unbind(ldp);
784 return ret;
787 /**********************************************************************
788 Get the sequence number for a Windows AD native mode domain using
789 LDAP queries
790 **********************************************************************/
792 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
794 int ret = -1;
795 int i, port = LDAP_PORT;
796 struct ip_service *ip_list = NULL;
797 int count;
799 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
800 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
801 return False;
804 /* Finally return first DC that we can contact */
806 for (i = 0; i < count; i++) {
807 fstring ipstr;
809 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
810 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
812 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
814 if (is_zero_ip(ip_list[i].ip))
815 continue;
817 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
818 goto done;
820 /* add to failed connection cache */
821 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
824 done:
825 if ( ret == 0 ) {
826 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n",
827 domain, inet_ntoa(ip_list[i].ip), port));
830 SAFE_FREE(ip_list);
832 return ret;
835 #endif /* HAVE_LDAP */
837 /* find the sequence number for a domain */
838 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
840 TALLOC_CTX *mem_ctx;
841 CLI_POLICY_HND *hnd;
842 SAM_UNK_CTR ctr;
843 uint16 switch_value = 2;
844 NTSTATUS result;
845 POLICY_HND dom_pol;
846 BOOL got_dom_pol = False;
847 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
848 int retry;
850 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
852 *seq = DOM_SEQUENCE_NONE;
854 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
855 return NT_STATUS_NO_MEMORY;
857 retry = 0;
858 do {
859 #ifdef HAVE_LDAP
860 if ( domain->native_mode )
862 DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
864 if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {
865 result = NT_STATUS_OK;
866 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
867 domain->name, *seq));
868 goto done;
871 DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
872 domain->name ));
874 #endif /* HAVE_LDAP */
875 /* Get sam handle */
876 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
877 goto done;
879 /* Get domain handle */
880 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
881 des_access, &domain->sid, &dom_pol);
882 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
884 if (!NT_STATUS_IS_OK(result))
885 goto done;
887 got_dom_pol = True;
889 /* Query domain info */
891 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
892 switch_value, &ctr);
894 if (NT_STATUS_IS_OK(result)) {
895 *seq = ctr.info.inf2.seq_num;
896 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
897 } else {
898 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
899 (unsigned)*seq, domain->name ));
902 done:
904 if (got_dom_pol)
905 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
907 talloc_destroy(mem_ctx);
909 return result;
912 /* get a list of trusted domains */
913 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
914 TALLOC_CTX *mem_ctx,
915 uint32 *num_domains,
916 char ***names,
917 char ***alt_names,
918 DOM_SID **dom_sids)
920 CLI_POLICY_HND *hnd;
921 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
922 uint32 enum_ctx = 0;
923 int retry;
925 DEBUG(3,("rpc: trusted_domains\n"));
927 *num_domains = 0;
928 *alt_names = NULL;
930 retry = 0;
931 do {
932 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
933 goto done;
935 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
936 &hnd->pol, &enum_ctx,
937 num_domains, names, dom_sids);
938 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
940 done:
941 return result;
944 /* find the domain sid for a domain */
945 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
947 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
948 TALLOC_CTX *mem_ctx;
949 CLI_POLICY_HND *hnd;
950 char *level5_dom;
951 DOM_SID *alloc_sid;
952 int retry;
954 DEBUG(3,("rpc: domain_sid\n"));
956 if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
957 return NT_STATUS_NO_MEMORY;
959 retry = 0;
960 do {
961 /* Get lsa handle */
962 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
963 goto done;
965 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
966 &hnd->pol, 0x05, &level5_dom, &alloc_sid);
967 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
969 if (NT_STATUS_IS_OK(result)) {
970 if (alloc_sid) {
971 sid_copy(sid, alloc_sid);
972 } else {
973 result = NT_STATUS_NO_MEMORY;
977 done:
978 talloc_destroy(mem_ctx);
979 return result;
982 /* find alternate names list for the domain - none for rpc */
983 static NTSTATUS alternate_name(struct winbindd_domain *domain)
985 return NT_STATUS_OK;
989 /* the rpc backend methods are exposed via this structure */
990 struct winbindd_methods msrpc_methods = {
991 False,
992 query_user_list,
993 enum_dom_groups,
994 enum_local_groups,
995 msrpc_name_to_sid,
996 msrpc_sid_to_name,
997 query_user,
998 lookup_usergroups,
999 lookup_groupmem,
1000 sequence_number,
1001 trusted_domains,
1002 domain_sid,
1003 alternate_name