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
30 /* Query display info for a domain. This returns enough information plus a
31 bit extra to give an overview of domain users for the User Manager
33 static NTSTATUS
query_user_list(struct winbindd_domain
*domain
,
36 WINBIND_USERINFO
**info
)
39 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
41 BOOL got_dom_pol
= False
;
42 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
43 unsigned int i
, start_idx
, retry
;
45 DEBUG(3,("rpc: query_user_list\n"));
54 if (!(hnd
= cm_get_sam_handle(domain
->name
)))
57 /* Get domain handle */
59 result
= cli_samr_open_domain(hnd
->cli
, mem_ctx
, &hnd
->pol
,
60 des_access
, &domain
->sid
, &dom_pol
);
62 } while (!NT_STATUS_IS_OK(result
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
64 if (!NT_STATUS_IS_OK(result
))
73 uint32 num_dom_users
, *dom_rids
, j
, size
= 0xffff;
74 uint16 acb_mask
= ACB_NORMAL
;
76 if (!(ctx2
= talloc_init("winbindd enum_users"))) {
77 result
= NT_STATUS_NO_MEMORY
;
81 result
= cli_samr_enum_dom_users(
82 hnd
->cli
, ctx2
, &dom_pol
, &start_idx
, acb_mask
,
83 size
, &dom_users
, &dom_rids
, &num_dom_users
);
85 *num_entries
+= num_dom_users
;
87 *info
= talloc_realloc(
89 (*num_entries
) * sizeof(WINBIND_USERINFO
));
92 result
= NT_STATUS_NO_MEMORY
;
97 for (j
= 0; j
< num_dom_users
; i
++, j
++) {
98 (*info
)[i
].acct_name
=
99 talloc_strdup(mem_ctx
, dom_users
[j
]);
100 (*info
)[i
].full_name
= talloc_strdup(mem_ctx
, "");
101 (*info
)[i
].user_sid
= rid_to_talloced_sid(domain
, mem_ctx
, dom_rids
[j
]);
102 /* For the moment we set the primary group for
103 every user to be the Domain Users group.
104 There are serious problems with determining
105 the actual primary group for large domains.
106 This should really be made into a 'winbind
107 force group' smb.conf parameter or
108 something like that. */
110 = rid_to_talloced_sid(domain
,
112 DOMAIN_GROUP_RID_USERS
);
115 talloc_destroy(ctx2
);
117 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
122 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
127 /* list all domain groups */
128 static NTSTATUS
enum_dom_groups(struct winbindd_domain
*domain
,
131 struct acct_info
**info
)
133 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
143 DEBUG(3,("rpc: enum_dom_groups\n"));
147 if (!(hnd
= cm_get_sam_handle(domain
->name
)))
148 return NT_STATUS_UNSUCCESSFUL
;
150 status
= cli_samr_open_domain(hnd
->cli
, mem_ctx
,
151 &hnd
->pol
, des_access
, &domain
->sid
, &dom_pol
);
152 } while (!NT_STATUS_IS_OK(status
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
154 if (!NT_STATUS_IS_OK(status
))
158 struct acct_info
*info2
= NULL
;
160 TALLOC_CTX
*mem_ctx2
;
162 mem_ctx2
= talloc_init("enum_dom_groups[rpc]");
164 /* start is updated by this call. */
165 status
= cli_samr_enum_dom_groups(hnd
->cli
, mem_ctx2
, &dom_pol
,
167 0xFFFF, /* buffer size? */
170 if (!NT_STATUS_IS_OK(status
) &&
171 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
172 talloc_destroy(mem_ctx2
);
176 (*info
) = talloc_realloc(mem_ctx
, *info
,
177 sizeof(**info
) * ((*num_entries
) + count
));
179 talloc_destroy(mem_ctx2
);
180 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
181 return NT_STATUS_NO_MEMORY
;
184 memcpy(&(*info
)[*num_entries
], info2
, count
*sizeof(*info2
));
185 (*num_entries
) += count
;
186 talloc_destroy(mem_ctx2
);
187 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
189 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
194 /* List all domain groups */
196 static NTSTATUS
enum_local_groups(struct winbindd_domain
*domain
,
199 struct acct_info
**info
)
201 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
212 if ( !(hnd
= cm_get_sam_handle(domain
->name
)) )
213 return NT_STATUS_UNSUCCESSFUL
;
215 result
= cli_samr_open_domain( hnd
->cli
, mem_ctx
, &hnd
->pol
,
216 des_access
, &domain
->sid
, &dom_pol
);
217 } while (!NT_STATUS_IS_OK(result
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
219 if ( !NT_STATUS_IS_OK(result
))
223 struct acct_info
*info2
= NULL
;
224 uint32 count
= 0, start
= *num_entries
;
225 TALLOC_CTX
*mem_ctx2
;
227 mem_ctx2
= talloc_init("enum_dom_local_groups[rpc]");
229 result
= cli_samr_enum_als_groups( hnd
->cli
, mem_ctx2
, &dom_pol
,
230 &start
, 0xFFFF, &info2
, &count
);
232 if ( !NT_STATUS_IS_OK(result
)
233 && !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
) )
235 talloc_destroy(mem_ctx2
);
239 (*info
) = talloc_realloc(mem_ctx
, *info
,
240 sizeof(**info
) * ((*num_entries
) + count
));
242 talloc_destroy(mem_ctx2
);
243 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
244 return NT_STATUS_NO_MEMORY
;
247 memcpy(&(*info
)[*num_entries
], info2
, count
*sizeof(*info2
));
248 (*num_entries
) += count
;
249 talloc_destroy(mem_ctx2
);
250 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
252 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
257 /* convert a single name to a sid in a domain */
258 static NTSTATUS
name_to_sid(struct winbindd_domain
*domain
,
262 enum SID_NAME_USE
*type
)
266 DOM_SID
*sids
= NULL
;
267 uint32
*types
= NULL
;
268 const char *full_name
;
271 DEBUG(3,("rpc: name_to_sid name=%s\n", name
));
273 full_name
= talloc_asprintf(mem_ctx
, "%s\\%s", domain
->name
, name
);
276 DEBUG(0, ("talloc_asprintf failed!\n"));
277 return NT_STATUS_NO_MEMORY
;
282 if (!(hnd
= cm_get_lsa_handle(domain
->name
))) {
283 return NT_STATUS_UNSUCCESSFUL
;
286 status
= cli_lsa_lookup_names(hnd
->cli
, mem_ctx
, &hnd
->pol
, 1,
287 &full_name
, &sids
, &types
);
288 } while (!NT_STATUS_IS_OK(status
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
290 /* Return rid and type if lookup successful */
292 if (NT_STATUS_IS_OK(status
)) {
293 sid_copy(sid
, &sids
[0]);
301 convert a domain SID to a user or group name
303 static NTSTATUS
sid_to_name(struct winbindd_domain
*domain
,
307 enum SID_NAME_USE
*type
)
316 DEBUG(3,("rpc: sid_to_name\n"));
320 if (!(hnd
= cm_get_lsa_handle(domain
->name
)))
321 return NT_STATUS_UNSUCCESSFUL
;
323 status
= cli_lsa_lookup_sids(hnd
->cli
, mem_ctx
, &hnd
->pol
,
324 1, sid
, &domains
, &names
, &types
);
325 } while (!NT_STATUS_IS_OK(status
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
327 if (NT_STATUS_IS_OK(status
)) {
330 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains
[0], *name
));
333 if (strcasecmp(domain
->name
, domains
[0]) != 0) {
334 DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain
->name
, domains
[0]));
335 return NT_STATUS_UNSUCCESSFUL
;
341 /* Lookup user information from a rid or username. */
342 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
345 WINBIND_USERINFO
*user_info
)
348 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
349 POLICY_HND dom_pol
, user_pol
;
350 BOOL got_dom_pol
= False
, got_user_pol
= False
;
351 SAM_USERINFO_CTR
*ctr
;
356 DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string
, user_sid
)));
357 if (!sid_peek_check_rid(&domain
->sid
, user_sid
, &user_rid
)) {
364 if (!(hnd
= cm_get_sam_handle(domain
->name
)))
367 /* Get domain handle */
369 result
= cli_samr_open_domain(hnd
->cli
, mem_ctx
, &hnd
->pol
,
370 SEC_RIGHTS_MAXIMUM_ALLOWED
,
371 &domain
->sid
, &dom_pol
);
372 } while (!NT_STATUS_IS_OK(result
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
374 if (!NT_STATUS_IS_OK(result
))
379 /* Get user handle */
380 result
= cli_samr_open_user(hnd
->cli
, mem_ctx
, &dom_pol
,
381 SEC_RIGHTS_MAXIMUM_ALLOWED
, user_rid
, &user_pol
);
383 if (!NT_STATUS_IS_OK(result
))
389 result
= cli_samr_query_userinfo(hnd
->cli
, mem_ctx
, &user_pol
,
392 if (!NT_STATUS_IS_OK(result
))
395 cli_samr_close(hnd
->cli
, mem_ctx
, &user_pol
);
396 got_user_pol
= False
;
398 user_info
->user_sid
= rid_to_talloced_sid(domain
, mem_ctx
, user_rid
);
399 user_info
->group_sid
= rid_to_talloced_sid(domain
, mem_ctx
, ctr
->info
.id21
->group_rid
);
400 user_info
->acct_name
= unistr2_tdup(mem_ctx
,
401 &ctr
->info
.id21
->uni_user_name
);
402 user_info
->full_name
= unistr2_tdup(mem_ctx
,
403 &ctr
->info
.id21
->uni_full_name
);
406 /* Clean up policy handles */
408 cli_samr_close(hnd
->cli
, mem_ctx
, &user_pol
);
411 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
416 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
417 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
420 uint32
*num_groups
, DOM_SID
***user_gids
)
423 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
424 POLICY_HND dom_pol
, user_pol
;
425 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
426 BOOL got_dom_pol
= False
, got_user_pol
= False
;
427 DOM_GID
*user_groups
;
433 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string
, user_sid
)));
437 /* First try cached universal groups from logon */
438 *user_gids
= uni_group_cache_fetch(&domain
->sid
, user_sid
, mem_ctx
, num_groups
);
439 if((*num_groups
> 0) && *user_gids
) {
449 if (!(hnd
= cm_get_sam_handle(domain
->name
)))
452 /* Get domain handle */
453 result
= cli_samr_open_domain(hnd
->cli
, mem_ctx
, &hnd
->pol
,
454 des_access
, &domain
->sid
, &dom_pol
);
455 } while (!NT_STATUS_IS_OK(result
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
457 if (!NT_STATUS_IS_OK(result
))
463 if (!sid_peek_check_rid(&domain
->sid
, user_sid
, &user_rid
)) {
467 /* Get user handle */
468 result
= cli_samr_open_user(hnd
->cli
, mem_ctx
, &dom_pol
,
469 des_access
, user_rid
, &user_pol
);
471 if (!NT_STATUS_IS_OK(result
))
476 /* Query user rids */
477 result
= cli_samr_query_usergroups(hnd
->cli
, mem_ctx
, &user_pol
,
478 num_groups
, &user_groups
);
480 if (!NT_STATUS_IS_OK(result
) || (*num_groups
) == 0)
483 (*user_gids
) = talloc(mem_ctx
, sizeof(uint32
) * (*num_groups
));
485 result
= NT_STATUS_NO_MEMORY
;
489 for (i
=0;i
<(*num_groups
);i
++) {
490 (*user_gids
)[i
] = rid_to_talloced_sid(domain
, mem_ctx
, user_groups
[i
].g_rid
);
494 /* Clean up policy handles */
496 cli_samr_close(hnd
->cli
, mem_ctx
, &user_pol
);
499 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
505 /* Lookup group membership given a rid. */
506 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
508 DOM_SID
*group_sid
, uint32
*num_names
,
509 DOM_SID
***sid_mem
, char ***names
,
513 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
514 uint32 i
, total_names
= 0;
515 POLICY_HND dom_pol
, group_pol
;
516 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
517 BOOL got_dom_pol
= False
, got_group_pol
= False
;
518 uint32
*rid_mem
= NULL
;
524 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain
->name
, sid_to_string(sid_string
, group_sid
)));
526 if (!sid_peek_check_rid(&domain
->sid
, group_sid
, &group_rid
)) {
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
);
542 } while (!NT_STATUS_IS_OK(result
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
544 if (!NT_STATUS_IS_OK(result
))
549 /* Get group handle */
551 result
= cli_samr_open_group(hnd
->cli
, mem_ctx
, &dom_pol
,
552 des_access
, group_rid
, &group_pol
);
554 if (!NT_STATUS_IS_OK(result
))
557 got_group_pol
= True
;
559 /* Step #1: Get a list of user rids that are the members of the
562 result
= cli_samr_query_groupmem(hnd
->cli
, mem_ctx
,
563 &group_pol
, num_names
, &rid_mem
,
566 if (!NT_STATUS_IS_OK(result
))
569 /* Step #2: Convert list of rids into list of usernames. Do this
570 in bunches of ~1000 to avoid crashing NT4. It looks like there
571 is a buffer overflow or something like that lurking around
574 #define MAX_LOOKUP_RIDS 900
576 *names
= talloc_zero(mem_ctx
, *num_names
* sizeof(char *));
577 *name_types
= talloc_zero(mem_ctx
, *num_names
* sizeof(uint32
));
578 *sid_mem
= talloc_zero(mem_ctx
, *num_names
* sizeof(DOM_SID
*));
580 for (j
=0;j
<(*num_names
);j
++) {
581 (*sid_mem
)[j
] = rid_to_talloced_sid(domain
, mem_ctx
, (rid_mem
)[j
]);
584 if (!*names
|| !*name_types
) {
585 result
= NT_STATUS_NO_MEMORY
;
589 for (i
= 0; i
< *num_names
; i
+= MAX_LOOKUP_RIDS
) {
590 int num_lookup_rids
= MIN(*num_names
- i
, MAX_LOOKUP_RIDS
);
591 uint32 tmp_num_names
= 0;
592 char **tmp_names
= NULL
;
593 uint32
*tmp_types
= NULL
;
595 /* Lookup a chunk of rids */
597 result
= cli_samr_lookup_rids(hnd
->cli
, mem_ctx
,
598 &dom_pol
, 1000, /* flags */
602 &tmp_names
, &tmp_types
);
604 if (!NT_STATUS_IS_OK(result
))
607 /* Copy result into array. The talloc system will take
608 care of freeing the temporary arrays later on. */
610 memcpy(&(*names
)[i
], tmp_names
, sizeof(char *) *
613 memcpy(&(*name_types
)[i
], tmp_types
, sizeof(uint32
) *
616 total_names
+= tmp_num_names
;
619 *num_names
= total_names
;
623 cli_samr_close(hnd
->cli
, mem_ctx
, &group_pol
);
626 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
631 /* find the sequence number for a domain */
632 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
637 uint16 switch_value
= 2;
639 uint32 seqnum
= DOM_SEQUENCE_NONE
;
641 BOOL got_dom_pol
= False
;
642 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
645 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain
->name
));
647 *seq
= DOM_SEQUENCE_NONE
;
649 if (!(mem_ctx
= talloc_init("sequence_number[rpc]")))
650 return NT_STATUS_NO_MEMORY
;
655 if (!(hnd
= cm_get_sam_handle(domain
->name
)))
658 /* Get domain handle */
659 result
= cli_samr_open_domain(hnd
->cli
, mem_ctx
, &hnd
->pol
,
660 des_access
, &domain
->sid
, &dom_pol
);
661 } while (!NT_STATUS_IS_OK(result
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
663 if (!NT_STATUS_IS_OK(result
))
668 /* Query domain info */
670 result
= cli_samr_query_dom_info(hnd
->cli
, mem_ctx
, &dom_pol
,
673 if (NT_STATUS_IS_OK(result
)) {
674 seqnum
= ctr
.info
.inf2
.seq_num
;
675 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain
->name
, (unsigned)seqnum
));
677 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
678 (unsigned)seqnum
, domain
->name
));
684 cli_samr_close(hnd
->cli
, mem_ctx
, &dom_pol
);
686 talloc_destroy(mem_ctx
);
693 /* get a list of trusted domains */
694 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
702 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
706 DEBUG(3,("rpc: trusted_domains\n"));
713 if (!(hnd
= cm_get_lsa_handle(lp_workgroup())))
716 result
= cli_lsa_enum_trust_dom(hnd
->cli
, mem_ctx
,
717 &hnd
->pol
, &enum_ctx
,
718 num_domains
, names
, dom_sids
);
719 } while (!NT_STATUS_IS_OK(result
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
725 /* find the domain sid for a domain */
726 static NTSTATUS
domain_sid(struct winbindd_domain
*domain
, DOM_SID
*sid
)
728 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
734 DEBUG(3,("rpc: domain_sid\n"));
736 if (!(mem_ctx
= talloc_init("domain_sid[rpc]")))
737 return NT_STATUS_NO_MEMORY
;
742 if (!(hnd
= cm_get_lsa_handle(domain
->name
)))
745 status
= cli_lsa_query_info_policy(hnd
->cli
, mem_ctx
,
746 &hnd
->pol
, 0x05, level5_dom
, sid
);
747 } while (!NT_STATUS_IS_OK(status
) && (retry
++ < 1) && hnd
&& hnd
->cli
&& hnd
->cli
->fd
== -1);
750 talloc_destroy(mem_ctx
);
754 /* find alternate names list for the domain - none for rpc */
755 static NTSTATUS
alternate_name(struct winbindd_domain
*domain
)
761 /* the rpc backend methods are exposed via this structure */
762 struct winbindd_methods msrpc_methods
= {