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 "winbindd_rpc.h"
29 #include "lib/util_unixsids.h"
30 #include "rpc_client/rpc_client.h"
31 #include "rpc_client/cli_pipe.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "rpc_client/cli_samr.h"
34 #include "../librpc/gen_ndr/ndr_lsa_c.h"
35 #include "rpc_client/cli_lsarpc.h"
36 #include "rpc_server/rpc_ncacn_np.h"
37 #include "../libcli/security/security.h"
38 #include "passdb/machine_sid.h"
42 #define DBGC_CLASS DBGC_WINBIND
45 * The other end of this won't go away easily, so we can trust it
47 * It is either a long-lived process with the same lifetime as
48 * winbindd or a part of this process
50 struct winbind_internal_pipes {
51 struct rpc_pipe_client *samr_pipe;
52 struct policy_handle samr_domain_hnd;
53 struct rpc_pipe_client *lsa_pipe;
54 struct policy_handle lsa_hnd;
58 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
59 struct winbindd_domain *domain,
60 struct rpc_pipe_client **samr_pipe,
61 struct policy_handle *samr_domain_hnd)
63 NTSTATUS status, result;
64 struct policy_handle samr_connect_hnd;
65 struct dcerpc_binding_handle *b;
67 status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
68 if (!NT_STATUS_IS_OK(status)) {
72 b = (*samr_pipe)->binding_handle;
74 status = dcerpc_samr_Connect2(b, mem_ctx,
75 (*samr_pipe)->desthost,
76 SEC_FLAG_MAXIMUM_ALLOWED,
79 if (!NT_STATUS_IS_OK(status)) {
82 if (!NT_STATUS_IS_OK(result)) {
86 status = dcerpc_samr_OpenDomain(b, mem_ctx,
88 SEC_FLAG_MAXIMUM_ALLOWED,
92 if (!NT_STATUS_IS_OK(status)) {
99 NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
100 struct rpc_pipe_client **lsa_pipe,
101 struct policy_handle *lsa_hnd)
105 status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
106 if (!NT_STATUS_IS_OK(status)) {
110 status = rpccli_lsa_open_policy((*lsa_pipe),
113 SEC_FLAG_MAXIMUM_ALLOWED,
120 static NTSTATUS open_cached_internal_pipe_conn(
121 struct winbindd_domain *domain,
122 struct rpc_pipe_client **samr_pipe,
123 struct policy_handle *samr_domain_hnd,
124 struct rpc_pipe_client **lsa_pipe,
125 struct policy_handle *lsa_hnd)
127 struct winbind_internal_pipes *internal_pipes = NULL;
129 if (domain->private_data == NULL) {
130 TALLOC_CTX *frame = talloc_stackframe();
133 internal_pipes = talloc_zero(frame,
134 struct winbind_internal_pipes);
136 status = open_internal_samr_conn(
139 &internal_pipes->samr_pipe,
140 &internal_pipes->samr_domain_hnd);
141 if (!NT_STATUS_IS_OK(status)) {
146 status = open_internal_lsa_conn(internal_pipes,
147 &internal_pipes->lsa_pipe,
148 &internal_pipes->lsa_hnd);
150 if (!NT_STATUS_IS_OK(status)) {
155 domain->private_data = talloc_move(domain, &internal_pipes);
161 internal_pipes = talloc_get_type_abort(
162 domain->private_data, struct winbind_internal_pipes);
164 if (samr_domain_hnd) {
165 *samr_domain_hnd = internal_pipes->samr_domain_hnd;
169 *samr_pipe = internal_pipes->samr_pipe;
173 *lsa_hnd = internal_pipes->lsa_hnd;
177 *lsa_pipe = internal_pipes->lsa_pipe;
183 static bool reset_connection_on_error(struct winbindd_domain *domain,
184 struct rpc_pipe_client *p,
187 struct winbind_internal_pipes *internal_pipes = NULL;
189 internal_pipes = talloc_get_type_abort(
190 domain->private_data, struct winbind_internal_pipes);
192 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
193 NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
195 TALLOC_FREE(internal_pipes);
196 domain->private_data = NULL;
200 if (!rpccli_is_connected(p)) {
201 TALLOC_FREE(internal_pipes);
202 domain->private_data = NULL;
209 /*********************************************************************
210 SAM specific functions.
211 *********************************************************************/
213 /* List all domain groups */
214 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
217 struct wb_acct_info **pinfo)
219 struct rpc_pipe_client *samr_pipe;
220 struct policy_handle dom_pol = { 0 };
221 struct wb_acct_info *info = NULL;
222 uint32_t num_info = 0;
227 DEBUG(3,("sam_enum_dom_groups\n"));
233 tmp_ctx = talloc_stackframe();
234 if (tmp_ctx == NULL) {
235 return NT_STATUS_NO_MEMORY;
239 status = open_cached_internal_pipe_conn(domain,
244 if (!NT_STATUS_IS_OK(status)) {
245 TALLOC_FREE(tmp_ctx);
249 status = rpc_enum_dom_groups(tmp_ctx,
255 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
260 if (!NT_STATUS_IS_OK(status)) {
261 TALLOC_FREE(tmp_ctx);
266 *pnum_info = num_info;
270 *pinfo = talloc_move(mem_ctx, &info);
273 TALLOC_FREE(tmp_ctx);
277 /* Query display info for a domain */
278 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
282 struct rpc_pipe_client *samr_pipe = NULL;
283 struct policy_handle dom_pol = { 0 };
284 uint32_t *rids = NULL;
289 DEBUG(3,("samr_query_user_list\n"));
291 tmp_ctx = talloc_stackframe();
292 if (tmp_ctx == NULL) {
293 return NT_STATUS_NO_MEMORY;
297 status = open_cached_internal_pipe_conn(domain,
302 if (!NT_STATUS_IS_OK(status)) {
306 status = rpc_query_user_list(tmp_ctx,
311 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
316 if (!NT_STATUS_IS_OK(status)) {
321 *prids = talloc_move(mem_ctx, &rids);
326 TALLOC_FREE(tmp_ctx);
330 /* get a list of trusted domains - builtin domain */
331 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
333 struct netr_DomainTrustList *ptrust_list)
335 struct rpc_pipe_client *lsa_pipe;
336 struct policy_handle lsa_policy = { 0 };
337 struct netr_DomainTrust *trusts = NULL;
338 uint32_t num_trusts = 0;
343 DEBUG(3,("samr: trusted domains\n"));
346 ZERO_STRUCTP(ptrust_list);
349 tmp_ctx = talloc_stackframe();
350 if (tmp_ctx == NULL) {
351 return NT_STATUS_NO_MEMORY;
355 status = open_cached_internal_pipe_conn(domain,
360 if (!NT_STATUS_IS_OK(status)) {
364 status = rpc_trusted_domains(tmp_ctx,
370 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
375 if (!NT_STATUS_IS_OK(status)) {
380 ptrust_list->count = num_trusts;
381 ptrust_list->array = talloc_move(mem_ctx, &trusts);
385 TALLOC_FREE(tmp_ctx);
389 /* Lookup group membership given a rid. */
390 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
392 const struct dom_sid *group_sid,
393 enum lsa_SidType type,
394 uint32_t *pnum_names,
395 struct dom_sid **psid_mem,
397 uint32_t **pname_types)
399 struct rpc_pipe_client *samr_pipe;
400 struct policy_handle dom_pol = { 0 };
402 uint32_t num_names = 0;
403 struct dom_sid *sid_mem = NULL;
405 uint32_t *name_types = NULL;
411 DEBUG(3,("sam_lookup_groupmem\n"));
414 if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
415 /* There's no groups, only aliases in BUILTIN */
416 return NT_STATUS_NO_SUCH_GROUP;
423 tmp_ctx = talloc_stackframe();
424 if (tmp_ctx == NULL) {
425 return NT_STATUS_NO_MEMORY;
429 status = open_cached_internal_pipe_conn(domain,
434 if (!NT_STATUS_IS_OK(status)) {
438 status = rpc_lookup_groupmem(tmp_ctx,
450 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
456 *pnum_names = num_names;
460 *pnames = talloc_move(mem_ctx, &names);
464 *pname_types = talloc_move(mem_ctx, &name_types);
468 *psid_mem = talloc_move(mem_ctx, &sid_mem);
472 TALLOC_FREE(tmp_ctx);
476 /*********************************************************************
477 BUILTIN specific functions.
478 *********************************************************************/
480 /* List all domain groups */
481 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
483 uint32_t *num_entries,
484 struct wb_acct_info **info)
486 /* BUILTIN doesn't have domain groups */
492 /* Query display info for a domain */
493 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
497 /* We don't have users */
502 /* get a list of trusted domains - builtin domain */
503 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
505 struct netr_DomainTrustList *trusts)
507 ZERO_STRUCTP(trusts);
511 /*********************************************************************
513 *********************************************************************/
515 /* List all local groups (aliases) */
516 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
519 struct wb_acct_info **pinfo)
521 struct rpc_pipe_client *samr_pipe;
522 struct policy_handle dom_pol = { 0 };
523 struct wb_acct_info *info = NULL;
524 uint32_t num_info = 0;
529 DEBUG(3,("samr: enum local groups\n"));
535 tmp_ctx = talloc_stackframe();
536 if (tmp_ctx == NULL) {
537 return NT_STATUS_NO_MEMORY;
541 status = open_cached_internal_pipe_conn(domain,
546 if (!NT_STATUS_IS_OK(status)) {
550 status = rpc_enum_local_groups(mem_ctx,
556 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
561 if (!NT_STATUS_IS_OK(status)) {
566 *pnum_info = num_info;
570 *pinfo = talloc_move(mem_ctx, &info);
574 TALLOC_FREE(tmp_ctx);
578 /* convert a single name to a sid in a domain */
579 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
581 const char *domain_name,
584 struct dom_sid *psid,
585 enum lsa_SidType *ptype)
587 struct rpc_pipe_client *lsa_pipe;
588 struct policy_handle lsa_policy = { 0 };
590 const char *dom_name;
591 enum lsa_SidType type;
596 DEBUG(3,("sam_name_to_sid\n"));
598 tmp_ctx = talloc_stackframe();
599 if (tmp_ctx == NULL) {
600 return NT_STATUS_NO_MEMORY;
604 status = open_cached_internal_pipe_conn(domain,
609 if (!NT_STATUS_IS_OK(status)) {
613 status = rpc_name_to_sid(tmp_ctx,
623 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
628 if (!NT_STATUS_IS_OK(status)) {
633 sid_copy(psid, &sid);
640 TALLOC_FREE(tmp_ctx);
644 /* convert a domain SID to a user or group name */
645 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
647 const struct dom_sid *sid,
650 enum lsa_SidType *ptype)
652 struct rpc_pipe_client *lsa_pipe;
653 struct policy_handle lsa_policy = { 0 };
654 char *domain_name = NULL;
656 enum lsa_SidType type;
661 DEBUG(3,("sam_sid_to_name\n"));
664 if (!sid_check_is_in_builtin(sid) &&
665 !sid_check_is_builtin(sid) &&
666 !sid_check_is_in_our_sam(sid) &&
667 !sid_check_is_our_sam(sid) &&
668 !sid_check_is_in_unix_users(sid) &&
669 !sid_check_is_unix_users(sid) &&
670 !sid_check_is_in_unix_groups(sid) &&
671 !sid_check_is_unix_groups(sid) &&
672 !sid_check_is_in_wellknown_domain(sid)) {
673 struct dom_sid_buf buf;
674 DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
676 dom_sid_str_buf(sid, &buf)));
677 return NT_STATUS_NONE_MAPPED;
680 tmp_ctx = talloc_stackframe();
681 if (tmp_ctx == NULL) {
682 return NT_STATUS_NO_MEMORY;
686 status = open_cached_internal_pipe_conn(domain,
691 if (!NT_STATUS_IS_OK(status)) {
695 status = rpc_sid_to_name(tmp_ctx,
704 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
714 *pname = talloc_move(mem_ctx, &name);
718 *pdomain_name = talloc_move(mem_ctx, &domain_name);
723 TALLOC_FREE(tmp_ctx);
727 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
729 const struct dom_sid *domain_sid,
734 enum lsa_SidType **ptypes)
736 struct rpc_pipe_client *lsa_pipe;
737 struct policy_handle lsa_policy = { 0 };
738 enum lsa_SidType *types = NULL;
739 char *domain_name = NULL;
745 DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
748 if (!sid_check_is_builtin(domain_sid) &&
749 !sid_check_is_our_sam(domain_sid) &&
750 !sid_check_is_unix_users(domain_sid) &&
751 !sid_check_is_unix_groups(domain_sid) &&
752 !sid_check_is_in_wellknown_domain(domain_sid)) {
753 struct dom_sid_buf buf;
754 DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to "
756 dom_sid_str_buf(domain_sid, &buf)));
757 return NT_STATUS_NONE_MAPPED;
760 tmp_ctx = talloc_stackframe();
761 if (tmp_ctx == NULL) {
762 return NT_STATUS_NO_MEMORY;
766 status = open_cached_internal_pipe_conn(domain,
771 if (!NT_STATUS_IS_OK(status)) {
775 status = rpc_rids_to_names(tmp_ctx,
786 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
791 if (!NT_STATUS_IS_OK(status)) {
796 *pdomain_name = talloc_move(mem_ctx, &domain_name);
800 *ptypes = talloc_move(mem_ctx, &types);
804 *pnames = talloc_move(mem_ctx, &names);
808 TALLOC_FREE(tmp_ctx);
812 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
814 struct samr_DomInfo12 *lockout_policy)
816 struct rpc_pipe_client *samr_pipe;
817 struct policy_handle dom_pol = { 0 };
818 union samr_DomainInfo *info = NULL;
820 NTSTATUS status, result;
821 struct dcerpc_binding_handle *b = NULL;
824 DEBUG(3,("sam_lockout_policy\n"));
826 tmp_ctx = talloc_stackframe();
827 if (tmp_ctx == NULL) {
828 return NT_STATUS_NO_MEMORY;
832 status = open_cached_internal_pipe_conn(domain,
837 if (!NT_STATUS_IS_OK(status)) {
841 b = samr_pipe->binding_handle;
843 status = dcerpc_samr_QueryDomainInfo(b,
846 DomainLockoutInformation,
850 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
855 if (!NT_STATUS_IS_OK(status)) {
858 if (!NT_STATUS_IS_OK(result)) {
863 *lockout_policy = info->info12;
866 TALLOC_FREE(tmp_ctx);
870 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
872 struct samr_DomInfo1 *passwd_policy)
874 struct rpc_pipe_client *samr_pipe;
875 struct policy_handle dom_pol = { 0 };
876 union samr_DomainInfo *info = NULL;
878 NTSTATUS status, result;
879 struct dcerpc_binding_handle *b = NULL;
882 DEBUG(3,("sam_password_policy\n"));
884 tmp_ctx = talloc_stackframe();
885 if (tmp_ctx == NULL) {
886 return NT_STATUS_NO_MEMORY;
890 status = open_cached_internal_pipe_conn(domain,
895 if (!NT_STATUS_IS_OK(status)) {
899 b = samr_pipe->binding_handle;
901 status = dcerpc_samr_QueryDomainInfo(b,
904 DomainPasswordInformation,
908 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
913 if (!NT_STATUS_IS_OK(status)) {
916 if (!NT_STATUS_IS_OK(result)) {
921 *passwd_policy = info->info1;
924 TALLOC_FREE(tmp_ctx);
928 /* Lookup groups a user is a member of. */
929 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
931 const struct dom_sid *user_sid,
932 uint32_t *pnum_groups,
933 struct dom_sid **puser_grpsids)
935 struct rpc_pipe_client *samr_pipe;
936 struct policy_handle dom_pol;
937 struct dom_sid *user_grpsids = NULL;
938 uint32_t num_groups = 0;
943 DEBUG(3,("sam_lookup_usergroups\n"));
945 ZERO_STRUCT(dom_pol);
951 tmp_ctx = talloc_stackframe();
952 if (tmp_ctx == NULL) {
953 return NT_STATUS_NO_MEMORY;
957 status = open_cached_internal_pipe_conn(domain,
962 if (!NT_STATUS_IS_OK(status)) {
966 status = rpc_lookup_usergroups(tmp_ctx,
974 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
979 if (!NT_STATUS_IS_OK(status)) {
984 *pnum_groups = num_groups;
988 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
993 TALLOC_FREE(tmp_ctx);
997 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
1000 const struct dom_sid *sids,
1001 uint32_t *pnum_aliases,
1002 uint32_t **palias_rids)
1004 struct rpc_pipe_client *samr_pipe;
1005 struct policy_handle dom_pol = { 0 };
1006 uint32_t num_aliases = 0;
1007 uint32_t *alias_rids = NULL;
1008 TALLOC_CTX *tmp_ctx;
1012 DEBUG(3,("sam_lookup_useraliases\n"));
1018 tmp_ctx = talloc_stackframe();
1019 if (tmp_ctx == NULL) {
1020 return NT_STATUS_NO_MEMORY;
1024 status = open_cached_internal_pipe_conn(domain,
1029 if (!NT_STATUS_IS_OK(status)) {
1033 status = rpc_lookup_useraliases(tmp_ctx,
1041 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1046 if (!NT_STATUS_IS_OK(status)) {
1051 *pnum_aliases = num_aliases;
1055 *palias_rids = talloc_move(mem_ctx, &alias_rids);
1060 TALLOC_FREE(tmp_ctx);
1064 /* find the sequence number for a domain */
1065 static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
1068 struct rpc_pipe_client *samr_pipe;
1069 struct policy_handle dom_pol = { 0 };
1070 uint32_t seq = DOM_SEQUENCE_NONE;
1071 TALLOC_CTX *tmp_ctx;
1075 DEBUG(3,("samr: sequence number\n"));
1078 *pseq = DOM_SEQUENCE_NONE;
1081 tmp_ctx = talloc_stackframe();
1082 if (tmp_ctx == NULL) {
1083 return NT_STATUS_NO_MEMORY;
1087 status = open_cached_internal_pipe_conn(domain,
1092 if (!NT_STATUS_IS_OK(status)) {
1096 status = rpc_sequence_number(tmp_ctx,
1102 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1107 if (!NT_STATUS_IS_OK(status)) {
1116 TALLOC_FREE(tmp_ctx);
1120 /* the rpc backend methods are exposed via this structure */
1121 struct winbindd_methods builtin_passdb_methods = {
1122 .consistent = false,
1124 .query_user_list = builtin_query_user_list,
1125 .enum_dom_groups = builtin_enum_dom_groups,
1126 .enum_local_groups = sam_enum_local_groups,
1127 .name_to_sid = sam_name_to_sid,
1128 .sid_to_name = sam_sid_to_name,
1129 .rids_to_names = sam_rids_to_names,
1130 .lookup_usergroups = sam_lookup_usergroups,
1131 .lookup_useraliases = sam_lookup_useraliases,
1132 .lookup_groupmem = sam_lookup_groupmem,
1133 .sequence_number = sam_sequence_number,
1134 .lockout_policy = sam_lockout_policy,
1135 .password_policy = sam_password_policy,
1136 .trusted_domains = builtin_trusted_domains
1139 /* the rpc backend methods are exposed via this structure */
1140 struct winbindd_methods sam_passdb_methods = {
1141 .consistent = false,
1143 .query_user_list = sam_query_user_list,
1144 .enum_dom_groups = sam_enum_dom_groups,
1145 .enum_local_groups = sam_enum_local_groups,
1146 .name_to_sid = sam_name_to_sid,
1147 .sid_to_name = sam_sid_to_name,
1148 .rids_to_names = sam_rids_to_names,
1149 .lookup_usergroups = sam_lookup_usergroups,
1150 .lookup_useraliases = sam_lookup_useraliases,
1151 .lookup_groupmem = sam_lookup_groupmem,
1152 .sequence_number = sam_sequence_number,
1153 .lockout_policy = sam_lockout_policy,
1154 .password_policy = sam_password_policy,
1155 .trusted_domains = sam_trusted_domains