[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / nsswitch / winbindd_rpc.c
blob3c79670d6359d3f74e9b452c3a712a6e7b7c069e
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 return NT_STATUS_NO_MEMORY;
174 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
175 (*num_entries) += count;
176 talloc_destroy(mem_ctx2);
177 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
179 return NT_STATUS_OK;
182 /* List all domain groups */
184 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
185 TALLOC_CTX *mem_ctx,
186 uint32 *num_entries,
187 struct acct_info **info)
189 POLICY_HND dom_pol;
190 NTSTATUS result;
191 struct rpc_pipe_client *cli;
193 *num_entries = 0;
194 *info = NULL;
196 DEBUG(3,("rpc: enum_local_groups\n"));
198 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
199 if (!NT_STATUS_IS_OK(result))
200 return result;
202 do {
203 struct acct_info *info2 = NULL;
204 uint32 count = 0, start = *num_entries;
205 TALLOC_CTX *mem_ctx2;
207 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
209 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
210 &start, 0xFFFF, &info2,
211 &count);
213 if (!NT_STATUS_IS_OK(result) &&
214 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
216 talloc_destroy(mem_ctx2);
217 return result;
220 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
221 struct acct_info,
222 (*num_entries) + count);
223 if (! *info) {
224 talloc_destroy(mem_ctx2);
225 return NT_STATUS_NO_MEMORY;
228 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
229 (*num_entries) += count;
230 talloc_destroy(mem_ctx2);
232 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
234 return NT_STATUS_OK;
237 /* convert a single name to a sid in a domain */
238 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
239 TALLOC_CTX *mem_ctx,
240 const char *domain_name,
241 const char *name,
242 DOM_SID *sid,
243 enum lsa_SidType *type)
245 NTSTATUS result;
246 DOM_SID *sids = NULL;
247 enum lsa_SidType *types = NULL;
248 char *full_name = NULL;
249 struct rpc_pipe_client *cli;
250 POLICY_HND lsa_policy;
252 if(name == NULL || *name=='\0') {
253 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name));
254 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
255 } else {
256 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name, name));
257 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
259 if (!full_name) {
260 DEBUG(0, ("talloc_asprintf failed!\n"));
261 return NT_STATUS_NO_MEMORY;
264 ws_name_return( full_name, WB_REPLACE_CHAR );
266 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
268 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
269 if (!NT_STATUS_IS_OK(result))
270 return result;
272 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
273 (const char**) &full_name, NULL, &sids, &types);
275 if (!NT_STATUS_IS_OK(result))
276 return result;
278 /* Return rid and type if lookup successful */
280 sid_copy(sid, &sids[0]);
281 *type = types[0];
283 return NT_STATUS_OK;
287 convert a domain SID to a user or group name
289 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
290 TALLOC_CTX *mem_ctx,
291 const DOM_SID *sid,
292 char **domain_name,
293 char **name,
294 enum lsa_SidType *type)
296 char **domains;
297 char **names;
298 enum lsa_SidType *types;
299 NTSTATUS result;
300 struct rpc_pipe_client *cli;
301 POLICY_HND lsa_policy;
303 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
304 domain->name ));
306 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
307 if (!NT_STATUS_IS_OK(result))
308 return result;
310 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
311 1, sid, &domains, &names, &types);
312 if (!NT_STATUS_IS_OK(result))
313 return result;
315 *type = (enum lsa_SidType)types[0];
316 *domain_name = domains[0];
317 *name = names[0];
319 ws_name_replace( *name, WB_REPLACE_CHAR );
321 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
322 return NT_STATUS_OK;
325 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
326 TALLOC_CTX *mem_ctx,
327 const DOM_SID *sid,
328 uint32 *rids,
329 size_t num_rids,
330 char **domain_name,
331 char ***names,
332 enum lsa_SidType **types)
334 char **domains;
335 NTSTATUS result;
336 struct rpc_pipe_client *cli;
337 POLICY_HND lsa_policy;
338 DOM_SID *sids;
339 size_t i;
340 char **ret_names;
342 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
344 if (num_rids) {
345 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
346 if (sids == NULL) {
347 return NT_STATUS_NO_MEMORY;
349 } else {
350 sids = NULL;
353 for (i=0; i<num_rids; i++) {
354 if (!sid_compose(&sids[i], sid, rids[i])) {
355 return NT_STATUS_INTERNAL_ERROR;
359 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
360 if (!NT_STATUS_IS_OK(result)) {
361 return result;
364 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
365 num_rids, sids, &domains,
366 names, types);
367 if (!NT_STATUS_IS_OK(result) &&
368 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
369 return result;
372 ret_names = *names;
373 for (i=0; i<num_rids; i++) {
374 if ((*types)[i] != SID_NAME_UNKNOWN) {
375 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
376 *domain_name = domains[i];
380 return result;
383 /* Lookup user information from a rid or username. */
384 static NTSTATUS query_user(struct winbindd_domain *domain,
385 TALLOC_CTX *mem_ctx,
386 const DOM_SID *user_sid,
387 WINBIND_USERINFO *user_info)
389 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
390 POLICY_HND dom_pol, user_pol;
391 SAM_USERINFO_CTR *ctr;
392 fstring sid_string;
393 uint32 user_rid;
394 NET_USER_INFO_3 *user;
395 struct rpc_pipe_client *cli;
397 DEBUG(3,("rpc: query_user sid=%s\n",
398 sid_to_string(sid_string, user_sid)));
400 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
401 return NT_STATUS_UNSUCCESSFUL;
403 /* try netsamlogon cache first */
405 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
408 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
409 sid_string_static(user_sid)));
411 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
412 sid_compose(&user_info->group_sid, &domain->sid,
413 user->group_rid);
415 user_info->acct_name = unistr2_tdup(mem_ctx,
416 &user->uni_user_name);
417 user_info->full_name = unistr2_tdup(mem_ctx,
418 &user->uni_full_name);
420 user_info->homedir = NULL;
421 user_info->shell = NULL;
422 user_info->primary_gid = (gid_t)-1;
424 TALLOC_FREE(user);
426 return NT_STATUS_OK;
429 /* no cache; hit the wire */
431 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
432 if (!NT_STATUS_IS_OK(result))
433 return result;
435 /* Get user handle */
436 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
437 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
438 &user_pol);
440 if (!NT_STATUS_IS_OK(result))
441 return result;
443 /* Get user info */
444 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
445 0x15, &ctr);
447 rpccli_samr_close(cli, mem_ctx, &user_pol);
449 if (!NT_STATUS_IS_OK(result))
450 return result;
452 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
453 sid_compose(&user_info->group_sid, &domain->sid,
454 ctr->info.id21->group_rid);
455 user_info->acct_name = unistr2_tdup(mem_ctx,
456 &ctr->info.id21->uni_user_name);
457 user_info->full_name = unistr2_tdup(mem_ctx,
458 &ctr->info.id21->uni_full_name);
459 user_info->homedir = NULL;
460 user_info->shell = NULL;
461 user_info->primary_gid = (gid_t)-1;
463 return NT_STATUS_OK;
466 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
467 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
468 TALLOC_CTX *mem_ctx,
469 const DOM_SID *user_sid,
470 uint32 *num_groups, DOM_SID **user_grpsids)
472 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
473 POLICY_HND dom_pol, user_pol;
474 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
475 DOM_GID *user_groups;
476 unsigned int i;
477 fstring sid_string;
478 uint32 user_rid;
479 struct rpc_pipe_client *cli;
481 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
482 sid_to_string(sid_string, user_sid)));
484 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
485 return NT_STATUS_UNSUCCESSFUL;
487 *num_groups = 0;
488 *user_grpsids = NULL;
490 /* so lets see if we have a cached user_info_3 */
491 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
492 num_groups, user_grpsids);
494 if (NT_STATUS_IS_OK(result)) {
495 return NT_STATUS_OK;
498 /* no cache; hit the wire */
500 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
501 if (!NT_STATUS_IS_OK(result))
502 return result;
504 /* Get user handle */
505 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
506 des_access, user_rid, &user_pol);
508 if (!NT_STATUS_IS_OK(result))
509 return result;
511 /* Query user rids */
512 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
513 num_groups, &user_groups);
515 rpccli_samr_close(cli, mem_ctx, &user_pol);
517 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
518 return result;
520 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
521 if (!(*user_grpsids))
522 return NT_STATUS_NO_MEMORY;
524 for (i=0;i<(*num_groups);i++) {
525 sid_copy(&((*user_grpsids)[i]), &domain->sid);
526 sid_append_rid(&((*user_grpsids)[i]),
527 user_groups[i].g_rid);
530 return NT_STATUS_OK;
533 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
534 TALLOC_CTX *mem_ctx,
535 uint32 num_sids, const DOM_SID *sids,
536 uint32 *num_aliases, uint32 **alias_rids)
538 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
539 POLICY_HND dom_pol;
540 DOM_SID2 *query_sids;
541 uint32 num_query_sids = 0;
542 int i;
543 struct rpc_pipe_client *cli;
544 uint32 *alias_rids_query, num_aliases_query;
545 int rangesize = MAX_SAM_ENTRIES_W2K;
546 uint32 total_sids = 0;
547 int num_queries = 1;
549 *num_aliases = 0;
550 *alias_rids = NULL;
552 DEBUG(3,("rpc: lookup_useraliases\n"));
554 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
555 if (!NT_STATUS_IS_OK(result))
556 return result;
558 do {
559 /* prepare query */
561 num_query_sids = MIN(num_sids - total_sids, rangesize);
563 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
564 num_queries, num_query_sids));
566 if (num_query_sids) {
567 query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
568 if (query_sids == NULL) {
569 return NT_STATUS_NO_MEMORY;
571 } else {
572 query_sids = NULL;
575 for (i=0; i<num_query_sids; i++) {
576 sid_copy(&query_sids[i].sid, &sids[total_sids++]);
577 query_sids[i].num_auths = query_sids[i].sid.num_auths;
580 /* do request */
582 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
583 num_query_sids, query_sids,
584 &num_aliases_query,
585 &alias_rids_query);
587 if (!NT_STATUS_IS_OK(result)) {
588 *num_aliases = 0;
589 *alias_rids = NULL;
590 TALLOC_FREE(query_sids);
591 goto done;
594 /* process output */
596 for (i=0; i<num_aliases_query; i++) {
597 size_t na = *num_aliases;
598 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
599 alias_rids, &na)) {
600 return NT_STATUS_NO_MEMORY;
602 *num_aliases = na;
605 TALLOC_FREE(query_sids);
607 num_queries++;
609 } while (total_sids < num_sids);
611 done:
612 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
613 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
615 return result;
619 /* Lookup group membership given a rid. */
620 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
621 TALLOC_CTX *mem_ctx,
622 const DOM_SID *group_sid, uint32 *num_names,
623 DOM_SID **sid_mem, char ***names,
624 uint32 **name_types)
626 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
627 uint32 i, total_names = 0;
628 POLICY_HND dom_pol, group_pol;
629 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
630 uint32 *rid_mem = NULL;
631 uint32 group_rid;
632 unsigned int j;
633 fstring sid_string;
634 struct rpc_pipe_client *cli;
635 unsigned int orig_timeout;
637 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
638 sid_to_string(sid_string, group_sid)));
640 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
641 return NT_STATUS_UNSUCCESSFUL;
643 *num_names = 0;
645 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
646 if (!NT_STATUS_IS_OK(result))
647 return result;
649 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
650 des_access, group_rid, &group_pol);
652 if (!NT_STATUS_IS_OK(result))
653 return result;
655 /* Step #1: Get a list of user rids that are the members of the
656 group. */
658 /* This call can take a long time - allow the server to time out.
659 35 seconds should do it. */
661 orig_timeout = cli_set_timeout(cli->cli, 35000);
663 result = rpccli_samr_query_groupmem(cli, mem_ctx,
664 &group_pol, num_names, &rid_mem,
665 name_types);
667 /* And restore our original timeout. */
668 cli_set_timeout(cli->cli, orig_timeout);
670 rpccli_samr_close(cli, mem_ctx, &group_pol);
672 if (!NT_STATUS_IS_OK(result))
673 return result;
675 if (!*num_names) {
676 names = NULL;
677 name_types = NULL;
678 sid_mem = NULL;
679 return NT_STATUS_OK;
682 /* Step #2: Convert list of rids into list of usernames. Do this
683 in bunches of ~1000 to avoid crashing NT4. It looks like there
684 is a buffer overflow or something like that lurking around
685 somewhere. */
687 #define MAX_LOOKUP_RIDS 900
689 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
690 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
691 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
693 for (j=0;j<(*num_names);j++)
694 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
696 if (*num_names>0 && (!*names || !*name_types))
697 return NT_STATUS_NO_MEMORY;
699 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
700 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
701 uint32 tmp_num_names = 0;
702 char **tmp_names = NULL;
703 uint32 *tmp_types = NULL;
705 /* Lookup a chunk of rids */
707 result = rpccli_samr_lookup_rids(cli, mem_ctx,
708 &dom_pol,
709 num_lookup_rids,
710 &rid_mem[i],
711 &tmp_num_names,
712 &tmp_names, &tmp_types);
714 /* see if we have a real error (and yes the
715 STATUS_SOME_UNMAPPED is the one returned from 2k) */
717 if (!NT_STATUS_IS_OK(result) &&
718 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
719 return result;
721 /* Copy result into array. The talloc system will take
722 care of freeing the temporary arrays later on. */
724 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
725 tmp_num_names);
727 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
728 tmp_num_names);
730 total_names += tmp_num_names;
733 *num_names = total_names;
735 return NT_STATUS_OK;
738 #ifdef HAVE_LDAP
740 #include <ldap.h>
742 static int get_ldap_seq(const char *server, int port, uint32 *seq)
744 int ret = -1;
745 struct timeval to;
746 const char *attrs[] = {"highestCommittedUSN", NULL};
747 LDAPMessage *res = NULL;
748 char **values = NULL;
749 LDAP *ldp = NULL;
751 *seq = DOM_SEQUENCE_NONE;
754 * Parameterised (5) second timeout on open. This is needed as the
755 * search timeout doesn't seem to apply to doing an open as well. JRA.
758 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
759 if (ldp == NULL)
760 return -1;
762 /* Timeout if no response within 20 seconds. */
763 to.tv_sec = 10;
764 to.tv_usec = 0;
766 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
767 CONST_DISCARD(char **, attrs), 0, &to, &res))
768 goto done;
770 if (ldap_count_entries(ldp, res) != 1)
771 goto done;
773 values = ldap_get_values(ldp, res, "highestCommittedUSN");
774 if (!values || !values[0])
775 goto done;
777 *seq = atoi(values[0]);
778 ret = 0;
780 done:
782 if (values)
783 ldap_value_free(values);
784 if (res)
785 ldap_msgfree(res);
786 if (ldp)
787 ldap_unbind(ldp);
788 return ret;
791 /**********************************************************************
792 Get the sequence number for a Windows AD native mode domain using
793 LDAP queries.
794 **********************************************************************/
796 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
798 int ret = -1;
799 fstring ipstr;
801 fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
802 if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
803 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
804 "number for Domain (%s) from DC (%s)\n",
805 domain->name, ipstr));
807 return ret;
810 #endif /* HAVE_LDAP */
812 /* find the sequence number for a domain */
813 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
815 TALLOC_CTX *mem_ctx;
816 SAM_UNK_CTR ctr;
817 NTSTATUS result;
818 POLICY_HND dom_pol;
819 BOOL got_seq_num = False;
820 struct rpc_pipe_client *cli;
822 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
824 *seq = DOM_SEQUENCE_NONE;
826 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
827 return NT_STATUS_NO_MEMORY;
829 #ifdef HAVE_LDAP
830 if ( domain->native_mode )
832 int res;
834 DEBUG(8,("using get_ldap_seq() to retrieve the "
835 "sequence number\n"));
837 res = get_ldap_sequence_number( domain, seq );
838 if (res == 0)
840 result = NT_STATUS_OK;
841 DEBUG(10,("domain_sequence_number: LDAP for "
842 "domain %s is %u\n",
843 domain->name, *seq));
844 goto done;
847 DEBUG(10,("domain_sequence_number: failed to get LDAP "
848 "sequence number for domain %s\n",
849 domain->name ));
851 #endif /* HAVE_LDAP */
853 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
854 if (!NT_STATUS_IS_OK(result)) {
855 goto done;
858 /* Query domain info */
860 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
862 if (NT_STATUS_IS_OK(result)) {
863 *seq = ctr.info.inf8.seq_num;
864 got_seq_num = True;
865 goto seq_num;
868 /* retry with info-level 2 in case the dc does not support info-level 8
869 * (like all older samba2 and samba3 dc's - Guenther */
871 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
873 if (NT_STATUS_IS_OK(result)) {
874 *seq = ctr.info.inf2.seq_num;
875 got_seq_num = True;
878 seq_num:
879 if (got_seq_num) {
880 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
881 domain->name, (unsigned)*seq));
882 } else {
883 DEBUG(10,("domain_sequence_number: failed to get sequence "
884 "number (%u) for domain %s\n",
885 (unsigned)*seq, domain->name ));
888 done:
890 talloc_destroy(mem_ctx);
892 return result;
895 /* get a list of trusted domains */
896 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
897 TALLOC_CTX *mem_ctx,
898 uint32 *num_domains,
899 char ***names,
900 char ***alt_names,
901 DOM_SID **dom_sids)
903 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
904 uint32 enum_ctx = 0;
905 struct rpc_pipe_client *cli;
906 POLICY_HND lsa_policy;
908 DEBUG(3,("rpc: trusted_domains\n"));
910 *num_domains = 0;
911 *names = NULL;
912 *alt_names = NULL;
913 *dom_sids = NULL;
915 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
916 if (!NT_STATUS_IS_OK(result))
917 return result;
919 result = STATUS_MORE_ENTRIES;
921 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
922 uint32 start_idx, num;
923 char **tmp_names;
924 DOM_SID *tmp_sids;
925 int i;
927 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
928 &lsa_policy, &enum_ctx,
929 &num, &tmp_names,
930 &tmp_sids);
932 if (!NT_STATUS_IS_OK(result) &&
933 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
934 break;
936 start_idx = *num_domains;
937 *num_domains += num;
938 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
939 char *, *num_domains);
940 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
941 DOM_SID, *num_domains);
942 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
943 char *, *num_domains);
944 if ((*names == NULL) || (*dom_sids == NULL) ||
945 (*alt_names == NULL))
946 return NT_STATUS_NO_MEMORY;
948 for (i=0; i<num; i++) {
949 (*names)[start_idx+i] = tmp_names[i];
950 (*dom_sids)[start_idx+i] = tmp_sids[i];
951 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
954 return result;
957 /* find the lockout policy for a domain */
958 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
959 TALLOC_CTX *mem_ctx,
960 SAM_UNK_INFO_12 *lockout_policy)
962 NTSTATUS result;
963 struct rpc_pipe_client *cli;
964 POLICY_HND dom_pol;
965 SAM_UNK_CTR ctr;
967 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
969 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
970 if (!NT_STATUS_IS_OK(result)) {
971 goto done;
974 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
975 if (!NT_STATUS_IS_OK(result)) {
976 goto done;
979 *lockout_policy = ctr.info.inf12;
981 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
982 ctr.info.inf12.bad_attempt_lockout));
984 done:
986 return result;
989 /* find the password policy for a domain */
990 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
991 TALLOC_CTX *mem_ctx,
992 SAM_UNK_INFO_1 *password_policy)
994 NTSTATUS result;
995 struct rpc_pipe_client *cli;
996 POLICY_HND dom_pol;
997 SAM_UNK_CTR ctr;
999 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1001 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1002 if (!NT_STATUS_IS_OK(result)) {
1003 goto done;
1006 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1007 if (!NT_STATUS_IS_OK(result)) {
1008 goto done;
1011 *password_policy = ctr.info.inf1;
1013 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1014 ctr.info.inf1.min_length_password));
1016 done:
1018 return result;
1022 /* the rpc backend methods are exposed via this structure */
1023 struct winbindd_methods msrpc_methods = {
1024 False,
1025 query_user_list,
1026 enum_dom_groups,
1027 enum_local_groups,
1028 msrpc_name_to_sid,
1029 msrpc_sid_to_name,
1030 msrpc_rids_to_names,
1031 query_user,
1032 lookup_usergroups,
1033 msrpc_lookup_useraliases,
1034 lookup_groupmem,
1035 sequence_number,
1036 msrpc_lockout_policy,
1037 msrpc_password_policy,
1038 trusted_domains,