2 * Unix SMB/CIFS implementation.
4 * Winbind rpc backend functions
6 * Copyright (c) 2000-2003 Tim Potter
7 * Copyright (c) 2001 Andrew Tridgell
8 * Copyright (c) 2005 Volker Lendecke
9 * Copyright (c) 2008 Guenther Deschner (pidl conversion)
10 * Copyright (c) 2010 Andreas Schneider <asn@samba.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "../librpc/gen_ndr/cli_samr.h"
29 #include "rpc_client/cli_samr.h"
30 #include "../librpc/gen_ndr/srv_samr.h"
31 #include "../librpc/gen_ndr/cli_lsa.h"
32 #include "rpc_client/cli_lsarpc.h"
33 #include "../librpc/gen_ndr/srv_lsa.h"
36 #define DBGC_CLASS DBGC_WINBIND
38 static NTSTATUS
open_internal_samr_pipe(TALLOC_CTX
*mem_ctx
,
39 struct rpc_pipe_client
**samr_pipe
)
41 static struct rpc_pipe_client
*cli
= NULL
;
42 struct auth_serversupplied_info
*server_info
= NULL
;
49 if (server_info
== NULL
) {
50 status
= make_server_info_system(mem_ctx
, &server_info
);
51 if (!NT_STATUS_IS_OK(status
)) {
52 DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
58 /* create a samr connection */
59 status
= rpc_pipe_open_internal(talloc_autofree_context(),
60 &ndr_table_samr
.syntax_id
,
64 if (!NT_STATUS_IS_OK(status
)) {
65 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
78 static NTSTATUS
open_internal_samr_conn(TALLOC_CTX
*mem_ctx
,
79 struct winbindd_domain
*domain
,
80 struct rpc_pipe_client
**samr_pipe
,
81 struct policy_handle
*samr_domain_hnd
)
84 struct policy_handle samr_connect_hnd
;
86 status
= open_internal_samr_pipe(mem_ctx
, samr_pipe
);
87 if (!NT_STATUS_IS_OK(status
)) {
91 status
= rpccli_samr_Connect2((*samr_pipe
),
93 (*samr_pipe
)->desthost
,
94 SEC_FLAG_MAXIMUM_ALLOWED
,
96 if (!NT_STATUS_IS_OK(status
)) {
100 status
= rpccli_samr_OpenDomain((*samr_pipe
),
103 SEC_FLAG_MAXIMUM_ALLOWED
,
110 static NTSTATUS
open_internal_lsa_pipe(TALLOC_CTX
*mem_ctx
,
111 struct rpc_pipe_client
**lsa_pipe
)
113 static struct rpc_pipe_client
*cli
= NULL
;
114 struct auth_serversupplied_info
*server_info
= NULL
;
121 if (server_info
== NULL
) {
122 status
= make_server_info_system(mem_ctx
, &server_info
);
123 if (!NT_STATUS_IS_OK(status
)) {
124 DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
130 /* create a samr connection */
131 status
= rpc_pipe_open_internal(talloc_autofree_context(),
132 &ndr_table_lsarpc
.syntax_id
,
136 if (!NT_STATUS_IS_OK(status
)) {
137 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
150 static NTSTATUS
open_internal_lsa_conn(TALLOC_CTX
*mem_ctx
,
151 struct rpc_pipe_client
**lsa_pipe
,
152 struct policy_handle
*lsa_hnd
)
156 status
= open_internal_lsa_pipe(mem_ctx
, lsa_pipe
);
157 if (!NT_STATUS_IS_OK(status
)) {
161 status
= rpccli_lsa_open_policy((*lsa_pipe
),
164 SEC_FLAG_MAXIMUM_ALLOWED
,
170 /*********************************************************************
171 SAM specific functions.
172 *********************************************************************/
174 /* List all domain groups */
175 static NTSTATUS
sam_enum_dom_groups(struct winbindd_domain
*domain
,
178 struct acct_info
**pinfo
)
180 struct rpc_pipe_client
*samr_pipe
;
181 struct policy_handle dom_pol
;
182 struct acct_info
*info
= NULL
;
185 uint32_t num_info
= 0;
188 DEBUG(3,("samr: query_user_list\n"));
194 tmp_ctx
= talloc_stackframe();
195 if (tmp_ctx
== NULL
) {
196 return NT_STATUS_NO_MEMORY
;
199 status
= open_internal_samr_conn(tmp_ctx
, domain
, &samr_pipe
, &dom_pol
);
200 if (!NT_STATUS_IS_OK(status
)) {
205 struct samr_SamArray
*sam_array
= NULL
;
209 /* start is updated by this call. */
210 status
= rpccli_samr_EnumDomainGroups(samr_pipe
,
215 0xFFFF, /* buffer size? */
217 if (!NT_STATUS_IS_OK(status
)) {
218 if (!NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
219 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
225 info
= TALLOC_REALLOC_ARRAY(tmp_ctx
,
230 status
= NT_STATUS_NO_MEMORY
;
234 for (g
= 0; g
< count
; g
++) {
235 fstrcpy(info
[num_info
+ g
].acct_name
,
236 sam_array
->entries
[g
].name
.string
);
238 info
[num_info
+ g
].rid
= sam_array
->entries
[g
].idx
;
242 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
245 *pnum_info
= num_info
;
249 *pinfo
= talloc_move(mem_ctx
, &info
);
253 TALLOC_FREE(tmp_ctx
);
257 /* Query display info for a domain */
258 static NTSTATUS
sam_query_user_list(struct winbindd_domain
*domain
,
261 struct wbint_userinfo
**pinfo
)
263 struct rpc_pipe_client
*samr_pipe
= NULL
;
264 struct wbint_userinfo
*info
= NULL
;
265 struct policy_handle dom_pol
;
266 uint32_t num_info
= 0;
267 uint32_t loop_count
= 0;
268 uint32_t start_idx
= 0;
273 DEBUG(3,("samr: query_user_list\n"));
279 tmp_ctx
= talloc_stackframe();
280 if (tmp_ctx
== NULL
) {
281 return NT_STATUS_NO_MEMORY
;
284 status
= open_internal_samr_conn(tmp_ctx
, domain
, &samr_pipe
, &dom_pol
);
285 if (!NT_STATUS_IS_OK(status
)) {
291 uint32_t num_dom_users
;
292 uint32_t max_entries
, max_size
;
293 uint32_t total_size
, returned_size
;
294 union samr_DispInfo disp_info
;
296 get_query_dispinfo_params(loop_count
,
300 status
= rpccli_samr_QueryDisplayInfo(samr_pipe
,
310 if (!NT_STATUS_IS_OK(status
)) {
311 if (!NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
316 /* increment required start query values */
317 start_idx
+= disp_info
.info1
.count
;
319 num_dom_users
= disp_info
.info1
.count
;
321 num_info
+= num_dom_users
;
323 info
= TALLOC_REALLOC_ARRAY(tmp_ctx
,
325 struct wbint_userinfo
,
328 status
= NT_STATUS_NO_MEMORY
;
332 for (j
= 0; j
< num_dom_users
; i
++, j
++) {
333 uint32_t rid
= disp_info
.info1
.entries
[j
].rid
;
334 struct samr_DispEntryGeneral
*src
;
335 struct wbint_userinfo
*dst
;
337 src
= &(disp_info
.info1
.entries
[j
]);
340 dst
->acct_name
= talloc_strdup(info
,
341 src
->account_name
.string
);
342 if (dst
->acct_name
== NULL
) {
343 status
= NT_STATUS_NO_MEMORY
;
347 dst
->full_name
= talloc_strdup(info
, src
->full_name
.string
);
348 if (dst
->full_name
== NULL
) {
349 status
= NT_STATUS_NO_MEMORY
;
356 sid_compose(&dst
->user_sid
, &domain
->sid
, rid
);
358 /* For the moment we set the primary group for
359 every user to be the Domain Users group.
360 There are serious problems with determining
361 the actual primary group for large domains.
362 This should really be made into a 'winbind
363 force group' smb.conf parameter or
364 something like that. */
365 sid_compose(&dst
->group_sid
, &domain
->sid
,
368 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
371 *pnum_info
= num_info
;
375 *pinfo
= talloc_move(mem_ctx
, &info
);
379 TALLOC_FREE(tmp_ctx
);
383 /* Lookup user information from a rid or username. */
384 static NTSTATUS
sam_query_user(struct winbindd_domain
*domain
,
386 const struct dom_sid
*user_sid
,
387 struct wbint_userinfo
*user_info
)
389 struct rpc_pipe_client
*samr_pipe
;
390 struct policy_handle dom_pol
, user_pol
;
391 union samr_UserInfo
*info
= NULL
;
396 DEBUG(3,("samr: query_user\n"));
398 if (!sid_peek_check_rid(&domain
->sid
, user_sid
, &user_rid
)) {
399 return NT_STATUS_UNSUCCESSFUL
;
403 user_info
->homedir
= NULL
;
404 user_info
->shell
= NULL
;
405 user_info
->primary_gid
= (gid_t
) -1;
408 tmp_ctx
= talloc_stackframe();
409 if (tmp_ctx
== NULL
) {
410 return NT_STATUS_NO_MEMORY
;
413 status
= open_internal_samr_conn(tmp_ctx
, domain
, &samr_pipe
, &dom_pol
);
414 if (!NT_STATUS_IS_OK(status
)) {
418 /* Get user handle */
419 status
= rpccli_samr_OpenUser(samr_pipe
,
422 SEC_FLAG_MAXIMUM_ALLOWED
,
425 if (!NT_STATUS_IS_OK(status
)) {
430 status
= rpccli_samr_QueryUserInfo(samr_pipe
,
436 rpccli_samr_Close(samr_pipe
, tmp_ctx
, &user_pol
);
438 if (!NT_STATUS_IS_OK(status
)) {
442 sid_compose(&user_info
->user_sid
, &domain
->sid
, user_rid
);
443 sid_compose(&user_info
->group_sid
, &domain
->sid
,
444 info
->info21
.primary_gid
);
447 user_info
->acct_name
= talloc_strdup(mem_ctx
,
448 info
->info21
.account_name
.string
);
449 if (user_info
->acct_name
== NULL
) {
450 status
= NT_STATUS_NO_MEMORY
;
454 user_info
->full_name
= talloc_strdup(mem_ctx
,
455 info
->info21
.full_name
.string
);
456 if (user_info
->acct_name
== NULL
) {
457 status
= NT_STATUS_NO_MEMORY
;
461 user_info
->homedir
= NULL
;
462 user_info
->shell
= NULL
;
463 user_info
->primary_gid
= (gid_t
)-1;
466 status
= NT_STATUS_OK
;
468 TALLOC_FREE(tmp_ctx
);
472 /* get a list of trusted domains - builtin domain */
473 static NTSTATUS
sam_trusted_domains(struct winbindd_domain
*domain
,
475 struct netr_DomainTrustList
*trusts
)
477 struct rpc_pipe_client
*lsa_pipe
;
478 struct netr_DomainTrust
*array
= NULL
;
479 struct policy_handle lsa_policy
;
480 uint32_t enum_ctx
= 0;
485 DEBUG(3,("samr: trusted domains\n"));
487 tmp_ctx
= talloc_stackframe();
488 if (tmp_ctx
== NULL
) {
489 return NT_STATUS_NO_MEMORY
;
492 status
= open_internal_lsa_conn(tmp_ctx
, &lsa_pipe
, &lsa_policy
);
493 if (!NT_STATUS_IS_OK(status
)) {
498 struct lsa_DomainList dom_list
;
503 * We don't run into deadlocks here, cause winbind_off() is
504 * called in the main function.
506 status
= rpccli_lsa_EnumTrustDom(lsa_pipe
,
512 if (!NT_STATUS_IS_OK(status
)) {
513 if (!NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
518 start_idx
= trusts
->count
;
519 count
+= dom_list
.count
;
521 array
= talloc_realloc(tmp_ctx
,
523 struct netr_DomainTrust
,
526 status
= NT_STATUS_NO_MEMORY
;
530 for (i
= 0; i
< dom_list
.count
; i
++) {
531 struct netr_DomainTrust
*trust
= &array
[i
];
536 trust
->netbios_name
= talloc_move(array
,
537 &dom_list
.domains
[i
].name
.string
);
538 trust
->dns_name
= NULL
;
540 sid
= talloc(array
, struct dom_sid
);
542 status
= NT_STATUS_NO_MEMORY
;
545 sid_copy(sid
, dom_list
.domains
[i
].sid
);
548 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
551 trusts
->count
= count
;
552 trusts
->array
= talloc_move(mem_ctx
, &array
);
556 TALLOC_FREE(tmp_ctx
);
560 /* Lookup group membership given a rid. */
561 static NTSTATUS
sam_lookup_groupmem(struct winbindd_domain
*domain
,
563 const struct dom_sid
*group_sid
,
564 enum lsa_SidType type
,
565 uint32_t *pnum_names
,
566 struct dom_sid
**psid_mem
,
568 uint32_t **pname_types
)
570 struct rpc_pipe_client
*samr_pipe
;
571 struct policy_handle dom_pol
, group_pol
;
572 uint32_t samr_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
573 struct samr_RidTypeArray
*rids
= NULL
;
575 uint32_t *rid_mem
= NULL
;
577 uint32_t num_names
= 0;
578 uint32_t total_names
= 0;
579 struct dom_sid
*sid_mem
= NULL
;
581 uint32_t *name_types
= NULL
;
583 struct lsa_Strings tmp_names
;
584 struct samr_Ids tmp_types
;
590 DEBUG(3,("samr: lookup groupmem\n"));
596 if (!sid_peek_check_rid(&domain
->sid
, group_sid
, &group_rid
)) {
597 return NT_STATUS_UNSUCCESSFUL
;
600 tmp_ctx
= talloc_stackframe();
601 if (tmp_ctx
== NULL
) {
602 return NT_STATUS_NO_MEMORY
;
605 status
= open_internal_samr_conn(tmp_ctx
, domain
, &samr_pipe
, &dom_pol
);
606 if (!NT_STATUS_IS_OK(status
)) {
610 status
= rpccli_samr_OpenGroup(samr_pipe
,
616 if (!NT_STATUS_IS_OK(status
)) {
621 * Step #1: Get a list of user rids that are the members of the group.
623 status
= rpccli_samr_QueryGroupMember(samr_pipe
,
628 rpccli_samr_Close(samr_pipe
, tmp_ctx
, &group_pol
);
630 if (!NT_STATUS_IS_OK(status
)) {
634 if (rids
== NULL
|| rids
->count
== 0) {
640 status
= NT_STATUS_OK
;
644 num_names
= rids
->count
;
645 rid_mem
= rids
->rids
;
648 * Step #2: Convert list of rids into list of usernames.
650 #define MAX_LOOKUP_RIDS 900
653 names
= TALLOC_ZERO_ARRAY(tmp_ctx
, char *, num_names
);
654 name_types
= TALLOC_ZERO_ARRAY(tmp_ctx
, uint32_t, num_names
);
655 sid_mem
= TALLOC_ZERO_ARRAY(tmp_ctx
, struct dom_sid
, num_names
);
656 if (names
== NULL
|| name_types
== NULL
|| sid_mem
== NULL
) {
657 status
= NT_STATUS_NO_MEMORY
;
662 for (j
= 0; j
< num_names
; j
++) {
663 sid_compose(&sid_mem
[j
], &domain
->sid
, rid_mem
[j
]);
666 status
= rpccli_samr_LookupRids(samr_pipe
,
673 if (!NT_STATUS_IS_OK(status
)) {
674 if (!NT_STATUS_EQUAL(status
, STATUS_SOME_UNMAPPED
)) {
679 /* Copy result into array. The talloc system will take
680 care of freeing the temporary arrays later on. */
681 if (tmp_names
.count
!= tmp_types
.count
) {
682 status
= NT_STATUS_UNSUCCESSFUL
;
686 for (r
= 0; r
< tmp_names
.count
; r
++) {
687 if (tmp_types
.ids
[r
] == SID_NAME_UNKNOWN
) {
690 names
[total_names
] = fill_domain_username_talloc(names
,
692 tmp_names
.names
[r
].string
,
694 name_types
[total_names
] = tmp_types
.ids
[r
];
699 *pnum_names
= total_names
;
703 *pnames
= talloc_move(mem_ctx
, &names
);
707 *pname_types
= talloc_move(mem_ctx
, &name_types
);
711 *psid_mem
= talloc_move(mem_ctx
, &sid_mem
);
715 TALLOC_FREE(tmp_ctx
);
719 /*********************************************************************
720 BUILTIN specific functions.
721 *********************************************************************/
723 /* List all domain groups */
724 static NTSTATUS
builtin_enum_dom_groups(struct winbindd_domain
*domain
,
727 struct acct_info
**info
)
729 /* BUILTIN doesn't have domain groups */
735 /* Query display info for a domain */
736 static NTSTATUS
builtin_query_user_list(struct winbindd_domain
*domain
,
739 struct wbint_userinfo
**info
)
741 /* We don't have users */
747 /* Lookup user information from a rid or username. */
748 static NTSTATUS
builtin_query_user(struct winbindd_domain
*domain
,
750 const struct dom_sid
*user_sid
,
751 struct wbint_userinfo
*user_info
)
753 return NT_STATUS_NO_SUCH_USER
;
756 /* get a list of trusted domains - builtin domain */
757 static NTSTATUS
builtin_trusted_domains(struct winbindd_domain
*domain
,
759 struct netr_DomainTrustList
*trusts
)
761 ZERO_STRUCTP(trusts
);
765 /*********************************************************************
767 *********************************************************************/
769 /* List all local groups (aliases) */
770 static NTSTATUS
common_enum_local_groups(struct winbindd_domain
*domain
,
772 uint32_t *num_entries
,
773 struct acct_info
**info
)
776 return NT_STATUS_NOT_IMPLEMENTED
;
779 /* convert a single name to a sid in a domain */
780 static NTSTATUS
common_name_to_sid(struct winbindd_domain
*domain
,
782 const char *domain_name
,
786 enum lsa_SidType
*type
)
789 return NT_STATUS_NOT_IMPLEMENTED
;
792 /* convert a domain SID to a user or group name */
793 static NTSTATUS
common_sid_to_name(struct winbindd_domain
*domain
,
795 const struct dom_sid
*sid
,
798 enum lsa_SidType
*type
)
801 return NT_STATUS_NOT_IMPLEMENTED
;
804 static NTSTATUS
common_rids_to_names(struct winbindd_domain
*domain
,
806 const struct dom_sid
*sid
,
811 enum lsa_SidType
**types
)
814 return NT_STATUS_NOT_IMPLEMENTED
;
817 static NTSTATUS
common_lockout_policy(struct winbindd_domain
*domain
,
819 struct samr_DomInfo12
*policy
)
822 return NT_STATUS_NOT_IMPLEMENTED
;
825 static NTSTATUS
common_password_policy(struct winbindd_domain
*domain
,
827 struct samr_DomInfo1
*policy
)
830 return NT_STATUS_NOT_IMPLEMENTED
;
833 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
834 static NTSTATUS
common_lookup_usergroups(struct winbindd_domain
*domain
,
836 const struct dom_sid
*user_sid
,
837 uint32_t *num_groups
,
838 struct dom_sid
**user_gids
)
841 return NT_STATUS_NOT_IMPLEMENTED
;
844 static NTSTATUS
common_lookup_useraliases(struct winbindd_domain
*domain
,
847 const struct dom_sid
*sids
,
848 uint32_t *p_num_aliases
,
852 return NT_STATUS_NOT_IMPLEMENTED
;
855 /* find the sequence number for a domain */
856 static NTSTATUS
common_sequence_number(struct winbindd_domain
*domain
,
860 return NT_STATUS_NOT_IMPLEMENTED
;
864 /* the rpc backend methods are exposed via this structure */
865 struct winbindd_methods builtin_passdb_methods
= {
868 .query_user_list
= builtin_query_user_list
,
869 .enum_dom_groups
= builtin_enum_dom_groups
,
870 .enum_local_groups
= common_enum_local_groups
,
871 .name_to_sid
= common_name_to_sid
,
872 .sid_to_name
= common_sid_to_name
,
873 .rids_to_names
= common_rids_to_names
,
874 .query_user
= builtin_query_user
,
875 .lookup_usergroups
= common_lookup_usergroups
,
876 .lookup_useraliases
= common_lookup_useraliases
,
877 .lookup_groupmem
= sam_lookup_groupmem
,
878 .sequence_number
= common_sequence_number
,
879 .lockout_policy
= common_lockout_policy
,
880 .password_policy
= common_password_policy
,
881 .trusted_domains
= builtin_trusted_domains
884 /* the rpc backend methods are exposed via this structure */
885 struct winbindd_methods sam_passdb_methods
= {
888 .query_user_list
= sam_query_user_list
,
889 .enum_dom_groups
= sam_enum_dom_groups
,
890 .enum_local_groups
= common_enum_local_groups
,
891 .name_to_sid
= common_name_to_sid
,
892 .sid_to_name
= common_sid_to_name
,
893 .rids_to_names
= common_rids_to_names
,
894 .query_user
= sam_query_user
,
895 .lookup_usergroups
= common_lookup_usergroups
,
896 .lookup_useraliases
= common_lookup_useraliases
,
897 .lookup_groupmem
= sam_lookup_groupmem
,
898 .sequence_number
= common_sequence_number
,
899 .lockout_policy
= common_lockout_policy
,
900 .password_policy
= common_password_policy
,
901 .trusted_domains
= sam_trusted_domains