From ce0be638b4ceb6474f967500d3ec68c67c36cfd3 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Wed, 16 Jun 2021 17:39:02 +0200 Subject: [PATCH] s3:winbind: Convert PamLogOff from struct based to ndr based Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison --- librpc/idl/winbind.idl | 9 ++++ source3/winbindd/winbindd_domain.c | 4 -- source3/winbindd/winbindd_pam.c | 58 ++++++++++++++++---------- source3/winbindd/winbindd_pam_logoff.c | 54 ++++++++++++++++-------- source3/winbindd/winbindd_proto.h | 4 +- 5 files changed, 83 insertions(+), 46 deletions(-) diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl index 3686809030a..93fd56dff05 100644 --- a/librpc/idl/winbind.idl +++ b/librpc/idl/winbind.idl @@ -217,6 +217,15 @@ interface winbind [out,ref] wbint_PamAuthCrapValidation *validation ); + NTSTATUS wbint_PamLogOff( + [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 *krb5ccname, + [in] hyper uid + ); + /* 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 80df55a5819..1e19f673038 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 = "PAM_LOGOFF", - .struct_cmd = WINBINDD_PAM_LOGOFF, - .struct_fn = winbindd_dual_pam_logoff, },{ .name = "CHNG_PSWD_AUTH_CRAP", .struct_cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 49a2cd7c83b..93955675106 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -3081,51 +3081,68 @@ process_result: return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, - struct winbindd_cli_state *state) +NTSTATUS _wbint_PamLogOff(struct pipes_struct *p, struct wbint_PamLogOff *r) { + struct winbindd_domain *domain = wb_child_domain(); NTSTATUS result = NT_STATUS_NOT_SUPPORTED; + pid_t client_pid; + uid_t user_uid; - DEBUG(3, ("[%5lu]: pam dual logoff %s\n", (unsigned long)state->pid, - state->request->data.logoff.user)); + if (domain == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } - if (!(state->request->flags & WBFLAG_PAM_KRB5)) { + /* 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; + } + + /* Cut uid to 32bit */ + user_uid = r->in.uid; + if ((uint64_t)user_uid != r->in.uid) { + DBG_DEBUG("uid out of range\n"); + return NT_STATUS_INVALID_PARAMETER; + } + + DBG_NOTICE("[%"PRIu32"]: pam dual logoff %s\n", client_pid, r->in.user); + + if (!(r->in.flags & WBFLAG_PAM_KRB5)) { result = NT_STATUS_OK; goto process_result; } - if (state->request->data.logoff.krb5ccname[0] == '\0') { + if ((r->in.krb5ccname == NULL) || (strlen(r->in.krb5ccname) == 0)) { result = NT_STATUS_OK; goto process_result; } #ifdef HAVE_KRB5 - if (state->request->data.logoff.uid == (uid_t)-1) { - DEBUG(0,("winbindd_pam_logoff: invalid uid\n")); + if (user_uid == (uid_t)-1) { + DBG_DEBUG("Invalid uid for user '%s'\n", r->in.user); goto process_result; } /* what we need here is to find the corresponding krb5 ccache name *we* * created for a given username and destroy it */ - if (!ccache_entry_exists(state->request->data.logoff.user)) { + if (!ccache_entry_exists(r->in.user)) { result = NT_STATUS_OK; - DEBUG(10,("winbindd_pam_logoff: no entry found.\n")); + DBG_DEBUG("No entry found for user '%s'.\n", r->in.user); goto process_result; } - if (!ccache_entry_identical(state->request->data.logoff.user, - state->request->data.logoff.uid, - state->request->data.logoff.krb5ccname)) { - DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n")); + if (!ccache_entry_identical(r->in.user, user_uid, r->in.krb5ccname)) { + DBG_DEBUG("Cached entry differs for user '%s'\n", r->in.user); goto process_result; } - result = remove_ccache(state->request->data.logoff.user); + result = remove_ccache(r->in.user); if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("winbindd_pam_logoff: failed to remove ccache: %s\n", - nt_errstr(result))); + DBG_DEBUG("Failed to remove ccache for user '%s': %s\n", + r->in.user, nt_errstr(result)); goto process_result; } @@ -3134,7 +3151,7 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, * we might be using for krb5 ticket renewal. */ - winbindd_delete_memory_creds(state->request->data.logoff.user); + winbindd_delete_memory_creds(r->in.user); #else result = NT_STATUS_NOT_SUPPORTED; @@ -3142,10 +3159,7 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, process_result: - - set_auth_errors(state->response, result); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; + return result; } /* Change user password with auth crap*/ diff --git a/source3/winbindd/winbindd_pam_logoff.c b/source3/winbindd/winbindd_pam_logoff.c index 553b1e5833b..5578f887dcc 100644 --- a/source3/winbindd/winbindd_pam_logoff.c +++ b/source3/winbindd/winbindd_pam_logoff.c @@ -20,10 +20,10 @@ #include "includes.h" #include "winbindd.h" #include "lib/global_contexts.h" +#include "librpc/gen_ndr/ndr_winbind_c.h" struct winbindd_pam_logoff_state { - struct winbindd_request *request; - struct winbindd_response *response; + struct wbint_PamLogOff r; }; static void winbindd_pam_logoff_done(struct tevent_req *subreq); @@ -47,7 +47,6 @@ struct tevent_req *winbindd_pam_logoff_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } - state->request = request; /* Ensure null termination */ /* Ensure null termination */ @@ -99,8 +98,28 @@ struct tevent_req *winbindd_pam_logoff_send(TALLOC_CTX *mem_ctx, break; } - subreq = wb_domain_request_send(state, global_event_context(), domain, - request); + state->r.in.client_name = talloc_strdup(state, request->client_name); + if (tevent_req_nomem(state->r.in.client_name, req)) { + return tevent_req_post(req, ev); + } + state->r.in.client_pid = request->pid; + + state->r.in.flags = request->flags; + state->r.in.user = talloc_strdup(state, request->data.logoff.user); + if (tevent_req_nomem(state->r.in.user, req)) { + return tevent_req_post(req, ev); + } + state->r.in.uid = request->data.logoff.uid; + state->r.in.krb5ccname = talloc_strdup(state, + request->data.logoff.krb5ccname); + if (tevent_req_nomem(state->r.in.krb5ccname, req)) { + return tevent_req_post(req, ev); + } + + subreq = dcerpc_wbint_PamLogOff_r_send(state, + global_event_context(), + dom_child_handle(domain), + &state->r); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -118,14 +137,14 @@ static void winbindd_pam_logoff_done(struct tevent_req *subreq) subreq, struct tevent_req); struct winbindd_pam_logoff_state *state = tevent_req_data( req, struct winbindd_pam_logoff_state); - int res, err; + NTSTATUS status; - res = wb_domain_request_recv(subreq, state, &state->response, &err); + status = dcerpc_wbint_PamLogOff_r_recv(subreq, state); TALLOC_FREE(subreq); - if (res == -1) { - tevent_req_nterror(req, map_nt_error_from_unix(err)); + if (tevent_req_nterror(req, status)) { return; } + tevent_req_done(req); } @@ -134,20 +153,19 @@ NTSTATUS winbindd_pam_logoff_recv(struct tevent_req *req, { struct winbindd_pam_logoff_state *state = tevent_req_data( req, struct winbindd_pam_logoff_state); - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; if (tevent_req_is_nterror(req, &status)) { set_auth_errors(response, status); return status; } - *response = *state->response; - response->result = WINBINDD_PENDING; - state->response = talloc_move(response, &state->response); - status = NT_STATUS(response->data.auth.nt_status); - if (!NT_STATUS_IS_OK(status)) { - return status; + response->result = WINBINDD_PENDING; + set_auth_errors(response, state->r.out.result); + + if (NT_STATUS_IS_OK(state->r.out.result)) { + winbindd_delete_memory_creds(state->r.in.user); } - winbindd_delete_memory_creds(state->request->data.logoff.user); - return status; + + return NT_STATUS(response->data.auth.nt_status); } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 2641101ee0c..6dad82fc0a8 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -445,8 +445,8 @@ 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, - struct winbindd_cli_state *state) ; +NTSTATUS _wbint_PamLogOff(struct pipes_struct *p, + struct wbint_PamLogOff *r); enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state); NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state, TALLOC_CTX *mem_ctx,