r4231: commiting changes to 3.0.10
[Samba.git] / source / nsswitch / winbindd_rpc.c
blobde7f2ff76fbec30178b2b055a630b2c347afc471
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_ARRAY( mem_ctx, *info, WINBIND_USERINFO, *num_entries);
103 if (!(*info)) {
104 result = NT_STATUS_NO_MEMORY;
105 talloc_destroy(ctx2);
106 goto done;
109 for (j = 0; j < num_dom_users; i++, j++) {
110 fstring username, fullname;
111 uint32 rid = ctr.sam.info1->sam[j].rid_user;
113 unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
114 unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
116 (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
117 (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
118 (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, rid );
120 /* For the moment we set the primary group for
121 every user to be the Domain Users group.
122 There are serious problems with determining
123 the actual primary group for large domains.
124 This should really be made into a 'winbind
125 force group' smb.conf parameter or
126 something like that. */
128 (*info)[i].group_sid = rid_to_talloced_sid(domain,
129 mem_ctx, DOMAIN_GROUP_RID_USERS);
132 talloc_destroy(ctx2);
134 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
136 done:
138 if (got_dom_pol)
139 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
141 return result;
144 /* list all domain groups */
145 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
146 TALLOC_CTX *mem_ctx,
147 uint32 *num_entries,
148 struct acct_info **info)
150 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
151 CLI_POLICY_HND *hnd;
152 POLICY_HND dom_pol;
153 NTSTATUS status;
154 uint32 start = 0;
155 int retry;
156 NTSTATUS result;
158 *num_entries = 0;
159 *info = NULL;
161 DEBUG(3,("rpc: enum_dom_groups\n"));
163 retry = 0;
164 do {
165 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
166 return result;
168 status = cli_samr_open_domain(hnd->cli, mem_ctx,
169 &hnd->pol, des_access, &domain->sid, &dom_pol);
170 } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
172 if (!NT_STATUS_IS_OK(status))
173 return status;
175 do {
176 struct acct_info *info2 = NULL;
177 uint32 count = 0;
178 TALLOC_CTX *mem_ctx2;
180 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
182 /* start is updated by this call. */
183 status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol,
184 &start,
185 0xFFFF, /* buffer size? */
186 &info2, &count);
188 if (!NT_STATUS_IS_OK(status) &&
189 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
190 talloc_destroy(mem_ctx2);
191 break;
194 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
195 if (! *info) {
196 talloc_destroy(mem_ctx2);
197 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
198 return NT_STATUS_NO_MEMORY;
201 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
202 (*num_entries) += count;
203 talloc_destroy(mem_ctx2);
204 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
206 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
208 return status;
211 /* List all domain groups */
213 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
214 TALLOC_CTX *mem_ctx,
215 uint32 *num_entries,
216 struct acct_info **info)
218 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
219 CLI_POLICY_HND *hnd;
220 POLICY_HND dom_pol;
221 NTSTATUS result;
222 int retry;
224 *num_entries = 0;
225 *info = NULL;
227 retry = 0;
228 do {
229 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
230 return result;
232 result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol,
233 des_access, &domain->sid, &dom_pol);
234 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
236 if ( !NT_STATUS_IS_OK(result))
237 return result;
239 do {
240 struct acct_info *info2 = NULL;
241 uint32 count = 0, start = *num_entries;
242 TALLOC_CTX *mem_ctx2;
244 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
246 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
247 &start, 0xFFFF, &info2, &count);
249 if ( !NT_STATUS_IS_OK(result)
250 && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
252 talloc_destroy(mem_ctx2);
253 break;
256 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
257 if (! *info) {
258 talloc_destroy(mem_ctx2);
259 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
260 return NT_STATUS_NO_MEMORY;
263 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
264 (*num_entries) += count;
265 talloc_destroy(mem_ctx2);
266 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
268 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
270 return result;
273 /* convert a single name to a sid in a domain */
274 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
275 TALLOC_CTX *mem_ctx,
276 const char *domain_name,
277 const char *name,
278 DOM_SID *sid,
279 enum SID_NAME_USE *type)
281 CLI_POLICY_HND *hnd;
282 NTSTATUS result;
283 DOM_SID *sids = NULL;
284 uint32 *types = NULL;
285 const char *full_name;
286 int retry;
288 DEBUG(3,("rpc: name_to_sid name=%s\n", name));
290 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
292 if (!full_name) {
293 DEBUG(0, ("talloc_asprintf failed!\n"));
294 return NT_STATUS_NO_MEMORY;
297 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name ));
299 retry = 0;
300 do {
301 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
302 return result;
305 result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
306 &full_name, &sids, &types);
307 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
308 hnd && hnd->cli && hnd->cli->fd == -1);
310 /* Return rid and type if lookup successful */
312 if (NT_STATUS_IS_OK(result)) {
313 sid_copy(sid, &sids[0]);
314 *type = (enum SID_NAME_USE)types[0];
317 return result;
321 convert a domain SID to a user or group name
323 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
324 TALLOC_CTX *mem_ctx,
325 const DOM_SID *sid,
326 char **domain_name,
327 char **name,
328 enum SID_NAME_USE *type)
330 CLI_POLICY_HND *hnd;
331 char **domains;
332 char **names;
333 uint32 *types;
334 NTSTATUS result;
335 int retry;
337 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
338 domain->name ));
340 retry = 0;
341 do {
342 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
343 return result;
345 result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
346 1, sid, &domains, &names, &types);
347 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
348 hnd && hnd->cli && hnd->cli->fd == -1);
350 if (NT_STATUS_IS_OK(result)) {
351 *type = (enum SID_NAME_USE)types[0];
352 *domain_name = domains[0];
353 *name = names[0];
354 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
357 return result;
360 /* Lookup user information from a rid or username. */
361 static NTSTATUS query_user(struct winbindd_domain *domain,
362 TALLOC_CTX *mem_ctx,
363 const DOM_SID *user_sid,
364 WINBIND_USERINFO *user_info)
366 CLI_POLICY_HND *hnd = NULL;
367 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
368 POLICY_HND dom_pol, user_pol;
369 BOOL got_dom_pol = False, got_user_pol = False;
370 SAM_USERINFO_CTR *ctr;
371 int retry;
372 fstring sid_string;
373 uint32 user_rid;
374 NET_USER_INFO_3 *user;
376 DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
377 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
378 goto done;
381 /* try netsamlogon cache first */
383 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
386 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
387 sid_string_static(user_sid)));
389 user_info->user_sid = rid_to_talloced_sid( domain, mem_ctx, user_rid );
390 user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid );
392 user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
393 user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
395 SAFE_FREE(user);
397 return NT_STATUS_OK;
400 /* no cache; hit the wire */
402 retry = 0;
403 do {
404 /* Get sam handle; if we fail here there is no hope */
406 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
407 goto done;
409 /* Get domain handle */
411 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
412 SEC_RIGHTS_MAXIMUM_ALLOWED,
413 &domain->sid, &dom_pol);
414 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
415 hnd && hnd->cli && hnd->cli->fd == -1);
417 if (!NT_STATUS_IS_OK(result))
418 goto done;
420 got_dom_pol = True;
422 /* Get user handle */
423 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
424 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
426 if (!NT_STATUS_IS_OK(result))
427 goto done;
429 got_user_pol = True;
431 /* Get user info */
432 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
433 0x15, &ctr);
435 if (!NT_STATUS_IS_OK(result))
436 goto done;
438 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
439 got_user_pol = False;
441 user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
442 user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
443 user_info->acct_name = unistr2_tdup(mem_ctx,
444 &ctr->info.id21->uni_user_name);
445 user_info->full_name = unistr2_tdup(mem_ctx,
446 &ctr->info.id21->uni_full_name);
448 done:
449 /* Clean up policy handles */
450 if (got_user_pol)
451 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
453 if (got_dom_pol)
454 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
456 return result;
459 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
460 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
461 TALLOC_CTX *mem_ctx,
462 const DOM_SID *user_sid,
463 uint32 *num_groups, DOM_SID ***user_grpsids)
465 CLI_POLICY_HND *hnd;
466 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
467 POLICY_HND dom_pol, user_pol;
468 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
469 BOOL got_dom_pol = False, got_user_pol = False;
470 DOM_GID *user_groups;
471 unsigned int i;
472 unsigned int retry;
473 fstring sid_string;
474 uint32 user_rid;
475 NET_USER_INFO_3 *user;
477 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
479 *num_groups = 0;
480 *user_grpsids = NULL;
482 /* so lets see if we have a cached user_info_3 */
484 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
486 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
487 sid_string_static(user_sid)));
489 *num_groups = user->num_groups;
491 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID*, *num_groups);
492 for (i=0;i<(*num_groups);i++) {
493 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
496 SAFE_FREE(user);
498 return NT_STATUS_OK;
501 /* no cache; hit the wire */
503 retry = 0;
504 do {
505 /* Get sam handle; if we fail here there is no hope */
507 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
508 goto done;
510 /* Get domain handle */
512 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
513 des_access, &domain->sid, &dom_pol);
514 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
515 hnd && hnd->cli && hnd->cli->fd == -1);
517 if (!NT_STATUS_IS_OK(result))
518 goto done;
520 got_dom_pol = True;
523 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
524 goto done;
527 /* Get user handle */
528 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
529 des_access, user_rid, &user_pol);
531 if (!NT_STATUS_IS_OK(result))
532 goto done;
534 got_user_pol = True;
536 /* Query user rids */
537 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
538 num_groups, &user_groups);
540 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
541 goto done;
543 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID *, *num_groups);
544 if (!(*user_grpsids)) {
545 result = NT_STATUS_NO_MEMORY;
546 goto done;
549 for (i=0;i<(*num_groups);i++) {
550 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
553 done:
554 /* Clean up policy handles */
555 if (got_user_pol)
556 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
558 if (got_dom_pol)
559 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
561 return result;
565 /* Lookup group membership given a rid. */
566 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
567 TALLOC_CTX *mem_ctx,
568 const DOM_SID *group_sid, uint32 *num_names,
569 DOM_SID ***sid_mem, char ***names,
570 uint32 **name_types)
572 CLI_POLICY_HND *hnd = NULL;
573 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
574 uint32 i, total_names = 0;
575 POLICY_HND dom_pol, group_pol;
576 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
577 BOOL got_dom_pol = False, got_group_pol = False;
578 uint32 *rid_mem = NULL;
579 uint32 group_rid;
580 int retry;
581 unsigned int j;
582 fstring sid_string;
584 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid)));
586 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
587 goto done;
590 *num_names = 0;
592 retry = 0;
593 do {
594 /* Get sam handle */
595 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
596 goto done;
598 /* Get domain handle */
600 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
601 des_access, &domain->sid, &dom_pol);
602 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
604 if (!NT_STATUS_IS_OK(result))
605 goto done;
607 got_dom_pol = True;
609 /* Get group handle */
611 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
612 des_access, group_rid, &group_pol);
614 if (!NT_STATUS_IS_OK(result))
615 goto done;
617 got_group_pol = True;
619 /* Step #1: Get a list of user rids that are the members of the
620 group. */
622 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
623 &group_pol, num_names, &rid_mem,
624 name_types);
626 if (!NT_STATUS_IS_OK(result))
627 goto done;
629 if (!*num_names) {
630 names = NULL;
631 name_types = NULL;
632 sid_mem = NULL;
633 goto done;
636 /* Step #2: Convert list of rids into list of usernames. Do this
637 in bunches of ~1000 to avoid crashing NT4. It looks like there
638 is a buffer overflow or something like that lurking around
639 somewhere. */
641 #define MAX_LOOKUP_RIDS 900
643 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
644 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
645 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID *, *num_names);
647 for (j=0;j<(*num_names);j++) {
648 (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]);
651 if (*num_names>0 && (!*names || !*name_types)) {
652 result = NT_STATUS_NO_MEMORY;
653 goto done;
656 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
657 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
658 uint32 tmp_num_names = 0;
659 char **tmp_names = NULL;
660 uint32 *tmp_types = NULL;
662 /* Lookup a chunk of rids */
664 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
665 &dom_pol, 1000, /* flags */
666 num_lookup_rids,
667 &rid_mem[i],
668 &tmp_num_names,
669 &tmp_names, &tmp_types);
671 /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is
672 the one returned from 2k) */
674 if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED))
675 goto done;
677 /* Copy result into array. The talloc system will take
678 care of freeing the temporary arrays later on. */
680 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
681 tmp_num_names);
683 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
684 tmp_num_names);
686 total_names += tmp_num_names;
689 *num_names = total_names;
691 result = NT_STATUS_OK;
693 done:
694 if (got_group_pol)
695 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
697 if (got_dom_pol)
698 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
700 return result;
703 #ifdef HAVE_LDAP
705 #include <ldap.h>
707 static int get_ldap_seq(const char *server, int port, uint32 *seq)
709 int ret = -1;
710 struct timeval to;
711 char *attrs[] = {"highestCommittedUSN", NULL};
712 LDAPMessage *res = NULL;
713 char **values = NULL;
714 LDAP *ldp = NULL;
716 *seq = DOM_SEQUENCE_NONE;
719 * Parameterised (5) second timeout on open. This is needed as the search timeout
720 * doesn't seem to apply to doing an open as well. JRA.
723 if ((ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout())) == NULL)
724 return -1;
726 /* Timeout if no response within 20 seconds. */
727 to.tv_sec = 10;
728 to.tv_usec = 0;
730 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res))
731 goto done;
733 if (ldap_count_entries(ldp, res) != 1)
734 goto done;
736 values = ldap_get_values(ldp, res, "highestCommittedUSN");
737 if (!values || !values[0])
738 goto done;
740 *seq = atoi(values[0]);
741 ret = 0;
743 done:
745 if (values)
746 ldap_value_free(values);
747 if (res)
748 ldap_msgfree(res);
749 if (ldp)
750 ldap_unbind(ldp);
751 return ret;
754 /**********************************************************************
755 Get the sequence number for a Windows AD native mode domain using
756 LDAP queries
757 **********************************************************************/
759 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
761 int ret = -1;
762 int i, port = LDAP_PORT;
763 struct ip_service *ip_list = NULL;
764 int count;
766 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
767 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
768 return False;
771 /* Finally return first DC that we can contact */
773 for (i = 0; i < count; i++) {
774 fstring ipstr;
776 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
777 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
779 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
781 if (is_zero_ip(ip_list[i].ip))
782 continue;
784 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
785 goto done;
787 /* add to failed connection cache */
788 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
791 done:
792 if ( ret == 0 ) {
793 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n",
794 domain, inet_ntoa(ip_list[i].ip), port));
797 SAFE_FREE(ip_list);
799 return ret;
802 #endif /* HAVE_LDAP */
804 /* find the sequence number for a domain */
805 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
807 TALLOC_CTX *mem_ctx;
808 CLI_POLICY_HND *hnd;
809 SAM_UNK_CTR ctr;
810 uint16 switch_value = 2;
811 NTSTATUS result;
812 POLICY_HND dom_pol;
813 BOOL got_dom_pol = False;
814 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
815 int retry;
817 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
819 *seq = DOM_SEQUENCE_NONE;
821 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
822 return NT_STATUS_NO_MEMORY;
824 retry = 0;
825 do {
826 #ifdef HAVE_LDAP
827 if ( domain->native_mode )
829 DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
831 if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {
832 result = NT_STATUS_OK;
833 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
834 domain->name, *seq));
835 goto done;
838 DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
839 domain->name ));
841 #endif /* HAVE_LDAP */
842 /* Get sam handle */
843 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
844 goto done;
846 /* Get domain handle */
847 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
848 des_access, &domain->sid, &dom_pol);
849 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
851 if (!NT_STATUS_IS_OK(result))
852 goto done;
854 got_dom_pol = True;
856 /* Query domain info */
858 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
859 switch_value, &ctr);
861 if (NT_STATUS_IS_OK(result)) {
862 *seq = ctr.info.inf2.seq_num;
863 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
864 } else {
865 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
866 (unsigned)*seq, domain->name ));
869 done:
871 if (got_dom_pol)
872 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
874 talloc_destroy(mem_ctx);
876 return result;
879 /* get a list of trusted domains */
880 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
881 TALLOC_CTX *mem_ctx,
882 uint32 *num_domains,
883 char ***names,
884 char ***alt_names,
885 DOM_SID **dom_sids)
887 CLI_POLICY_HND *hnd;
888 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
889 uint32 enum_ctx = 0;
890 int retry;
892 DEBUG(3,("rpc: trusted_domains\n"));
894 *num_domains = 0;
895 *alt_names = NULL;
897 retry = 0;
898 do {
899 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
900 goto done;
902 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
903 &hnd->pol, &enum_ctx,
904 num_domains, names, dom_sids);
905 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
907 done:
908 return result;
911 /* find the domain sid for a domain */
912 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
914 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
915 TALLOC_CTX *mem_ctx;
916 CLI_POLICY_HND *hnd;
917 char *level5_dom;
918 DOM_SID *alloc_sid;
919 int retry;
921 DEBUG(3,("rpc: domain_sid\n"));
923 if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
924 return NT_STATUS_NO_MEMORY;
926 retry = 0;
927 do {
928 /* Get lsa handle */
929 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
930 goto done;
932 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
933 &hnd->pol, 0x05, &level5_dom, &alloc_sid);
934 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
936 if (NT_STATUS_IS_OK(result)) {
937 if (alloc_sid) {
938 sid_copy(sid, alloc_sid);
939 } else {
940 result = NT_STATUS_NO_MEMORY;
944 done:
945 talloc_destroy(mem_ctx);
946 return result;
949 /* find alternate names list for the domain - none for rpc */
950 static NTSTATUS alternate_name(struct winbindd_domain *domain)
952 return NT_STATUS_OK;
956 /* the rpc backend methods are exposed via this structure */
957 struct winbindd_methods msrpc_methods = {
958 False,
959 query_user_list,
960 enum_dom_groups,
961 enum_local_groups,
962 msrpc_name_to_sid,
963 msrpc_sid_to_name,
964 query_user,
965 lookup_usergroups,
966 lookup_groupmem,
967 sequence_number,
968 trusted_domains,
969 domain_sid,
970 alternate_name