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,