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"
40 #include "source3/lib/global_contexts.h"
43 #define DBGC_CLASS DBGC_WINBIND
46 * The other end of this won't go away easily, so we can trust it
48 * It is either a long-lived process with the same lifetime as
49 * winbindd or a part of this process
51 struct winbind_internal_pipes {
52 struct tevent_timer *shutdown_timer;
53 struct rpc_pipe_client *samr_pipe;
54 struct policy_handle samr_domain_hnd;
55 struct rpc_pipe_client *lsa_pipe;
56 struct policy_handle lsa_hnd;
60 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
61 struct winbindd_domain *domain,
62 struct rpc_pipe_client **samr_pipe,
63 struct policy_handle *samr_domain_hnd)
65 NTSTATUS status, result;
66 struct policy_handle samr_connect_hnd;
67 struct dcerpc_binding_handle *b;
69 status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
70 if (!NT_STATUS_IS_OK(status)) {
71 DBG_ERR("Could not connect to %s pipe: %s\n",
72 ndr_table_samr.name, nt_errstr(status));
76 b = (*samr_pipe)->binding_handle;
78 status = dcerpc_samr_Connect2(b, mem_ctx,
79 (*samr_pipe)->desthost,
80 SEC_FLAG_MAXIMUM_ALLOWED,
83 if (!NT_STATUS_IS_OK(status)) {
86 if (!NT_STATUS_IS_OK(result)) {
90 status = dcerpc_samr_OpenDomain(b, mem_ctx,
92 SEC_FLAG_MAXIMUM_ALLOWED,
96 if (!NT_STATUS_IS_OK(status)) {
103 NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
104 struct rpc_pipe_client **lsa_pipe,
105 struct policy_handle *lsa_hnd)
109 status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
110 if (!NT_STATUS_IS_OK(status)) {
111 DBG_ERR("Could not connect to %s pipe: %s\n",
112 ndr_table_lsarpc.name, nt_errstr(status));
116 status = rpccli_lsa_open_policy((*lsa_pipe),
119 SEC_FLAG_MAXIMUM_ALLOWED,
125 static void cached_internal_pipe_close(
126 struct tevent_context *ev,
127 struct tevent_timer *te,
128 struct timeval current_time,
131 struct winbindd_domain *domain = talloc_get_type_abort(
132 private_data, struct winbindd_domain);
134 * Freeing samr_pipes closes the cached pipes.
136 * We can do a hard close because at the time of this commit
137 * we only use sychronous calls to external pipes. So we can't
138 * have any outstanding requests. Also, we don't set
139 * dcerpc_binding_handle_set_sync_ev in winbind, so we don't
140 * get nested event loops. Once we start to get async in
141 * winbind children, we need to check for outstanding calls
143 TALLOC_FREE(domain->backend_data.samr_pipes);
146 static NTSTATUS open_cached_internal_pipe_conn(
147 struct winbindd_domain *domain,
148 struct rpc_pipe_client **samr_pipe,
149 struct policy_handle *samr_domain_hnd,
150 struct rpc_pipe_client **lsa_pipe,
151 struct policy_handle *lsa_hnd)
153 struct winbind_internal_pipes *internal_pipes =
154 domain->backend_data.samr_pipes;
156 if (internal_pipes == NULL) {
157 TALLOC_CTX *frame = talloc_stackframe();
160 internal_pipes = talloc_zero(frame,
161 struct winbind_internal_pipes);
163 status = open_internal_samr_conn(
166 &internal_pipes->samr_pipe,
167 &internal_pipes->samr_domain_hnd);
168 if (!NT_STATUS_IS_OK(status)) {
173 status = open_internal_lsa_conn(internal_pipes,
174 &internal_pipes->lsa_pipe,
175 &internal_pipes->lsa_hnd);
177 if (!NT_STATUS_IS_OK(status)) {
182 internal_pipes->shutdown_timer = tevent_add_timer(
183 global_event_context(),
185 timeval_current_ofs(5, 0),
186 cached_internal_pipe_close,
188 if (internal_pipes->shutdown_timer == NULL) {
190 return NT_STATUS_NO_MEMORY;
193 domain->backend_data.samr_pipes =
194 talloc_steal(domain, internal_pipes);
199 if (samr_domain_hnd) {
200 *samr_domain_hnd = internal_pipes->samr_domain_hnd;
204 *samr_pipe = internal_pipes->samr_pipe;
208 *lsa_hnd = internal_pipes->lsa_hnd;
212 *lsa_pipe = internal_pipes->lsa_pipe;
216 internal_pipes->shutdown_timer,
217 timeval_current_ofs(5, 0));
222 static bool reset_connection_on_error(struct winbindd_domain *domain,
223 struct rpc_pipe_client *p,
226 struct dcerpc_binding_handle *b = p->binding_handle;
228 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
229 NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
231 TALLOC_FREE(domain->backend_data.samr_pipes);
235 if (!dcerpc_binding_handle_is_connected(b)) {
236 TALLOC_FREE(domain->backend_data.samr_pipes);
243 /*********************************************************************
244 SAM specific functions.
245 *********************************************************************/
247 /* List all domain groups */
248 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
251 struct wb_acct_info **pinfo)
253 struct rpc_pipe_client *samr_pipe;
254 struct policy_handle dom_pol = { 0 };
255 struct wb_acct_info *info = NULL;
256 uint32_t num_info = 0;
257 TALLOC_CTX *tmp_ctx = talloc_stackframe();
261 DEBUG(3,("sam_enum_dom_groups\n"));
268 status = open_cached_internal_pipe_conn(domain,
273 if (!NT_STATUS_IS_OK(status)) {
274 TALLOC_FREE(tmp_ctx);
278 status = rpc_enum_dom_groups(tmp_ctx,
284 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
289 if (!NT_STATUS_IS_OK(status)) {
290 TALLOC_FREE(tmp_ctx);
295 *pnum_info = num_info;
299 *pinfo = talloc_move(mem_ctx, &info);
302 TALLOC_FREE(tmp_ctx);
306 /* Query display info for a domain */
307 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
311 struct rpc_pipe_client *samr_pipe = NULL;
312 struct policy_handle dom_pol = { 0 };
313 uint32_t *rids = NULL;
314 TALLOC_CTX *tmp_ctx = talloc_stackframe();
318 DEBUG(3,("samr_query_user_list\n"));
321 status = open_cached_internal_pipe_conn(domain,
326 if (!NT_STATUS_IS_OK(status)) {
330 status = rpc_query_user_list(tmp_ctx,
335 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
340 if (!NT_STATUS_IS_OK(status)) {
345 *prids = talloc_move(mem_ctx, &rids);
350 TALLOC_FREE(tmp_ctx);
354 /* get a list of trusted domains - builtin domain */
355 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
357 struct netr_DomainTrustList *ptrust_list)
359 struct rpc_pipe_client *lsa_pipe;
360 struct policy_handle lsa_policy = { 0 };
361 struct netr_DomainTrust *trusts = NULL;
362 uint32_t num_trusts = 0;
363 TALLOC_CTX *tmp_ctx = talloc_stackframe();
367 DEBUG(3,("samr: trusted domains\n"));
370 ZERO_STRUCTP(ptrust_list);
374 status = open_cached_internal_pipe_conn(domain,
379 if (!NT_STATUS_IS_OK(status)) {
383 status = rpc_trusted_domains(tmp_ctx,
389 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
394 if (!NT_STATUS_IS_OK(status)) {
399 ptrust_list->count = num_trusts;
400 ptrust_list->array = talloc_move(mem_ctx, &trusts);
404 TALLOC_FREE(tmp_ctx);
408 /* Lookup group membership given a rid. */
409 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
411 const struct dom_sid *group_sid,
412 enum lsa_SidType type,
413 uint32_t *pnum_names,
414 struct dom_sid **psid_mem,
416 uint32_t **pname_types)
418 struct rpc_pipe_client *samr_pipe;
419 struct policy_handle dom_pol = { 0 };
421 uint32_t num_names = 0;
422 struct dom_sid *sid_mem = NULL;
424 uint32_t *name_types = NULL;
426 TALLOC_CTX *tmp_ctx = talloc_stackframe();
430 DEBUG(3,("sam_lookup_groupmem\n"));
433 if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
434 /* There's no groups, only aliases in BUILTIN */
435 status = NT_STATUS_NO_SUCH_GROUP;
444 status = open_cached_internal_pipe_conn(domain,
449 if (!NT_STATUS_IS_OK(status)) {
453 status = rpc_lookup_groupmem(tmp_ctx,
465 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
471 *pnum_names = num_names;
475 *pnames = talloc_move(mem_ctx, &names);
479 *pname_types = talloc_move(mem_ctx, &name_types);
483 *psid_mem = talloc_move(mem_ctx, &sid_mem);
487 TALLOC_FREE(tmp_ctx);
491 /*********************************************************************
492 BUILTIN specific functions.
493 *********************************************************************/
495 /* List all domain groups */
496 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
498 uint32_t *num_entries,
499 struct wb_acct_info **info)
501 /* BUILTIN doesn't have domain groups */
507 /* Query display info for a domain */
508 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
512 /* We don't have users */
517 /* get a list of trusted domains - builtin domain */
518 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
520 struct netr_DomainTrustList *trusts)
522 ZERO_STRUCTP(trusts);
526 /*********************************************************************
528 *********************************************************************/
530 /* List all local groups (aliases) */
531 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
534 struct wb_acct_info **pinfo)
536 struct rpc_pipe_client *samr_pipe;
537 struct policy_handle dom_pol = { 0 };
538 struct wb_acct_info *info = NULL;
539 uint32_t num_info = 0;
540 TALLOC_CTX *tmp_ctx = talloc_stackframe();
544 DEBUG(3,("samr: enum local groups\n"));
551 status = open_cached_internal_pipe_conn(domain,
556 if (!NT_STATUS_IS_OK(status)) {
560 status = rpc_enum_local_groups(mem_ctx,
566 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
571 if (!NT_STATUS_IS_OK(status)) {
576 *pnum_info = num_info;
580 *pinfo = talloc_move(mem_ctx, &info);
584 TALLOC_FREE(tmp_ctx);
588 /* convert a single name to a sid in a domain */
589 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
591 const char *domain_name,
594 const char **pdom_name,
595 struct dom_sid *psid,
596 enum lsa_SidType *ptype)
598 struct rpc_pipe_client *samr_pipe = NULL;
599 struct dcerpc_binding_handle *h = NULL;
600 struct policy_handle dom_pol = { .handle_type = 0, };
602 const char *dom_name = domain_name;
603 struct lsa_String lsa_name = { .string = name };
604 struct samr_Ids rids = { .count = 0 };
605 struct samr_Ids types = { .count = 0 };
606 enum lsa_SidType type;
607 TALLOC_CTX *tmp_ctx = talloc_stackframe();
608 NTSTATUS status = NT_STATUS_NONE_MAPPED;
613 DBG_NOTICE("%s\\%s\n", domain_name, name);
615 if (strequal(domain_name, unix_users_domain_name())) {
616 struct passwd *pwd = NULL;
618 if (name[0] == '\0') {
619 sid_copy(&sid, &global_sid_Unix_Users);
620 type = SID_NAME_DOMAIN;
624 pwd = Get_Pwnam_alloc(tmp_ctx, name);
628 ok = sid_compose(&sid, &global_sid_Unix_Users, pwd->pw_uid);
630 status = NT_STATUS_INTERNAL_ERROR;
633 type = SID_NAME_USER;
637 if (strequal(domain_name, unix_groups_domain_name())) {
638 struct group *grp = NULL;
640 if (name[0] == '\0') {
641 sid_copy(&sid, &global_sid_Unix_Groups);
642 type = SID_NAME_DOMAIN;
646 grp = getgrnam(name);
650 ok = sid_compose(&sid, &global_sid_Unix_Groups, grp->gr_gid);
652 status = NT_STATUS_INTERNAL_ERROR;
655 type = SID_NAME_DOM_GRP;
659 if (name[0] == '\0') {
660 sid_copy(&sid, &domain->sid);
661 type = SID_NAME_DOMAIN;
665 ok = lookup_wellknown_name(tmp_ctx, name, &sid, &dom_name);
667 type = SID_NAME_WKN_GRP;
672 char *normalized = NULL;
673 NTSTATUS nstatus = normalize_name_unmap(
674 tmp_ctx, name, &normalized);
675 if (NT_STATUS_IS_OK(nstatus) ||
676 NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
677 lsa_name.string = normalized;
682 status = open_cached_internal_pipe_conn(
683 domain, &samr_pipe, &dom_pol, NULL, NULL);
684 if (!NT_STATUS_IS_OK(status)) {
687 h = samr_pipe->binding_handle;
689 status = dcerpc_samr_LookupNames(
690 h, tmp_ctx, &dom_pol, 1, &lsa_name, &rids, &types, &result);
692 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
697 if (!NT_STATUS_IS_OK(status)) {
698 DBG_DEBUG("dcerpc_samr_LookupNames returned %s\n",
702 if (!NT_STATUS_IS_OK(result)) {
703 DBG_DEBUG("dcerpc_samr_LookupNames resulted in %s\n",
709 sid_compose(&sid, &domain->sid, rids.ids[0]);
713 if (pdom_name != NULL) {
714 *pdom_name = talloc_strdup(mem_ctx, dom_name);
715 if (*pdom_name == NULL) {
716 status = NT_STATUS_NO_MEMORY;
722 sid_copy(psid, &sid);
728 status = NT_STATUS_OK;
730 TALLOC_FREE(tmp_ctx);
734 /* convert a domain SID to a user or group name */
735 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
737 const struct dom_sid *sid,
740 enum lsa_SidType *ptype)
742 struct rpc_pipe_client *samr_pipe = NULL;
743 struct dcerpc_binding_handle *h = NULL;
744 struct policy_handle dom_pol = { .handle_type = 0, };
745 const char *domain_name = "";
746 const char *name = "";
747 enum lsa_SidType type = SID_NAME_USE_NONE;
748 struct lsa_Strings names = { .count = 0, };
749 struct samr_Ids types = { .count = 0 };
750 struct dom_sid domain_sid;
752 TALLOC_CTX *tmp_ctx = talloc_stackframe();
753 NTSTATUS status = NT_STATUS_NONE_MAPPED;
758 DEBUG(3,("sam_sid_to_name\n"));
760 if (sid_check_is_unix_users(sid)) {
761 domain_name = unix_users_domain_name();
762 type = SID_NAME_DOMAIN;
765 if (sid_check_is_in_unix_users(sid)) {
766 struct passwd *pwd = NULL;
768 ok = sid_peek_rid(sid, &rid);
777 domain_name = unix_users_domain_name();
778 name = talloc_strdup(tmp_ctx, pwd->pw_name);
780 status = NT_STATUS_NO_MEMORY;
783 type = SID_NAME_USER;
787 if (sid_check_is_unix_groups(sid)) {
788 domain_name = unix_groups_domain_name();
789 type = SID_NAME_DOMAIN;
792 if (sid_check_is_in_unix_groups(sid)) {
793 struct group *grp = NULL;
795 ok = sid_peek_rid(sid, &rid);
804 domain_name = unix_groups_domain_name();
805 name = talloc_strdup(tmp_ctx, grp->gr_name);
807 status = NT_STATUS_NO_MEMORY;
810 type = SID_NAME_DOM_GRP;
814 ok = lookup_wellknown_sid(tmp_ctx, sid, &domain_name, &name);
816 type = SID_NAME_WKN_GRP;
820 if (dom_sid_equal(sid, &domain->sid)) {
821 domain_name = domain->name;
822 type = SID_NAME_DOMAIN;
826 sid_copy(&domain_sid, sid);
827 ok = sid_split_rid(&domain_sid, &rid);
832 if (!dom_sid_equal(&domain_sid, &domain->sid)) {
837 status = open_cached_internal_pipe_conn(
838 domain, &samr_pipe, &dom_pol, NULL, NULL);
839 if (!NT_STATUS_IS_OK(status)) {
842 h = samr_pipe->binding_handle;
844 status = dcerpc_samr_LookupRids(
845 h, tmp_ctx, &dom_pol, 1, &rid, &names, &types, &result);
847 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
852 if (!NT_STATUS_IS_OK(status)) {
853 DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
857 if (!NT_STATUS_IS_OK(result)) {
858 DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
864 domain_name = domain->name;
865 name = names.names[0].string;
869 char *normalized = NULL;
870 NTSTATUS nstatus = normalize_name_map(
871 tmp_ctx, domain_name, name, &normalized);
872 if (NT_STATUS_IS_OK(nstatus) ||
873 NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
884 *pname = talloc_strdup(mem_ctx, name);
885 if (*pname == NULL) {
886 status = NT_STATUS_NO_MEMORY;
892 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
893 if (*pdomain_name == NULL) {
894 status = NT_STATUS_NO_MEMORY;
899 status = NT_STATUS_OK;
901 TALLOC_FREE(tmp_ctx);
905 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
907 const struct dom_sid *domain_sid,
912 enum lsa_SidType **ptypes)
914 struct rpc_pipe_client *samr_pipe = NULL;
915 struct dcerpc_binding_handle *h = NULL;
916 struct policy_handle dom_pol = { .handle_type = 0, };
917 enum lsa_SidType *types = NULL;
919 const char *domain_name = NULL;
920 TALLOC_CTX *tmp_ctx = talloc_stackframe();
921 NTSTATUS status = NT_STATUS_NO_MEMORY;
926 DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
928 types = talloc_array(tmp_ctx, enum lsa_SidType, num_rids);
933 names = talloc_array(tmp_ctx, char *, num_rids);
938 if (sid_check_is_unix_users(domain_sid)) {
939 domain_name = unix_users_domain_name();
940 domain_sid = &global_sid_Unix_Users;
942 if (sid_check_is_unix_groups(domain_sid)) {
943 domain_name = unix_groups_domain_name();
944 domain_sid = &global_sid_Unix_Groups;
947 /* Here we're only interested in the domain name being set */
948 sid_check_is_wellknown_domain(domain_sid, &domain_name);
950 if (domain_name != NULL) {
951 uint32_t num_mapped = 0;
954 * Do unix users/groups and wkn in a loop. There is no
955 * getpwuids() call & friends anyway
958 for (i=0; i<num_rids; i++) {
962 sid_compose(&sid, domain_sid, rids[i]);
964 types[i] = SID_NAME_UNKNOWN;
967 status = sam_sid_to_name(
974 if (NT_STATUS_IS_OK(status)) {
975 names[i] = talloc_move(names, &name);
980 status = NT_STATUS_NONE_MAPPED;
981 if (num_mapped > 0) {
982 status = (num_mapped == num_rids) ?
983 NT_STATUS_OK : STATUS_SOME_UNMAPPED;
988 domain_name = domain->name;
991 status = open_cached_internal_pipe_conn(
992 domain, &samr_pipe, &dom_pol, NULL, NULL);
993 if (!NT_STATUS_IS_OK(status)) {
996 h = samr_pipe->binding_handle;
999 * Magic number 1000 comes from samr.idl
1002 for (i = 0; i < num_rids; i += 1000) {
1003 uint32_t num_lookup_rids = MIN(num_rids - i, 1000);
1004 struct lsa_Strings lsa_names = {
1007 struct samr_Ids samr_types = {
1012 status = dcerpc_samr_LookupRids(h,
1022 reset_connection_on_error(domain, samr_pipe, status)) {
1027 if (!NT_STATUS_IS_OK(status)) {
1028 DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
1032 if (!NT_STATUS_IS_OK(result) &&
1033 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
1034 DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
1040 for (j = 0; j < num_lookup_rids; j++) {
1041 uint32_t dst = i + j;
1043 types[dst] = samr_types.ids[j];
1044 names[dst] = talloc_move(
1046 discard_const_p(char *,
1047 &lsa_names.names[j].string));
1048 if (names[dst] != NULL) {
1049 char *normalized = NULL;
1051 normalize_name_map(names,
1055 if (NT_STATUS_IS_OK(nstatus) ||
1056 NT_STATUS_EQUAL(nstatus,
1057 NT_STATUS_FILE_RENAMED)) {
1058 names[dst] = normalized;
1063 TALLOC_FREE(samr_types.ids);
1064 TALLOC_FREE(lsa_names.names);
1069 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
1070 if (*pdomain_name == NULL) {
1071 status = NT_STATUS_NO_MEMORY;
1077 *ptypes = talloc_move(mem_ctx, &types);
1081 *pnames = talloc_move(mem_ctx, &names);
1085 TALLOC_FREE(tmp_ctx);
1089 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
1090 TALLOC_CTX *mem_ctx,
1091 struct samr_DomInfo12 *lockout_policy)
1093 struct rpc_pipe_client *samr_pipe;
1094 struct policy_handle dom_pol = { 0 };
1095 union samr_DomainInfo *info = NULL;
1096 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1097 NTSTATUS status, result;
1098 struct dcerpc_binding_handle *b = NULL;
1101 DEBUG(3,("sam_lockout_policy\n"));
1104 status = open_cached_internal_pipe_conn(domain,
1109 if (!NT_STATUS_IS_OK(status)) {
1113 b = samr_pipe->binding_handle;
1115 status = dcerpc_samr_QueryDomainInfo(b,
1118 DomainLockoutInformation,
1122 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1127 if (!NT_STATUS_IS_OK(status)) {
1130 if (!NT_STATUS_IS_OK(result)) {
1135 *lockout_policy = info->info12;
1138 TALLOC_FREE(tmp_ctx);
1142 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
1143 TALLOC_CTX *mem_ctx,
1144 struct samr_DomInfo1 *passwd_policy)
1146 struct rpc_pipe_client *samr_pipe;
1147 struct policy_handle dom_pol = { 0 };
1148 union samr_DomainInfo *info = NULL;
1149 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1150 NTSTATUS status, result;
1151 struct dcerpc_binding_handle *b = NULL;
1154 DEBUG(3,("sam_password_policy\n"));
1157 status = open_cached_internal_pipe_conn(domain,
1162 if (!NT_STATUS_IS_OK(status)) {
1166 b = samr_pipe->binding_handle;
1168 status = dcerpc_samr_QueryDomainInfo(b,
1171 DomainPasswordInformation,
1175 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1180 if (!NT_STATUS_IS_OK(status)) {
1183 if (!NT_STATUS_IS_OK(result)) {
1188 *passwd_policy = info->info1;
1191 TALLOC_FREE(tmp_ctx);
1195 /* Lookup groups a user is a member of. */
1196 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
1197 TALLOC_CTX *mem_ctx,
1198 const struct dom_sid *user_sid,
1199 uint32_t *pnum_groups,
1200 struct dom_sid **puser_grpsids)
1202 struct rpc_pipe_client *samr_pipe;
1203 struct policy_handle dom_pol;
1204 struct dom_sid *user_grpsids = NULL;
1205 uint32_t num_groups = 0;
1206 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1210 DEBUG(3,("sam_lookup_usergroups\n"));
1212 ZERO_STRUCT(dom_pol);
1219 status = open_cached_internal_pipe_conn(domain,
1224 if (!NT_STATUS_IS_OK(status)) {
1228 status = rpc_lookup_usergroups(tmp_ctx,
1236 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1241 if (!NT_STATUS_IS_OK(status)) {
1246 *pnum_groups = num_groups;
1249 if (puser_grpsids) {
1250 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
1255 TALLOC_FREE(tmp_ctx);
1259 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
1260 TALLOC_CTX *mem_ctx,
1262 const struct dom_sid *sids,
1263 uint32_t *pnum_aliases,
1264 uint32_t **palias_rids)
1266 struct rpc_pipe_client *samr_pipe;
1267 struct policy_handle dom_pol = { 0 };
1268 uint32_t num_aliases = 0;
1269 uint32_t *alias_rids = NULL;
1270 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1274 DEBUG(3,("sam_lookup_useraliases\n"));
1281 status = open_cached_internal_pipe_conn(domain,
1286 if (!NT_STATUS_IS_OK(status)) {
1290 status = rpc_lookup_useraliases(tmp_ctx,
1298 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1303 if (!NT_STATUS_IS_OK(status)) {
1308 *pnum_aliases = num_aliases;
1312 *palias_rids = talloc_move(mem_ctx, &alias_rids);
1317 TALLOC_FREE(tmp_ctx);
1321 /* the rpc backend methods are exposed via this structure */
1322 struct winbindd_methods builtin_passdb_methods = {
1323 .consistent = false,
1325 .query_user_list = builtin_query_user_list,
1326 .enum_dom_groups = builtin_enum_dom_groups,
1327 .enum_local_groups = sam_enum_local_groups,
1328 .name_to_sid = sam_name_to_sid,
1329 .sid_to_name = sam_sid_to_name,
1330 .rids_to_names = sam_rids_to_names,
1331 .lookup_usergroups = sam_lookup_usergroups,
1332 .lookup_useraliases = sam_lookup_useraliases,
1333 .lookup_groupmem = sam_lookup_groupmem,
1334 .lockout_policy = sam_lockout_policy,
1335 .password_policy = sam_password_policy,
1336 .trusted_domains = builtin_trusted_domains
1339 /* the rpc backend methods are exposed via this structure */
1340 struct winbindd_methods sam_passdb_methods = {
1341 .consistent = false,
1343 .query_user_list = sam_query_user_list,
1344 .enum_dom_groups = sam_enum_dom_groups,
1345 .enum_local_groups = sam_enum_local_groups,
1346 .name_to_sid = sam_name_to_sid,
1347 .sid_to_name = sam_sid_to_name,
1348 .rids_to_names = sam_rids_to_names,
1349 .lookup_usergroups = sam_lookup_usergroups,
1350 .lookup_useraliases = sam_lookup_useraliases,
1351 .lookup_groupmem = sam_lookup_groupmem,
1352 .lockout_policy = sam_lockout_policy,
1353 .password_policy = sam_password_policy,
1354 .trusted_domains = sam_trusted_domains