r3780: final release notes
[Samba.git] / source / nsswitch / winbindd_rpc.c
blobba24749fbef07cd036c48a9e6580d14d6148815f
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 int get_ldap_seq(const char *server, int port, uint32 *seq)
712 int ret = -1;
713 struct timeval to;
714 char *attrs[] = {"highestCommittedUSN", NULL};
715 LDAPMessage *res = NULL;
716 char **values = NULL;
717 LDAP *ldp = NULL;
719 *seq = DOM_SEQUENCE_NONE;
722 * Parameterised (5) second timeout on open. This is needed as the search timeout
723 * doesn't seem to apply to doing an open as well. JRA.
726 if ((ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout())) == NULL)
727 return -1;
729 /* Timeout if no response within 20 seconds. */
730 to.tv_sec = 10;
731 to.tv_usec = 0;
733 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res))
734 goto done;
736 if (ldap_count_entries(ldp, res) != 1)
737 goto done;
739 values = ldap_get_values(ldp, res, "highestCommittedUSN");
740 if (!values || !values[0])
741 goto done;
743 *seq = atoi(values[0]);
744 ret = 0;
746 done:
748 if (values)
749 ldap_value_free(values);
750 if (res)
751 ldap_msgfree(res);
752 if (ldp)
753 ldap_unbind(ldp);
754 return ret;
757 /**********************************************************************
758 Get the sequence number for a Windows AD native mode domain using
759 LDAP queries
760 **********************************************************************/
762 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
764 int ret = -1;
765 int i, port = LDAP_PORT;
766 struct ip_service *ip_list = NULL;
767 int count;
769 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
770 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
771 return False;
774 /* Finally return first DC that we can contact */
776 for (i = 0; i < count; i++) {
777 fstring ipstr;
779 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
780 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
782 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
784 if (is_zero_ip(ip_list[i].ip))
785 continue;
787 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
788 goto done;
790 /* add to failed connection cache */
791 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
794 done:
795 if ( ret == 0 ) {
796 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n",
797 domain, inet_ntoa(ip_list[i].ip), port));
800 SAFE_FREE(ip_list);
802 return ret;
805 #endif /* HAVE_LDAP */
807 /* find the sequence number for a domain */
808 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
810 TALLOC_CTX *mem_ctx;
811 CLI_POLICY_HND *hnd;
812 SAM_UNK_CTR ctr;
813 uint16 switch_value = 2;
814 NTSTATUS result;
815 POLICY_HND dom_pol;
816 BOOL got_dom_pol = False;
817 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
818 int retry;
820 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
822 *seq = DOM_SEQUENCE_NONE;
824 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
825 return NT_STATUS_NO_MEMORY;
827 retry = 0;
828 do {
829 #ifdef HAVE_LDAP
830 if ( domain->native_mode )
832 DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
834 if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {
835 result = NT_STATUS_OK;
836 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
837 domain->name, *seq));
838 goto done;
841 DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
842 domain->name ));
844 #endif /* HAVE_LDAP */
845 /* Get sam handle */
846 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
847 goto done;
849 /* Get domain handle */
850 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
851 des_access, &domain->sid, &dom_pol);
852 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
854 if (!NT_STATUS_IS_OK(result))
855 goto done;
857 got_dom_pol = True;
859 /* Query domain info */
861 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
862 switch_value, &ctr);
864 if (NT_STATUS_IS_OK(result)) {
865 *seq = ctr.info.inf2.seq_num;
866 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
867 } else {
868 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
869 (unsigned)*seq, domain->name ));
872 done:
874 if (got_dom_pol)
875 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
877 talloc_destroy(mem_ctx);
879 return result;
882 /* get a list of trusted domains */
883 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
884 TALLOC_CTX *mem_ctx,
885 uint32 *num_domains,
886 char ***names,
887 char ***alt_names,
888 DOM_SID **dom_sids)
890 CLI_POLICY_HND *hnd;
891 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
892 uint32 enum_ctx = 0;
893 int retry;
895 DEBUG(3,("rpc: trusted_domains\n"));
897 *num_domains = 0;
898 *alt_names = NULL;
900 retry = 0;
901 do {
902 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
903 goto done;
905 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
906 &hnd->pol, &enum_ctx,
907 num_domains, names, dom_sids);
908 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
910 done:
911 return result;
914 /* find the domain sid for a domain */
915 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
917 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
918 TALLOC_CTX *mem_ctx;
919 CLI_POLICY_HND *hnd;
920 char *level5_dom;
921 DOM_SID *alloc_sid;
922 int retry;
924 DEBUG(3,("rpc: domain_sid\n"));
926 if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
927 return NT_STATUS_NO_MEMORY;
929 retry = 0;
930 do {
931 /* Get lsa handle */
932 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
933 goto done;
935 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
936 &hnd->pol, 0x05, &level5_dom, &alloc_sid);
937 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
939 if (NT_STATUS_IS_OK(result)) {
940 if (alloc_sid) {
941 sid_copy(sid, alloc_sid);
942 } else {
943 result = NT_STATUS_NO_MEMORY;
947 done:
948 talloc_destroy(mem_ctx);
949 return result;
952 /* find alternate names list for the domain - none for rpc */
953 static NTSTATUS alternate_name(struct winbindd_domain *domain)
955 return NT_STATUS_OK;
959 /* the rpc backend methods are exposed via this structure */
960 struct winbindd_methods msrpc_methods = {
961 False,
962 query_user_list,
963 enum_dom_groups,
964 enum_local_groups,
965 msrpc_name_to_sid,
966 msrpc_sid_to_name,
967 query_user,
968 lookup_usergroups,
969 lookup_groupmem,
970 sequence_number,
971 trusted_domains,
972 domain_sid,
973 alternate_name