r23672: Allow msrpc_name_to_sid() to be called without a domain_name and just a name.
[Samba.git] / source / nsswitch / winbindd_rpc.c
blob31ccdc1f73a4d486a15a58db8eca3c735e2c651a
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 enum winbindd_cmd original_cmd,
260 const char *domain_name,
261 const char *name,
262 DOM_SID *sid,
263 enum lsa_SidType *type)
265 NTSTATUS result;
266 DOM_SID *sids = NULL;
267 enum lsa_SidType *types = NULL;
268 char *full_name = NULL;
269 struct rpc_pipe_client *cli;
270 POLICY_HND lsa_policy;
272 if (name == NULL || *name=='\0') {
273 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
274 } else if (domain_name == NULL || *domain_name == '\0') {
275 full_name = talloc_asprintf(mem_ctx, "%s", name);
276 } else {
277 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
279 if (!full_name) {
280 DEBUG(0, ("talloc_asprintf failed!\n"));
281 return NT_STATUS_NO_MEMORY;
284 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
286 ws_name_return( full_name, WB_REPLACE_CHAR );
288 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
290 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
291 if (!NT_STATUS_IS_OK(result))
292 return result;
294 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
295 (const char**) &full_name, NULL, 1, &sids, &types);
297 if (!NT_STATUS_IS_OK(result))
298 return result;
300 /* Return rid and type if lookup successful */
302 sid_copy(sid, &sids[0]);
303 *type = types[0];
305 return NT_STATUS_OK;
309 convert a domain SID to a user or group name
311 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
312 TALLOC_CTX *mem_ctx,
313 const DOM_SID *sid,
314 char **domain_name,
315 char **name,
316 enum lsa_SidType *type)
318 char **domains;
319 char **names;
320 enum lsa_SidType *types;
321 NTSTATUS result;
322 struct rpc_pipe_client *cli;
323 POLICY_HND lsa_policy;
325 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
326 domain->name ));
328 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
329 if (!NT_STATUS_IS_OK(result)) {
330 DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
331 nt_errstr(result)));
332 return result;
336 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
337 1, sid, &domains, &names, &types);
338 if (!NT_STATUS_IS_OK(result)) {
339 DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n",
340 nt_errstr(result)));
341 return result;
344 *type = (enum lsa_SidType)types[0];
345 *domain_name = domains[0];
346 *name = names[0];
348 ws_name_replace( *name, WB_REPLACE_CHAR );
350 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
351 return NT_STATUS_OK;
354 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
355 TALLOC_CTX *mem_ctx,
356 const DOM_SID *sid,
357 uint32 *rids,
358 size_t num_rids,
359 char **domain_name,
360 char ***names,
361 enum lsa_SidType **types)
363 char **domains;
364 NTSTATUS result;
365 struct rpc_pipe_client *cli;
366 POLICY_HND lsa_policy;
367 DOM_SID *sids;
368 size_t i;
369 char **ret_names;
371 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
373 if (num_rids) {
374 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
375 if (sids == NULL) {
376 return NT_STATUS_NO_MEMORY;
378 } else {
379 sids = NULL;
382 for (i=0; i<num_rids; i++) {
383 if (!sid_compose(&sids[i], sid, rids[i])) {
384 return NT_STATUS_INTERNAL_ERROR;
388 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
389 if (!NT_STATUS_IS_OK(result)) {
390 return result;
393 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
394 num_rids, sids, &domains,
395 names, types);
396 if (!NT_STATUS_IS_OK(result) &&
397 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
398 return result;
401 ret_names = *names;
402 for (i=0; i<num_rids; i++) {
403 if ((*types)[i] != SID_NAME_UNKNOWN) {
404 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
405 *domain_name = domains[i];
409 return result;
412 /* Lookup user information from a rid or username. */
413 static NTSTATUS query_user(struct winbindd_domain *domain,
414 TALLOC_CTX *mem_ctx,
415 const DOM_SID *user_sid,
416 WINBIND_USERINFO *user_info)
418 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
419 POLICY_HND dom_pol, user_pol;
420 SAM_USERINFO_CTR *ctr;
421 fstring sid_string;
422 uint32 user_rid;
423 NET_USER_INFO_3 *user;
424 struct rpc_pipe_client *cli;
426 DEBUG(3,("rpc: query_user sid=%s\n",
427 sid_to_string(sid_string, user_sid)));
429 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
430 return NT_STATUS_UNSUCCESSFUL;
432 user_info->homedir = NULL;
433 user_info->shell = NULL;
434 user_info->primary_gid = (gid_t)-1;
436 /* try netsamlogon cache first */
438 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
441 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
442 sid_string_static(user_sid)));
444 sid_compose(&user_info->user_sid, &domain->sid, user->user_rid);
445 sid_compose(&user_info->group_sid, &domain->sid,
446 user->group_rid);
448 user_info->acct_name = unistr2_tdup(mem_ctx,
449 &user->uni_user_name);
450 user_info->full_name = unistr2_tdup(mem_ctx,
451 &user->uni_full_name);
453 TALLOC_FREE(user);
455 return NT_STATUS_OK;
458 if ( !winbindd_can_contact_domain( domain ) ) {
459 DEBUG(10,("query_user: No incoming trust for domain %s\n",
460 domain->name));
461 return NT_STATUS_OK;
464 if ( !winbindd_can_contact_domain( domain ) ) {
465 DEBUG(10,("query_user: No incoming trust for domain %s\n",
466 domain->name));
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 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
479 &user_pol);
481 if (!NT_STATUS_IS_OK(result))
482 return result;
484 /* Get user info */
485 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
486 0x15, &ctr);
488 rpccli_samr_close(cli, mem_ctx, &user_pol);
490 if (!NT_STATUS_IS_OK(result))
491 return result;
493 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
494 sid_compose(&user_info->group_sid, &domain->sid,
495 ctr->info.id21->group_rid);
496 user_info->acct_name = unistr2_tdup(mem_ctx,
497 &ctr->info.id21->uni_user_name);
498 user_info->full_name = unistr2_tdup(mem_ctx,
499 &ctr->info.id21->uni_full_name);
500 user_info->homedir = NULL;
501 user_info->shell = NULL;
502 user_info->primary_gid = (gid_t)-1;
504 return NT_STATUS_OK;
507 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
508 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
509 TALLOC_CTX *mem_ctx,
510 const DOM_SID *user_sid,
511 uint32 *num_groups, DOM_SID **user_grpsids)
513 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
514 POLICY_HND dom_pol, user_pol;
515 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
516 DOM_GID *user_groups;
517 unsigned int i;
518 fstring sid_string;
519 uint32 user_rid;
520 struct rpc_pipe_client *cli;
522 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
523 sid_to_string(sid_string, user_sid)));
525 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
526 return NT_STATUS_UNSUCCESSFUL;
528 *num_groups = 0;
529 *user_grpsids = NULL;
531 /* so lets see if we have a cached user_info_3 */
532 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
533 num_groups, user_grpsids);
535 if (NT_STATUS_IS_OK(result)) {
536 return NT_STATUS_OK;
539 if ( !winbindd_can_contact_domain( domain ) ) {
540 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
541 domain->name));
543 /* Tell the cache manager not to remember this one */
545 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
548 /* no cache; hit the wire */
550 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
551 if (!NT_STATUS_IS_OK(result))
552 return result;
554 /* Get user handle */
555 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
556 des_access, user_rid, &user_pol);
558 if (!NT_STATUS_IS_OK(result))
559 return result;
561 /* Query user rids */
562 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
563 num_groups, &user_groups);
565 rpccli_samr_close(cli, mem_ctx, &user_pol);
567 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
568 return result;
570 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
571 if (!(*user_grpsids))
572 return NT_STATUS_NO_MEMORY;
574 for (i=0;i<(*num_groups);i++) {
575 sid_copy(&((*user_grpsids)[i]), &domain->sid);
576 sid_append_rid(&((*user_grpsids)[i]),
577 user_groups[i].g_rid);
580 return NT_STATUS_OK;
583 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
584 TALLOC_CTX *mem_ctx,
585 uint32 num_sids, const DOM_SID *sids,
586 uint32 *num_aliases, uint32 **alias_rids)
588 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
589 POLICY_HND dom_pol;
590 DOM_SID2 *query_sids;
591 uint32 num_query_sids = 0;
592 int i;
593 struct rpc_pipe_client *cli;
594 uint32 *alias_rids_query, num_aliases_query;
595 int rangesize = MAX_SAM_ENTRIES_W2K;
596 uint32 total_sids = 0;
597 int num_queries = 1;
599 *num_aliases = 0;
600 *alias_rids = NULL;
602 DEBUG(3,("rpc: lookup_useraliases\n"));
604 if ( !winbindd_can_contact_domain( domain ) ) {
605 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
606 domain->name));
607 return NT_STATUS_OK;
610 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
611 if (!NT_STATUS_IS_OK(result))
612 return result;
614 do {
615 /* prepare query */
617 num_query_sids = MIN(num_sids - total_sids, rangesize);
619 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
620 num_queries, num_query_sids));
622 if (num_query_sids) {
623 query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
624 if (query_sids == NULL) {
625 return NT_STATUS_NO_MEMORY;
627 } else {
628 query_sids = NULL;
631 for (i=0; i<num_query_sids; i++) {
632 sid_copy(&query_sids[i].sid, &sids[total_sids++]);
633 query_sids[i].num_auths = query_sids[i].sid.num_auths;
636 /* do request */
638 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
639 num_query_sids, query_sids,
640 &num_aliases_query,
641 &alias_rids_query);
643 if (!NT_STATUS_IS_OK(result)) {
644 *num_aliases = 0;
645 *alias_rids = NULL;
646 TALLOC_FREE(query_sids);
647 goto done;
650 /* process output */
652 for (i=0; i<num_aliases_query; i++) {
653 size_t na = *num_aliases;
654 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
655 alias_rids, &na)) {
656 return NT_STATUS_NO_MEMORY;
658 *num_aliases = na;
661 TALLOC_FREE(query_sids);
663 num_queries++;
665 } while (total_sids < num_sids);
667 done:
668 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
669 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
671 return result;
675 /* Lookup group membership given a rid. */
676 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
677 TALLOC_CTX *mem_ctx,
678 const DOM_SID *group_sid, uint32 *num_names,
679 DOM_SID **sid_mem, char ***names,
680 uint32 **name_types)
682 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
683 uint32 i, total_names = 0;
684 POLICY_HND dom_pol, group_pol;
685 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
686 uint32 *rid_mem = NULL;
687 uint32 group_rid;
688 unsigned int j;
689 fstring sid_string;
690 struct rpc_pipe_client *cli;
691 unsigned int orig_timeout;
693 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
694 sid_to_string(sid_string, group_sid)));
696 if ( !winbindd_can_contact_domain( domain ) ) {
697 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
698 domain->name));
699 return NT_STATUS_OK;
702 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
703 return NT_STATUS_UNSUCCESSFUL;
705 *num_names = 0;
707 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
708 if (!NT_STATUS_IS_OK(result))
709 return result;
711 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
712 des_access, group_rid, &group_pol);
714 if (!NT_STATUS_IS_OK(result))
715 return result;
717 /* Step #1: Get a list of user rids that are the members of the
718 group. */
720 /* This call can take a long time - allow the server to time out.
721 35 seconds should do it. */
723 orig_timeout = cli_set_timeout(cli->cli, 35000);
725 result = rpccli_samr_query_groupmem(cli, mem_ctx,
726 &group_pol, num_names, &rid_mem,
727 name_types);
729 /* And restore our original timeout. */
730 cli_set_timeout(cli->cli, orig_timeout);
732 rpccli_samr_close(cli, mem_ctx, &group_pol);
734 if (!NT_STATUS_IS_OK(result))
735 return result;
737 if (!*num_names) {
738 names = NULL;
739 name_types = NULL;
740 sid_mem = NULL;
741 return NT_STATUS_OK;
744 /* Step #2: Convert list of rids into list of usernames. Do this
745 in bunches of ~1000 to avoid crashing NT4. It looks like there
746 is a buffer overflow or something like that lurking around
747 somewhere. */
749 #define MAX_LOOKUP_RIDS 900
751 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
752 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
753 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
755 for (j=0;j<(*num_names);j++)
756 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
758 if (*num_names>0 && (!*names || !*name_types))
759 return NT_STATUS_NO_MEMORY;
761 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
762 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
763 uint32 tmp_num_names = 0;
764 char **tmp_names = NULL;
765 uint32 *tmp_types = NULL;
767 /* Lookup a chunk of rids */
769 result = rpccli_samr_lookup_rids(cli, mem_ctx,
770 &dom_pol,
771 num_lookup_rids,
772 &rid_mem[i],
773 &tmp_num_names,
774 &tmp_names, &tmp_types);
776 /* see if we have a real error (and yes the
777 STATUS_SOME_UNMAPPED is the one returned from 2k) */
779 if (!NT_STATUS_IS_OK(result) &&
780 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
781 return result;
783 /* Copy result into array. The talloc system will take
784 care of freeing the temporary arrays later on. */
786 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
787 tmp_num_names);
789 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
790 tmp_num_names);
792 total_names += tmp_num_names;
795 *num_names = total_names;
797 return NT_STATUS_OK;
800 #ifdef HAVE_LDAP
802 #include <ldap.h>
804 static int get_ldap_seq(const char *server, int port, uint32 *seq)
806 int ret = -1;
807 struct timeval to;
808 const char *attrs[] = {"highestCommittedUSN", NULL};
809 LDAPMessage *res = NULL;
810 char **values = NULL;
811 LDAP *ldp = NULL;
813 *seq = DOM_SEQUENCE_NONE;
816 * Parameterised (5) second timeout on open. This is needed as the
817 * search timeout doesn't seem to apply to doing an open as well. JRA.
820 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
821 if (ldp == NULL)
822 return -1;
824 /* Timeout if no response within 20 seconds. */
825 to.tv_sec = 10;
826 to.tv_usec = 0;
828 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
829 CONST_DISCARD(char **, attrs), 0, &to, &res))
830 goto done;
832 if (ldap_count_entries(ldp, res) != 1)
833 goto done;
835 values = ldap_get_values(ldp, res, "highestCommittedUSN");
836 if (!values || !values[0])
837 goto done;
839 *seq = atoi(values[0]);
840 ret = 0;
842 done:
844 if (values)
845 ldap_value_free(values);
846 if (res)
847 ldap_msgfree(res);
848 if (ldp)
849 ldap_unbind(ldp);
850 return ret;
853 /**********************************************************************
854 Get the sequence number for a Windows AD native mode domain using
855 LDAP queries.
856 **********************************************************************/
858 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
860 int ret = -1;
861 fstring ipstr;
863 fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
864 if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
865 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
866 "number for Domain (%s) from DC (%s)\n",
867 domain->name, ipstr));
869 return ret;
872 #endif /* HAVE_LDAP */
874 /* find the sequence number for a domain */
875 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
877 TALLOC_CTX *mem_ctx;
878 SAM_UNK_CTR ctr;
879 NTSTATUS result;
880 POLICY_HND dom_pol;
881 BOOL got_seq_num = False;
882 struct rpc_pipe_client *cli;
884 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
886 if ( !winbindd_can_contact_domain( domain ) ) {
887 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
888 domain->name));
889 *seq = time(NULL);
890 return NT_STATUS_OK;
893 *seq = DOM_SEQUENCE_NONE;
895 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
896 return NT_STATUS_NO_MEMORY;
898 #ifdef HAVE_LDAP
899 if ( domain->active_directory )
901 int res;
903 DEBUG(8,("using get_ldap_seq() to retrieve the "
904 "sequence number\n"));
906 res = get_ldap_sequence_number( domain, seq );
907 if (res == 0)
909 result = NT_STATUS_OK;
910 DEBUG(10,("domain_sequence_number: LDAP for "
911 "domain %s is %u\n",
912 domain->name, *seq));
913 goto done;
916 DEBUG(10,("domain_sequence_number: failed to get LDAP "
917 "sequence number for domain %s\n",
918 domain->name ));
920 #endif /* HAVE_LDAP */
922 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
923 if (!NT_STATUS_IS_OK(result)) {
924 goto done;
927 /* Query domain info */
929 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
931 if (NT_STATUS_IS_OK(result)) {
932 *seq = ctr.info.inf8.seq_num;
933 got_seq_num = True;
934 goto seq_num;
937 /* retry with info-level 2 in case the dc does not support info-level 8
938 * (like all older samba2 and samba3 dc's - Guenther */
940 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
942 if (NT_STATUS_IS_OK(result)) {
943 *seq = ctr.info.inf2.seq_num;
944 got_seq_num = True;
947 seq_num:
948 if (got_seq_num) {
949 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
950 domain->name, (unsigned)*seq));
951 } else {
952 DEBUG(10,("domain_sequence_number: failed to get sequence "
953 "number (%u) for domain %s\n",
954 (unsigned)*seq, domain->name ));
957 done:
959 talloc_destroy(mem_ctx);
961 return result;
964 /* get a list of trusted domains */
965 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
966 TALLOC_CTX *mem_ctx,
967 uint32 *num_domains,
968 char ***names,
969 char ***alt_names,
970 DOM_SID **dom_sids)
972 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
973 uint32 enum_ctx = 0;
974 struct rpc_pipe_client *cli;
975 POLICY_HND lsa_policy;
977 DEBUG(3,("rpc: trusted_domains\n"));
979 *num_domains = 0;
980 *names = NULL;
981 *alt_names = NULL;
982 *dom_sids = NULL;
984 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
985 if (!NT_STATUS_IS_OK(result))
986 return result;
988 result = STATUS_MORE_ENTRIES;
990 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
991 uint32 start_idx, num;
992 char **tmp_names;
993 DOM_SID *tmp_sids;
994 int i;
996 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
997 &lsa_policy, &enum_ctx,
998 &num, &tmp_names,
999 &tmp_sids);
1001 if (!NT_STATUS_IS_OK(result) &&
1002 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1003 break;
1005 start_idx = *num_domains;
1006 *num_domains += num;
1007 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1008 char *, *num_domains);
1009 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1010 DOM_SID, *num_domains);
1011 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1012 char *, *num_domains);
1013 if ((*names == NULL) || (*dom_sids == NULL) ||
1014 (*alt_names == NULL))
1015 return NT_STATUS_NO_MEMORY;
1017 for (i=0; i<num; i++) {
1018 (*names)[start_idx+i] = tmp_names[i];
1019 (*dom_sids)[start_idx+i] = tmp_sids[i];
1020 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1023 return result;
1026 /* find the lockout policy for a domain */
1027 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1028 TALLOC_CTX *mem_ctx,
1029 SAM_UNK_INFO_12 *lockout_policy)
1031 NTSTATUS result;
1032 struct rpc_pipe_client *cli;
1033 POLICY_HND dom_pol;
1034 SAM_UNK_CTR ctr;
1036 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1038 if ( !winbindd_can_contact_domain( domain ) ) {
1039 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1040 domain->name));
1041 return NT_STATUS_NOT_SUPPORTED;
1044 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1045 if (!NT_STATUS_IS_OK(result)) {
1046 goto done;
1049 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
1050 if (!NT_STATUS_IS_OK(result)) {
1051 goto done;
1054 *lockout_policy = ctr.info.inf12;
1056 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
1057 ctr.info.inf12.bad_attempt_lockout));
1059 done:
1061 return result;
1064 /* find the password policy for a domain */
1065 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1066 TALLOC_CTX *mem_ctx,
1067 SAM_UNK_INFO_1 *password_policy)
1069 NTSTATUS result;
1070 struct rpc_pipe_client *cli;
1071 POLICY_HND dom_pol;
1072 SAM_UNK_CTR ctr;
1074 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1076 if ( !winbindd_can_contact_domain( domain ) ) {
1077 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1078 domain->name));
1079 return NT_STATUS_NOT_SUPPORTED;
1082 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1083 if (!NT_STATUS_IS_OK(result)) {
1084 goto done;
1087 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1088 if (!NT_STATUS_IS_OK(result)) {
1089 goto done;
1092 *password_policy = ctr.info.inf1;
1094 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1095 ctr.info.inf1.min_length_password));
1097 done:
1099 return result;
1103 /* the rpc backend methods are exposed via this structure */
1104 struct winbindd_methods msrpc_methods = {
1105 False,
1106 query_user_list,
1107 enum_dom_groups,
1108 enum_local_groups,
1109 msrpc_name_to_sid,
1110 msrpc_sid_to_name,
1111 msrpc_rids_to_names,
1112 query_user,
1113 lookup_usergroups,
1114 msrpc_lookup_useraliases,
1115 lookup_groupmem,
1116 sequence_number,
1117 msrpc_lockout_policy,
1118 msrpc_password_policy,
1119 trusted_domains,