r7415: * big change -- volker's new async winbindd from trunk
[Samba/gbeck.git] / source / nsswitch / winbindd_rpc.c
blob2b4c020d889a54e82245a8b52735fb3268738259
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Volker Lendecke 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
26 #include "winbindd.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
32 /* Query display info for a domain. This returns enough information plus a
33 bit extra to give an overview of domain users for the User Manager
34 application. */
35 static NTSTATUS query_user_list(struct winbindd_domain *domain,
36 TALLOC_CTX *mem_ctx,
37 uint32 *num_entries,
38 WINBIND_USERINFO **info)
40 NTSTATUS result;
41 POLICY_HND dom_pol;
42 unsigned int i, start_idx;
43 uint32 loop_count;
44 struct rpc_pipe_client *cli;
46 DEBUG(3,("rpc: query_user_list\n"));
48 *num_entries = 0;
49 *info = NULL;
51 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
52 if (!NT_STATUS_IS_OK(result))
53 return result;
55 i = start_idx = 0;
56 loop_count = 0;
58 do {
59 TALLOC_CTX *ctx2;
60 uint32 num_dom_users, j;
61 uint32 max_entries, max_size;
62 SAM_DISPINFO_CTR ctr;
63 SAM_DISPINFO_1 info1;
65 ZERO_STRUCT( ctr );
66 ZERO_STRUCT( info1 );
67 ctr.sam.info1 = &info1;
69 if (!(ctx2 = talloc_init("winbindd enum_users")))
70 return NT_STATUS_NO_MEMORY;
72 /* this next bit is copied from net_user_list_internal() */
74 get_query_dispinfo_params(loop_count, &max_entries,
75 &max_size);
77 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol,
78 &start_idx, 1,
79 &num_dom_users,
80 max_entries, max_size,
81 &ctr);
83 loop_count++;
85 *num_entries += num_dom_users;
87 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
88 *num_entries);
90 if (!(*info)) {
91 talloc_destroy(ctx2);
92 return NT_STATUS_NO_MEMORY;
95 for (j = 0; j < num_dom_users; i++, j++) {
96 fstring username, fullname;
97 uint32 rid = ctr.sam.info1->sam[j].rid_user;
99 unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
100 unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
102 (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
103 (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
104 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
106 /* For the moment we set the primary group for
107 every user to be the Domain Users group.
108 There are serious problems with determining
109 the actual primary group for large domains.
110 This should really be made into a 'winbind
111 force group' smb.conf parameter or
112 something like that. */
114 sid_compose(&(*info)[i].group_sid, &domain->sid,
115 DOMAIN_GROUP_RID_USERS);
118 talloc_destroy(ctx2);
120 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
122 return result;
125 /* list all domain groups */
126 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
127 TALLOC_CTX *mem_ctx,
128 uint32 *num_entries,
129 struct acct_info **info)
131 POLICY_HND dom_pol;
132 NTSTATUS status;
133 uint32 start = 0;
134 struct rpc_pipe_client *cli;
136 *num_entries = 0;
137 *info = NULL;
139 DEBUG(3,("rpc: enum_dom_groups\n"));
141 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
142 if (!NT_STATUS_IS_OK(status))
143 return status;
145 do {
146 struct acct_info *info2 = NULL;
147 uint32 count = 0;
148 TALLOC_CTX *mem_ctx2;
150 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
152 /* start is updated by this call. */
153 status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
154 &start,
155 0xFFFF, /* buffer size? */
156 &info2, &count);
158 if (!NT_STATUS_IS_OK(status) &&
159 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
160 talloc_destroy(mem_ctx2);
161 break;
164 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
165 struct acct_info,
166 (*num_entries) + count);
167 if (! *info) {
168 talloc_destroy(mem_ctx2);
169 status = NT_STATUS_NO_MEMORY;
170 break;
173 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
174 (*num_entries) += count;
175 talloc_destroy(mem_ctx2);
176 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
178 return NT_STATUS_OK;
181 /* List all domain groups */
183 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
184 TALLOC_CTX *mem_ctx,
185 uint32 *num_entries,
186 struct acct_info **info)
188 POLICY_HND dom_pol;
189 NTSTATUS result;
190 struct rpc_pipe_client *cli;
192 *num_entries = 0;
193 *info = NULL;
195 DEBUG(3,("rpc: enum_local_groups\n"));
197 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
198 if (!NT_STATUS_IS_OK(result))
199 return result;
201 do {
202 struct acct_info *info2 = NULL;
203 uint32 count = 0, start = *num_entries;
204 TALLOC_CTX *mem_ctx2;
206 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
208 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
209 &start, 0xFFFF, &info2,
210 &count);
212 if (!NT_STATUS_IS_OK(result) &&
213 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
215 talloc_destroy(mem_ctx2);
216 return result;
219 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
220 struct acct_info,
221 (*num_entries) + count);
222 if (! *info) {
223 talloc_destroy(mem_ctx2);
224 return NT_STATUS_NO_MEMORY;
227 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
228 (*num_entries) += count;
229 talloc_destroy(mem_ctx2);
231 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
233 return NT_STATUS_OK;
236 /* convert a single name to a sid in a domain */
237 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
238 TALLOC_CTX *mem_ctx,
239 const char *domain_name,
240 const char *name,
241 DOM_SID *sid,
242 enum SID_NAME_USE *type)
244 NTSTATUS result;
245 DOM_SID *sids = NULL;
246 uint32 *types = NULL;
247 const char *full_name;
248 struct rpc_pipe_client *cli;
249 POLICY_HND lsa_policy;
251 if(name == NULL || *name=='\0') {
252 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name));
253 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
254 } else {
255 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name, name));
256 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
258 if (!full_name) {
259 DEBUG(0, ("talloc_asprintf failed!\n"));
260 return NT_STATUS_NO_MEMORY;
263 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name?name:"", domain_name ));
265 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
266 if (!NT_STATUS_IS_OK(result))
267 return result;
269 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
270 &full_name, &sids, &types);
272 if (!NT_STATUS_IS_OK(result))
273 return result;
275 /* Return rid and type if lookup successful */
277 sid_copy(sid, &sids[0]);
278 *type = (enum SID_NAME_USE)types[0];
280 return NT_STATUS_OK;
284 convert a domain SID to a user or group name
286 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
287 TALLOC_CTX *mem_ctx,
288 const DOM_SID *sid,
289 char **domain_name,
290 char **name,
291 enum SID_NAME_USE *type)
293 char **domains;
294 char **names;
295 uint32 *types;
296 NTSTATUS result;
297 struct rpc_pipe_client *cli;
298 POLICY_HND lsa_policy;
300 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
301 domain->name ));
303 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
304 if (!NT_STATUS_IS_OK(result))
305 return result;
307 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
308 1, sid, &domains, &names, &types);
309 if (!NT_STATUS_IS_OK(result))
310 return result;
312 *type = (enum SID_NAME_USE)types[0];
313 *domain_name = domains[0];
314 *name = names[0];
315 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
316 return NT_STATUS_OK;
319 /* Lookup user information from a rid or username. */
320 static NTSTATUS query_user(struct winbindd_domain *domain,
321 TALLOC_CTX *mem_ctx,
322 const DOM_SID *user_sid,
323 WINBIND_USERINFO *user_info)
325 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
326 POLICY_HND dom_pol, user_pol;
327 SAM_USERINFO_CTR *ctr;
328 fstring sid_string;
329 uint32 user_rid;
330 NET_USER_INFO_3 *user;
331 struct rpc_pipe_client *cli;
333 DEBUG(3,("rpc: query_user rid=%s\n",
334 sid_to_string(sid_string, user_sid)));
336 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
337 return NT_STATUS_UNSUCCESSFUL;
339 /* try netsamlogon cache first */
341 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
344 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
345 sid_string_static(user_sid)));
347 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
348 sid_compose(&user_info->group_sid, &domain->sid,
349 user->group_rid);
351 user_info->acct_name = unistr2_tdup(mem_ctx,
352 &user->uni_user_name);
353 user_info->full_name = unistr2_tdup(mem_ctx,
354 &user->uni_full_name);
356 SAFE_FREE(user);
358 return NT_STATUS_OK;
361 /* no cache; hit the wire */
363 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
364 if (!NT_STATUS_IS_OK(result))
365 return result;
367 /* Get user handle */
368 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
369 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
370 &user_pol);
372 if (!NT_STATUS_IS_OK(result))
373 return result;
375 /* Get user info */
376 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
377 0x15, &ctr);
379 rpccli_samr_close(cli, mem_ctx, &user_pol);
381 if (!NT_STATUS_IS_OK(result))
382 return result;
384 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
385 sid_compose(&user_info->group_sid, &domain->sid,
386 ctr->info.id21->group_rid);
387 user_info->acct_name = unistr2_tdup(mem_ctx,
388 &ctr->info.id21->uni_user_name);
389 user_info->full_name = unistr2_tdup(mem_ctx,
390 &ctr->info.id21->uni_full_name);
392 return NT_STATUS_OK;
395 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
396 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
397 TALLOC_CTX *mem_ctx,
398 const DOM_SID *user_sid,
399 uint32 *num_groups, DOM_SID **user_grpsids)
401 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
402 POLICY_HND dom_pol, user_pol;
403 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
404 DOM_GID *user_groups;
405 unsigned int i;
406 fstring sid_string;
407 uint32 user_rid;
408 NET_USER_INFO_3 *user;
409 struct rpc_pipe_client *cli;
411 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
412 sid_to_string(sid_string, user_sid)));
414 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
415 return NT_STATUS_UNSUCCESSFUL;
417 *num_groups = 0;
418 *user_grpsids = NULL;
420 /* so lets see if we have a cached user_info_3 */
422 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
424 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
425 sid_string_static(user_sid)));
427 *num_groups = user->num_groups;
429 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
430 for (i=0;i<(*num_groups);i++) {
431 sid_copy(&((*user_grpsids)[i]), &domain->sid);
432 sid_append_rid(&((*user_grpsids)[i]),
433 user->gids[i].g_rid);
436 SAFE_FREE(user);
438 return NT_STATUS_OK;
441 /* no cache; hit the wire */
443 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
444 if (!NT_STATUS_IS_OK(result))
445 return result;
447 /* Get user handle */
448 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
449 des_access, user_rid, &user_pol);
451 if (!NT_STATUS_IS_OK(result))
452 return result;
454 /* Query user rids */
455 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
456 num_groups, &user_groups);
458 rpccli_samr_close(cli, mem_ctx, &user_pol);
460 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
461 return result;
463 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
464 if (!(*user_grpsids))
465 return NT_STATUS_NO_MEMORY;
467 for (i=0;i<(*num_groups);i++) {
468 sid_copy(&((*user_grpsids)[i]), &domain->sid);
469 sid_append_rid(&((*user_grpsids)[i]),
470 user_groups[i].g_rid);
473 return NT_STATUS_OK;
476 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
477 TALLOC_CTX *mem_ctx,
478 uint32 num_sids, const DOM_SID *sids,
479 uint32 *num_aliases, uint32 **alias_rids)
481 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
482 POLICY_HND dom_pol;
483 DOM_SID2 *sid2;
484 int i;
485 struct rpc_pipe_client *cli;
487 *num_aliases = 0;
488 *alias_rids = NULL;
490 DEBUG(3,("rpc: lookup_useraliases\n"));
492 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
493 if (!NT_STATUS_IS_OK(result))
494 return result;
496 sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
498 if (sid2 == NULL)
499 return NT_STATUS_NO_MEMORY;
501 for (i=0; i<num_sids; i++) {
502 sid_copy(&sid2[i].sid, &sids[i]);
503 sid2[i].num_auths = sid2[i].sid.num_auths;
506 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
507 num_sids, sid2,
508 num_aliases, alias_rids);
510 return result;
514 /* Lookup group membership given a rid. */
515 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
516 TALLOC_CTX *mem_ctx,
517 const DOM_SID *group_sid, uint32 *num_names,
518 DOM_SID **sid_mem, char ***names,
519 uint32 **name_types)
521 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
522 uint32 i, total_names = 0;
523 POLICY_HND dom_pol, group_pol;
524 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
525 uint32 *rid_mem = NULL;
526 uint32 group_rid;
527 unsigned int j;
528 fstring sid_string;
529 struct rpc_pipe_client *cli;
531 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
532 sid_to_string(sid_string, group_sid)));
534 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
535 return NT_STATUS_UNSUCCESSFUL;
537 *num_names = 0;
539 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
540 if (!NT_STATUS_IS_OK(result))
541 return result;
543 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
544 des_access, group_rid, &group_pol);
546 if (!NT_STATUS_IS_OK(result))
547 return result;
549 /* Step #1: Get a list of user rids that are the members of the
550 group. */
552 result = rpccli_samr_query_groupmem(cli, mem_ctx,
553 &group_pol, num_names, &rid_mem,
554 name_types);
556 rpccli_samr_close(cli, mem_ctx, &group_pol);
558 if (!NT_STATUS_IS_OK(result))
559 return result;
561 if (!*num_names) {
562 names = NULL;
563 name_types = NULL;
564 sid_mem = NULL;
565 return NT_STATUS_OK;
568 /* Step #2: Convert list of rids into list of usernames. Do this
569 in bunches of ~1000 to avoid crashing NT4. It looks like there
570 is a buffer overflow or something like that lurking around
571 somewhere. */
573 #define MAX_LOOKUP_RIDS 900
575 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
576 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
577 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
579 for (j=0;j<(*num_names);j++)
580 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
582 if (*num_names>0 && (!*names || !*name_types))
583 return NT_STATUS_NO_MEMORY;
585 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
586 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
587 uint32 tmp_num_names = 0;
588 char **tmp_names = NULL;
589 uint32 *tmp_types = NULL;
591 /* Lookup a chunk of rids */
593 result = rpccli_samr_lookup_rids(cli, mem_ctx,
594 &dom_pol,
595 num_lookup_rids,
596 &rid_mem[i],
597 &tmp_num_names,
598 &tmp_names, &tmp_types);
600 /* see if we have a real error (and yes the
601 STATUS_SOME_UNMAPPED is the one returned from 2k) */
603 if (!NT_STATUS_IS_OK(result) &&
604 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
605 return result;
607 /* Copy result into array. The talloc system will take
608 care of freeing the temporary arrays later on. */
610 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
611 tmp_num_names);
613 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
614 tmp_num_names);
616 total_names += tmp_num_names;
619 *num_names = total_names;
621 return NT_STATUS_OK;
624 #ifdef HAVE_LDAP
626 #include <ldap.h>
628 static int get_ldap_seq(const char *server, int port, uint32 *seq)
630 int ret = -1;
631 struct timeval to;
632 const char *attrs[] = {"highestCommittedUSN", NULL};
633 LDAPMessage *res = NULL;
634 char **values = NULL;
635 LDAP *ldp = NULL;
637 *seq = DOM_SEQUENCE_NONE;
640 * Parameterised (5) second timeout on open. This is needed as the
641 * search timeout doesn't seem to apply to doing an open as well. JRA.
644 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
645 if (ldp == NULL)
646 return -1;
648 /* Timeout if no response within 20 seconds. */
649 to.tv_sec = 10;
650 to.tv_usec = 0;
652 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
653 CONST_DISCARD(char **, attrs), 0, &to, &res))
654 goto done;
656 if (ldap_count_entries(ldp, res) != 1)
657 goto done;
659 values = ldap_get_values(ldp, res, "highestCommittedUSN");
660 if (!values || !values[0])
661 goto done;
663 *seq = atoi(values[0]);
664 ret = 0;
666 done:
668 if (values)
669 ldap_value_free(values);
670 if (res)
671 ldap_msgfree(res);
672 if (ldp)
673 ldap_unbind(ldp);
674 return ret;
677 /**********************************************************************
678 Get the sequence number for a Windows AD native mode domain using
679 LDAP queries
680 **********************************************************************/
682 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
684 int ret = -1;
685 int i, port = LDAP_PORT;
686 struct ip_service *ip_list = NULL;
687 int count;
689 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
690 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
691 return False;
694 /* Finally return first DC that we can contact */
696 for (i = 0; i < count; i++) {
697 fstring ipstr;
699 /* since the is an LDAP lookup, default to the LDAP_PORT is
700 * not set */
701 port = (ip_list[i].port!= PORT_NONE) ?
702 ip_list[i].port : LDAP_PORT;
704 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
706 if (is_zero_ip(ip_list[i].ip))
707 continue;
709 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
710 goto done;
712 /* add to failed connection cache */
713 add_failed_connection_entry( domain, ipstr,
714 NT_STATUS_UNSUCCESSFUL );
717 done:
718 if ( ret == 0 ) {
719 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
720 "number for Domain (%s) from DC (%s:%d)\n",
721 domain, inet_ntoa(ip_list[i].ip), port));
724 SAFE_FREE(ip_list);
726 return ret;
729 #endif /* HAVE_LDAP */
731 /* find the sequence number for a domain */
732 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
734 TALLOC_CTX *mem_ctx;
735 SAM_UNK_CTR ctr;
736 NTSTATUS result;
737 POLICY_HND dom_pol;
738 BOOL got_seq_num = False;
739 int retry;
740 struct rpc_pipe_client *cli;
742 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
744 *seq = DOM_SEQUENCE_NONE;
746 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
747 return NT_STATUS_NO_MEMORY;
749 retry = 0;
751 #ifdef HAVE_LDAP
752 if ( domain->native_mode )
754 int res;
756 DEBUG(8,("using get_ldap_seq() to retrieve the "
757 "sequence number\n"));
759 res = get_ldap_sequence_number( domain->name, seq );
760 if (res == 0)
762 result = NT_STATUS_OK;
763 DEBUG(10,("domain_sequence_number: LDAP for "
764 "domain %s is %u\n",
765 domain->name, *seq));
766 goto done;
769 DEBUG(10,("domain_sequence_number: failed to get LDAP "
770 "sequence number for domain %s\n",
771 domain->name ));
773 #endif /* HAVE_LDAP */
775 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
776 if (!NT_STATUS_IS_OK(result)) {
777 goto done;
780 /* Query domain info */
782 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
784 if (NT_STATUS_IS_OK(result)) {
785 *seq = ctr.info.inf8.seq_num.low;
786 got_seq_num = True;
787 goto seq_num;
790 /* retry with info-level 2 in case the dc does not support info-level 8
791 * (like all older samba2 and samba3 dc's - Guenther */
793 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
795 if (NT_STATUS_IS_OK(result)) {
796 *seq = ctr.info.inf2.seq_num.low;
797 got_seq_num = True;
800 seq_num:
801 if (got_seq_num) {
802 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
803 domain->name, (unsigned)*seq));
804 } else {
805 DEBUG(10,("domain_sequence_number: failed to get sequence "
806 "number (%u) for domain %s\n",
807 (unsigned)*seq, domain->name ));
810 done:
812 talloc_destroy(mem_ctx);
814 return result;
817 /* get a list of trusted domains */
818 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
819 TALLOC_CTX *mem_ctx,
820 uint32 *num_domains,
821 char ***names,
822 char ***alt_names,
823 DOM_SID **dom_sids)
825 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
826 uint32 enum_ctx = 0;
827 struct rpc_pipe_client *cli;
828 POLICY_HND lsa_policy;
830 DEBUG(3,("rpc: trusted_domains\n"));
832 *num_domains = 0;
833 *names = NULL;
834 *alt_names = NULL;
835 *dom_sids = NULL;
837 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
838 if (!NT_STATUS_IS_OK(result))
839 return result;
841 result = STATUS_MORE_ENTRIES;
843 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
844 uint32 start_idx, num;
845 char **tmp_names;
846 DOM_SID *tmp_sids;
847 int i;
849 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
850 &lsa_policy, &enum_ctx,
851 &num, &tmp_names,
852 &tmp_sids);
854 if (!NT_STATUS_IS_OK(result) &&
855 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
856 break;
858 start_idx = *num_domains;
859 *num_domains += num;
860 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
861 char *, *num_domains);
862 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
863 DOM_SID, *num_domains);
864 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
865 char *, *num_domains);
866 if ((*names == NULL) || (*dom_sids == NULL) ||
867 (*alt_names == NULL))
868 return NT_STATUS_NO_MEMORY;
870 for (i=0; i<num; i++) {
871 (*names)[start_idx+i] = tmp_names[i];
872 (*dom_sids)[start_idx+i] = tmp_sids[i];
873 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
876 return result;
879 /* find alternate names list for the domain - none for rpc */
880 static NTSTATUS alternate_name(struct winbindd_domain *domain)
882 return NT_STATUS_OK;
886 /* the rpc backend methods are exposed via this structure */
887 struct winbindd_methods msrpc_methods = {
888 False,
889 query_user_list,
890 enum_dom_groups,
891 enum_local_groups,
892 msrpc_name_to_sid,
893 msrpc_sid_to_name,
894 query_user,
895 lookup_usergroups,
896 msrpc_lookup_useraliases,
897 lookup_groupmem,
898 sequence_number,
899 trusted_domains,
900 alternate_name