From: Samuel Cabrero Date: Fri, 25 Feb 2022 10:32:14 +0000 (+0100) Subject: s3:winbind: Convert PAM_AUTH_CRAP from struct based to NDR based X-Git-Tag: talloc-2.3.4~300 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c68f21f26f10b60ca1ac294b7294bfbf37c9bb86;p=thirdparty%2Fsamba.git s3:winbind: Convert PAM_AUTH_CRAP from struct based to NDR based Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison --- diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl index 2737c563c69..8a50a53eea1 100644 --- a/librpc/idl/winbind.idl +++ b/librpc/idl/winbind.idl @@ -196,6 +196,27 @@ interface winbind [out,ref] wbint_Validation *validation ); + typedef [public] struct { + uint16 level; + [switch_is(level)] netr_Validation *validation; + } wbint_PamAuthCrapValidation; + + NTSTATUS wbint_PamAuthCrap( + [in,string,charset(UTF8)] char *client_name, + [in] hyper client_pid, + [in] uint32 flags, + [in, string,charset(UTF8)] char *user, + [in, string,charset(UTF8)] char *domain, + [in, string,charset(UTF8)] char *workstation, + [in] DATA_BLOB lm_resp, + [in] DATA_BLOB nt_resp, + [in] DATA_BLOB chal, + [in] uint32 logon_parameters, + [in] wbint_SidArray *require_membership_of_sid, + [out,ref] uint8 *authoritative, + [out,ref] wbint_PamAuthCrapValidation *validation + ); + /* Public methods available via IRPC */ typedef [switch_type(uint16)] union netr_LogonLevel netr_LogonLevel; diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c index 6f85d0779a0..80df55a5819 100644 --- a/source3/winbindd/winbindd_domain.c +++ b/source3/winbindd/winbindd_domain.c @@ -30,10 +30,6 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = { .name = "INIT_CONNECTION", .struct_cmd = WINBINDD_INIT_CONNECTION, .struct_fn = winbindd_dual_init_connection, - },{ - .name = "AUTH_CRAP", - .struct_cmd = WINBINDD_PAM_AUTH_CRAP, - .struct_fn = winbindd_dual_pam_auth_crap, },{ .name = "PAM_LOGOFF", .struct_cmd = WINBINDD_PAM_LOGOFF, diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 878e169b761..cbcc96595d7 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2115,7 +2115,7 @@ done: * @brief build a tsocket_address for the remote address of the supplied socket * */ -static struct tsocket_address *get_remote_address(TALLOC_CTX *mem_ctx, int sock) +_UNUSED_ static struct tsocket_address *get_remote_address(TALLOC_CTX *mem_ctx, int sock) { struct sockaddr_storage st = {0}; struct sockaddr *sar = (struct sockaddr *)&st; @@ -2141,7 +2141,7 @@ static struct tsocket_address *get_remote_address(TALLOC_CTX *mem_ctx, int sock) * @brief build a tsocket_address for the local address of the supplied socket * */ -static struct tsocket_address *get_local_address(TALLOC_CTX *mem_ctx, int sock) +_UNUSED_ static struct tsocket_address *get_local_address(TALLOC_CTX *mem_ctx, int sock) { struct sockaddr_storage st = {0}; struct sockaddr *sar = (struct sockaddr *)&st; @@ -2836,71 +2836,52 @@ done: return NT_STATUS_OK; } -enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, - struct winbindd_cli_state *state) +NTSTATUS _wbint_PamAuthCrap(struct pipes_struct *p, struct wbint_PamAuthCrap *r) { + struct winbindd_domain *domain = wb_child_domain(); NTSTATUS result; - const char *name_user = NULL; - const char *name_domain = NULL; - const char *workstation; uint64_t logon_id = 0; uint8_t authoritative = 1; uint32_t flags = 0; uint16_t validation_level = UINT16_MAX; union netr_Validation *validation = NULL; - DATA_BLOB lm_resp = { 0 }, nt_resp = { 0 }; - DATA_BLOB chal = data_blob_null; const struct timeval start_time = timeval_current(); const struct tsocket_address *remote = NULL; const struct tsocket_address *local = NULL; struct netr_SamInfo3 *info3 = NULL; - struct wbint_SidArray *sid_array = NULL; + pid_t client_pid; - /* This is child-only, so no check for privileged access is needed - anymore */ + if (domain == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } - /* Ensure null termination */ - state->request->data.auth_crap.user[sizeof(state->request->data.auth_crap.user)-1]=0; - state->request->data.auth_crap.domain[sizeof(state->request->data.auth_crap.domain)-1]=0; + /* Cut client_pid to 32bit */ + client_pid = r->in.client_pid; + if ((uint64_t)client_pid != r->in.client_pid) { + DBG_DEBUG("pid out of range\n"); + return NT_STATUS_INVALID_PARAMETER; + } - name_user = state->request->data.auth_crap.user; - name_domain = state->request->data.auth_crap.domain; - workstation = state->request->data.auth_crap.workstation; logon_id = generate_random_u64(); - remote = get_remote_address(state->mem_ctx, state->sock); - local = get_local_address(state->mem_ctx, state->sock); - - DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, - name_domain, name_user)); + remote = dcesrv_connection_get_remote_address(p->dce_call->conn); + local = dcesrv_connection_get_local_address(p->dce_call->conn); - lm_resp = data_blob_talloc(state->mem_ctx, state->request->data.auth_crap.lm_resp, - state->request->data.auth_crap.lm_resp_len); - - if (state->request->flags & WBFLAG_BIG_NTLMV2_BLOB) { - nt_resp = data_blob_talloc(state->mem_ctx, - state->request->extra_data.data, - state->request->data.auth_crap.nt_resp_len); - } else { - nt_resp = data_blob_talloc(state->mem_ctx, - state->request->data.auth_crap.nt_resp, - state->request->data.auth_crap.nt_resp_len); - } - chal = data_blob_const(state->request->data.auth_crap.chal, 8); + DBG_NOTICE("[%"PRIu32"]: pam auth crap domain: %s user: %s\n", + client_pid, r->in.domain, r->in.user); result = winbind_dual_SamLogon(domain, - state->mem_ctx, + p->mem_ctx, false, /* interactive */ - state->request->data.auth_crap.logon_parameters, - name_user, - name_domain, - /* Bug #3248 - found by Stefan Burkei. */ - workstation, /* We carefully set this above so use it... */ + r->in.logon_parameters, + r->in.user, + r->in.domain, + r->in.workstation, logon_id, - state->request->client_name, - state->request->pid, - chal, - lm_resp, - nt_resp, + r->in.client_name, + client_pid, + r->in.chal, + r->in.lm_resp, + r->in.nt_resp, remote, local, &authoritative, @@ -2912,7 +2893,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = map_validation_to_info3(state->mem_ctx, + result = map_validation_to_info3(p->mem_ctx, validation_level, validation, &info3); @@ -2920,32 +2901,19 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = extra_data_to_sid_array( - state->request->data.auth_crap.require_membership_of_sid, - state->mem_ctx, - &sid_array); - if (!NT_STATUS_IS_OK(result)) { - DBG_ERR("Failed to parse '%s' into a sid array: %s\n", - state->request->data.auth_crap.require_membership_of_sid, - nt_errstr(result)); - goto done; - } - /* Check if the user is in the right group */ - result = check_info3_in_group(info3, sid_array); + result = check_info3_in_group(info3, r->in.require_membership_of_sid); if (!NT_STATUS_IS_OK(result)) { - char *s = NDR_PRINT_STRUCT_STRING(state->mem_ctx, + char *s = NDR_PRINT_STRUCT_STRING(p->mem_ctx, wbint_SidArray, - sid_array); + r->in.require_membership_of_sid); DBG_NOTICE("User %s is not in the required groups:\n", - state->request->data.auth_crap.user); + r->in.user); DEBUGADD(DBGLVL_NOTICE, ("%s", s)); DEBUGADD(DBGLVL_NOTICE, ("CRAP authentication is rejected\n")); - TALLOC_FREE(sid_array); goto done; } - TALLOC_FREE(sid_array); if (!is_allowed_domain(info3->base.logon_domain.string)) { DBG_NOTICE("Authentication failed for user [%s] " @@ -2956,45 +2924,48 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = append_auth_data(state->mem_ctx, state->response, - state->request->flags, - validation_level, - validation, - name_domain, name_user); + r->out.validation = talloc_zero(p->mem_ctx, + struct wbint_PamAuthCrapValidation); + if (r->out.validation == NULL) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + r->out.validation->level = validation_level; + r->out.validation->validation = talloc_move(r->out.validation, + &validation); done: - if (state->request->flags & WBFLAG_PAM_NT_STATUS_SQUASH) { + if (r->in.flags & WBFLAG_PAM_NT_STATUS_SQUASH) { result = nt_status_squash(result); } - set_auth_errors(state->response, result); - state->response->data.auth.authoritative = authoritative; + *r->out.authoritative = authoritative; /* * Log the winbind pam authentication, the logon_id will tie this to * any of the logons invoked from this request. */ log_authentication( - state->mem_ctx, + p->mem_ctx, domain, - state->request->client_name, - state->pid, - validation_level, - validation, + r->in.client_name, + client_pid, + r->out.validation->level, + r->out.validation->validation, start_time, logon_id, "NTLM_AUTH", - name_user, - name_domain, - workstation, - lm_resp, - nt_resp, + r->in.user, + r->in.domain, + r->in.workstation, + r->in.lm_resp, + r->in.nt_resp, remote, local, result); - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; + return result; } enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain, diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c index 1a945c55ee3..6120522ce3c 100644 --- a/source3/winbindd/winbindd_pam_auth_crap.c +++ b/source3/winbindd/winbindd_pam_auth_crap.c @@ -23,14 +23,16 @@ #include "libcli/security/dom_sid.h" #include "lib/util/string_wrappers.h" #include "lib/global_contexts.h" +#include "librpc/gen_ndr/ndr_winbind_c.h" struct winbindd_pam_auth_crap_state { - struct winbindd_response *response; uint8_t authoritative; uint32_t flags; bool pac_is_trusted; - uint16_t validation_level; - union netr_Validation *validation; + char *domain; + char *user; + struct wbint_PamAuthCrapValidation validation; + NTSTATUS result; }; static void winbindd_pam_auth_crap_done(struct tevent_req *subreq); @@ -45,6 +47,11 @@ struct tevent_req *winbindd_pam_auth_crap_send( struct winbindd_pam_auth_crap_state *state; struct winbindd_domain *domain; const char *auth_domain = NULL; + DATA_BLOB lm_resp = data_blob_null; + DATA_BLOB nt_resp = data_blob_null; + DATA_BLOB chal = data_blob_null; + struct wbint_SidArray *require_membership_of_sid = NULL; + NTSTATUS status; req = tevent_req_create(mem_ctx, &state, struct winbindd_pam_auth_crap_state); @@ -55,14 +62,12 @@ struct tevent_req *winbindd_pam_auth_crap_send( state->flags = request->flags; if (state->flags & WBFLAG_PAM_AUTH_PAC) { - NTSTATUS status; - - status = winbindd_pam_auth_pac_verify(cli, - state, - &state->pac_is_trusted, - &state->validation_level, - &state->validation); - if (tevent_req_nterror(req, status)) { + state->result = winbindd_pam_auth_pac_verify(cli, + state, + &state->pac_is_trusted, + &state->validation.level, + &state->validation.validation); + if (tevent_req_nterror(req, state->result)) { return tevent_req_post(req, ev); } @@ -78,10 +83,12 @@ struct tevent_req *winbindd_pam_auth_crap_send( request->data.auth_crap.workstation[ sizeof(request->data.auth_crap.workstation)-1] = '\0'; - DEBUG(3, ("[%5lu]: pam auth crap domain: [%s] user: %s\n", - (unsigned long)cli->pid, - request->data.auth_crap.domain, - request->data.auth_crap.user)); + DBG_NOTICE("[%5lu]: pam auth crap domain: [%s] user: [%s] " + "workstation: [%s]\n", + (unsigned long)cli->pid, + request->data.auth_crap.domain, + request->data.auth_crap.user, + request->data.auth_crap.workstation); if (!check_request_flags(request->flags)) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); @@ -120,8 +127,67 @@ struct tevent_req *winbindd_pam_auth_crap_send( } } - subreq = wb_domain_request_send(state, global_event_context(), domain, - request); + state->domain = talloc_strdup(state, request->data.auth_crap.domain); + if (tevent_req_nomem(state->domain, req)) { + return tevent_req_post(req, ev); + } + + state->user = talloc_strdup(state, request->data.auth_crap.user); + if (tevent_req_nomem(state->user, req)) { + return tevent_req_post(req, ev); + } + + status = extra_data_to_sid_array( + request->data.auth_crap.require_membership_of_sid, + state, + &require_membership_of_sid); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + lm_resp = data_blob_talloc(state, + request->data.auth_crap.lm_resp, + request->data.auth_crap.lm_resp_len); + if (tevent_req_nomem(lm_resp.data, req)) { + return tevent_req_post(req, ev); + } + + if (request->flags & WBFLAG_BIG_NTLMV2_BLOB) { + nt_resp = data_blob_talloc(state, + request->extra_data.data, + request->data.auth_crap.nt_resp_len); + } else { + nt_resp = data_blob_talloc(state, + request->data.auth_crap.nt_resp, + request->data.auth_crap.nt_resp_len); + } + if (tevent_req_nomem(nt_resp.data, req)) { + return tevent_req_post(req, ev); + } + + chal = data_blob_talloc(state, + request->data.auth_crap.chal, + 8); + if (tevent_req_nomem(chal.data, req)) { + return tevent_req_post(req, ev); + } + + subreq = dcerpc_wbint_PamAuthCrap_send(state, + global_event_context(), + dom_child_handle(domain), + request->client_name, + request->pid, + request->flags, + request->data.auth_crap.user, + request->data.auth_crap.domain, + request->data.auth_crap.workstation, + lm_resp, + nt_resp, + chal, + request->data.auth_crap.logon_parameters, + require_membership_of_sid, + &state->authoritative, + &state->validation); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -135,12 +201,11 @@ static void winbindd_pam_auth_crap_done(struct tevent_req *subreq) subreq, struct tevent_req); struct winbindd_pam_auth_crap_state *state = tevent_req_data( req, struct winbindd_pam_auth_crap_state); - int res, err; + NTSTATUS status; - res = wb_domain_request_recv(subreq, state, &state->response, &err); + status = dcerpc_wbint_PamAuthCrap_recv(subreq, state, &state->result); TALLOC_FREE(subreq); - if (res == -1) { - tevent_req_nterror(req, map_nt_error_from_unix(err)); + if (tevent_req_nterror(req, status)) { return; } @@ -155,52 +220,40 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req, NTSTATUS status; if (tevent_req_is_nterror(req, &status)) { - set_auth_errors(response, status); - response->data.auth.authoritative = state->authoritative; - return status; + goto out; } - if (state->flags & WBFLAG_PAM_AUTH_PAC) { - state->response = talloc_zero(state, - struct winbindd_response); - if (state->response == NULL) { - status = NT_STATUS_NO_MEMORY; - set_auth_errors(response, status); - response->data.auth.authoritative = state->authoritative; - return status; - } - state->response->result = WINBINDD_PENDING; - state->response->length = sizeof(struct winbindd_response); - - status = append_auth_data(state->response, - state->response, - state->flags, - state->validation_level, - state->validation, - NULL, NULL); - if (NT_STATUS_IS_ERR(status)) { - set_auth_errors(response, status); - response->data.auth.authoritative = state->authoritative; - return status; - } + if (NT_STATUS_IS_ERR(state->result)) { + status = state->result; + goto out; + } - if (!state->pac_is_trusted) { - /* - * Clear the flag in state to do no add the domain - * from auth below. - */ - state->flags &= ~WBFLAG_PAM_INFO3_TEXT; - } + status = append_auth_data(response, + response, + state->flags, + state->validation.level, + state->validation.validation, + state->domain, + state->user); + if (NT_STATUS_IS_ERR(status)) { + goto out; } - if (NT_STATUS_IS_OK(NT_STATUS(state->response->data.auth.nt_status)) && - (state->flags & WBFLAG_PAM_INFO3_TEXT)) { + if (state->flags & WBFLAG_PAM_AUTH_PAC && !state->pac_is_trusted) { + /* + * Clear the flag just in state to do no add the domain + * from auth below. + */ + state->flags &= ~WBFLAG_PAM_INFO3_TEXT; + } + + if (state->flags & WBFLAG_PAM_INFO3_TEXT) { bool ok; ok = add_trusted_domain_from_auth( - state->response->data.auth.validation_level, - &state->response->data.auth.info3, - &state->response->data.auth.info6); + response->data.auth.validation_level, + &response->data.auth.info3, + &response->data.auth.info6); if (!ok) { status = NT_STATUS_LOGON_FAILURE; DBG_ERR("add_trusted_domain_from_auth failed\n"); @@ -211,8 +264,11 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req, } } - *response = *state->response; + status = NT_STATUS_OK; + +out: + set_auth_errors(response, status); + response->data.auth.authoritative = state->authoritative; response->result = WINBINDD_PENDING; - state->response = talloc_move(response, &state->response); return NT_STATUS(response->data.auth.nt_status); } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index b80ba72d5e2..2641101ee0c 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -441,8 +441,8 @@ struct pipes_struct; struct wbint_PamAuth; NTSTATUS _wbint_PamAuth(struct pipes_struct *p, struct wbint_PamAuth *r); -enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, - struct winbindd_cli_state *state) ; +NTSTATUS _wbint_PamAuthCrap(struct pipes_struct *p, + struct wbint_PamAuthCrap *r); enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain, struct winbindd_cli_state *state); enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,