diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl index 93fd56dff05..9ec98bd0878 100644 --- a/librpc/idl/winbind.idl +++ b/librpc/idl/winbind.idl @@ -226,6 +226,17 @@ interface winbind [in] hyper uid ); + NTSTATUS wbint_PamAuthCrapChangePassword( + [in,string,charset(UTF8)] char *client_name, + [in] hyper client_pid, + [in,string,charset(UTF8)] char *user, + [in,string,charset(UTF8)] char *domain, + [in,flag(NDR_SECRET)] DATA_BLOB new_nt_pswd, + [in,flag(NDR_SECRET)] DATA_BLOB old_nt_hash_enc, + [in,flag(NDR_SECRET)] DATA_BLOB new_lm_pswd, + [in,flag(NDR_SECRET)] DATA_BLOB old_lm_hash_enc + ); + /* 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 1e19f673038..6ea83706524 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 = "CHNG_PSWD_AUTH_CRAP", - .struct_cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, - .struct_fn = winbindd_dual_pam_chng_pswd_auth_crap, },{ .name = "PAM_CHAUTHTOK", .struct_cmd = WINBINDD_PAM_CHAUTHTOK, diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 93955675106..868dc813892 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -3164,34 +3164,36 @@ process_result: /* Change user password with auth crap*/ -enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state) +NTSTATUS _wbint_PamAuthCrapChangePassword(struct pipes_struct *p, + struct wbint_PamAuthCrapChangePassword *r) { NTSTATUS result; - DATA_BLOB new_nt_password; - DATA_BLOB old_nt_hash_enc; - DATA_BLOB new_lm_password; - DATA_BLOB old_lm_hash_enc; fstring namespace, domain, user; struct policy_handle dom_pol; - struct winbindd_domain *contact_domain = domainSt; + struct winbindd_domain *contact_domain = wb_child_domain(); struct rpc_pipe_client *cli = NULL; struct dcerpc_binding_handle *b = NULL; + pid_t client_pid; ZERO_STRUCT(dom_pol); - /* Ensure null termination */ - state->request->data.chng_pswd_auth_crap.user[ - sizeof(state->request->data.chng_pswd_auth_crap.user)-1]=0; - state->request->data.chng_pswd_auth_crap.domain[ - sizeof(state->request->data.chng_pswd_auth_crap.domain)-1]=0; + 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; + } + domain[0] = '\0'; namespace[0] = '\0'; user[0] = '\0'; - DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", - (unsigned long)state->pid, - state->request->data.chng_pswd_auth_crap.domain, - state->request->data.chng_pswd_auth_crap.user)); + DBG_NOTICE("[%"PRIu32"]: pam change pswd auth crap domain: %s " + "user: %s\n", client_pid, r->in.domain, r->in.user); if (lp_winbind_offline_logon()) { DEBUG(0,("Refusing password change as winbind offline logons are enabled. ")); @@ -3200,12 +3202,12 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai goto done; } - if (*state->request->data.chng_pswd_auth_crap.domain) { - fstrcpy(domain,state->request->data.chng_pswd_auth_crap.domain); + if (r->in.domain != NULL && strlen(r->in.domain) > 0) { + fstrcpy(domain, r->in.domain); } else { bool ok; - ok = parse_domain_user(state->request->data.chng_pswd_auth_crap.user, + ok = parse_domain_user(r->in.user, namespace, domain, user); @@ -3214,10 +3216,9 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai goto done; } - if(!*domain) { - DEBUG(3,("no domain specified with username (%s) - " - "failing auth\n", - state->request->data.chng_pswd_auth_crap.user)); + if (strlen(domain) == 0) { + DBG_NOTICE("no domain specified with username (%s) - " + "failing auth\n", r->in.user); result = NT_STATUS_NO_SUCH_USER; goto done; } @@ -3230,44 +3231,23 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai if (!is_allowed_domain(domain)) { DBG_NOTICE("Authentication failed for user [%s] " "from firewalled domain [%s]\n", - state->request->data.chng_pswd_auth_crap.user, + r->in.user, domain); result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; goto done; } if(!*user) { - fstrcpy(user, state->request->data.chng_pswd_auth_crap.user); - } - - DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", - (unsigned long)state->pid, domain, user)); - - /* Change password */ - new_nt_password = data_blob_const( - state->request->data.chng_pswd_auth_crap.new_nt_pswd, - state->request->data.chng_pswd_auth_crap.new_nt_pswd_len); - - old_nt_hash_enc = data_blob_const( - state->request->data.chng_pswd_auth_crap.old_nt_hash_enc, - state->request->data.chng_pswd_auth_crap.old_nt_hash_enc_len); - - if(state->request->data.chng_pswd_auth_crap.new_lm_pswd_len > 0) { - new_lm_password = data_blob_const( - state->request->data.chng_pswd_auth_crap.new_lm_pswd, - state->request->data.chng_pswd_auth_crap.new_lm_pswd_len); - - old_lm_hash_enc = data_blob_const( - state->request->data.chng_pswd_auth_crap.old_lm_hash_enc, - state->request->data.chng_pswd_auth_crap.old_lm_hash_enc_len); - } else { - new_lm_password = data_blob_null; - old_lm_hash_enc = data_blob_null; + fstrcpy(user, r->in.user); } /* Get sam handle */ - result = cm_connect_sam(contact_domain, state->mem_ctx, true, &cli, &dom_pol); + 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)); goto done; @@ -3275,9 +3255,13 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai b = cli->binding_handle; - result = rpccli_samr_chng_pswd_auth_crap( - cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc, - new_lm_password, old_lm_hash_enc); + result = rpccli_samr_chng_pswd_auth_crap(cli, + p->mem_ctx, + user, + r->in.new_nt_pswd, + r->in.old_nt_hash_enc, + r->in.new_lm_pswd, + r->in.old_lm_hash_enc); done: @@ -3286,21 +3270,22 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai 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; } #ifdef HAVE_KRB5 diff --git a/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.c b/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.c index 4c39ce0b5ac..8b69f024af1 100644 --- a/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.c +++ b/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.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_chng_pswd_auth_crap_state { - struct winbindd_request *request; - struct winbindd_response *response; + struct wbint_PamAuthCrapChangePassword r; }; static void winbindd_pam_chng_pswd_auth_crap_done(struct tevent_req *subreq); @@ -44,7 +44,6 @@ struct tevent_req *winbindd_pam_chng_pswd_auth_crap_send( if (req == NULL) { return NULL; } - state->request = request; /* Ensure null termination */ request->data.chng_pswd_auth_crap.user[ @@ -58,8 +57,8 @@ struct tevent_req *winbindd_pam_chng_pswd_auth_crap_send( request->data.chng_pswd_auth_crap.user)); domain_name = NULL; - if (*state->request->data.chng_pswd_auth_crap.domain != '\0') { - domain_name = state->request->data.chng_pswd_auth_crap.domain; + if (*request->data.chng_pswd_auth_crap.domain != '\0') { + domain_name = request->data.chng_pswd_auth_crap.domain; } else if (lp_winbind_use_default_domain()) { domain_name = lp_workgroup(); } @@ -74,8 +73,59 @@ struct tevent_req *winbindd_pam_chng_pswd_auth_crap_send( return tevent_req_post(req, ev); } - subreq = wb_domain_request_send(state, global_event_context(), - domain, request); + state->r.in.client_pid = request->pid; + 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.domain = talloc_strdup(state, domain_name); + if (tevent_req_nomem(state->r.in.domain, req)) { + return tevent_req_post(req, ev); + } + state->r.in.user = talloc_strdup(state, + request->data.chng_pswd_auth_crap.user); + if (tevent_req_nomem(state->r.in.user, req)) { + return tevent_req_post(req, ev); + } + + state->r.in.new_nt_pswd = data_blob_talloc(state, + request->data.chng_pswd_auth_crap.new_nt_pswd, + request->data.chng_pswd_auth_crap.new_nt_pswd_len); + if (tevent_req_nomem(state->r.in.new_nt_pswd.data, req)) { + return tevent_req_post(req, ev); + } + + state->r.in.old_nt_hash_enc = data_blob_talloc(state, + request->data.chng_pswd_auth_crap.old_nt_hash_enc, + request->data.chng_pswd_auth_crap.old_nt_hash_enc_len); + if (tevent_req_nomem(state->r.in.old_nt_hash_enc.data, req)) { + return tevent_req_post(req, ev); + } + + if (request->data.chng_pswd_auth_crap.new_lm_pswd_len > 0) { + state->r.in.new_lm_pswd = data_blob_talloc(state, + request->data.chng_pswd_auth_crap.new_lm_pswd, + request->data.chng_pswd_auth_crap.new_lm_pswd_len); + if (tevent_req_nomem(state->r.in.new_lm_pswd.data, req)) { + return tevent_req_post(req, ev); + } + + state->r.in.old_lm_hash_enc = data_blob_talloc(state, + request->data.chng_pswd_auth_crap.old_lm_hash_enc, + request->data.chng_pswd_auth_crap.old_lm_hash_enc_len); + if (tevent_req_nomem(state->r.in.old_lm_hash_enc.data, req)) { + return tevent_req_post(req, ev); + } + } else { + state->r.in.new_lm_pswd = data_blob_null; + state->r.in.old_lm_hash_enc = data_blob_null; + } + + subreq = dcerpc_wbint_PamAuthCrapChangePassword_r_send(state, + global_event_context(), + dom_child_handle(domain), + &state->r); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -90,14 +140,14 @@ static void winbindd_pam_chng_pswd_auth_crap_done(struct tevent_req *subreq) subreq, struct tevent_req); struct winbindd_pam_chng_pswd_auth_crap_state *state = tevent_req_data( req, struct winbindd_pam_chng_pswd_auth_crap_state); - int res, err; + NTSTATUS status; - res = wb_domain_request_recv(subreq, state, &state->response, &err); + status = dcerpc_wbint_PamAuthCrapChangePassword_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); } @@ -107,15 +157,15 @@ NTSTATUS winbindd_pam_chng_pswd_auth_crap_recv( { struct winbindd_pam_chng_pswd_auth_crap_state *state = tevent_req_data( req, struct winbindd_pam_chng_pswd_auth_crap_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); + set_auth_errors(response, state->r.out.result); return NT_STATUS(response->data.auth.nt_status); } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 6dad82fc0a8..76fd4cb0865 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -447,7 +447,8 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact 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 _wbint_PamAuthCrapChangePassword(struct pipes_struct *p, + struct wbint_PamAuthCrapChangePassword *r); NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state, TALLOC_CTX *mem_ctx, bool *p_is_trusted,