r148: Ensure we do not dereference a null pointer when we return the user
[Samba/gebeck_regimport.git] / source3 / nsswitch / winbindd_rpc.c
blob25d5f64df67efc197bf87ee87a22c252b3a8c0e5
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 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
278 TALLOC_CTX *mem_ctx,
279 const char *name,
280 DOM_SID *sid,
281 enum SID_NAME_USE *type)
283 CLI_POLICY_HND *hnd;
284 NTSTATUS result;
285 DOM_SID *sids = NULL;
286 uint32 *types = NULL;
287 const char *full_name;
288 int retry;
290 DEBUG(3,("rpc: name_to_sid name=%s\n", name));
292 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name);
294 if (!full_name) {
295 DEBUG(0, ("talloc_asprintf failed!\n"));
296 return NT_STATUS_NO_MEMORY;
299 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain->name ));
301 retry = 0;
302 do {
303 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
304 return result;
307 result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
308 &full_name, &sids, &types);
309 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
310 hnd && hnd->cli && hnd->cli->fd == -1);
312 /* Return rid and type if lookup successful */
314 if (NT_STATUS_IS_OK(result)) {
315 sid_copy(sid, &sids[0]);
316 *type = (enum SID_NAME_USE)types[0];
319 return result;
323 convert a domain SID to a user or group name
325 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
326 TALLOC_CTX *mem_ctx,
327 const DOM_SID *sid,
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 *name = names[0];
354 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
356 /* Paranoia */
357 if (!strequal(domain->name, domains[0])) {
358 DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0]));
359 return NT_STATUS_UNSUCCESSFUL;
363 return result;
366 /* Lookup user information from a rid or username. */
367 static NTSTATUS query_user(struct winbindd_domain *domain,
368 TALLOC_CTX *mem_ctx,
369 const DOM_SID *user_sid,
370 WINBIND_USERINFO *user_info)
372 CLI_POLICY_HND *hnd = NULL;
373 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
374 POLICY_HND dom_pol, user_pol;
375 BOOL got_dom_pol = False, got_user_pol = False;
376 SAM_USERINFO_CTR *ctr;
377 int retry;
378 fstring sid_string;
379 uint32 user_rid;
380 NET_USER_INFO_3 *user;
382 DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
383 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
384 goto done;
387 /* try netsamlogon cache first */
389 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
392 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
393 sid_string_static(user_sid)));
395 user_info->user_sid = rid_to_talloced_sid( domain, mem_ctx, user_rid );
396 user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid );
398 user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
399 user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
401 SAFE_FREE(user);
403 return NT_STATUS_OK;
406 /* no cache; hit the wire */
408 retry = 0;
409 do {
410 /* Get sam handle; if we fail here there is no hope */
412 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
413 goto done;
415 /* Get domain handle */
417 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
418 SEC_RIGHTS_MAXIMUM_ALLOWED,
419 &domain->sid, &dom_pol);
420 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
421 hnd && hnd->cli && hnd->cli->fd == -1);
423 if (!NT_STATUS_IS_OK(result))
424 goto done;
426 got_dom_pol = True;
428 /* Get user handle */
429 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
430 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
432 if (!NT_STATUS_IS_OK(result))
433 goto done;
435 got_user_pol = True;
437 /* Get user info */
438 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
439 0x15, &ctr);
441 if (!NT_STATUS_IS_OK(result))
442 goto done;
444 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
445 got_user_pol = False;
447 user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
448 user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
449 user_info->acct_name = unistr2_tdup(mem_ctx,
450 &ctr->info.id21->uni_user_name);
451 user_info->full_name = unistr2_tdup(mem_ctx,
452 &ctr->info.id21->uni_full_name);
454 done:
455 /* Clean up policy handles */
456 if (got_user_pol)
457 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
459 if (got_dom_pol)
460 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
462 return result;
465 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
466 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
467 TALLOC_CTX *mem_ctx,
468 const DOM_SID *user_sid,
469 uint32 *num_groups, DOM_SID ***user_grpsids)
471 CLI_POLICY_HND *hnd;
472 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
473 POLICY_HND dom_pol, user_pol;
474 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
475 BOOL got_dom_pol = False, got_user_pol = False;
476 DOM_GID *user_groups;
477 unsigned int i;
478 unsigned int retry;
479 fstring sid_string;
480 uint32 user_rid;
481 NET_USER_INFO_3 *user;
483 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
485 *num_groups = 0;
486 *user_grpsids = NULL;
488 /* so lets see if we have a cached user_info_3 */
490 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
492 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
493 sid_string_static(user_sid)));
495 *num_groups = user->num_groups;
497 (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
498 for (i=0;i<(*num_groups);i++) {
499 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
502 SAFE_FREE(user);
504 return NT_STATUS_OK;
507 /* no cache; hit the wire */
509 retry = 0;
510 do {
511 /* Get sam handle; if we fail here there is no hope */
513 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
514 goto done;
516 /* Get domain handle */
518 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
519 des_access, &domain->sid, &dom_pol);
520 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
521 hnd && hnd->cli && hnd->cli->fd == -1);
523 if (!NT_STATUS_IS_OK(result))
524 goto done;
526 got_dom_pol = True;
529 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
530 goto done;
533 /* Get user handle */
534 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
535 des_access, user_rid, &user_pol);
537 if (!NT_STATUS_IS_OK(result))
538 goto done;
540 got_user_pol = True;
542 /* Query user rids */
543 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
544 num_groups, &user_groups);
546 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
547 goto done;
549 (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
550 if (!(*user_grpsids)) {
551 result = NT_STATUS_NO_MEMORY;
552 goto done;
555 for (i=0;i<(*num_groups);i++) {
556 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
559 done:
560 /* Clean up policy handles */
561 if (got_user_pol)
562 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
564 if (got_dom_pol)
565 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
567 return result;
571 /* Lookup group membership given a rid. */
572 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
573 TALLOC_CTX *mem_ctx,
574 const DOM_SID *group_sid, uint32 *num_names,
575 DOM_SID ***sid_mem, char ***names,
576 uint32 **name_types)
578 CLI_POLICY_HND *hnd = NULL;
579 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
580 uint32 i, total_names = 0;
581 POLICY_HND dom_pol, group_pol;
582 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
583 BOOL got_dom_pol = False, got_group_pol = False;
584 uint32 *rid_mem = NULL;
585 uint32 group_rid;
586 int retry;
587 unsigned int j;
588 fstring sid_string;
590 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid)));
592 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
593 goto done;
596 *num_names = 0;
598 retry = 0;
599 do {
600 /* Get sam handle */
601 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
602 goto done;
604 /* Get domain handle */
606 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
607 des_access, &domain->sid, &dom_pol);
608 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
610 if (!NT_STATUS_IS_OK(result))
611 goto done;
613 got_dom_pol = True;
615 /* Get group handle */
617 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
618 des_access, group_rid, &group_pol);
620 if (!NT_STATUS_IS_OK(result))
621 goto done;
623 got_group_pol = True;
625 /* Step #1: Get a list of user rids that are the members of the
626 group. */
628 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
629 &group_pol, num_names, &rid_mem,
630 name_types);
632 if (!NT_STATUS_IS_OK(result))
633 goto done;
635 if (!*num_names) {
636 names = NULL;
637 name_types = NULL;
638 sid_mem = NULL;
639 goto done;
642 /* Step #2: Convert list of rids into list of usernames. Do this
643 in bunches of ~1000 to avoid crashing NT4. It looks like there
644 is a buffer overflow or something like that lurking around
645 somewhere. */
647 #define MAX_LOOKUP_RIDS 900
649 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *));
650 *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32));
651 *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *));
653 for (j=0;j<(*num_names);j++) {
654 (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]);
657 if (*num_names>0 && (!*names || !*name_types)) {
658 result = NT_STATUS_NO_MEMORY;
659 goto done;
662 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
663 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
664 uint32 tmp_num_names = 0;
665 char **tmp_names = NULL;
666 uint32 *tmp_types = NULL;
668 /* Lookup a chunk of rids */
670 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
671 &dom_pol, 1000, /* flags */
672 num_lookup_rids,
673 &rid_mem[i],
674 &tmp_num_names,
675 &tmp_names, &tmp_types);
677 /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is
678 the one returned from 2k) */
680 if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED))
681 goto done;
683 /* Copy result into array. The talloc system will take
684 care of freeing the temporary arrays later on. */
686 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
687 tmp_num_names);
689 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
690 tmp_num_names);
692 total_names += tmp_num_names;
695 *num_names = total_names;
697 result = NT_STATUS_OK;
699 done:
700 if (got_group_pol)
701 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
703 if (got_dom_pol)
704 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
706 return result;
709 #ifdef HAVE_LDAP
711 #include <ldap.h>
713 static SIG_ATOMIC_T gotalarm;
715 /***************************************************************
716 Signal function to tell us we timed out.
717 ****************************************************************/
719 static void gotalarm_sig(void)
721 gotalarm = 1;
724 static LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
726 LDAP *ldp = NULL;
728 /* Setup timeout */
729 gotalarm = 0;
730 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
731 alarm(to);
732 /* End setup timeout. */
734 ldp = ldap_open(server, port);
736 /* Teardown timeout. */
737 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
738 alarm(0);
740 return ldp;
743 static int get_ldap_seq(const char *server, int port, uint32 *seq)
745 int ret = -1;
746 struct timeval to;
747 char *attrs[] = {"highestCommittedUSN", NULL};
748 LDAPMessage *res = NULL;
749 char **values = NULL;
750 LDAP *ldp = NULL;
752 *seq = DOM_SEQUENCE_NONE;
755 * 10 second timeout on open. This is needed as the search timeout
756 * doesn't seem to apply to doing an open as well. JRA.
759 if ((ldp = ldap_open_with_timeout(server, port, 10)) == NULL)
760 return -1;
762 /* Timeout if no response within 20 seconds. */
763 to.tv_sec = 10;
764 to.tv_usec = 0;
766 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res))
767 goto done;
769 if (ldap_count_entries(ldp, res) != 1)
770 goto done;
772 values = ldap_get_values(ldp, res, "highestCommittedUSN");
773 if (!values || !values[0])
774 goto done;
776 *seq = atoi(values[0]);
777 ret = 0;
779 done:
781 if (values)
782 ldap_value_free(values);
783 if (res)
784 ldap_msgfree(res);
785 if (ldp)
786 ldap_unbind(ldp);
787 return ret;
790 /**********************************************************************
791 Get the sequence number for a Windows AD native mode domain using
792 LDAP queries
793 **********************************************************************/
795 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
797 int ret = -1;
798 int i, port = LDAP_PORT;
799 struct ip_service *ip_list = NULL;
800 int count;
802 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
803 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
804 return False;
807 /* Finally return first DC that we can contact */
809 for (i = 0; i < count; i++) {
810 fstring ipstr;
812 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
813 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
815 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
817 if (is_zero_ip(ip_list[i].ip))
818 continue;
820 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
821 goto done;
823 /* add to failed connection cache */
824 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
827 done:
828 if ( ret == 0 ) {
829 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n",
830 domain, inet_ntoa(ip_list[i].ip), port));
833 SAFE_FREE(ip_list);
835 return ret;
838 #endif /* HAVE_LDAP */
840 /* find the sequence number for a domain */
841 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
843 TALLOC_CTX *mem_ctx;
844 CLI_POLICY_HND *hnd;
845 SAM_UNK_CTR ctr;
846 uint16 switch_value = 2;
847 NTSTATUS result;
848 POLICY_HND dom_pol;
849 BOOL got_dom_pol = False;
850 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
851 int retry;
853 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
855 *seq = DOM_SEQUENCE_NONE;
857 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
858 return NT_STATUS_NO_MEMORY;
860 retry = 0;
861 do {
862 #ifdef HAVE_LDAP
863 if ( domain->native_mode )
865 DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
867 if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {
868 result = NT_STATUS_OK;
869 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
870 domain->name, *seq));
871 goto done;
874 DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
875 domain->name ));
877 #endif /* HAVE_LDAP */
878 /* Get sam handle */
879 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
880 goto done;
882 /* Get domain handle */
883 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
884 des_access, &domain->sid, &dom_pol);
885 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
887 if (!NT_STATUS_IS_OK(result))
888 goto done;
890 got_dom_pol = True;
892 /* Query domain info */
894 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
895 switch_value, &ctr);
897 if (NT_STATUS_IS_OK(result)) {
898 *seq = ctr.info.inf2.seq_num;
899 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
900 } else {
901 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
902 (unsigned)*seq, domain->name ));
905 done:
907 if (got_dom_pol)
908 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
910 talloc_destroy(mem_ctx);
912 return result;
915 /* get a list of trusted domains */
916 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
917 TALLOC_CTX *mem_ctx,
918 uint32 *num_domains,
919 char ***names,
920 char ***alt_names,
921 DOM_SID **dom_sids)
923 CLI_POLICY_HND *hnd;
924 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
925 uint32 enum_ctx = 0;
926 int retry;
928 DEBUG(3,("rpc: trusted_domains\n"));
930 *num_domains = 0;
931 *alt_names = NULL;
933 retry = 0;
934 do {
935 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
936 goto done;
938 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
939 &hnd->pol, &enum_ctx,
940 num_domains, names, dom_sids);
941 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
943 done:
944 return result;
947 /* find the domain sid for a domain */
948 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
950 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
951 TALLOC_CTX *mem_ctx;
952 CLI_POLICY_HND *hnd;
953 char *level5_dom;
954 DOM_SID *alloc_sid;
955 int retry;
957 DEBUG(3,("rpc: domain_sid\n"));
959 if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
960 return NT_STATUS_NO_MEMORY;
962 retry = 0;
963 do {
964 /* Get lsa handle */
965 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
966 goto done;
968 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
969 &hnd->pol, 0x05, &level5_dom, &alloc_sid);
970 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
972 if (NT_STATUS_IS_OK(result)) {
973 if (alloc_sid) {
974 sid_copy(sid, alloc_sid);
975 } else {
976 result = NT_STATUS_NO_MEMORY;
980 done:
981 talloc_destroy(mem_ctx);
982 return result;
985 /* find alternate names list for the domain - none for rpc */
986 static NTSTATUS alternate_name(struct winbindd_domain *domain)
988 return NT_STATUS_OK;
992 /* the rpc backend methods are exposed via this structure */
993 struct winbindd_methods msrpc_methods = {
994 False,
995 query_user_list,
996 enum_dom_groups,
997 enum_local_groups,
998 name_to_sid,
999 sid_to_name,
1000 query_user,
1001 lookup_usergroups,
1002 lookup_groupmem,
1003 sequence_number,
1004 trusted_domains,
1005 domain_sid,
1006 alternate_name