2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001
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;
44 DEBUG(3,("rpc: query_user_list\n"));
51 if (!(hnd = cm_get_sam_handle(domain->name)))
54 /* Get domain handle */
56 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
57 des_access, &domain->sid, &dom_pol);
59 if (!NT_STATUS_IS_OK(result))
68 uint32 count = 0, start=i;
72 ctr.sam.info1 = &info1;
74 ctx2 = talloc_init_named("winbindd dispinfo");
76 result = NT_STATUS_NO_MEMORY;
80 /* Query display info level 1 */
81 result = cli_samr_query_dispinfo(hnd->cli, ctx2,
83 &count, 0xFFFF, &ctr);
85 if (!NT_STATUS_IS_OK(result) &&
86 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) break;
88 (*num_entries) += count;
90 /* now map the result into the WINBIND_USERINFO structure */
91 (*info) = talloc_realloc(mem_ctx, *info,
92 (*num_entries)*sizeof(WINBIND_USERINFO));
94 result = NT_STATUS_NO_MEMORY;
99 for (j=0;j<count;i++, j++) {
100 (*info)[i].acct_name = unistr2_tdup(mem_ctx, &info1.str[j].uni_acct_name);
101 (*info)[i].full_name = unistr2_tdup(mem_ctx, &info1.str[j].uni_full_name);
102 (*info)[i].user_rid = info1.sam[j].rid_user;
103 /* For the moment we set the primary group for
104 every user to be the Domain Users group.
105 There are serious problems with determining
106 the actual primary group for large domains.
107 This should really be made into a 'winbind
108 force group' smb.conf parameter or
109 something like that. */
110 (*info)[i].group_rid = DOMAIN_GROUP_RID_USERS;
113 talloc_destroy(ctx2);
114 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
119 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
124 /* list all domain groups */
125 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
128 struct acct_info **info)
130 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
138 DEBUG(3,("rpc: enum_dom_groups\n"));
140 if (!(hnd = cm_get_sam_handle(domain->name))) {
141 return NT_STATUS_UNSUCCESSFUL;
144 status = cli_samr_open_domain(hnd->cli, mem_ctx,
145 &hnd->pol, des_access, &domain->sid, &dom_pol);
146 if (!NT_STATUS_IS_OK(status)) {
151 struct acct_info *info2 = NULL;
152 uint32 count = 0, start = *num_entries;
153 TALLOC_CTX *mem_ctx2;
155 mem_ctx2 = talloc_init_named("enum_dom_groups[rpc]");
157 status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol,
159 0xFFFF, /* buffer size? */
162 if (!NT_STATUS_IS_OK(status) &&
163 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
164 talloc_destroy(mem_ctx2);
168 (*info) = talloc_realloc(mem_ctx, *info,
169 sizeof(**info) * ((*num_entries) + count));
171 talloc_destroy(mem_ctx2);
172 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
173 return NT_STATUS_NO_MEMORY;
176 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
177 (*num_entries) += count;
178 talloc_destroy(mem_ctx2);
179 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
181 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
186 /* List all domain groups */
188 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
191 struct acct_info **info)
193 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
201 if ( !(hnd = cm_get_sam_handle(domain->name)) )
202 return NT_STATUS_UNSUCCESSFUL;
204 if ( !NT_STATUS_IS_OK(result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol,
205 des_access, &domain->sid, &dom_pol)) )
211 struct acct_info *info2 = NULL;
212 uint32 count = 0, start = *num_entries;
213 TALLOC_CTX *mem_ctx2;
215 mem_ctx2 = talloc_init_named("enum_dom_local_groups[rpc]");
217 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
218 &start, 0xFFFF, &info2, &count);
220 if ( !NT_STATUS_IS_OK(result)
221 && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
223 talloc_destroy(mem_ctx2);
227 (*info) = talloc_realloc(mem_ctx, *info,
228 sizeof(**info) * ((*num_entries) + count));
230 talloc_destroy(mem_ctx2);
231 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
232 return NT_STATUS_NO_MEMORY;
235 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
236 (*num_entries) += count;
237 talloc_destroy(mem_ctx2);
238 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
240 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
245 /* convert a single name to a sid in a domain */
246 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
249 enum SID_NAME_USE *type)
254 DOM_SID *sids = NULL;
255 uint32 *types = NULL;
256 const char *full_name;
258 DEBUG(3,("rpc: name_to_sid name=%s\n", name));
260 if (!(mem_ctx = talloc_init_named("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) {
261 DEBUG(0, ("talloc_init failed!\n"));
262 return NT_STATUS_NO_MEMORY;
265 if (!(hnd = cm_get_lsa_handle(domain->name))) {
266 talloc_destroy(mem_ctx);
267 return NT_STATUS_UNSUCCESSFUL;
270 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name);
273 DEBUG(0, ("talloc_asprintf failed!\n"));
274 talloc_destroy(mem_ctx);
275 return NT_STATUS_NO_MEMORY;
278 status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
279 &full_name, &sids, &types);
281 /* Return rid and type if lookup successful */
283 if (NT_STATUS_IS_OK(status)) {
284 sid_copy(sid, &sids[0]);
288 talloc_destroy(mem_ctx);
293 convert a domain SID to a user or group name
295 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
299 enum SID_NAME_USE *type)
307 DEBUG(3,("rpc: sid_to_name\n"));
309 if (!(hnd = cm_get_lsa_handle(domain->name)))
310 return NT_STATUS_UNSUCCESSFUL;
312 status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
313 1, sid, &domains, &names, &types);
315 if (NT_STATUS_IS_OK(status)) {
318 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
321 if (strcasecmp(domain->name, domains[0]) != 0) {
322 DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0]));
323 return NT_STATUS_UNSUCCESSFUL;
329 /* Lookup user information from a rid or username. */
330 static NTSTATUS query_user(struct winbindd_domain *domain,
333 WINBIND_USERINFO *user_info)
337 POLICY_HND dom_pol, user_pol;
338 BOOL got_dom_pol = False, got_user_pol = False;
339 SAM_USERINFO_CTR *ctr;
341 DEBUG(3,("rpc: query_user rid=%u\n", user_rid));
344 if (!(hnd = cm_get_sam_handle(domain->name)))
347 /* Get domain handle */
349 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
350 SEC_RIGHTS_MAXIMUM_ALLOWED,
351 &domain->sid, &dom_pol);
353 if (!NT_STATUS_IS_OK(result))
358 /* Get user handle */
359 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
360 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
362 if (!NT_STATUS_IS_OK(result))
368 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
371 if (!NT_STATUS_IS_OK(result))
374 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
375 got_user_pol = False;
377 user_info->user_rid = user_rid;
378 user_info->group_rid = ctr->info.id21->group_rid;
379 user_info->acct_name = unistr2_tdup(mem_ctx,
380 &ctr->info.id21->uni_user_name);
381 user_info->full_name = unistr2_tdup(mem_ctx,
382 &ctr->info.id21->uni_full_name);
385 /* Clean up policy handles */
387 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
390 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
395 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
396 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
399 uint32 *num_groups, uint32 **user_gids)
402 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
403 POLICY_HND dom_pol, user_pol;
404 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
405 BOOL got_dom_pol = False, got_user_pol = False;
406 DOM_GID *user_groups;
409 DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid));
413 /* First try cached universal groups from logon */
414 *user_gids = uni_group_cache_fetch(&domain->sid, user_rid, mem_ctx, num_groups);
415 if((*num_groups > 0) && *user_gids) {
423 if (!(hnd = cm_get_sam_handle(domain->name)))
426 /* Get domain handle */
427 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
428 des_access, &domain->sid, &dom_pol);
430 if (!NT_STATUS_IS_OK(result))
435 /* Get user handle */
436 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
437 des_access, user_rid, &user_pol);
439 if (!NT_STATUS_IS_OK(result))
444 /* Query user rids */
445 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
446 num_groups, &user_groups);
448 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
451 (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups));
452 for (i=0;i<(*num_groups);i++) {
453 (*user_gids)[i] = user_groups[i].g_rid;
457 /* Clean up policy handles */
459 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
462 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
468 /* Lookup group membership given a rid. */
469 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
471 uint32 group_rid, uint32 *num_names,
472 uint32 **rid_mem, char ***names,
476 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
477 uint32 i, total_names = 0;
478 POLICY_HND dom_pol, group_pol;
479 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
480 BOOL got_dom_pol = False, got_group_pol = False;
482 DEBUG(10,("rpc: lookup_groupmem %s rid=%u\n", domain->name, group_rid));
488 if (!(hnd = cm_get_sam_handle(domain->name)))
491 /* Get domain handle */
493 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
494 des_access, &domain->sid, &dom_pol);
496 if (!NT_STATUS_IS_OK(result))
501 /* Get group handle */
503 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
504 des_access, group_rid, &group_pol);
506 if (!NT_STATUS_IS_OK(result))
509 got_group_pol = True;
511 /* Step #1: Get a list of user rids that are the members of the
514 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
515 &group_pol, num_names, rid_mem,
518 if (!NT_STATUS_IS_OK(result))
521 /* Step #2: Convert list of rids into list of usernames. Do this
522 in bunches of ~1000 to avoid crashing NT4. It looks like there
523 is a buffer overflow or something like that lurking around
526 #define MAX_LOOKUP_RIDS 900
528 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *));
529 *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32));
531 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
532 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
533 uint32 tmp_num_names = 0;
534 char **tmp_names = NULL;
535 uint32 *tmp_types = NULL;
537 /* Lookup a chunk of rids */
539 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
540 &dom_pol, 1000, /* flags */
544 &tmp_names, &tmp_types);
546 if (!NT_STATUS_IS_OK(result))
549 /* Copy result into array. The talloc system will take
550 care of freeing the temporary arrays later on. */
552 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
555 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
558 total_names += tmp_num_names;
561 *num_names = total_names;
565 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
568 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
573 /* find the sequence number for a domain */
574 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
579 uint16 switch_value = 2;
581 uint32 seqnum = DOM_SEQUENCE_NONE;
583 BOOL got_dom_pol = False;
584 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
586 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
588 *seq = DOM_SEQUENCE_NONE;
590 if (!(mem_ctx = talloc_init_named("sequence_number[rpc]")))
591 return NT_STATUS_NO_MEMORY;
595 if (!(hnd = cm_get_sam_handle(domain->name)))
598 /* Get domain handle */
600 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
601 des_access, &domain->sid, &dom_pol);
603 if (!NT_STATUS_IS_OK(result))
608 /* Query domain info */
610 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
613 if (NT_STATUS_IS_OK(result)) {
614 seqnum = ctr.info.inf2.seq_num;
615 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum ));
617 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
618 (unsigned)seqnum, domain->name ));
624 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
626 talloc_destroy(mem_ctx);
633 /* get a list of trusted domains */
634 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
642 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
645 DEBUG(3,("rpc: trusted_domains\n"));
650 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
653 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
654 &hnd->pol, &enum_ctx,
655 num_domains, names, dom_sids);
660 /* find the domain sid for a domain */
661 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
663 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
668 DEBUG(3,("rpc: domain_sid\n"));
670 if (!(mem_ctx = talloc_init_named("domain_sid[rpc]")))
671 return NT_STATUS_NO_MEMORY;
674 if (!(hnd = cm_get_lsa_handle(domain->name)))
677 status = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
678 &hnd->pol, 0x05, level5_dom, sid);
681 talloc_destroy(mem_ctx);
685 /* find alternate names list for the domain - none for rpc */
686 static NTSTATUS alternate_name(struct winbindd_domain *domain)
692 /* the rpc backend methods are exposed via this structure */
693 struct winbindd_methods msrpc_methods = {