s3:winbind: Convert winbindd_dual_pam_chauthtok() from struct based to NDR based
authorSamuel Cabrero <scabrero@samba.org>
Tue, 22 Jun 2021 08:23:04 +0000 (10:23 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 19 May 2022 17:51:33 +0000 (17:51 +0000)
Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
librpc/idl/samr.idl
librpc/idl/winbind.idl
source3/winbindd/winbindd_domain.c
source3/winbindd/winbindd_pam.c
source3/winbindd/winbindd_pam_chauthtok.c
source3/winbindd/winbindd_proto.h

index 867862dcd5cd8607bf386c38caf4f53fc4260a4f..fffa853ce3ffd10e069b0764daa0bc2c24d2e87d 100644 (file)
@@ -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;
index 9ec98bd0878407d1bfd9c6e41e2b6eaae9d103a7..2d209448841db19a6b6f25cd347d866e48c1f938 100644 (file)
@@ -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;
index 6ea837065242ee9d9e2b84718abb0611b2e1579f..c206b9589c988dc952d8cd4fad62bbdb96922285 100644 (file)
@@ -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,
index f4d8ab39c413fb9591eeede64b13900c52604b64..21649c69b1046ce4cd9dc697858eb98c9e35c534 100644 (file)
@@ -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)
index e476d53f0306f4b47e4ff30e26d43b7133f9e15e..336654e91939506e4d89fe6a5a46e3818c77971e 100644 (file)
 #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);
 }
index 76fd4cb0865839ea558083e1879e31150de68276..57f7cebd2cf30a76d1fb4af1756f34342d27e245 100644 (file)
@@ -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,