2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define DBGC_CLASS DBGC_WINBIND
29 /* Query display info for a domain. This returns enough information plus a
30 bit extra to give an overview of domain users for the User Manager
32 static NTSTATUS query_user_list(struct winbindd_domain *domain,
35 WINBIND_USERINFO **info)
38 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
40 BOOL got_dom_pol = False;
41 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
42 int i, start_idx, retry;
44 DEBUG(3,("rpc: query_user_list\n"));
53 if (!(hnd = cm_get_sam_handle(domain->name)))
56 /* Get domain handle */
58 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
59 des_access, &domain->sid, &dom_pol);
61 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
63 if (!NT_STATUS_IS_OK(result))
72 uint32 num_dom_users, *dom_rids, j, size = 0xffff;
73 uint16 acb_mask = ACB_NORMAL;
75 if (!(ctx2 = talloc_init("winbindd enum_users"))) {
76 result = NT_STATUS_NO_MEMORY;
80 result = cli_samr_enum_dom_users(
81 hnd->cli, ctx2, &dom_pol, &start_idx, acb_mask,
82 size, &dom_users, &dom_rids, &num_dom_users);
84 *num_entries += num_dom_users;
86 *info = talloc_realloc(
88 (*num_entries) * sizeof(WINBIND_USERINFO));
91 result = NT_STATUS_NO_MEMORY;
96 for (j = 0; j < num_dom_users; i++, j++) {
97 (*info)[i].acct_name =
98 talloc_strdup(mem_ctx, dom_users[j]);
99 (*info)[i].full_name = talloc_strdup(mem_ctx, "");
100 (*info)[i].user_rid = dom_rids[j];
101 /* For the moment we set the primary group for
102 every user to be the Domain Users group.
103 There are serious problems with determining
104 the actual primary group for large domains.
105 This should really be made into a 'winbind
106 force group' smb.conf parameter or
107 something like that. */
108 (*info)[i].group_rid = DOMAIN_GROUP_RID_USERS;
111 talloc_destroy(ctx2);
113 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
118 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
123 /* list all domain groups */
124 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
127 struct acct_info **info)
129 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
139 DEBUG(3,("rpc: enum_dom_groups\n"));
143 if (!(hnd = cm_get_sam_handle(domain->name)))
144 return NT_STATUS_UNSUCCESSFUL;
146 status = cli_samr_open_domain(hnd->cli, mem_ctx,
147 &hnd->pol, des_access, &domain->sid, &dom_pol);
148 } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
150 if (!NT_STATUS_IS_OK(status))
154 struct acct_info *info2 = NULL;
156 TALLOC_CTX *mem_ctx2;
158 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
160 /* start is updated by this call. */
161 status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol,
163 0xFFFF, /* buffer size? */
166 if (!NT_STATUS_IS_OK(status) &&
167 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
168 talloc_destroy(mem_ctx2);
172 (*info) = talloc_realloc(mem_ctx, *info,
173 sizeof(**info) * ((*num_entries) + count));
175 talloc_destroy(mem_ctx2);
176 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
177 return NT_STATUS_NO_MEMORY;
180 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
181 (*num_entries) += count;
182 talloc_destroy(mem_ctx2);
183 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
185 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
190 /* List all domain groups */
192 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
195 struct acct_info **info)
197 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
208 if ( !(hnd = cm_get_sam_handle(domain->name)) )
209 return NT_STATUS_UNSUCCESSFUL;
211 result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol,
212 des_access, &domain->sid, &dom_pol);
213 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
215 if ( !NT_STATUS_IS_OK(result))
219 struct acct_info *info2 = NULL;
220 uint32 count = 0, start = *num_entries;
221 TALLOC_CTX *mem_ctx2;
223 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
225 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
226 &start, 0xFFFF, &info2, &count);
228 if ( !NT_STATUS_IS_OK(result)
229 && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
231 talloc_destroy(mem_ctx2);
235 (*info) = talloc_realloc(mem_ctx, *info,
236 sizeof(**info) * ((*num_entries) + count));
238 talloc_destroy(mem_ctx2);
239 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
240 return NT_STATUS_NO_MEMORY;
243 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
244 (*num_entries) += count;
245 talloc_destroy(mem_ctx2);
246 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
248 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
253 /* convert a single name to a sid in a domain */
254 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
257 enum SID_NAME_USE *type)
262 DOM_SID *sids = NULL;
263 uint32 *types = NULL;
264 const char *full_name;
267 DEBUG(3,("rpc: name_to_sid name=%s\n", name));
269 if (!(mem_ctx = talloc_init("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) {
270 DEBUG(0, ("talloc_init failed!\n"));
271 return NT_STATUS_NO_MEMORY;
274 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name);
277 DEBUG(0, ("talloc_asprintf failed!\n"));
278 talloc_destroy(mem_ctx);
279 return NT_STATUS_NO_MEMORY;
284 if (!(hnd = cm_get_lsa_handle(domain->name))) {
285 talloc_destroy(mem_ctx);
286 return NT_STATUS_UNSUCCESSFUL;
289 status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
290 &full_name, &sids, &types);
291 } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
293 /* Return rid and type if lookup successful */
295 if (NT_STATUS_IS_OK(status)) {
296 sid_copy(sid, &sids[0]);
300 talloc_destroy(mem_ctx);
305 convert a domain SID to a user or group name
307 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
311 enum SID_NAME_USE *type)
320 DEBUG(3,("rpc: sid_to_name\n"));
324 if (!(hnd = cm_get_lsa_handle(domain->name)))
325 return NT_STATUS_UNSUCCESSFUL;
327 status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
328 1, sid, &domains, &names, &types);
329 } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
331 if (NT_STATUS_IS_OK(status)) {
334 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
337 if (strcasecmp(domain->name, domains[0]) != 0) {
338 DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0]));
339 return NT_STATUS_UNSUCCESSFUL;
345 /* Lookup user information from a rid or username. */
346 static NTSTATUS query_user(struct winbindd_domain *domain,
349 WINBIND_USERINFO *user_info)
353 POLICY_HND dom_pol, user_pol;
354 BOOL got_dom_pol = False, got_user_pol = False;
355 SAM_USERINFO_CTR *ctr;
358 DEBUG(3,("rpc: query_user rid=%u\n", user_rid));
363 if (!(hnd = cm_get_sam_handle(domain->name)))
366 /* Get domain handle */
368 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
369 SEC_RIGHTS_MAXIMUM_ALLOWED,
370 &domain->sid, &dom_pol);
371 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
373 if (!NT_STATUS_IS_OK(result))
378 /* Get user handle */
379 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
380 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
382 if (!NT_STATUS_IS_OK(result))
388 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
391 if (!NT_STATUS_IS_OK(result))
394 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
395 got_user_pol = False;
397 user_info->user_rid = user_rid;
398 user_info->group_rid = ctr->info.id21->group_rid;
399 user_info->acct_name = unistr2_tdup(mem_ctx,
400 &ctr->info.id21->uni_user_name);
401 user_info->full_name = unistr2_tdup(mem_ctx,
402 &ctr->info.id21->uni_full_name);
405 /* Clean up policy handles */
407 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
410 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
415 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
416 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
419 uint32 *num_groups, uint32 **user_gids)
422 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
423 POLICY_HND dom_pol, user_pol;
424 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
425 BOOL got_dom_pol = False, got_user_pol = False;
426 DOM_GID *user_groups;
430 DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid));
434 /* First try cached universal groups from logon */
435 *user_gids = uni_group_cache_fetch(&domain->sid, user_rid, mem_ctx, num_groups);
436 if((*num_groups > 0) && *user_gids) {
446 if (!(hnd = cm_get_sam_handle(domain->name)))
449 /* Get domain handle */
450 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
451 des_access, &domain->sid, &dom_pol);
452 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
454 if (!NT_STATUS_IS_OK(result))
459 /* Get user handle */
460 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
461 des_access, user_rid, &user_pol);
463 if (!NT_STATUS_IS_OK(result))
468 /* Query user rids */
469 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
470 num_groups, &user_groups);
472 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
475 (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups));
476 for (i=0;i<(*num_groups);i++) {
477 (*user_gids)[i] = user_groups[i].g_rid;
481 /* Clean up policy handles */
483 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
486 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
492 /* Lookup group membership given a rid. */
493 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
495 uint32 group_rid, uint32 *num_names,
496 uint32 **rid_mem, char ***names,
500 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
501 uint32 i, total_names = 0;
502 POLICY_HND dom_pol, group_pol;
503 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
504 BOOL got_dom_pol = False, got_group_pol = False;
507 DEBUG(10,("rpc: lookup_groupmem %s rid=%u\n", domain->name, group_rid));
514 if (!(hnd = cm_get_sam_handle(domain->name)))
517 /* Get domain handle */
519 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
520 des_access, &domain->sid, &dom_pol);
521 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
523 if (!NT_STATUS_IS_OK(result))
528 /* Get group handle */
530 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
531 des_access, group_rid, &group_pol);
533 if (!NT_STATUS_IS_OK(result))
536 got_group_pol = True;
538 /* Step #1: Get a list of user rids that are the members of the
541 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
542 &group_pol, num_names, rid_mem,
545 if (!NT_STATUS_IS_OK(result))
548 /* Step #2: Convert list of rids into list of usernames. Do this
549 in bunches of ~1000 to avoid crashing NT4. It looks like there
550 is a buffer overflow or something like that lurking around
553 #define MAX_LOOKUP_RIDS 900
555 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *));
556 *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32));
558 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
559 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
560 uint32 tmp_num_names = 0;
561 char **tmp_names = NULL;
562 uint32 *tmp_types = NULL;
564 /* Lookup a chunk of rids */
566 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
567 &dom_pol, 1000, /* flags */
571 &tmp_names, &tmp_types);
573 if (!NT_STATUS_IS_OK(result))
576 /* Copy result into array. The talloc system will take
577 care of freeing the temporary arrays later on. */
579 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
582 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
585 total_names += tmp_num_names;
588 *num_names = total_names;
592 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
595 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
600 /* find the sequence number for a domain */
601 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
606 uint16 switch_value = 2;
608 uint32 seqnum = DOM_SEQUENCE_NONE;
610 BOOL got_dom_pol = False;
611 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
614 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
616 *seq = DOM_SEQUENCE_NONE;
618 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
619 return NT_STATUS_NO_MEMORY;
624 if (!(hnd = cm_get_sam_handle(domain->name)))
627 /* Get domain handle */
628 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
629 des_access, &domain->sid, &dom_pol);
630 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
632 if (!NT_STATUS_IS_OK(result))
637 /* Query domain info */
639 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
642 if (NT_STATUS_IS_OK(result)) {
643 seqnum = ctr.info.inf2.seq_num;
644 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum ));
646 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
647 (unsigned)seqnum, domain->name ));
653 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
655 talloc_destroy(mem_ctx);
662 /* get a list of trusted domains */
663 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
671 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
675 DEBUG(3,("rpc: trusted_domains\n"));
682 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
685 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
686 &hnd->pol, &enum_ctx,
687 num_domains, names, dom_sids);
688 } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
694 /* find the domain sid for a domain */
695 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
697 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
703 DEBUG(3,("rpc: domain_sid\n"));
705 if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
706 return NT_STATUS_NO_MEMORY;
711 if (!(hnd = cm_get_lsa_handle(domain->name)))
714 status = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
715 &hnd->pol, 0x05, level5_dom, sid);
716 } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
719 talloc_destroy(mem_ctx);
723 /* find alternate names list for the domain - none for rpc */
724 static NTSTATUS alternate_name(struct winbindd_domain *domain)
730 /* the rpc backend methods are exposed via this structure */
731 struct winbindd_methods msrpc_methods = {