From: Samuel Cabrero Date: Tue, 22 Jun 2021 08:23:04 +0000 (+0200) Subject: s3:winbind: Convert winbindd_dual_pam_chauthtok() from struct based to NDR based X-Git-Tag: talloc-2.3.4~103 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc0ef447cdc1c5f77162e52f44852aaaf6047d12;p=thirdparty%2Fsamba.git s3:winbind: Convert winbindd_dual_pam_chauthtok() from struct based to NDR based Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison --- diff --git a/librpc/idl/samr.idl b/librpc/idl/samr.idl index 867862dcd5c..fffa853ce3f 100644 --- a/librpc/idl/samr.idl +++ b/librpc/idl/samr.idl @@ -347,7 +347,7 @@ import "misc.idl", "lsa.idl", "security.idl"; DOMAIN_SERVER_DISABLED = 2 } samr_DomainServerState; - typedef struct { + typedef [public] struct { uint16 min_password_length; uint16 password_history_length; samr_PasswordProperties password_properties; diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl index 9ec98bd0878..2d209448841 100644 --- a/librpc/idl/winbind.idl +++ b/librpc/idl/winbind.idl @@ -1,5 +1,5 @@ #include "idl_types.h" -import "lsa.idl", "netlogon.idl", "misc.idl", "security.idl", "idmap.idl"; +import "lsa.idl", "netlogon.idl", "samr.idl", "misc.idl", "security.idl", "idmap.idl"; [ uuid("bf09192c-ed60-4928-9dff-d0d7bcb03ed8"), @@ -237,6 +237,17 @@ interface winbind [in,flag(NDR_SECRET)] DATA_BLOB old_lm_hash_enc ); + NTSTATUS wbint_PamAuthChangePassword( + [in,string,charset(UTF8)] char *client_name, + [in] hyper client_pid, + [in] uint32 flags, + [in,string,charset(UTF8)] char *user, + [in,string,charset(UTF8),flag(NDR_SECRET)] char *old_password, + [in,string,charset(UTF8),flag(NDR_SECRET)] char *new_password, + [out,ref] samr_DomInfo1 **dominfo, + [out,ref] samPwdChangeReason *reject_reason + ); + /* 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 6ea83706524..c206b9589c9 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_CHAUTHTOK", - .struct_cmd = WINBINDD_PAM_CHAUTHTOK, - .struct_fn = winbindd_dual_pam_chauthtok, },{ .name = "NDRCMD", .struct_cmd = WINBINDD_DUAL_NDRCMD, diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index f4d8ab39c41..21649c69b10 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -548,21 +548,6 @@ struct winbindd_domain *find_auth_domain(uint8_t flags, return find_our_domain(); } -static void fill_in_password_policy(struct winbindd_response *r, - const struct samr_DomInfo1 *p) -{ - r->data.auth.policy.min_length_password = - p->min_password_length; - r->data.auth.policy.password_history = - p->password_history_length; - r->data.auth.policy.password_properties = - p->password_properties; - r->data.auth.policy.expire = - nt_time_to_unix_abs((const NTTIME *)&(p->max_password_age)); - r->data.auth.policy.min_passwordage = - nt_time_to_unix_abs((const NTTIME *)&(p->min_password_age)); -} - static NTSTATUS get_password_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct samr_DomInfo1 **_policy) @@ -2918,11 +2903,10 @@ done: return result; } -enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain, - struct winbindd_cli_state *state) +NTSTATUS _wbint_PamAuthChangePassword(struct pipes_struct *p, + struct wbint_PamAuthChangePassword *r) { - char *oldpass; - char *newpass = NULL; + struct winbindd_domain *contact_domain = wb_child_domain(); struct policy_handle dom_pol; struct rpc_pipe_client *cli = NULL; bool got_info = false; @@ -2932,13 +2916,25 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact fstring namespace, domain, user; struct dcerpc_binding_handle *b = NULL; bool ok; + pid_t client_pid; ZERO_STRUCT(dom_pol); - DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid, - state->request->data.auth.user)); + if (contact_domain == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } + + /* 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; + } + + DBG_NOTICE("[%"PRIu32"]: dual pam chauthtok %s\n", + client_pid, r->in.user); - ok = parse_domain_user(state->request->data.chauthtok.user, + ok = parse_domain_user(r->in.user, namespace, domain, user); @@ -2954,17 +2950,15 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } - /* Change password */ - - oldpass = state->request->data.chauthtok.oldpass; - newpass = state->request->data.chauthtok.newpass; - /* Initialize reject reason */ - state->response->data.auth.reject_reason = Undefined; + *r->out.reject_reason = Undefined; /* Get sam handle */ - result = cm_connect_sam(contact_domain, state->mem_ctx, true, &cli, + result = cm_connect_sam(contact_domain, + p->mem_ctx, + true, + &cli, &dom_pol); if (!NT_STATUS_IS_OK(result)) { DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); @@ -2973,10 +2967,11 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact b = cli->binding_handle; - result = rpccli_samr_chgpasswd_user3(cli, state->mem_ctx, + result = rpccli_samr_chgpasswd_user3(cli, + p->mem_ctx, user, - newpass, - oldpass, + r->in.new_password, + r->in.old_password, &info, &reject); @@ -2984,10 +2979,8 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) { - fill_in_password_policy(state->response, info); - - state->response->data.auth.reject_reason = - reject->extendedFailureReason; + *r->out.dominfo = talloc_steal(p->mem_ctx, info); + *r->out.reject_reason = reject->extendedFailureReason; got_info = true; } @@ -3006,7 +2999,11 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n", nt_errstr(result))); - result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); + result = rpccli_samr_chgpasswd_user2(cli, + p->mem_ctx, + user, + r->in.new_password, + r->in.old_password); /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. Map to the same status code as Windows 2003. */ @@ -3019,10 +3016,10 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact done: if (NT_STATUS_IS_OK(result) - && (state->request->flags & WBFLAG_PAM_CACHED_LOGIN) + && (r->in.flags & WBFLAG_PAM_CACHED_LOGIN) && lp_winbind_offline_logon()) { result = winbindd_update_creds_by_name(contact_domain, user, - newpass); + r->in.new_password); /* Again, this happens when we login from gdm or xdm * and the password expires, *BUT* cached crendentials * doesn't exist. winbindd_update_creds_by_name() @@ -3046,7 +3043,7 @@ done: NTSTATUS policy_ret; policy_ret = get_password_policy(contact_domain, - state->mem_ctx, + p->mem_ctx, &info); /* failure of this is non critical, it will just provide no @@ -3058,8 +3055,7 @@ done: goto process_result; } - fill_in_password_policy(state->response, info); - TALLOC_FREE(info); + *r->out.dominfo = talloc_steal(p->mem_ctx, info); } process_result: @@ -3069,22 +3065,23 @@ process_result: if (b) { if (is_valid_policy_hnd(&dom_pol)) { NTSTATUS _result; - dcerpc_samr_Close(b, state->mem_ctx, &dom_pol, &_result); + dcerpc_samr_Close(b, + p->mem_ctx, + &dom_pol, + &_result); } TALLOC_FREE(cli); } } - set_auth_errors(state->response, result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", domain, user, - state->response->data.auth.nt_status_string, - state->response->data.auth.pam_error)); + nt_errstr(result), + nt_status_to_pam(result))); - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; + return result; } NTSTATUS _wbint_PamLogOff(struct pipes_struct *p, struct wbint_PamLogOff *r) diff --git a/source3/winbindd/winbindd_pam_chauthtok.c b/source3/winbindd/winbindd_pam_chauthtok.c index e476d53f030..336654e9193 100644 --- a/source3/winbindd/winbindd_pam_chauthtok.c +++ b/source3/winbindd/winbindd_pam_chauthtok.c @@ -21,10 +21,25 @@ #include "winbindd.h" #include "lib/util/string_wrappers.h" #include "lib/global_contexts.h" +#include "librpc/gen_ndr/ndr_winbind_c.h" + +static void fill_in_password_policy(struct winbindd_response *r, + const struct samr_DomInfo1 *p) +{ + r->data.auth.policy.min_length_password = + p->min_password_length; + r->data.auth.policy.password_history = + p->password_history_length; + r->data.auth.policy.password_properties = + p->password_properties; + r->data.auth.policy.expire = + nt_time_to_unix_abs((const NTTIME *)&(p->max_password_age)); + r->data.auth.policy.min_passwordage = + nt_time_to_unix_abs((const NTTIME *)&(p->min_password_age)); +} struct winbindd_pam_chauthtok_state { - struct winbindd_request *request; - struct winbindd_response *response; + struct wbint_PamAuthChangePassword r; }; static void winbindd_pam_chauthtok_done(struct tevent_req *subreq); @@ -48,7 +63,6 @@ struct tevent_req *winbindd_pam_chauthtok_send( if (req == NULL) { return NULL; } - state->request = request; /* Ensure null termination */ request->data.chauthtok.user[ @@ -85,8 +99,35 @@ struct tevent_req *winbindd_pam_chauthtok_send( return tevent_req_post(req, ev); } - subreq = wb_domain_request_send(state, global_event_context(), - contact_domain, request); + state->r.in.client_pid = request->pid; + state->r.in.flags = request->flags; + + 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.user = talloc_strdup(state, request->data.chauthtok.user); + if (tevent_req_nomem(state->r.in.user, req)) { + return tevent_req_post(req, ev); + } + + state->r.in.old_password = talloc_strdup(state, + request->data.chauthtok.oldpass); + if (tevent_req_nomem(state->r.in.old_password, req)) { + return tevent_req_post(req, ev); + } + + state->r.in.new_password = talloc_strdup(state, + request->data.chauthtok.newpass); + if (tevent_req_nomem(state->r.in.new_password, req)) { + return tevent_req_post(req, ev); + } + + subreq = dcerpc_wbint_PamAuthChangePassword_r_send(state, + global_event_context(), + dom_child_handle(contact_domain), + &state->r); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -100,14 +141,14 @@ static void winbindd_pam_chauthtok_done(struct tevent_req *subreq) subreq, struct tevent_req); struct winbindd_pam_chauthtok_state *state = tevent_req_data( req, struct winbindd_pam_chauthtok_state); - int res, err; + NTSTATUS status; - res = wb_domain_request_recv(subreq, state, &state->response, &err); + status = dcerpc_wbint_PamAuthChangePassword_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); } @@ -116,27 +157,26 @@ NTSTATUS winbindd_pam_chauthtok_recv(struct tevent_req *req, { struct winbindd_pam_chauthtok_state *state = tevent_req_data( req, struct winbindd_pam_chauthtok_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; + set_auth_errors(response, state->r.out.result); + if (*state->r.out.dominfo != NULL) { + fill_in_password_policy(response, *state->r.out.dominfo); } + response->data.auth.reject_reason = *state->r.out.reject_reason; - if (state->request->flags & WBFLAG_PAM_CACHED_LOGIN) { + if (state->r.in.flags & WBFLAG_PAM_CACHED_LOGIN) { /* Update the single sign-on memory creds. */ status = winbindd_replace_memory_creds( - state->request->data.chauthtok.user, - state->request->data.chauthtok.newpass); + state->r.in.user, state->r.in.new_password); DEBUG(10, ("winbindd_replace_memory_creds returned %s\n", nt_errstr(status))); @@ -152,5 +192,6 @@ NTSTATUS winbindd_pam_chauthtok_recv(struct tevent_req *req, status = NT_STATUS_OK; } } - 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 76fd4cb0865..57f7cebd2cf 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -443,8 +443,8 @@ NTSTATUS _wbint_PamAuth(struct pipes_struct *p, struct wbint_PamAuth *r); 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); +NTSTATUS _wbint_PamAuthChangePassword(struct pipes_struct *p, + struct wbint_PamAuthChangePassword *r); NTSTATUS _wbint_PamLogOff(struct pipes_struct *p, struct wbint_PamLogOff *r); NTSTATUS _wbint_PamAuthCrapChangePassword(struct pipes_struct *p,