Fix bogus uninitialized variable warnings
[Samba/gbeck.git] / source3 / winbindd / winbindd_rpc.c
blob34ba0498e0a6128e85df41e9211e3e8eacf33482
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 3 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, see <http://www.gnu.org/licenses/>.
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 NTSTATUS result;
40 POLICY_HND dom_pol;
41 unsigned int i, start_idx;
42 uint32 loop_count;
43 struct rpc_pipe_client *cli;
45 DEBUG(3,("rpc: query_user_list\n"));
47 *num_entries = 0;
48 *info = NULL;
50 if ( !winbindd_can_contact_domain( domain ) ) {
51 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
52 domain->name));
53 return NT_STATUS_OK;
56 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
57 if (!NT_STATUS_IS_OK(result))
58 return result;
60 i = start_idx = 0;
61 loop_count = 0;
63 do {
64 uint32 num_dom_users, j;
65 uint32 max_entries, max_size;
66 SAM_DISPINFO_CTR ctr;
67 SAM_DISPINFO_1 info1;
69 ZERO_STRUCT( ctr );
70 ZERO_STRUCT( info1 );
71 ctr.sam.info1 = &info1;
73 /* this next bit is copied from net_user_list_internal() */
75 get_query_dispinfo_params(loop_count, &max_entries,
76 &max_size);
78 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol,
79 &start_idx, 1,
80 &num_dom_users,
81 max_entries, max_size,
82 &ctr);
84 loop_count++;
86 *num_entries += num_dom_users;
88 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
89 *num_entries);
91 if (!(*info)) {
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));
100 unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname));
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 } 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 if ( !winbindd_can_contact_domain( domain ) ) {
142 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
143 domain->name));
144 return NT_STATUS_OK;
147 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
148 if (!NT_STATUS_IS_OK(status))
149 return status;
151 do {
152 struct acct_info *info2 = NULL;
153 uint32 count = 0;
154 TALLOC_CTX *mem_ctx2;
156 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
158 /* start is updated by this call. */
159 status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
160 &start,
161 0xFFFF, /* buffer size? */
162 &info2, &count);
164 if (!NT_STATUS_IS_OK(status) &&
165 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
166 talloc_destroy(mem_ctx2);
167 break;
170 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
171 struct acct_info,
172 (*num_entries) + count);
173 if (! *info) {
174 talloc_destroy(mem_ctx2);
175 return NT_STATUS_NO_MEMORY;
178 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
179 (*num_entries) += count;
180 talloc_destroy(mem_ctx2);
181 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
183 return NT_STATUS_OK;
186 /* List all domain groups */
188 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
189 TALLOC_CTX *mem_ctx,
190 uint32 *num_entries,
191 struct acct_info **info)
193 POLICY_HND dom_pol;
194 NTSTATUS result;
195 struct rpc_pipe_client *cli;
197 *num_entries = 0;
198 *info = NULL;
200 DEBUG(3,("rpc: enum_local_groups\n"));
202 if ( !winbindd_can_contact_domain( domain ) ) {
203 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
204 domain->name));
205 return NT_STATUS_OK;
208 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
209 if (!NT_STATUS_IS_OK(result))
210 return result;
212 do {
213 struct acct_info *info2 = NULL;
214 uint32 count = 0, start = *num_entries;
215 TALLOC_CTX *mem_ctx2;
217 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
219 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
220 &start, 0xFFFF, &info2,
221 &count);
223 if (!NT_STATUS_IS_OK(result) &&
224 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
226 talloc_destroy(mem_ctx2);
227 return result;
230 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
231 struct acct_info,
232 (*num_entries) + count);
233 if (! *info) {
234 talloc_destroy(mem_ctx2);
235 return NT_STATUS_NO_MEMORY;
238 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
239 (*num_entries) += count;
240 talloc_destroy(mem_ctx2);
242 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
244 return NT_STATUS_OK;
247 /* convert a single name to a sid in a domain */
248 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
249 TALLOC_CTX *mem_ctx,
250 enum winbindd_cmd original_cmd,
251 const char *domain_name,
252 const char *name,
253 DOM_SID *sid,
254 enum lsa_SidType *type)
256 NTSTATUS result;
257 DOM_SID *sids = NULL;
258 enum lsa_SidType *types = NULL;
259 char *full_name = NULL;
260 struct rpc_pipe_client *cli;
261 POLICY_HND lsa_policy;
263 if (name == NULL || *name=='\0') {
264 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
265 } else if (domain_name == NULL || *domain_name == '\0') {
266 full_name = talloc_asprintf(mem_ctx, "%s", name);
267 } else {
268 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
270 if (!full_name) {
271 DEBUG(0, ("talloc_asprintf failed!\n"));
272 return NT_STATUS_NO_MEMORY;
275 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
277 ws_name_return( full_name, WB_REPLACE_CHAR );
279 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
281 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
282 if (!NT_STATUS_IS_OK(result))
283 return result;
285 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
286 (const char**) &full_name, NULL, 1, &sids, &types);
288 if (!NT_STATUS_IS_OK(result))
289 return result;
291 /* Return rid and type if lookup successful */
293 sid_copy(sid, &sids[0]);
294 *type = types[0];
296 return NT_STATUS_OK;
300 convert a domain SID to a user or group name
302 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
303 TALLOC_CTX *mem_ctx,
304 const DOM_SID *sid,
305 char **domain_name,
306 char **name,
307 enum lsa_SidType *type)
309 char **domains;
310 char **names;
311 enum lsa_SidType *types = NULL;
312 NTSTATUS result;
313 struct rpc_pipe_client *cli;
314 POLICY_HND lsa_policy;
316 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
317 domain->name ));
319 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
320 if (!NT_STATUS_IS_OK(result)) {
321 DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
322 nt_errstr(result)));
323 return result;
327 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
328 1, sid, &domains, &names, &types);
329 if (!NT_STATUS_IS_OK(result)) {
330 DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n",
331 nt_errstr(result)));
332 return result;
335 *type = (enum lsa_SidType)types[0];
336 *domain_name = domains[0];
337 *name = names[0];
339 ws_name_replace( *name, WB_REPLACE_CHAR );
341 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
342 return NT_STATUS_OK;
345 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
346 TALLOC_CTX *mem_ctx,
347 const DOM_SID *sid,
348 uint32 *rids,
349 size_t num_rids,
350 char **domain_name,
351 char ***names,
352 enum lsa_SidType **types)
354 char **domains;
355 NTSTATUS result;
356 struct rpc_pipe_client *cli;
357 POLICY_HND lsa_policy;
358 DOM_SID *sids;
359 size_t i;
360 char **ret_names;
362 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
364 if (num_rids) {
365 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
366 if (sids == NULL) {
367 return NT_STATUS_NO_MEMORY;
369 } else {
370 sids = NULL;
373 for (i=0; i<num_rids; i++) {
374 if (!sid_compose(&sids[i], sid, rids[i])) {
375 return NT_STATUS_INTERNAL_ERROR;
379 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
380 if (!NT_STATUS_IS_OK(result)) {
381 return result;
384 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
385 num_rids, sids, &domains,
386 names, types);
387 if (!NT_STATUS_IS_OK(result) &&
388 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
389 return result;
392 ret_names = *names;
393 for (i=0; i<num_rids; i++) {
394 if ((*types)[i] != SID_NAME_UNKNOWN) {
395 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
396 *domain_name = domains[i];
400 return result;
403 /* Lookup user information from a rid or username. */
404 static NTSTATUS query_user(struct winbindd_domain *domain,
405 TALLOC_CTX *mem_ctx,
406 const DOM_SID *user_sid,
407 WINBIND_USERINFO *user_info)
409 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
410 POLICY_HND dom_pol, user_pol;
411 SAM_USERINFO_CTR *ctr;
412 uint32 user_rid;
413 NET_USER_INFO_3 *user;
414 struct rpc_pipe_client *cli;
416 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
418 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
419 return NT_STATUS_UNSUCCESSFUL;
421 user_info->homedir = NULL;
422 user_info->shell = NULL;
423 user_info->primary_gid = (gid_t)-1;
425 /* try netsamlogon cache first */
427 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
430 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
431 sid_string_dbg(user_sid)));
433 sid_compose(&user_info->user_sid, &domain->sid, user->user_rid);
434 sid_compose(&user_info->group_sid, &domain->sid,
435 user->group_rid);
437 user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx,
438 &user->uni_user_name);
439 user_info->full_name = unistr2_to_ascii_talloc(mem_ctx,
440 &user->uni_full_name);
442 TALLOC_FREE(user);
444 return NT_STATUS_OK;
447 if ( !winbindd_can_contact_domain( domain ) ) {
448 DEBUG(10,("query_user: No incoming trust for domain %s\n",
449 domain->name));
450 return NT_STATUS_OK;
453 if ( !winbindd_can_contact_domain( domain ) ) {
454 DEBUG(10,("query_user: No incoming trust for domain %s\n",
455 domain->name));
456 return NT_STATUS_OK;
459 if ( !winbindd_can_contact_domain( domain ) ) {
460 DEBUG(10,("query_user: No incoming trust for domain %s\n",
461 domain->name));
462 return NT_STATUS_OK;
465 /* no cache; hit the wire */
467 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
468 if (!NT_STATUS_IS_OK(result))
469 return result;
471 /* Get user handle */
472 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
473 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
474 &user_pol);
476 if (!NT_STATUS_IS_OK(result))
477 return result;
479 /* Get user info */
480 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
481 0x15, &ctr);
483 rpccli_samr_close(cli, mem_ctx, &user_pol);
485 if (!NT_STATUS_IS_OK(result))
486 return result;
488 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
489 sid_compose(&user_info->group_sid, &domain->sid,
490 ctr->info.id21->group_rid);
491 user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx,
492 &ctr->info.id21->uni_user_name);
493 user_info->full_name = unistr2_to_ascii_talloc(mem_ctx,
494 &ctr->info.id21->uni_full_name);
495 user_info->homedir = NULL;
496 user_info->shell = NULL;
497 user_info->primary_gid = (gid_t)-1;
499 return NT_STATUS_OK;
502 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
503 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
504 TALLOC_CTX *mem_ctx,
505 const DOM_SID *user_sid,
506 uint32 *num_groups, DOM_SID **user_grpsids)
508 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
509 POLICY_HND dom_pol, user_pol;
510 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
511 DOM_GID *user_groups;
512 unsigned int i;
513 uint32 user_rid;
514 struct rpc_pipe_client *cli;
516 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
518 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
519 return NT_STATUS_UNSUCCESSFUL;
521 *num_groups = 0;
522 *user_grpsids = NULL;
524 /* so lets see if we have a cached user_info_3 */
525 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
526 num_groups, user_grpsids);
528 if (NT_STATUS_IS_OK(result)) {
529 return NT_STATUS_OK;
532 if ( !winbindd_can_contact_domain( domain ) ) {
533 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
534 domain->name));
536 /* Tell the cache manager not to remember this one */
538 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
541 /* no cache; hit the wire */
543 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
544 if (!NT_STATUS_IS_OK(result))
545 return result;
547 /* Get user handle */
548 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
549 des_access, user_rid, &user_pol);
551 if (!NT_STATUS_IS_OK(result))
552 return result;
554 /* Query user rids */
555 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
556 num_groups, &user_groups);
558 rpccli_samr_close(cli, mem_ctx, &user_pol);
560 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
561 return result;
563 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
564 if (!(*user_grpsids))
565 return NT_STATUS_NO_MEMORY;
567 for (i=0;i<(*num_groups);i++) {
568 sid_copy(&((*user_grpsids)[i]), &domain->sid);
569 sid_append_rid(&((*user_grpsids)[i]),
570 user_groups[i].g_rid);
573 return NT_STATUS_OK;
576 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
577 TALLOC_CTX *mem_ctx,
578 uint32 num_sids, const DOM_SID *sids,
579 uint32 *num_aliases, uint32 **alias_rids)
581 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
582 POLICY_HND dom_pol;
583 DOM_SID2 *query_sids;
584 uint32 num_query_sids = 0;
585 int i;
586 struct rpc_pipe_client *cli;
587 uint32 *alias_rids_query, num_aliases_query;
588 int rangesize = MAX_SAM_ENTRIES_W2K;
589 uint32 total_sids = 0;
590 int num_queries = 1;
592 *num_aliases = 0;
593 *alias_rids = NULL;
595 DEBUG(3,("rpc: lookup_useraliases\n"));
597 if ( !winbindd_can_contact_domain( domain ) ) {
598 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
599 domain->name));
600 return NT_STATUS_OK;
603 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
604 if (!NT_STATUS_IS_OK(result))
605 return result;
607 do {
608 /* prepare query */
610 num_query_sids = MIN(num_sids - total_sids, rangesize);
612 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
613 num_queries, num_query_sids));
615 if (num_query_sids) {
616 query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
617 if (query_sids == NULL) {
618 return NT_STATUS_NO_MEMORY;
620 } else {
621 query_sids = NULL;
624 for (i=0; i<num_query_sids; i++) {
625 sid_copy(&query_sids[i].sid, &sids[total_sids++]);
626 query_sids[i].num_auths = query_sids[i].sid.num_auths;
629 /* do request */
631 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
632 num_query_sids, query_sids,
633 &num_aliases_query,
634 &alias_rids_query);
636 if (!NT_STATUS_IS_OK(result)) {
637 *num_aliases = 0;
638 *alias_rids = NULL;
639 TALLOC_FREE(query_sids);
640 goto done;
643 /* process output */
645 for (i=0; i<num_aliases_query; i++) {
646 size_t na = *num_aliases;
647 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
648 alias_rids, &na)) {
649 return NT_STATUS_NO_MEMORY;
651 *num_aliases = na;
654 TALLOC_FREE(query_sids);
656 num_queries++;
658 } while (total_sids < num_sids);
660 done:
661 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
662 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
664 return result;
668 /* Lookup group membership given a rid. */
669 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
670 TALLOC_CTX *mem_ctx,
671 const DOM_SID *group_sid, uint32 *num_names,
672 DOM_SID **sid_mem, char ***names,
673 uint32 **name_types)
675 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
676 uint32 i, total_names = 0;
677 POLICY_HND dom_pol, group_pol;
678 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
679 uint32 *rid_mem = NULL;
680 uint32 group_rid;
681 unsigned int j;
682 struct rpc_pipe_client *cli;
683 unsigned int orig_timeout;
685 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
686 sid_string_dbg(group_sid)));
688 if ( !winbindd_can_contact_domain( domain ) ) {
689 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
690 domain->name));
691 return NT_STATUS_OK;
694 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
695 return NT_STATUS_UNSUCCESSFUL;
697 *num_names = 0;
699 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
700 if (!NT_STATUS_IS_OK(result))
701 return result;
703 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
704 des_access, group_rid, &group_pol);
706 if (!NT_STATUS_IS_OK(result))
707 return result;
709 /* Step #1: Get a list of user rids that are the members of the
710 group. */
712 /* This call can take a long time - allow the server to time out.
713 35 seconds should do it. */
715 orig_timeout = cli_set_timeout(cli->cli, 35000);
717 result = rpccli_samr_query_groupmem(cli, mem_ctx,
718 &group_pol, num_names, &rid_mem,
719 name_types);
721 /* And restore our original timeout. */
722 cli_set_timeout(cli->cli, orig_timeout);
724 rpccli_samr_close(cli, mem_ctx, &group_pol);
726 if (!NT_STATUS_IS_OK(result))
727 return result;
729 if (!*num_names) {
730 names = NULL;
731 name_types = NULL;
732 sid_mem = NULL;
733 return NT_STATUS_OK;
736 /* Step #2: Convert list of rids into list of usernames. Do this
737 in bunches of ~1000 to avoid crashing NT4. It looks like there
738 is a buffer overflow or something like that lurking around
739 somewhere. */
741 #define MAX_LOOKUP_RIDS 900
743 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
744 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
745 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
747 for (j=0;j<(*num_names);j++)
748 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
750 if (*num_names>0 && (!*names || !*name_types))
751 return NT_STATUS_NO_MEMORY;
753 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
754 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
755 uint32 tmp_num_names = 0;
756 char **tmp_names = NULL;
757 uint32 *tmp_types = NULL;
759 /* Lookup a chunk of rids */
761 result = rpccli_samr_lookup_rids(cli, mem_ctx,
762 &dom_pol,
763 num_lookup_rids,
764 &rid_mem[i],
765 &tmp_num_names,
766 &tmp_names, &tmp_types);
768 /* see if we have a real error (and yes the
769 STATUS_SOME_UNMAPPED is the one returned from 2k) */
771 if (!NT_STATUS_IS_OK(result) &&
772 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
773 return result;
775 /* Copy result into array. The talloc system will take
776 care of freeing the temporary arrays later on. */
778 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
779 tmp_num_names);
781 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
782 tmp_num_names);
784 total_names += tmp_num_names;
787 *num_names = total_names;
789 return NT_STATUS_OK;
792 #ifdef HAVE_LDAP
794 #include <ldap.h>
796 static int get_ldap_seq(const char *server, int port, uint32 *seq)
798 int ret = -1;
799 struct timeval to;
800 const char *attrs[] = {"highestCommittedUSN", NULL};
801 LDAPMessage *res = NULL;
802 char **values = NULL;
803 LDAP *ldp = NULL;
805 *seq = DOM_SEQUENCE_NONE;
808 * Parameterised (5) second timeout on open. This is needed as the
809 * search timeout doesn't seem to apply to doing an open as well. JRA.
812 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
813 if (ldp == NULL)
814 return -1;
816 /* Timeout if no response within 20 seconds. */
817 to.tv_sec = 10;
818 to.tv_usec = 0;
820 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
821 CONST_DISCARD(char **, attrs), 0, &to, &res))
822 goto done;
824 if (ldap_count_entries(ldp, res) != 1)
825 goto done;
827 values = ldap_get_values(ldp, res, "highestCommittedUSN");
828 if (!values || !values[0])
829 goto done;
831 *seq = atoi(values[0]);
832 ret = 0;
834 done:
836 if (values)
837 ldap_value_free(values);
838 if (res)
839 ldap_msgfree(res);
840 if (ldp)
841 ldap_unbind(ldp);
842 return ret;
845 /**********************************************************************
846 Get the sequence number for a Windows AD native mode domain using
847 LDAP queries.
848 **********************************************************************/
850 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
852 int ret = -1;
853 char addr[INET6_ADDRSTRLEN];
855 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
856 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
857 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
858 "number for Domain (%s) from DC (%s)\n",
859 domain->name, addr));
861 return ret;
864 #endif /* HAVE_LDAP */
866 /* find the sequence number for a domain */
867 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
869 TALLOC_CTX *mem_ctx;
870 SAM_UNK_CTR ctr;
871 NTSTATUS result;
872 POLICY_HND dom_pol;
873 bool got_seq_num = False;
874 struct rpc_pipe_client *cli;
876 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
878 if ( !winbindd_can_contact_domain( domain ) ) {
879 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
880 domain->name));
881 *seq = time(NULL);
882 return NT_STATUS_OK;
885 *seq = DOM_SEQUENCE_NONE;
887 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
888 return NT_STATUS_NO_MEMORY;
890 #ifdef HAVE_LDAP
891 if ( domain->active_directory )
893 int res;
895 DEBUG(8,("using get_ldap_seq() to retrieve the "
896 "sequence number\n"));
898 res = get_ldap_sequence_number( domain, seq );
899 if (res == 0)
901 result = NT_STATUS_OK;
902 DEBUG(10,("domain_sequence_number: LDAP for "
903 "domain %s is %u\n",
904 domain->name, *seq));
905 goto done;
908 DEBUG(10,("domain_sequence_number: failed to get LDAP "
909 "sequence number for domain %s\n",
910 domain->name ));
912 #endif /* HAVE_LDAP */
914 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
915 if (!NT_STATUS_IS_OK(result)) {
916 goto done;
919 /* Query domain info */
921 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
923 if (NT_STATUS_IS_OK(result)) {
924 *seq = ctr.info.inf8.seq_num;
925 got_seq_num = True;
926 goto seq_num;
929 /* retry with info-level 2 in case the dc does not support info-level 8
930 * (like all older samba2 and samba3 dc's - Guenther */
932 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
934 if (NT_STATUS_IS_OK(result)) {
935 *seq = ctr.info.inf2.seq_num;
936 got_seq_num = True;
939 seq_num:
940 if (got_seq_num) {
941 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
942 domain->name, (unsigned)*seq));
943 } else {
944 DEBUG(10,("domain_sequence_number: failed to get sequence "
945 "number (%u) for domain %s\n",
946 (unsigned)*seq, domain->name ));
949 done:
951 talloc_destroy(mem_ctx);
953 return result;
956 /* get a list of trusted domains */
957 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
958 TALLOC_CTX *mem_ctx,
959 uint32 *num_domains,
960 char ***names,
961 char ***alt_names,
962 DOM_SID **dom_sids)
964 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
965 uint32 enum_ctx = 0;
966 struct rpc_pipe_client *cli;
967 POLICY_HND lsa_policy;
969 DEBUG(3,("rpc: trusted_domains\n"));
971 *num_domains = 0;
972 *names = NULL;
973 *alt_names = NULL;
974 *dom_sids = NULL;
976 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
977 if (!NT_STATUS_IS_OK(result))
978 return result;
980 result = STATUS_MORE_ENTRIES;
982 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
983 uint32 start_idx, num;
984 char **tmp_names;
985 DOM_SID *tmp_sids;
986 int i;
988 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
989 &lsa_policy, &enum_ctx,
990 &num, &tmp_names,
991 &tmp_sids);
993 if (!NT_STATUS_IS_OK(result) &&
994 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
995 break;
997 start_idx = *num_domains;
998 *num_domains += num;
999 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1000 char *, *num_domains);
1001 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1002 DOM_SID, *num_domains);
1003 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1004 char *, *num_domains);
1005 if ((*names == NULL) || (*dom_sids == NULL) ||
1006 (*alt_names == NULL))
1007 return NT_STATUS_NO_MEMORY;
1009 for (i=0; i<num; i++) {
1010 (*names)[start_idx+i] = tmp_names[i];
1011 (*dom_sids)[start_idx+i] = tmp_sids[i];
1012 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1015 return result;
1018 /* find the lockout policy for a domain */
1019 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1020 TALLOC_CTX *mem_ctx,
1021 SAM_UNK_INFO_12 *lockout_policy)
1023 NTSTATUS result;
1024 struct rpc_pipe_client *cli;
1025 POLICY_HND dom_pol;
1026 SAM_UNK_CTR ctr;
1028 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1030 if ( !winbindd_can_contact_domain( domain ) ) {
1031 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1032 domain->name));
1033 return NT_STATUS_NOT_SUPPORTED;
1036 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1037 if (!NT_STATUS_IS_OK(result)) {
1038 goto done;
1041 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
1042 if (!NT_STATUS_IS_OK(result)) {
1043 goto done;
1046 *lockout_policy = ctr.info.inf12;
1048 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
1049 ctr.info.inf12.bad_attempt_lockout));
1051 done:
1053 return result;
1056 /* find the password policy for a domain */
1057 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1058 TALLOC_CTX *mem_ctx,
1059 SAM_UNK_INFO_1 *password_policy)
1061 NTSTATUS result;
1062 struct rpc_pipe_client *cli;
1063 POLICY_HND dom_pol;
1064 SAM_UNK_CTR ctr;
1066 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1068 if ( !winbindd_can_contact_domain( domain ) ) {
1069 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1070 domain->name));
1071 return NT_STATUS_NOT_SUPPORTED;
1074 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1075 if (!NT_STATUS_IS_OK(result)) {
1076 goto done;
1079 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1080 if (!NT_STATUS_IS_OK(result)) {
1081 goto done;
1084 *password_policy = ctr.info.inf1;
1086 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1087 ctr.info.inf1.min_length_password));
1089 done:
1091 return result;
1095 /* the rpc backend methods are exposed via this structure */
1096 struct winbindd_methods msrpc_methods = {
1097 False,
1098 query_user_list,
1099 enum_dom_groups,
1100 enum_local_groups,
1101 msrpc_name_to_sid,
1102 msrpc_sid_to_name,
1103 msrpc_rids_to_names,
1104 query_user,
1105 lookup_usergroups,
1106 msrpc_lookup_useraliases,
1107 lookup_groupmem,
1108 sequence_number,
1109 msrpc_lockout_policy,
1110 msrpc_password_policy,
1111 trusted_domains,