r22710: Support one-way trusts.
[Samba.git] / source / nsswitch / winbindd_rpc.c
blob0fafff196b38efd9d900b32fe26275ddc3f5e4d5
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 if ( !winbindd_can_contact_domain( domain ) ) {
52 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
53 domain->name));
54 return NT_STATUS_OK;
57 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
58 if (!NT_STATUS_IS_OK(result))
59 return result;
61 i = start_idx = 0;
62 loop_count = 0;
64 do {
65 TALLOC_CTX *ctx2;
66 uint32 num_dom_users, j;
67 uint32 max_entries, max_size;
68 SAM_DISPINFO_CTR ctr;
69 SAM_DISPINFO_1 info1;
71 ZERO_STRUCT( ctr );
72 ZERO_STRUCT( info1 );
73 ctr.sam.info1 = &info1;
75 if (!(ctx2 = talloc_init("winbindd enum_users")))
76 return NT_STATUS_NO_MEMORY;
78 /* this next bit is copied from net_user_list_internal() */
80 get_query_dispinfo_params(loop_count, &max_entries,
81 &max_size);
83 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol,
84 &start_idx, 1,
85 &num_dom_users,
86 max_entries, max_size,
87 &ctr);
89 loop_count++;
91 *num_entries += num_dom_users;
93 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
94 *num_entries);
96 if (!(*info)) {
97 talloc_destroy(ctx2);
98 return NT_STATUS_NO_MEMORY;
101 for (j = 0; j < num_dom_users; i++, j++) {
102 fstring username, fullname;
103 uint32 rid = ctr.sam.info1->sam[j].rid_user;
105 unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
106 unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
108 (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
109 (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
110 (*info)[i].homedir = NULL;
111 (*info)[i].shell = NULL;
112 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
114 /* For the moment we set the primary group for
115 every user to be the Domain Users group.
116 There are serious problems with determining
117 the actual primary group for large domains.
118 This should really be made into a 'winbind
119 force group' smb.conf parameter or
120 something like that. */
122 sid_compose(&(*info)[i].group_sid, &domain->sid,
123 DOMAIN_GROUP_RID_USERS);
126 talloc_destroy(ctx2);
128 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
130 return result;
133 /* list all domain groups */
134 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
135 TALLOC_CTX *mem_ctx,
136 uint32 *num_entries,
137 struct acct_info **info)
139 POLICY_HND dom_pol;
140 NTSTATUS status;
141 uint32 start = 0;
142 struct rpc_pipe_client *cli;
144 *num_entries = 0;
145 *info = NULL;
147 DEBUG(3,("rpc: enum_dom_groups\n"));
149 if ( !winbindd_can_contact_domain( domain ) ) {
150 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
151 domain->name));
152 return NT_STATUS_OK;
155 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
156 if (!NT_STATUS_IS_OK(status))
157 return status;
159 do {
160 struct acct_info *info2 = NULL;
161 uint32 count = 0;
162 TALLOC_CTX *mem_ctx2;
164 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
166 /* start is updated by this call. */
167 status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
168 &start,
169 0xFFFF, /* buffer size? */
170 &info2, &count);
172 if (!NT_STATUS_IS_OK(status) &&
173 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
174 talloc_destroy(mem_ctx2);
175 break;
178 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
179 struct acct_info,
180 (*num_entries) + count);
181 if (! *info) {
182 talloc_destroy(mem_ctx2);
183 status = NT_STATUS_NO_MEMORY;
184 break;
187 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
188 (*num_entries) += count;
189 talloc_destroy(mem_ctx2);
190 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
192 return NT_STATUS_OK;
195 /* List all domain groups */
197 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
198 TALLOC_CTX *mem_ctx,
199 uint32 *num_entries,
200 struct acct_info **info)
202 POLICY_HND dom_pol;
203 NTSTATUS result;
204 struct rpc_pipe_client *cli;
206 *num_entries = 0;
207 *info = NULL;
209 DEBUG(3,("rpc: enum_local_groups\n"));
211 if ( !winbindd_can_contact_domain( domain ) ) {
212 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
213 domain->name));
214 return NT_STATUS_OK;
217 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
218 if (!NT_STATUS_IS_OK(result))
219 return result;
221 do {
222 struct acct_info *info2 = NULL;
223 uint32 count = 0, start = *num_entries;
224 TALLOC_CTX *mem_ctx2;
226 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
228 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
229 &start, 0xFFFF, &info2,
230 &count);
232 if (!NT_STATUS_IS_OK(result) &&
233 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
235 talloc_destroy(mem_ctx2);
236 return result;
239 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
240 struct acct_info,
241 (*num_entries) + count);
242 if (! *info) {
243 talloc_destroy(mem_ctx2);
244 return NT_STATUS_NO_MEMORY;
247 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
248 (*num_entries) += count;
249 talloc_destroy(mem_ctx2);
251 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
253 return NT_STATUS_OK;
256 /* convert a single name to a sid in a domain */
257 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
258 TALLOC_CTX *mem_ctx,
259 const char *domain_name,
260 const char *name,
261 DOM_SID *sid,
262 enum lsa_SidType *type)
264 NTSTATUS result;
265 DOM_SID *sids = NULL;
266 enum lsa_SidType *types = NULL;
267 char *full_name = NULL;
268 struct rpc_pipe_client *cli;
269 POLICY_HND lsa_policy;
271 if(name == NULL || *name=='\0') {
272 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name));
273 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
274 } else {
275 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name, name));
276 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
278 if (!full_name) {
279 DEBUG(0, ("talloc_asprintf failed!\n"));
280 return NT_STATUS_NO_MEMORY;
283 ws_name_return( full_name, WB_REPLACE_CHAR );
285 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
287 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
288 if (!NT_STATUS_IS_OK(result))
289 return result;
291 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
292 (const char**) &full_name, NULL, &sids, &types);
294 if (!NT_STATUS_IS_OK(result))
295 return result;
297 /* Return rid and type if lookup successful */
299 sid_copy(sid, &sids[0]);
300 *type = types[0];
302 return NT_STATUS_OK;
306 convert a domain SID to a user or group name
308 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
309 TALLOC_CTX *mem_ctx,
310 const DOM_SID *sid,
311 char **domain_name,
312 char **name,
313 enum lsa_SidType *type)
315 char **domains;
316 char **names;
317 enum lsa_SidType *types;
318 NTSTATUS result;
319 struct rpc_pipe_client *cli;
320 POLICY_HND lsa_policy;
322 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
323 domain->name ));
325 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
326 if (!NT_STATUS_IS_OK(result)) {
327 DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
328 nt_errstr(result)));
329 return result;
333 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
334 1, sid, &domains, &names, &types);
335 if (!NT_STATUS_IS_OK(result)) {
336 DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n",
337 nt_errstr(result)));
338 return result;
341 *type = (enum lsa_SidType)types[0];
342 *domain_name = domains[0];
343 *name = names[0];
345 ws_name_replace( *name, WB_REPLACE_CHAR );
347 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
348 return NT_STATUS_OK;
351 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
352 TALLOC_CTX *mem_ctx,
353 const DOM_SID *sid,
354 uint32 *rids,
355 size_t num_rids,
356 char **domain_name,
357 char ***names,
358 enum lsa_SidType **types)
360 char **domains;
361 NTSTATUS result;
362 struct rpc_pipe_client *cli;
363 POLICY_HND lsa_policy;
364 DOM_SID *sids;
365 size_t i;
366 char **ret_names;
368 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
370 if (num_rids) {
371 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
372 if (sids == NULL) {
373 return NT_STATUS_NO_MEMORY;
375 } else {
376 sids = NULL;
379 for (i=0; i<num_rids; i++) {
380 if (!sid_compose(&sids[i], sid, rids[i])) {
381 return NT_STATUS_INTERNAL_ERROR;
385 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
386 if (!NT_STATUS_IS_OK(result)) {
387 return result;
390 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
391 num_rids, sids, &domains,
392 names, types);
393 if (!NT_STATUS_IS_OK(result) &&
394 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
395 return result;
398 ret_names = *names;
399 for (i=0; i<num_rids; i++) {
400 if ((*types)[i] != SID_NAME_UNKNOWN) {
401 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
402 *domain_name = domains[i];
406 return result;
409 /* Lookup user information from a rid or username. */
410 static NTSTATUS query_user(struct winbindd_domain *domain,
411 TALLOC_CTX *mem_ctx,
412 const DOM_SID *user_sid,
413 WINBIND_USERINFO *user_info)
415 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
416 POLICY_HND dom_pol, user_pol;
417 SAM_USERINFO_CTR *ctr;
418 fstring sid_string;
419 uint32 user_rid;
420 NET_USER_INFO_3 *user;
421 struct rpc_pipe_client *cli;
423 DEBUG(3,("rpc: query_user sid=%s\n",
424 sid_to_string(sid_string, user_sid)));
426 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
427 return NT_STATUS_UNSUCCESSFUL;
429 user_info->homedir = NULL;
430 user_info->shell = NULL;
431 user_info->primary_gid = (gid_t)-1;
433 /* try netsamlogon cache first */
435 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
438 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
439 sid_string_static(user_sid)));
441 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
442 sid_compose(&user_info->group_sid, &domain->sid,
443 user->group_rid);
445 user_info->acct_name = unistr2_tdup(mem_ctx,
446 &user->uni_user_name);
447 user_info->full_name = unistr2_tdup(mem_ctx,
448 &user->uni_full_name);
450 TALLOC_FREE(user);
452 return NT_STATUS_OK;
455 if ( !winbindd_can_contact_domain( domain ) ) {
456 DEBUG(10,("query_user: No incoming trust for domain %s\n",
457 domain->name));
458 return NT_STATUS_OK;
461 /* no cache; hit the wire */
463 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
464 if (!NT_STATUS_IS_OK(result))
465 return result;
467 /* Get user handle */
468 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
469 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
470 &user_pol);
472 if (!NT_STATUS_IS_OK(result))
473 return result;
475 /* Get user info */
476 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
477 0x15, &ctr);
479 rpccli_samr_close(cli, mem_ctx, &user_pol);
481 if (!NT_STATUS_IS_OK(result))
482 return result;
484 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
485 sid_compose(&user_info->group_sid, &domain->sid,
486 ctr->info.id21->group_rid);
487 user_info->acct_name = unistr2_tdup(mem_ctx,
488 &ctr->info.id21->uni_user_name);
489 user_info->full_name = unistr2_tdup(mem_ctx,
490 &ctr->info.id21->uni_full_name);
491 user_info->homedir = NULL;
492 user_info->shell = NULL;
493 user_info->primary_gid = (gid_t)-1;
495 return NT_STATUS_OK;
498 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
499 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
500 TALLOC_CTX *mem_ctx,
501 const DOM_SID *user_sid,
502 uint32 *num_groups, DOM_SID **user_grpsids)
504 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
505 POLICY_HND dom_pol, user_pol;
506 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
507 DOM_GID *user_groups;
508 unsigned int i;
509 fstring sid_string;
510 uint32 user_rid;
511 struct rpc_pipe_client *cli;
513 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
514 sid_to_string(sid_string, user_sid)));
516 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
517 return NT_STATUS_UNSUCCESSFUL;
519 *num_groups = 0;
520 *user_grpsids = NULL;
522 /* so lets see if we have a cached user_info_3 */
523 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
524 num_groups, user_grpsids);
526 if (NT_STATUS_IS_OK(result)) {
527 return NT_STATUS_OK;
530 if ( !winbindd_can_contact_domain( domain ) ) {
531 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
532 domain->name));
534 /* Tell the cache manager not to remember this one */
536 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
539 /* no cache; hit the wire */
541 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
542 if (!NT_STATUS_IS_OK(result))
543 return result;
545 /* Get user handle */
546 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
547 des_access, user_rid, &user_pol);
549 if (!NT_STATUS_IS_OK(result))
550 return result;
552 /* Query user rids */
553 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
554 num_groups, &user_groups);
556 rpccli_samr_close(cli, mem_ctx, &user_pol);
558 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
559 return result;
561 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
562 if (!(*user_grpsids))
563 return NT_STATUS_NO_MEMORY;
565 for (i=0;i<(*num_groups);i++) {
566 sid_copy(&((*user_grpsids)[i]), &domain->sid);
567 sid_append_rid(&((*user_grpsids)[i]),
568 user_groups[i].g_rid);
571 return NT_STATUS_OK;
574 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
575 TALLOC_CTX *mem_ctx,
576 uint32 num_sids, const DOM_SID *sids,
577 uint32 *num_aliases, uint32 **alias_rids)
579 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
580 POLICY_HND dom_pol;
581 DOM_SID2 *query_sids;
582 uint32 num_query_sids = 0;
583 int i;
584 struct rpc_pipe_client *cli;
585 uint32 *alias_rids_query, num_aliases_query;
586 int rangesize = MAX_SAM_ENTRIES_W2K;
587 uint32 total_sids = 0;
588 int num_queries = 1;
590 *num_aliases = 0;
591 *alias_rids = NULL;
593 DEBUG(3,("rpc: lookup_useraliases\n"));
595 if ( !winbindd_can_contact_domain( domain ) ) {
596 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
597 domain->name));
598 return NT_STATUS_OK;
601 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
602 if (!NT_STATUS_IS_OK(result))
603 return result;
605 do {
606 /* prepare query */
608 num_query_sids = MIN(num_sids - total_sids, rangesize);
610 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
611 num_queries, num_query_sids));
613 if (num_query_sids) {
614 query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
615 if (query_sids == NULL) {
616 return NT_STATUS_NO_MEMORY;
618 } else {
619 query_sids = NULL;
622 for (i=0; i<num_query_sids; i++) {
623 sid_copy(&query_sids[i].sid, &sids[total_sids++]);
624 query_sids[i].num_auths = query_sids[i].sid.num_auths;
627 /* do request */
629 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
630 num_query_sids, query_sids,
631 &num_aliases_query,
632 &alias_rids_query);
634 if (!NT_STATUS_IS_OK(result)) {
635 *num_aliases = 0;
636 *alias_rids = NULL;
637 TALLOC_FREE(query_sids);
638 goto done;
641 /* process output */
643 for (i=0; i<num_aliases_query; i++) {
644 size_t na = *num_aliases;
645 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
646 alias_rids, &na)) {
647 return NT_STATUS_NO_MEMORY;
649 *num_aliases = na;
652 TALLOC_FREE(query_sids);
654 num_queries++;
656 } while (total_sids < num_sids);
658 done:
659 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
660 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
662 return result;
666 /* Lookup group membership given a rid. */
667 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
668 TALLOC_CTX *mem_ctx,
669 const DOM_SID *group_sid, uint32 *num_names,
670 DOM_SID **sid_mem, char ***names,
671 uint32 **name_types)
673 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
674 uint32 i, total_names = 0;
675 POLICY_HND dom_pol, group_pol;
676 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
677 uint32 *rid_mem = NULL;
678 uint32 group_rid;
679 unsigned int j;
680 fstring sid_string;
681 struct rpc_pipe_client *cli;
682 unsigned int orig_timeout;
684 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
685 sid_to_string(sid_string, group_sid)));
687 if ( !winbindd_can_contact_domain( domain ) ) {
688 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
689 domain->name));
690 return NT_STATUS_OK;
693 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
694 return NT_STATUS_UNSUCCESSFUL;
696 *num_names = 0;
698 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
699 if (!NT_STATUS_IS_OK(result))
700 return result;
702 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
703 des_access, group_rid, &group_pol);
705 if (!NT_STATUS_IS_OK(result))
706 return result;
708 /* Step #1: Get a list of user rids that are the members of the
709 group. */
711 /* This call can take a long time - allow the server to time out.
712 35 seconds should do it. */
714 orig_timeout = cli_set_timeout(cli->cli, 35000);
716 result = rpccli_samr_query_groupmem(cli, mem_ctx,
717 &group_pol, num_names, &rid_mem,
718 name_types);
720 /* And restore our original timeout. */
721 cli_set_timeout(cli->cli, orig_timeout);
723 rpccli_samr_close(cli, mem_ctx, &group_pol);
725 if (!NT_STATUS_IS_OK(result))
726 return result;
728 if (!*num_names) {
729 names = NULL;
730 name_types = NULL;
731 sid_mem = NULL;
732 return NT_STATUS_OK;
735 /* Step #2: Convert list of rids into list of usernames. Do this
736 in bunches of ~1000 to avoid crashing NT4. It looks like there
737 is a buffer overflow or something like that lurking around
738 somewhere. */
740 #define MAX_LOOKUP_RIDS 900
742 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
743 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
744 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
746 for (j=0;j<(*num_names);j++)
747 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
749 if (*num_names>0 && (!*names || !*name_types))
750 return NT_STATUS_NO_MEMORY;
752 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
753 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
754 uint32 tmp_num_names = 0;
755 char **tmp_names = NULL;
756 uint32 *tmp_types = NULL;
758 /* Lookup a chunk of rids */
760 result = rpccli_samr_lookup_rids(cli, mem_ctx,
761 &dom_pol,
762 num_lookup_rids,
763 &rid_mem[i],
764 &tmp_num_names,
765 &tmp_names, &tmp_types);
767 /* see if we have a real error (and yes the
768 STATUS_SOME_UNMAPPED is the one returned from 2k) */
770 if (!NT_STATUS_IS_OK(result) &&
771 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
772 return result;
774 /* Copy result into array. The talloc system will take
775 care of freeing the temporary arrays later on. */
777 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
778 tmp_num_names);
780 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
781 tmp_num_names);
783 total_names += tmp_num_names;
786 *num_names = total_names;
788 return NT_STATUS_OK;
791 #ifdef HAVE_LDAP
793 #include <ldap.h>
795 static int get_ldap_seq(const char *server, int port, uint32 *seq)
797 int ret = -1;
798 struct timeval to;
799 const char *attrs[] = {"highestCommittedUSN", NULL};
800 LDAPMessage *res = NULL;
801 char **values = NULL;
802 LDAP *ldp = NULL;
804 *seq = DOM_SEQUENCE_NONE;
807 * Parameterised (5) second timeout on open. This is needed as the
808 * search timeout doesn't seem to apply to doing an open as well. JRA.
811 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
812 if (ldp == NULL)
813 return -1;
815 /* Timeout if no response within 20 seconds. */
816 to.tv_sec = 10;
817 to.tv_usec = 0;
819 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
820 CONST_DISCARD(char **, attrs), 0, &to, &res))
821 goto done;
823 if (ldap_count_entries(ldp, res) != 1)
824 goto done;
826 values = ldap_get_values(ldp, res, "highestCommittedUSN");
827 if (!values || !values[0])
828 goto done;
830 *seq = atoi(values[0]);
831 ret = 0;
833 done:
835 if (values)
836 ldap_value_free(values);
837 if (res)
838 ldap_msgfree(res);
839 if (ldp)
840 ldap_unbind(ldp);
841 return ret;
844 /**********************************************************************
845 Get the sequence number for a Windows AD native mode domain using
846 LDAP queries.
847 **********************************************************************/
849 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
851 int ret = -1;
852 fstring ipstr;
854 fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
855 if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
856 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
857 "number for Domain (%s) from DC (%s)\n",
858 domain->name, ipstr));
860 return ret;
863 #endif /* HAVE_LDAP */
865 /* find the sequence number for a domain */
866 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
868 TALLOC_CTX *mem_ctx;
869 SAM_UNK_CTR ctr;
870 NTSTATUS result;
871 POLICY_HND dom_pol;
872 BOOL got_seq_num = False;
873 struct rpc_pipe_client *cli;
875 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
877 if ( !winbindd_can_contact_domain( domain ) ) {
878 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
879 domain->name));
880 *seq = time(NULL);
881 return NT_STATUS_OK;
884 *seq = DOM_SEQUENCE_NONE;
886 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
887 return NT_STATUS_NO_MEMORY;
889 #ifdef HAVE_LDAP
890 if ( domain->active_directory )
892 int res;
894 DEBUG(8,("using get_ldap_seq() to retrieve the "
895 "sequence number\n"));
897 res = get_ldap_sequence_number( domain, seq );
898 if (res == 0)
900 result = NT_STATUS_OK;
901 DEBUG(10,("domain_sequence_number: LDAP for "
902 "domain %s is %u\n",
903 domain->name, *seq));
904 goto done;
907 DEBUG(10,("domain_sequence_number: failed to get LDAP "
908 "sequence number for domain %s\n",
909 domain->name ));
911 #endif /* HAVE_LDAP */
913 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
914 if (!NT_STATUS_IS_OK(result)) {
915 goto done;
918 /* Query domain info */
920 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
922 if (NT_STATUS_IS_OK(result)) {
923 *seq = ctr.info.inf8.seq_num;
924 got_seq_num = True;
925 goto seq_num;
928 /* retry with info-level 2 in case the dc does not support info-level 8
929 * (like all older samba2 and samba3 dc's - Guenther */
931 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
933 if (NT_STATUS_IS_OK(result)) {
934 *seq = ctr.info.inf2.seq_num;
935 got_seq_num = True;
938 seq_num:
939 if (got_seq_num) {
940 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
941 domain->name, (unsigned)*seq));
942 } else {
943 DEBUG(10,("domain_sequence_number: failed to get sequence "
944 "number (%u) for domain %s\n",
945 (unsigned)*seq, domain->name ));
948 done:
950 talloc_destroy(mem_ctx);
952 return result;
955 /* get a list of trusted domains */
956 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
957 TALLOC_CTX *mem_ctx,
958 uint32 *num_domains,
959 char ***names,
960 char ***alt_names,
961 DOM_SID **dom_sids)
963 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
964 uint32 enum_ctx = 0;
965 struct rpc_pipe_client *cli;
966 POLICY_HND lsa_policy;
968 DEBUG(3,("rpc: trusted_domains\n"));
970 *num_domains = 0;
971 *names = NULL;
972 *alt_names = NULL;
973 *dom_sids = NULL;
975 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
976 if (!NT_STATUS_IS_OK(result))
977 return result;
979 result = STATUS_MORE_ENTRIES;
981 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
982 uint32 start_idx, num;
983 char **tmp_names;
984 DOM_SID *tmp_sids;
985 int i;
987 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
988 &lsa_policy, &enum_ctx,
989 &num, &tmp_names,
990 &tmp_sids);
992 if (!NT_STATUS_IS_OK(result) &&
993 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
994 break;
996 start_idx = *num_domains;
997 *num_domains += num;
998 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
999 char *, *num_domains);
1000 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1001 DOM_SID, *num_domains);
1002 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1003 char *, *num_domains);
1004 if ((*names == NULL) || (*dom_sids == NULL) ||
1005 (*alt_names == NULL))
1006 return NT_STATUS_NO_MEMORY;
1008 for (i=0; i<num; i++) {
1009 (*names)[start_idx+i] = tmp_names[i];
1010 (*dom_sids)[start_idx+i] = tmp_sids[i];
1011 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1014 return result;
1017 /* find the lockout policy for a domain */
1018 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1019 TALLOC_CTX *mem_ctx,
1020 SAM_UNK_INFO_12 *lockout_policy)
1022 NTSTATUS result;
1023 struct rpc_pipe_client *cli;
1024 POLICY_HND dom_pol;
1025 SAM_UNK_CTR ctr;
1027 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1029 if ( !winbindd_can_contact_domain( domain ) ) {
1030 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1031 domain->name));
1032 return NT_STATUS_NOT_SUPPORTED;
1035 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1036 if (!NT_STATUS_IS_OK(result)) {
1037 goto done;
1040 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
1041 if (!NT_STATUS_IS_OK(result)) {
1042 goto done;
1045 *lockout_policy = ctr.info.inf12;
1047 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
1048 ctr.info.inf12.bad_attempt_lockout));
1050 done:
1052 return result;
1055 /* find the password policy for a domain */
1056 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1057 TALLOC_CTX *mem_ctx,
1058 SAM_UNK_INFO_1 *password_policy)
1060 NTSTATUS result;
1061 struct rpc_pipe_client *cli;
1062 POLICY_HND dom_pol;
1063 SAM_UNK_CTR ctr;
1065 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1067 if ( !winbindd_can_contact_domain( domain ) ) {
1068 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1069 domain->name));
1070 return NT_STATUS_NOT_SUPPORTED;
1073 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1074 if (!NT_STATUS_IS_OK(result)) {
1075 goto done;
1078 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1079 if (!NT_STATUS_IS_OK(result)) {
1080 goto done;
1083 *password_policy = ctr.info.inf1;
1085 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1086 ctr.info.inf1.min_length_password));
1088 done:
1090 return result;
1094 /* the rpc backend methods are exposed via this structure */
1095 struct winbindd_methods msrpc_methods = {
1096 False,
1097 query_user_list,
1098 enum_dom_groups,
1099 enum_local_groups,
1100 msrpc_name_to_sid,
1101 msrpc_sid_to_name,
1102 msrpc_rids_to_names,
1103 query_user,
1104 lookup_usergroups,
1105 msrpc_lookup_useraliases,
1106 lookup_groupmem,
1107 sequence_number,
1108 msrpc_lockout_policy,
1109 msrpc_password_policy,
1110 trusted_domains,