X-Git-Url: http://git.samba.org/idra/samba.git/?p=idra%2Fsamba.git;a=blobdiff_plain;f=source3%2Fwinbindd%2Fwinbindd_samr.c;h=582e2a696207cbc9ead82cb2e752c7b8b70d78cd;hp=e4faaef1191f899720420ce7ee1af01af4bf1928;hb=eb8a0c76725500d183c50eb795c683f23d4aede7;hpb=9d0d6ed66f582464dd874ec793cdeb7cf1b9aece diff --git a/source3/winbindd/winbindd_samr.c b/source3/winbindd/winbindd_samr.c index e4faaef1191..582e2a69620 100644 --- a/source3/winbindd/winbindd_samr.c +++ b/source3/winbindd/winbindd_samr.c @@ -25,12 +25,16 @@ #include "includes.h" #include "winbindd.h" -#include "../librpc/gen_ndr/cli_samr.h" +#include "winbindd_rpc.h" +#include "rpc_client/rpc_client.h" +#include "../librpc/gen_ndr/ndr_samr_c.h" #include "rpc_client/cli_samr.h" -#include "../librpc/gen_ndr/srv_samr.h" -#include "../librpc/gen_ndr/cli_lsa.h" +#include "../librpc/gen_ndr/ndr_lsa_c.h" #include "rpc_client/cli_lsarpc.h" -#include "../librpc/gen_ndr/srv_lsa.h" +#include "rpc_server/rpc_ncacn_np.h" +#include "../libcli/security/security.h" +#include "passdb/machine_sid.h" +#include "auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -38,28 +42,25 @@ static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx, struct rpc_pipe_client **samr_pipe) { - static struct rpc_pipe_client *cli = NULL; - struct auth_serversupplied_info *server_info = NULL; + struct rpc_pipe_client *cli = NULL; + struct auth_session_info *session_info = NULL; NTSTATUS status; - if (cli != NULL) { - goto done; - } - - if (server_info == NULL) { - status = make_server_info_system(mem_ctx, &server_info); + if (session_info == NULL) { + status = make_session_info_system(mem_ctx, &session_info); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n", + DEBUG(0, ("open_samr_pipe: Could not create auth_session_info: %s\n", nt_errstr(status))); return status; } } /* create a samr connection */ - status = rpc_pipe_open_internal(talloc_autofree_context(), + status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id, - rpc_samr_dispatch, - server_info, + session_info, + NULL, + winbind_messaging_context(), &cli); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n", @@ -67,7 +68,6 @@ static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx, return status; } -done: if (samr_pipe) { *samr_pipe = cli; } @@ -75,71 +75,76 @@ done: return NT_STATUS_OK; } -static NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - struct rpc_pipe_client **samr_pipe, - struct policy_handle *samr_domain_hnd) +NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + struct rpc_pipe_client **samr_pipe, + struct policy_handle *samr_domain_hnd) { - NTSTATUS status; + NTSTATUS status, result; struct policy_handle samr_connect_hnd; + struct dcerpc_binding_handle *b; status = open_internal_samr_pipe(mem_ctx, samr_pipe); if (!NT_STATUS_IS_OK(status)) { return status; } - status = rpccli_samr_Connect2((*samr_pipe), - mem_ctx, + b = (*samr_pipe)->binding_handle; + + status = dcerpc_samr_Connect2(b, mem_ctx, (*samr_pipe)->desthost, SEC_FLAG_MAXIMUM_ALLOWED, - &samr_connect_hnd); + &samr_connect_hnd, + &result); if (!NT_STATUS_IS_OK(status)) { return status; } + if (!NT_STATUS_IS_OK(result)) { + return result; + } - status = rpccli_samr_OpenDomain((*samr_pipe), - mem_ctx, + status = dcerpc_samr_OpenDomain(b, mem_ctx, &samr_connect_hnd, SEC_FLAG_MAXIMUM_ALLOWED, &domain->sid, - samr_domain_hnd); + samr_domain_hnd, + &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - return status; + return result; } static NTSTATUS open_internal_lsa_pipe(TALLOC_CTX *mem_ctx, struct rpc_pipe_client **lsa_pipe) { - static struct rpc_pipe_client *cli = NULL; - struct auth_serversupplied_info *server_info = NULL; + struct rpc_pipe_client *cli = NULL; + struct auth_session_info *session_info = NULL; NTSTATUS status; - if (cli != NULL) { - goto done; - } - - if (server_info == NULL) { - status = make_server_info_system(mem_ctx, &server_info); + if (session_info == NULL) { + status = make_session_info_system(mem_ctx, &session_info); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n", + DEBUG(0, ("open_lsa_pipe: Could not create auth_session_info: %s\n", nt_errstr(status))); return status; } } - /* create a samr connection */ - status = rpc_pipe_open_internal(talloc_autofree_context(), + /* create a lsa connection */ + status = rpc_pipe_open_internal(mem_ctx, &ndr_table_lsarpc.syntax_id, - rpc_lsarpc_dispatch, - server_info, + session_info, + NULL, + winbind_messaging_context(), &cli); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n", + DEBUG(0, ("open_lsa_pipe: Could not connect to lsa_pipe: %s\n", nt_errstr(status))); return status; } -done: if (lsa_pipe) { *lsa_pipe = cli; } @@ -174,11 +179,60 @@ static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx, /* List all domain groups */ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint32_t *num_entries, - struct acct_info **info) + uint32_t *pnum_info, + struct wb_acct_info **pinfo) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + struct wb_acct_info *info = NULL; + uint32_t num_info = 0; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_enum_dom_groups\n")); + + ZERO_STRUCT(dom_pol); + + if (pnum_info) { + *pnum_info = 0; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + + b = samr_pipe->binding_handle; + + status = rpc_enum_dom_groups(tmp_ctx, + samr_pipe, + &dom_pol, + &num_info, + &info); + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + + if (pnum_info) { + *pnum_info = num_info; + } + + if (pinfo) { + *pinfo = talloc_move(mem_ctx, &info); + } + +error: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + TALLOC_FREE(tmp_ctx); + return status; } /* Query display info for a domain */ @@ -188,16 +242,16 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, struct wbint_userinfo **pinfo) { struct rpc_pipe_client *samr_pipe = NULL; - struct wbint_userinfo *info = NULL; struct policy_handle dom_pol; + struct wbint_userinfo *info = NULL; uint32_t num_info = 0; - uint32_t loop_count = 0; - uint32_t start_idx = 0; - uint32_t i = 0; TALLOC_CTX *tmp_ctx; - NTSTATUS status; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; - DEBUG(3,("samr: query_user_list\n")); + DEBUG(3,("samr_query_user_list\n")); + + ZERO_STRUCT(dom_pol); if (pnum_info) { *pnum_info = 0; @@ -210,89 +264,20 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { - goto error; + goto done; } - do { - uint32_t j; - uint32_t num_dom_users; - uint32_t max_entries, max_size; - uint32_t total_size, returned_size; - union samr_DispInfo disp_info; - - get_query_dispinfo_params(loop_count, - &max_entries, - &max_size); - - status = rpccli_samr_QueryDisplayInfo(samr_pipe, - tmp_ctx, - &dom_pol, - 1, /* level */ - start_idx, - max_entries, - max_size, - &total_size, - &returned_size, - &disp_info); - if (!NT_STATUS_IS_OK(status)) { - if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { - goto error; - } - } - - /* increment required start query values */ - start_idx += disp_info.info1.count; - loop_count++; - num_dom_users = disp_info.info1.count; - - num_info += num_dom_users; + b = samr_pipe->binding_handle; - info = TALLOC_REALLOC_ARRAY(tmp_ctx, - info, - struct wbint_userinfo, - num_info); - if (info == NULL) { - status = NT_STATUS_NO_MEMORY; - goto error; - } - - for (j = 0; j < num_dom_users; i++, j++) { - uint32_t rid = disp_info.info1.entries[j].rid; - struct samr_DispEntryGeneral *src; - struct wbint_userinfo *dst; - - src = &(disp_info.info1.entries[j]); - dst = &(info[i]); - - dst->acct_name = talloc_strdup(info, - src->account_name.string); - if (dst->acct_name == NULL) { - status = NT_STATUS_NO_MEMORY; - goto error; - } - - dst->full_name = talloc_strdup(info, src->full_name.string); - if (dst->full_name == NULL) { - status = NT_STATUS_NO_MEMORY; - goto error; - } - - dst->homedir = NULL; - dst->shell = NULL; - - sid_compose(&dst->user_sid, &domain->sid, rid); - - /* For the moment we set the primary group for - every user to be the Domain Users group. - There are serious problems with determining - the actual primary group for large domains. - This should really be made into a 'winbind - force group' smb.conf parameter or - something like that. */ - sid_compose(&dst->group_sid, &domain->sid, - DOMAIN_RID_USERS); - } - } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)); + status = rpc_query_user_list(tmp_ctx, + samr_pipe, + &dom_pol, + &domain->sid, + &num_info, + &info); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } if (pnum_info) { *pnum_info = num_info; @@ -302,7 +287,11 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, *pinfo = talloc_move(mem_ctx, &info); } -error: +done: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + TALLOC_FREE(tmp_ctx); return status; } @@ -313,17 +302,109 @@ static NTSTATUS sam_query_user(struct winbindd_domain *domain, const struct dom_sid *user_sid, struct wbint_userinfo *user_info) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_query_user\n")); + + ZERO_STRUCT(dom_pol); + + /* Paranoia check */ + if (!sid_check_is_in_our_domain(user_sid)) { + return NT_STATUS_NO_SUCH_USER; + } + + if (user_info) { + user_info->homedir = NULL; + user_info->shell = NULL; + user_info->primary_gid = (gid_t) -1; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = samr_pipe->binding_handle; + + status = rpc_query_user(tmp_ctx, + samr_pipe, + &dom_pol, + &domain->sid, + user_sid, + user_info); + +done: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } /* get a list of trusted domains - builtin domain */ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - struct netr_DomainTrustList *trusts) + struct netr_DomainTrustList *ptrust_list) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *lsa_pipe; + struct policy_handle lsa_policy; + struct netr_DomainTrust *trusts = NULL; + uint32_t num_trusts = 0; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("samr: trusted domains\n")); + + ZERO_STRUCT(lsa_policy); + + if (ptrust_list) { + ZERO_STRUCTP(ptrust_list); + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = lsa_pipe->binding_handle; + + status = rpc_trusted_domains(tmp_ctx, + lsa_pipe, + &lsa_policy, + &num_trusts, + &trusts); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (ptrust_list) { + ptrust_list->count = num_trusts; + ptrust_list->array = talloc_move(mem_ctx, &trusts); + } + +done: + if (b && is_valid_policy_hnd(&lsa_policy)) { + dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } /* Lookup group membership given a rid. */ @@ -331,13 +412,84 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *group_sid, enum lsa_SidType type, - uint32_t *num_names, - struct dom_sid **sid_mem, - char ***names, - uint32_t **name_types) + uint32_t *pnum_names, + struct dom_sid **psid_mem, + char ***pnames, + uint32_t **pname_types) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + + uint32_t num_names = 0; + struct dom_sid *sid_mem = NULL; + char **names = NULL; + uint32_t *name_types = NULL; + + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_lookup_groupmem\n")); + + ZERO_STRUCT(dom_pol); + + /* Paranoia check */ + if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) { + /* There's no groups, only aliases in BUILTIN */ + return NT_STATUS_NO_SUCH_GROUP; + } + + if (pnum_names) { + *pnum_names = 0; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = samr_pipe->binding_handle; + + status = rpc_lookup_groupmem(tmp_ctx, + samr_pipe, + &dom_pol, + domain->name, + &domain->sid, + group_sid, + type, + &num_names, + &sid_mem, + &names, + &name_types); + + if (pnum_names) { + *pnum_names = num_names; + } + + if (pnames) { + *pnames = talloc_move(mem_ctx, &names); + } + + if (pname_types) { + *pname_types = talloc_move(mem_ctx, &name_types); + } + + if (psid_mem) { + *psid_mem = talloc_move(mem_ctx, &sid_mem); + } + +done: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } /********************************************************************* @@ -348,7 +500,7 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, - struct acct_info **info) + struct wb_acct_info **info) { /* BUILTIN doesn't have domain groups */ *num_entries = 0; @@ -391,117 +543,581 @@ static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain, *********************************************************************/ /* List all local groups (aliases) */ -static NTSTATUS common_enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32_t *num_entries, - struct acct_info **info) +static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32_t *pnum_info, + struct wb_acct_info **pinfo) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + struct wb_acct_info *info = NULL; + uint32_t num_info = 0; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("samr: enum local groups\n")); + + ZERO_STRUCT(dom_pol); + + if (pnum_info) { + *pnum_info = 0; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = samr_pipe->binding_handle; + + status = rpc_enum_local_groups(mem_ctx, + samr_pipe, + &dom_pol, + &num_info, + &info); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (pnum_info) { + *pnum_info = num_info; + } + + if (pinfo) { + *pinfo = talloc_move(mem_ctx, &info); + } + +done: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } /* convert a single name to a sid in a domain */ -static NTSTATUS common_name_to_sid(struct winbindd_domain *domain, +static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *domain_name, const char *name, uint32_t flags, - struct dom_sid *sid, - enum lsa_SidType *type) + struct dom_sid *psid, + enum lsa_SidType *ptype) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *lsa_pipe; + struct policy_handle lsa_policy; + struct dom_sid sid; + enum lsa_SidType type; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_name_to_sid\n")); + + ZERO_STRUCT(lsa_policy); + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = lsa_pipe->binding_handle; + + status = rpc_name_to_sid(tmp_ctx, + lsa_pipe, + &lsa_policy, + domain_name, + name, + flags, + &sid, + &type); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (psid) { + sid_copy(psid, &sid); + } + if (ptype) { + *ptype = type; + } + +done: + if (b && is_valid_policy_hnd(&lsa_policy)) { + dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } /* convert a domain SID to a user or group name */ -static NTSTATUS common_sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const struct dom_sid *sid, - char **domain_name, - char **name, - enum lsa_SidType *type) +static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *sid, + char **pdomain_name, + char **pname, + enum lsa_SidType *ptype) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *lsa_pipe; + struct policy_handle lsa_policy; + char *domain_name = NULL; + char *name = NULL; + enum lsa_SidType type; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_sid_to_name\n")); + + ZERO_STRUCT(lsa_policy); + + /* Paranoia check */ + if (!sid_check_is_in_builtin(sid) && + !sid_check_is_in_our_domain(sid) && + !sid_check_is_in_unix_users(sid) && + !sid_check_is_unix_users(sid) && + !sid_check_is_in_unix_groups(sid) && + !sid_check_is_unix_groups(sid) && + !sid_check_is_in_wellknown_domain(sid)) { + DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to " + "lookup SID %s\n", sid_string_dbg(sid))); + return NT_STATUS_NONE_MAPPED; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = lsa_pipe->binding_handle; + + status = rpc_sid_to_name(tmp_ctx, + lsa_pipe, + &lsa_policy, + domain, + sid, + &domain_name, + &name, + &type); + + if (ptype) { + *ptype = type; + } + + if (pname) { + *pname = talloc_move(mem_ctx, &name); + } + + if (pdomain_name) { + *pdomain_name = talloc_move(mem_ctx, &domain_name); + } + +done: + if (b && is_valid_policy_hnd(&lsa_policy)) { + dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } -static NTSTATUS common_rids_to_names(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const struct dom_sid *sid, - uint32 *rids, - size_t num_rids, - char **domain_name, - char ***names, - enum lsa_SidType **types) +static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *domain_sid, + uint32 *rids, + size_t num_rids, + char **pdomain_name, + char ***pnames, + enum lsa_SidType **ptypes) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *lsa_pipe; + struct policy_handle lsa_policy; + enum lsa_SidType *types = NULL; + char *domain_name = NULL; + char **names = NULL; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_rids_to_names for %s\n", domain->name)); + + ZERO_STRUCT(lsa_policy); + + /* Paranoia check */ + if (!sid_check_is_builtin(domain_sid) && + !sid_check_is_domain(domain_sid) && + !sid_check_is_unix_users(domain_sid) && + !sid_check_is_unix_groups(domain_sid) && + !sid_check_is_in_wellknown_domain(domain_sid)) { + DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to " + "lookup SID %s\n", sid_string_dbg(domain_sid))); + return NT_STATUS_NONE_MAPPED; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = lsa_pipe->binding_handle; + + status = rpc_rids_to_names(tmp_ctx, + lsa_pipe, + &lsa_policy, + domain, + domain_sid, + rids, + num_rids, + &domain_name, + &names, + &types); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (pdomain_name) { + *pdomain_name = talloc_move(mem_ctx, &domain_name); + } + + if (ptypes) { + *ptypes = talloc_move(mem_ctx, &types); + } + + if (pnames) { + *pnames = talloc_move(mem_ctx, &names); + } + +done: + if (b && is_valid_policy_hnd(&lsa_policy)) { + dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } -static NTSTATUS common_lockout_policy(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - struct samr_DomInfo12 *policy) +static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + struct samr_DomInfo12 *lockout_policy) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + union samr_DomainInfo *info = NULL; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_lockout_policy\n")); + + ZERO_STRUCT(dom_pol); + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + + b = samr_pipe->binding_handle; + + status = dcerpc_samr_QueryDomainInfo(b, + mem_ctx, + &dom_pol, + 12, + &info, + &result); + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + if (!NT_STATUS_IS_OK(result)) { + status = result; + goto error; + } + + *lockout_policy = info->info12; + +error: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } -static NTSTATUS common_password_policy(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - struct samr_DomInfo1 *policy) +static NTSTATUS sam_password_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + struct samr_DomInfo1 *passwd_policy) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + union samr_DomainInfo *info = NULL; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_password_policy\n")); + + ZERO_STRUCT(dom_pol); + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + + b = samr_pipe->binding_handle; + + status = dcerpc_samr_QueryDomainInfo(b, + mem_ctx, + &dom_pol, + 1, + &info, + &result); + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + if (!NT_STATUS_IS_OK(result)) { + status = result; + goto error; + } + + *passwd_policy = info->info1; + +error: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } -/* Lookup groups a user is a member of. I wish Unix had a call like this! */ -static NTSTATUS common_lookup_usergroups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const struct dom_sid *user_sid, - uint32_t *num_groups, - struct dom_sid **user_gids) +/* Lookup groups a user is a member of. */ +static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *user_sid, + uint32_t *pnum_groups, + struct dom_sid **puser_grpsids) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + struct dom_sid *user_grpsids = NULL; + uint32_t num_groups = 0; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_lookup_usergroups\n")); + + ZERO_STRUCT(dom_pol); + + if (pnum_groups) { + *pnum_groups = 0; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = samr_pipe->binding_handle; + + status = rpc_lookup_usergroups(tmp_ctx, + samr_pipe, + &dom_pol, + &domain->sid, + user_sid, + &num_groups, + &user_grpsids); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (pnum_groups) { + *pnum_groups = num_groups; + } + + if (puser_grpsids) { + *puser_grpsids = talloc_move(mem_ctx, &user_grpsids); + } + +done: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } -static NTSTATUS common_lookup_useraliases(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32_t num_sids, - const struct dom_sid *sids, - uint32_t *p_num_aliases, - uint32_t **rids) +static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32_t num_sids, + const struct dom_sid *sids, + uint32_t *pnum_aliases, + uint32_t **palias_rids) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + uint32_t num_aliases = 0; + uint32_t *alias_rids = NULL; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("sam_lookup_useraliases\n")); + + ZERO_STRUCT(dom_pol); + + if (pnum_aliases) { + *pnum_aliases = 0; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = samr_pipe->binding_handle; + + status = rpc_lookup_useraliases(tmp_ctx, + samr_pipe, + &dom_pol, + num_sids, + sids, + &num_aliases, + &alias_rids); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (pnum_aliases) { + *pnum_aliases = num_aliases; + } + + if (palias_rids) { + *palias_rids = talloc_move(mem_ctx, &alias_rids); + } + +done: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } /* find the sequence number for a domain */ -static NTSTATUS common_sequence_number(struct winbindd_domain *domain, - uint32_t *seq) +static NTSTATUS sam_sequence_number(struct winbindd_domain *domain, + uint32_t *pseq) { - /* TODO FIXME */ - return NT_STATUS_NOT_IMPLEMENTED; + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol; + uint32_t seq; + TALLOC_CTX *tmp_ctx; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = NULL; + + DEBUG(3,("samr: sequence number\n")); + + ZERO_STRUCT(dom_pol); + + if (pseq) { + *pseq = DOM_SEQUENCE_NONE; + } + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + b = samr_pipe->binding_handle; + + status = rpc_sequence_number(tmp_ctx, + samr_pipe, + &dom_pol, + domain->name, + &seq); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (pseq) { + *pseq = seq; + } +done: + if (b && is_valid_policy_hnd(&dom_pol)) { + dcerpc_samr_Close(b, tmp_ctx, &dom_pol, &result); + } + + TALLOC_FREE(tmp_ctx); + return status; } -#if 0 /* the rpc backend methods are exposed via this structure */ struct winbindd_methods builtin_passdb_methods = { .consistent = false, .query_user_list = builtin_query_user_list, .enum_dom_groups = builtin_enum_dom_groups, - .enum_local_groups = common_enum_local_groups, - .name_to_sid = common_name_to_sid, - .sid_to_name = common_sid_to_name, - .rids_to_names = common_rids_to_names, + .enum_local_groups = sam_enum_local_groups, + .name_to_sid = sam_name_to_sid, + .sid_to_name = sam_sid_to_name, + .rids_to_names = sam_rids_to_names, .query_user = builtin_query_user, - .lookup_usergroups = common_lookup_usergroups, - .lookup_useraliases = common_lookup_useraliases, + .lookup_usergroups = sam_lookup_usergroups, + .lookup_useraliases = sam_lookup_useraliases, .lookup_groupmem = sam_lookup_groupmem, - .sequence_number = common_sequence_number, - .lockout_policy = common_lockout_policy, - .password_policy = common_password_policy, + .sequence_number = sam_sequence_number, + .lockout_policy = sam_lockout_policy, + .password_policy = sam_password_policy, .trusted_domains = builtin_trusted_domains }; @@ -511,17 +1127,16 @@ struct winbindd_methods sam_passdb_methods = { .query_user_list = sam_query_user_list, .enum_dom_groups = sam_enum_dom_groups, - .enum_local_groups = common_enum_local_groups, - .name_to_sid = common_name_to_sid, - .sid_to_name = common_sid_to_name, - .rids_to_names = common_rids_to_names, + .enum_local_groups = sam_enum_local_groups, + .name_to_sid = sam_name_to_sid, + .sid_to_name = sam_sid_to_name, + .rids_to_names = sam_rids_to_names, .query_user = sam_query_user, - .lookup_usergroups = common_lookup_usergroups, - .lookup_useraliases = common_lookup_useraliases, + .lookup_usergroups = sam_lookup_usergroups, + .lookup_useraliases = sam_lookup_useraliases, .lookup_groupmem = sam_lookup_groupmem, - .sequence_number = common_sequence_number, - .lockout_policy = common_lockout_policy, - .password_policy = common_password_policy, + .sequence_number = sam_sequence_number, + .lockout_policy = sam_lockout_policy, + .password_policy = sam_password_policy, .trusted_domains = sam_trusted_domains }; -#endif