r8839: adding patches from Marcin. Have to still work on
[Samba.git] / source / nsswitch / winbindd_rpc.c
blob63b8bb8cc49369fd7a8e0ca22f19747a3b5dd5a9
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 (*info)[i].homedir = NULL;
105 (*info)[i].shell = NULL;
106 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
108 /* For the moment we set the primary group for
109 every user to be the Domain Users group.
110 There are serious problems with determining
111 the actual primary group for large domains.
112 This should really be made into a 'winbind
113 force group' smb.conf parameter or
114 something like that. */
116 sid_compose(&(*info)[i].group_sid, &domain->sid,
117 DOMAIN_GROUP_RID_USERS);
120 talloc_destroy(ctx2);
122 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
124 return result;
127 /* list all domain groups */
128 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
129 TALLOC_CTX *mem_ctx,
130 uint32 *num_entries,
131 struct acct_info **info)
133 POLICY_HND dom_pol;
134 NTSTATUS status;
135 uint32 start = 0;
136 struct rpc_pipe_client *cli;
138 *num_entries = 0;
139 *info = NULL;
141 DEBUG(3,("rpc: enum_dom_groups\n"));
143 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
144 if (!NT_STATUS_IS_OK(status))
145 return status;
147 do {
148 struct acct_info *info2 = NULL;
149 uint32 count = 0;
150 TALLOC_CTX *mem_ctx2;
152 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
154 /* start is updated by this call. */
155 status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
156 &start,
157 0xFFFF, /* buffer size? */
158 &info2, &count);
160 if (!NT_STATUS_IS_OK(status) &&
161 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
162 talloc_destroy(mem_ctx2);
163 break;
166 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
167 struct acct_info,
168 (*num_entries) + count);
169 if (! *info) {
170 talloc_destroy(mem_ctx2);
171 status = NT_STATUS_NO_MEMORY;
172 break;
175 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
176 (*num_entries) += count;
177 talloc_destroy(mem_ctx2);
178 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
180 return NT_STATUS_OK;
183 /* List all domain groups */
185 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
186 TALLOC_CTX *mem_ctx,
187 uint32 *num_entries,
188 struct acct_info **info)
190 POLICY_HND dom_pol;
191 NTSTATUS result;
192 struct rpc_pipe_client *cli;
194 *num_entries = 0;
195 *info = NULL;
197 DEBUG(3,("rpc: enum_local_groups\n"));
199 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
200 if (!NT_STATUS_IS_OK(result))
201 return result;
203 do {
204 struct acct_info *info2 = NULL;
205 uint32 count = 0, start = *num_entries;
206 TALLOC_CTX *mem_ctx2;
208 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
210 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
211 &start, 0xFFFF, &info2,
212 &count);
214 if (!NT_STATUS_IS_OK(result) &&
215 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
217 talloc_destroy(mem_ctx2);
218 return result;
221 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
222 struct acct_info,
223 (*num_entries) + count);
224 if (! *info) {
225 talloc_destroy(mem_ctx2);
226 return NT_STATUS_NO_MEMORY;
229 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
230 (*num_entries) += count;
231 talloc_destroy(mem_ctx2);
233 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
235 return NT_STATUS_OK;
238 /* convert a single name to a sid in a domain */
239 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
240 TALLOC_CTX *mem_ctx,
241 const char *domain_name,
242 const char *name,
243 DOM_SID *sid,
244 enum SID_NAME_USE *type)
246 NTSTATUS result;
247 DOM_SID *sids = NULL;
248 uint32 *types = NULL;
249 const char *full_name;
250 struct rpc_pipe_client *cli;
251 POLICY_HND lsa_policy;
253 if(name == NULL || *name=='\0') {
254 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name));
255 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
256 } else {
257 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name, name));
258 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
260 if (!full_name) {
261 DEBUG(0, ("talloc_asprintf failed!\n"));
262 return NT_STATUS_NO_MEMORY;
265 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name?name:"", domain_name ));
267 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
268 if (!NT_STATUS_IS_OK(result))
269 return result;
271 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
272 &full_name, &sids, &types);
274 if (!NT_STATUS_IS_OK(result))
275 return result;
277 /* Return rid and type if lookup successful */
279 sid_copy(sid, &sids[0]);
280 *type = (enum SID_NAME_USE)types[0];
282 return NT_STATUS_OK;
286 convert a domain SID to a user or group name
288 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
289 TALLOC_CTX *mem_ctx,
290 const DOM_SID *sid,
291 char **domain_name,
292 char **name,
293 enum SID_NAME_USE *type)
295 char **domains;
296 char **names;
297 uint32 *types;
298 NTSTATUS result;
299 struct rpc_pipe_client *cli;
300 POLICY_HND lsa_policy;
302 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
303 domain->name ));
305 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
306 if (!NT_STATUS_IS_OK(result))
307 return result;
309 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
310 1, sid, &domains, &names, &types);
311 if (!NT_STATUS_IS_OK(result))
312 return result;
314 *type = (enum SID_NAME_USE)types[0];
315 *domain_name = domains[0];
316 *name = names[0];
317 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
318 return NT_STATUS_OK;
321 NTSTATUS msrpc_lookupsids(struct winbindd_domain *domain,
322 TALLOC_CTX *mem_ctx,
323 uint32 num_sids, const DOM_SID *sids,
324 char ***domain_names,
325 char ***names,
326 enum SID_NAME_USE **types)
328 NTSTATUS result;
329 struct rpc_pipe_client *cli;
330 POLICY_HND lsa_policy;
332 DEBUG(3,("lookupsids [rpc] for domain %s\n", domain->name ));
334 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
335 if (!NT_STATUS_IS_OK(result))
336 return result;
338 return rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
339 num_sids, sids, domain_names, names,
340 types);
343 /* Lookup user information from a rid or username. */
344 static NTSTATUS query_user(struct winbindd_domain *domain,
345 TALLOC_CTX *mem_ctx,
346 const DOM_SID *user_sid,
347 WINBIND_USERINFO *user_info)
349 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
350 POLICY_HND dom_pol, user_pol;
351 SAM_USERINFO_CTR *ctr;
352 fstring sid_string;
353 uint32 user_rid;
354 NET_USER_INFO_3 *user;
355 struct rpc_pipe_client *cli;
357 DEBUG(3,("rpc: query_user rid=%s\n",
358 sid_to_string(sid_string, user_sid)));
360 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
361 return NT_STATUS_UNSUCCESSFUL;
363 /* try netsamlogon cache first */
365 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
368 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
369 sid_string_static(user_sid)));
371 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
372 sid_compose(&user_info->group_sid, &domain->sid,
373 user->group_rid);
375 user_info->acct_name = unistr2_tdup(mem_ctx,
376 &user->uni_user_name);
377 user_info->full_name = unistr2_tdup(mem_ctx,
378 &user->uni_full_name);
380 user_info->homedir = NULL;
381 user_info->shell = NULL;
383 SAFE_FREE(user);
385 return NT_STATUS_OK;
388 /* no cache; hit the wire */
390 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
391 if (!NT_STATUS_IS_OK(result))
392 return result;
394 /* Get user handle */
395 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
396 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
397 &user_pol);
399 if (!NT_STATUS_IS_OK(result))
400 return result;
402 /* Get user info */
403 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
404 0x15, &ctr);
406 rpccli_samr_close(cli, mem_ctx, &user_pol);
408 if (!NT_STATUS_IS_OK(result))
409 return result;
411 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
412 sid_compose(&user_info->group_sid, &domain->sid,
413 ctr->info.id21->group_rid);
414 user_info->acct_name = unistr2_tdup(mem_ctx,
415 &ctr->info.id21->uni_user_name);
416 user_info->full_name = unistr2_tdup(mem_ctx,
417 &ctr->info.id21->uni_full_name);
418 user_info->homedir = NULL;
419 user_info->shell = NULL;
421 return NT_STATUS_OK;
424 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
425 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
426 TALLOC_CTX *mem_ctx,
427 const DOM_SID *user_sid,
428 uint32 *num_groups, DOM_SID **user_grpsids)
430 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
431 POLICY_HND dom_pol, user_pol;
432 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
433 DOM_GID *user_groups;
434 unsigned int i;
435 fstring sid_string;
436 uint32 user_rid;
437 NET_USER_INFO_3 *user;
438 struct rpc_pipe_client *cli;
440 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
441 sid_to_string(sid_string, user_sid)));
443 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
444 return NT_STATUS_UNSUCCESSFUL;
446 *num_groups = 0;
447 *user_grpsids = NULL;
449 /* so lets see if we have a cached user_info_3 */
451 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
453 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
454 sid_string_static(user_sid)));
456 *num_groups = user->num_groups;
458 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
459 for (i=0;i<(*num_groups);i++) {
460 sid_copy(&((*user_grpsids)[i]), &domain->sid);
461 sid_append_rid(&((*user_grpsids)[i]),
462 user->gids[i].g_rid);
465 SAFE_FREE(user);
467 return NT_STATUS_OK;
470 /* no cache; hit the wire */
472 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
473 if (!NT_STATUS_IS_OK(result))
474 return result;
476 /* Get user handle */
477 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
478 des_access, user_rid, &user_pol);
480 if (!NT_STATUS_IS_OK(result))
481 return result;
483 /* Query user rids */
484 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
485 num_groups, &user_groups);
487 rpccli_samr_close(cli, mem_ctx, &user_pol);
489 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
490 return result;
492 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
493 if (!(*user_grpsids))
494 return NT_STATUS_NO_MEMORY;
496 for (i=0;i<(*num_groups);i++) {
497 sid_copy(&((*user_grpsids)[i]), &domain->sid);
498 sid_append_rid(&((*user_grpsids)[i]),
499 user_groups[i].g_rid);
502 return NT_STATUS_OK;
505 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
506 TALLOC_CTX *mem_ctx,
507 uint32 num_sids, const DOM_SID *sids,
508 uint32 *num_aliases, uint32 **alias_rids)
510 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
511 POLICY_HND dom_pol;
512 DOM_SID2 *sid2;
513 int i;
514 struct rpc_pipe_client *cli;
516 *num_aliases = 0;
517 *alias_rids = NULL;
519 DEBUG(3,("rpc: lookup_useraliases\n"));
521 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
522 if (!NT_STATUS_IS_OK(result))
523 return result;
525 sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
527 if (sid2 == NULL)
528 return NT_STATUS_NO_MEMORY;
530 for (i=0; i<num_sids; i++) {
531 sid_copy(&sid2[i].sid, &sids[i]);
532 sid2[i].num_auths = sid2[i].sid.num_auths;
535 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
536 num_sids, sid2,
537 num_aliases, alias_rids);
539 return result;
543 /* Lookup group membership given a rid. */
544 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
545 TALLOC_CTX *mem_ctx,
546 const DOM_SID *group_sid, uint32 *num_names,
547 DOM_SID **sid_mem, char ***names,
548 uint32 **name_types)
550 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
551 uint32 i, total_names = 0;
552 POLICY_HND dom_pol, group_pol;
553 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
554 uint32 *rid_mem = NULL;
555 uint32 group_rid;
556 unsigned int j;
557 fstring sid_string;
558 struct rpc_pipe_client *cli;
560 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
561 sid_to_string(sid_string, group_sid)));
563 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
564 return NT_STATUS_UNSUCCESSFUL;
566 *num_names = 0;
568 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
569 if (!NT_STATUS_IS_OK(result))
570 return result;
572 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
573 des_access, group_rid, &group_pol);
575 if (!NT_STATUS_IS_OK(result))
576 return result;
578 /* Step #1: Get a list of user rids that are the members of the
579 group. */
581 result = rpccli_samr_query_groupmem(cli, mem_ctx,
582 &group_pol, num_names, &rid_mem,
583 name_types);
585 rpccli_samr_close(cli, mem_ctx, &group_pol);
587 if (!NT_STATUS_IS_OK(result))
588 return result;
590 if (!*num_names) {
591 names = NULL;
592 name_types = NULL;
593 sid_mem = NULL;
594 return NT_STATUS_OK;
597 /* Step #2: Convert list of rids into list of usernames. Do this
598 in bunches of ~1000 to avoid crashing NT4. It looks like there
599 is a buffer overflow or something like that lurking around
600 somewhere. */
602 #define MAX_LOOKUP_RIDS 900
604 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
605 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
606 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
608 for (j=0;j<(*num_names);j++)
609 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
611 if (*num_names>0 && (!*names || !*name_types))
612 return NT_STATUS_NO_MEMORY;
614 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
615 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
616 uint32 tmp_num_names = 0;
617 char **tmp_names = NULL;
618 uint32 *tmp_types = NULL;
620 /* Lookup a chunk of rids */
622 result = rpccli_samr_lookup_rids(cli, mem_ctx,
623 &dom_pol,
624 num_lookup_rids,
625 &rid_mem[i],
626 &tmp_num_names,
627 &tmp_names, &tmp_types);
629 /* see if we have a real error (and yes the
630 STATUS_SOME_UNMAPPED is the one returned from 2k) */
632 if (!NT_STATUS_IS_OK(result) &&
633 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
634 return result;
636 /* Copy result into array. The talloc system will take
637 care of freeing the temporary arrays later on. */
639 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
640 tmp_num_names);
642 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
643 tmp_num_names);
645 total_names += tmp_num_names;
648 *num_names = total_names;
650 return NT_STATUS_OK;
653 NTSTATUS msrpc_query_aliasmem(struct winbindd_domain *domain,
654 TALLOC_CTX *mem_ctx,
655 uint32 alias_rid,
656 uint32 *num_members,
657 DOM_SID **members)
659 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
660 POLICY_HND dom_pol, alias_pol;
661 struct rpc_pipe_client *cli;
663 DEBUG(10, ("rpc: lookup_aliasmem %s, rid=%d\n", domain->name,
664 alias_rid));
666 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
667 if (!NT_STATUS_IS_OK(result)) {
668 return result;
671 result = rpccli_samr_open_alias(cli, mem_ctx, &dom_pol,
672 SEC_RIGHTS_MAXIMUM_ALLOWED,
673 alias_rid, &alias_pol);
674 if (!NT_STATUS_IS_OK(result)) {
675 return result;
678 result = rpccli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
679 num_members, members);
681 rpccli_samr_close(cli, mem_ctx, &alias_pol);
682 return result;
685 NTSTATUS msrpc_query_groupmem(struct winbindd_domain *domain,
686 TALLOC_CTX *mem_ctx,
687 uint32 group_rid,
688 uint32 *num_members,
689 uint32 **members)
691 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
692 POLICY_HND dom_pol, group_pol;
693 struct rpc_pipe_client *cli;
694 uint32 *attr;
696 DEBUG(10, ("rpc: lookup_groupmem %s, rid=%d\n", domain->name,
697 group_rid));
699 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
700 if (!NT_STATUS_IS_OK(result)) {
701 return result;
704 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
705 SEC_RIGHTS_MAXIMUM_ALLOWED,
706 group_rid, &group_pol);
707 if (!NT_STATUS_IS_OK(result)) {
708 return result;
711 result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
712 num_members, members, &attr);
714 rpccli_samr_close(cli, mem_ctx, &group_pol);
715 return result;
718 #ifdef HAVE_LDAP
720 #include <ldap.h>
722 static int get_ldap_seq(const char *server, int port, uint32 *seq)
724 int ret = -1;
725 struct timeval to;
726 const char *attrs[] = {"highestCommittedUSN", NULL};
727 LDAPMessage *res = NULL;
728 char **values = NULL;
729 LDAP *ldp = NULL;
731 *seq = DOM_SEQUENCE_NONE;
734 * Parameterised (5) second timeout on open. This is needed as the
735 * search timeout doesn't seem to apply to doing an open as well. JRA.
738 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
739 if (ldp == NULL)
740 return -1;
742 /* Timeout if no response within 20 seconds. */
743 to.tv_sec = 10;
744 to.tv_usec = 0;
746 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
747 CONST_DISCARD(char **, attrs), 0, &to, &res))
748 goto done;
750 if (ldap_count_entries(ldp, res) != 1)
751 goto done;
753 values = ldap_get_values(ldp, res, "highestCommittedUSN");
754 if (!values || !values[0])
755 goto done;
757 *seq = atoi(values[0]);
758 ret = 0;
760 done:
762 if (values)
763 ldap_value_free(values);
764 if (res)
765 ldap_msgfree(res);
766 if (ldp)
767 ldap_unbind(ldp);
768 return ret;
771 /**********************************************************************
772 Get the sequence number for a Windows AD native mode domain using
773 LDAP queries
774 **********************************************************************/
776 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
778 int ret = -1;
779 int i, port = LDAP_PORT;
780 struct ip_service *ip_list = NULL;
781 int count;
783 if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
784 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
785 return False;
788 /* Finally return first DC that we can contact */
790 for (i = 0; i < count; i++) {
791 fstring ipstr;
793 /* since the is an LDAP lookup, default to the LDAP_PORT is
794 * not set */
795 port = (ip_list[i].port!= PORT_NONE) ?
796 ip_list[i].port : LDAP_PORT;
798 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
800 if (is_zero_ip(ip_list[i].ip))
801 continue;
803 if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
804 goto done;
806 /* add to failed connection cache */
807 add_failed_connection_entry( domain, ipstr,
808 NT_STATUS_UNSUCCESSFUL );
811 done:
812 if ( ret == 0 ) {
813 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
814 "number for Domain (%s) from DC (%s:%d)\n",
815 domain, inet_ntoa(ip_list[i].ip), port));
818 SAFE_FREE(ip_list);
820 return ret;
823 #endif /* HAVE_LDAP */
825 /* find the sequence number for a domain */
826 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
828 TALLOC_CTX *mem_ctx;
829 SAM_UNK_CTR ctr;
830 NTSTATUS result;
831 POLICY_HND dom_pol;
832 BOOL got_seq_num = False;
833 int retry;
834 struct rpc_pipe_client *cli;
836 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
838 *seq = DOM_SEQUENCE_NONE;
840 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
841 return NT_STATUS_NO_MEMORY;
843 retry = 0;
845 #ifdef HAVE_LDAP
846 if ( domain->native_mode )
848 int res;
850 DEBUG(8,("using get_ldap_seq() to retrieve the "
851 "sequence number\n"));
853 res = get_ldap_sequence_number( domain->name, seq );
854 if (res == 0)
856 result = NT_STATUS_OK;
857 DEBUG(10,("domain_sequence_number: LDAP for "
858 "domain %s is %u\n",
859 domain->name, *seq));
860 goto done;
863 DEBUG(10,("domain_sequence_number: failed to get LDAP "
864 "sequence number for domain %s\n",
865 domain->name ));
867 #endif /* HAVE_LDAP */
869 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
870 if (!NT_STATUS_IS_OK(result)) {
871 goto done;
874 /* Query domain info */
876 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
878 if (NT_STATUS_IS_OK(result)) {
879 *seq = ctr.info.inf8.seq_num.low;
880 got_seq_num = True;
881 goto seq_num;
884 /* retry with info-level 2 in case the dc does not support info-level 8
885 * (like all older samba2 and samba3 dc's - Guenther */
887 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
889 if (NT_STATUS_IS_OK(result)) {
890 *seq = ctr.info.inf2.seq_num.low;
891 got_seq_num = True;
894 seq_num:
895 if (got_seq_num) {
896 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
897 domain->name, (unsigned)*seq));
898 } else {
899 DEBUG(10,("domain_sequence_number: failed to get sequence "
900 "number (%u) for domain %s\n",
901 (unsigned)*seq, domain->name ));
904 done:
906 talloc_destroy(mem_ctx);
908 return result;
911 /* get a list of trusted domains */
912 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
913 TALLOC_CTX *mem_ctx,
914 uint32 *num_domains,
915 char ***names,
916 char ***alt_names,
917 DOM_SID **dom_sids)
919 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
920 uint32 enum_ctx = 0;
921 struct rpc_pipe_client *cli;
922 POLICY_HND lsa_policy;
924 DEBUG(3,("rpc: trusted_domains\n"));
926 *num_domains = 0;
927 *names = NULL;
928 *alt_names = NULL;
929 *dom_sids = NULL;
931 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
932 if (!NT_STATUS_IS_OK(result))
933 return result;
935 result = STATUS_MORE_ENTRIES;
937 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
938 uint32 start_idx, num;
939 char **tmp_names;
940 DOM_SID *tmp_sids;
941 int i;
943 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
944 &lsa_policy, &enum_ctx,
945 &num, &tmp_names,
946 &tmp_sids);
948 if (!NT_STATUS_IS_OK(result) &&
949 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
950 break;
952 start_idx = *num_domains;
953 *num_domains += num;
954 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
955 char *, *num_domains);
956 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
957 DOM_SID, *num_domains);
958 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
959 char *, *num_domains);
960 if ((*names == NULL) || (*dom_sids == NULL) ||
961 (*alt_names == NULL))
962 return NT_STATUS_NO_MEMORY;
964 for (i=0; i<num; i++) {
965 (*names)[start_idx+i] = tmp_names[i];
966 (*dom_sids)[start_idx+i] = tmp_sids[i];
967 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
970 return result;
973 /* find alternate names list for the domain - none for rpc */
974 static NTSTATUS alternate_name(struct winbindd_domain *domain)
976 return NT_STATUS_OK;
980 /* the rpc backend methods are exposed via this structure */
981 struct winbindd_methods msrpc_methods = {
982 False,
983 query_user_list,
984 enum_dom_groups,
985 enum_local_groups,
986 msrpc_name_to_sid,
987 msrpc_sid_to_name,
988 msrpc_lookupsids,
989 query_user,
990 lookup_usergroups,
991 msrpc_lookup_useraliases,
992 lookup_groupmem,
993 msrpc_query_aliasmem,
994 msrpc_query_groupmem,
995 sequence_number,
996 trusted_domains,
997 alternate_name