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 /* convert a single name to a sid in a domain */
187 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
190 enum SID_NAME_USE *type)
195 DOM_SID *sids = NULL;
196 uint32 *types = NULL;
197 const char *full_name;
199 DEBUG(3,("rpc: name_to_sid name=%s\n", name));
201 if (!(mem_ctx = talloc_init_named("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) {
202 DEBUG(0, ("talloc_init failed!\n"));
203 return NT_STATUS_NO_MEMORY;
206 if (!(hnd = cm_get_lsa_handle(domain->name))) {
207 talloc_destroy(mem_ctx);
208 return NT_STATUS_UNSUCCESSFUL;
211 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name);
214 DEBUG(0, ("talloc_asprintf failed!\n"));
215 talloc_destroy(mem_ctx);
216 return NT_STATUS_NO_MEMORY;
219 status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
220 &full_name, &sids, &types);
222 /* Return rid and type if lookup successful */
224 if (NT_STATUS_IS_OK(status)) {
225 sid_copy(sid, &sids[0]);
229 talloc_destroy(mem_ctx);
234 convert a domain SID to a user or group name
236 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
240 enum SID_NAME_USE *type)
248 DEBUG(3,("rpc: sid_to_name\n"));
250 if (!(hnd = cm_get_lsa_handle(domain->name)))
251 return NT_STATUS_UNSUCCESSFUL;
253 status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
254 1, sid, &domains, &names, &types);
256 if (NT_STATUS_IS_OK(status)) {
259 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
262 if (strcasecmp(domain->name, domains[0]) != 0) {
263 DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0]));
264 return NT_STATUS_UNSUCCESSFUL;
270 /* Lookup user information from a rid or username. */
271 static NTSTATUS query_user(struct winbindd_domain *domain,
274 WINBIND_USERINFO *user_info)
278 POLICY_HND dom_pol, user_pol;
279 BOOL got_dom_pol = False, got_user_pol = False;
280 SAM_USERINFO_CTR *ctr;
282 DEBUG(3,("rpc: query_user rid=%u\n", user_rid));
285 if (!(hnd = cm_get_sam_handle(domain->name)))
288 /* Get domain handle */
290 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
291 SEC_RIGHTS_MAXIMUM_ALLOWED,
292 &domain->sid, &dom_pol);
294 if (!NT_STATUS_IS_OK(result))
299 /* Get user handle */
300 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
301 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
303 if (!NT_STATUS_IS_OK(result))
309 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
312 if (!NT_STATUS_IS_OK(result))
315 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
316 got_user_pol = False;
318 user_info->group_rid = ctr->info.id21->group_rid;
319 user_info->acct_name = unistr2_tdup(mem_ctx,
320 &ctr->info.id21->uni_user_name);
321 user_info->full_name = unistr2_tdup(mem_ctx,
322 &ctr->info.id21->uni_full_name);
325 /* Clean up policy handles */
327 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
330 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
335 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
336 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
339 uint32 *num_groups, uint32 **user_gids)
342 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
343 POLICY_HND dom_pol, user_pol;
344 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
345 BOOL got_dom_pol = False, got_user_pol = False;
346 DOM_GID *user_groups;
349 DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid));
353 /* First try cached universal groups from logon */
354 *user_gids = uni_group_cache_fetch(&domain->sid, user_rid, mem_ctx, num_groups);
355 if((*num_groups > 0) && *user_gids) {
363 if (!(hnd = cm_get_sam_handle(domain->name)))
366 /* Get domain handle */
367 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
368 des_access, &domain->sid, &dom_pol);
370 if (!NT_STATUS_IS_OK(result))
375 /* Get user handle */
376 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
377 des_access, user_rid, &user_pol);
379 if (!NT_STATUS_IS_OK(result))
384 /* Query user rids */
385 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
386 num_groups, &user_groups);
388 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
391 (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups));
392 for (i=0;i<(*num_groups);i++) {
393 (*user_gids)[i] = user_groups[i].g_rid;
397 /* Clean up policy handles */
399 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
402 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
408 /* Lookup group membership given a rid. */
409 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
411 uint32 group_rid, uint32 *num_names,
412 uint32 **rid_mem, char ***names,
416 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
417 uint32 i, total_names = 0;
418 POLICY_HND dom_pol, group_pol;
419 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
420 BOOL got_dom_pol = False, got_group_pol = False;
422 DEBUG(3,("rpc: lookup_groupmem rid=%u\n", group_rid));
428 if (!(hnd = cm_get_sam_handle(domain->name)))
431 /* Get domain handle */
433 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
434 des_access, &domain->sid, &dom_pol);
436 if (!NT_STATUS_IS_OK(result))
441 /* Get group handle */
443 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
444 des_access, group_rid, &group_pol);
446 if (!NT_STATUS_IS_OK(result))
449 got_group_pol = True;
451 /* Step #1: Get a list of user rids that are the members of the
454 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
455 &group_pol, num_names, rid_mem,
458 if (!NT_STATUS_IS_OK(result))
461 /* Step #2: Convert list of rids into list of usernames. Do this
462 in bunches of ~1000 to avoid crashing NT4. It looks like there
463 is a buffer overflow or something like that lurking around
466 #define MAX_LOOKUP_RIDS 900
468 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *));
469 *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32));
471 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
472 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
473 uint32 tmp_num_names = 0;
474 char **tmp_names = NULL;
475 uint32 *tmp_types = NULL;
477 /* Lookup a chunk of rids */
479 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
480 &dom_pol, 1000, /* flags */
484 &tmp_names, &tmp_types);
486 if (!NT_STATUS_IS_OK(result))
489 /* Copy result into array. The talloc system will take
490 care of freeing the temporary arrays later on. */
492 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
495 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
498 total_names += tmp_num_names;
501 *num_names = total_names;
505 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
508 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
513 /* find the sequence number for a domain */
514 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
519 uint16 switch_value = 2;
521 uint32 seqnum = DOM_SEQUENCE_NONE;
523 BOOL got_dom_pol = False;
524 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
526 DEBUG(3,("rpc: sequence_number\n"));
528 *seq = DOM_SEQUENCE_NONE;
530 if (!(mem_ctx = talloc_init_named("sequence_number[rpc]")))
531 return NT_STATUS_NO_MEMORY;
535 if (!(hnd = cm_get_sam_handle(domain->name)))
538 /* Get domain handle */
540 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
541 des_access, &domain->sid, &dom_pol);
543 if (!NT_STATUS_IS_OK(result))
548 /* Query domain info */
550 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
553 if (NT_STATUS_IS_OK(result)) {
554 seqnum = ctr.info.inf2.seq_num;
555 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum ));
557 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
558 (unsigned)seqnum, domain->name ));
564 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
566 talloc_destroy(mem_ctx);
573 /* get a list of trusted domains */
574 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
581 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
583 uint32 pref_num_domains = 5;
585 DEBUG(3,("rpc: trusted_domains\n"));
589 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
592 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
593 &hnd->pol, &enum_ctx, &pref_num_domains,
594 num_domains, names, dom_sids);
599 /* find the domain sid for a domain */
600 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
602 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
607 DEBUG(3,("rpc: domain_sid\n"));
609 if (!(mem_ctx = talloc_init_named("domain_sid[rpc]")))
610 return NT_STATUS_NO_MEMORY;
613 if (!(hnd = cm_get_lsa_handle(domain->name)))
616 status = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
617 &hnd->pol, 0x05, level5_dom, sid);
620 talloc_destroy(mem_ctx);
624 /* the rpc backend methods are exposed via this structure */
625 struct winbindd_methods msrpc_methods = {