2 Unix SMB/Netbios 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.
26 /* Query display info for a domain. This returns enough information plus a
27 bit extra to give an overview of domain users for the User Manager
29 static NTSTATUS query_user_list(struct winbindd_domain *domain,
31 uint32 *start_ndx, uint32 *num_entries,
32 WINBIND_USERINFO **info)
35 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
37 BOOL got_dom_pol = False;
38 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
45 if (!(hnd = cm_get_sam_handle(domain->name)))
48 /* Get domain handle */
50 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
51 des_access, &domain->sid, &dom_pol);
53 if (!NT_STATUS_IS_OK(result))
58 ctr.sam.info1 = &info1;
60 /* Query display info level 1 */
61 result = cli_samr_query_dispinfo(hnd->cli, mem_ctx,
62 &dom_pol, start_ndx, 1,
63 num_entries, 0xffff, &ctr);
65 /* now map the result into the WINBIND_USERINFO structure */
66 (*info) = (WINBIND_USERINFO *)talloc(mem_ctx, (*num_entries)*sizeof(WINBIND_USERINFO));
68 return NT_STATUS_NO_MEMORY;
71 for (i=0;i<*num_entries;i++) {
72 (*info)[i].acct_name = unistr2_tdup(mem_ctx, &info1.str[i].uni_acct_name);
73 (*info)[i].full_name = unistr2_tdup(mem_ctx, &info1.str[i].uni_full_name);
74 (*info)[i].user_rid = info1.sam[i].rid_user;
75 /* For the moment we set the primary group for every user to be the
76 Domain Users group. There are serious problems with determining
77 the actual primary group for large domains. This should really
78 be made into a 'winbind force group' smb.conf parameter or
79 something like that. */
80 (*info)[i].group_rid = DOMAIN_GROUP_RID_USERS;
86 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
91 /* list all domain groups */
92 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
94 uint32 *start_ndx, uint32 *num_entries,
95 struct acct_info **info)
97 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
104 if (!(hnd = cm_get_sam_handle(domain->name))) {
105 return NT_STATUS_UNSUCCESSFUL;
108 status = cli_samr_open_domain(hnd->cli, mem_ctx,
109 &hnd->pol, des_access, &domain->sid, &dom_pol);
110 if (!NT_STATUS_IS_OK(status)) {
114 status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx, &dom_pol,
116 0x8000, /* buffer size? */
119 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
124 /* convert a single name to a sid in a domain */
125 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
128 enum SID_NAME_USE *type)
133 DOM_SID *sids = NULL;
134 uint32 *types = NULL;
137 if (!(mem_ctx = talloc_init()))
138 return NT_STATUS_NO_MEMORY;
140 if (!(hnd = cm_get_lsa_handle(domain->name)))
141 return NT_STATUS_UNSUCCESSFUL;
143 status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, &name,
144 &sids, &types, &num_sids);
146 /* Return rid and type if lookup successful */
147 if (NT_STATUS_IS_OK(status)) {
148 sid_copy(sid, &sids[0]);
152 talloc_destroy(mem_ctx);
157 convert a domain SID to a user or group name
159 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
163 enum SID_NAME_USE *type)
171 if (!(hnd = cm_get_lsa_handle(domain->name)))
172 return NT_STATUS_UNSUCCESSFUL;
174 status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
175 1, sid, &names, &types,
178 if (NT_STATUS_IS_OK(status)) {
181 DEBUG(5,("Mapped sid to %s\n", *name));
187 /* Lookup user information from a rid or username. */
188 static NTSTATUS query_user(struct winbindd_domain *domain,
191 WINBIND_USERINFO *user_info)
195 POLICY_HND dom_pol, user_pol;
196 BOOL got_dom_pol = False, got_user_pol = False;
197 SAM_USERINFO_CTR *ctr;
200 if (!(hnd = cm_get_sam_handle(domain->name)))
203 /* Get domain handle */
205 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
206 SEC_RIGHTS_MAXIMUM_ALLOWED,
207 &domain->sid, &dom_pol);
209 if (!NT_STATUS_IS_OK(result))
214 /* Get user handle */
215 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
216 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
218 if (!NT_STATUS_IS_OK(result))
222 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
225 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
227 user_info->group_rid = ctr->info.id21->group_rid;
228 user_info->acct_name = unistr2_tdup(mem_ctx,
229 &ctr->info.id21->uni_user_name);
230 user_info->full_name = unistr2_tdup(mem_ctx,
231 &ctr->info.id21->uni_full_name);
234 /* Clean up policy handles */
236 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
239 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
244 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
245 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
248 uint32 *num_groups, uint32 **user_gids)
251 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
252 POLICY_HND dom_pol, user_pol;
253 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
254 BOOL got_dom_pol = False, got_user_pol = False;
255 DOM_GID *user_groups;
259 if (!(hnd = cm_get_sam_handle(domain->name)))
262 /* Get domain handle */
263 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
264 des_access, &domain->sid, &dom_pol);
266 if (!NT_STATUS_IS_OK(result))
271 /* Get user handle */
272 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
273 des_access, user_rid, &user_pol);
275 if (!NT_STATUS_IS_OK(result))
280 /* Query user rids */
281 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
282 num_groups, &user_groups);
284 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
287 (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups));
288 for (i=0;i<(*num_groups);i++) {
289 (*user_gids)[i] = user_groups[i].g_rid;
293 /* Clean up policy handles */
295 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
298 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
304 /* Lookup group membership given a rid. */
305 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
307 uint32 group_rid, uint32 *num_names,
308 uint32 **rid_mem, char ***names,
312 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
313 uint32 i, total_names = 0;
314 POLICY_HND dom_pol, group_pol;
315 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
316 BOOL got_dom_pol = False, got_group_pol = False;
320 if (!(hnd = cm_get_sam_handle(domain->name)))
323 /* Get domain handle */
325 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
326 des_access, &domain->sid, &dom_pol);
328 if (!NT_STATUS_IS_OK(result))
333 /* Get group handle */
335 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
336 des_access, group_rid, &group_pol);
338 if (!NT_STATUS_IS_OK(result))
341 got_group_pol = True;
343 /* Step #1: Get a list of user rids that are the members of the
346 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
347 &group_pol, num_names, rid_mem,
350 if (!NT_STATUS_IS_OK(result))
353 /* Step #2: Convert list of rids into list of usernames. Do this
354 in bunches of ~1000 to avoid crashing NT4. It looks like there
355 is a buffer overflow or something like that lurking around
358 #define MAX_LOOKUP_RIDS 900
360 *names = talloc(mem_ctx, *num_names * sizeof(char *));
361 *name_types = talloc(mem_ctx, *num_names * sizeof(uint32));
363 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
364 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
365 uint32 tmp_num_names = 0;
366 char **tmp_names = NULL;
367 uint32 *tmp_types = NULL;
369 /* Lookup a chunk of rids */
371 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
372 &dom_pol, 1000, /* flags */
376 &tmp_names, &tmp_types);
378 if (!NT_STATUS_IS_OK(result))
381 /* Copy result into array. The talloc system will take
382 care of freeing the temporary arrays later on. */
384 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
387 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
390 total_names += tmp_num_names;
393 *num_names = total_names;
397 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
400 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
405 /* find the sequence number for a domain */
406 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
411 uint16 switch_value = 2;
413 uint32 seqnum = DOM_SEQUENCE_NONE;
415 BOOL got_dom_pol = False;
416 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
418 *seq = DOM_SEQUENCE_NONE;
420 if (!(mem_ctx = talloc_init()))
421 return NT_STATUS_NO_MEMORY;
425 if (!(hnd = cm_get_sam_handle(domain->name)))
428 /* Get domain handle */
430 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
431 des_access, &domain->sid, &dom_pol);
433 if (!NT_STATUS_IS_OK(result))
438 /* Query domain info */
440 result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
443 if (NT_STATUS_IS_OK(result)) {
444 seqnum = ctr.info.inf2.seq_num;
445 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum ));
447 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
448 (unsigned)seqnum, domain->name ));
454 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
456 talloc_destroy(mem_ctx);
463 /* get a list of trusted domains */
464 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
471 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
474 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
477 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
478 &hnd->pol, &enum_ctx, num_domains,
484 /* find the domain sid for a domain */
485 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
487 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
492 if (!(mem_ctx = talloc_init()))
493 return NT_STATUS_NO_MEMORY;
496 if (!(hnd = cm_get_lsa_handle(domain->name)))
499 status = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
500 &hnd->pol, 0x05, level5_dom, sid);
503 talloc_destroy(mem_ctx);
507 /* the rpc backend methods are exposed via this structure */
508 struct winbindd_methods msrpc_methods = {