s3:winbind: Convert PAM_AUTH_CRAP from struct based to NDR based
authorSamuel Cabrero <scabrero@samba.org>
Fri, 25 Feb 2022 10:32:14 +0000 (11:32 +0100)
committerJeremy Allison <jra@samba.org>
Sat, 30 Apr 2022 00:10:34 +0000 (00:10 +0000)
Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
librpc/idl/winbind.idl
source3/winbindd/winbindd_domain.c
source3/winbindd/winbindd_pam.c
source3/winbindd/winbindd_pam_auth_crap.c
source3/winbindd/winbindd_proto.h

index 2737c563c693987376e2efb5fe904803729d98af..8a50a53eea1b7cf811d504d2c7d73439b12c4de8 100644 (file)
@@ -196,6 +196,27 @@ interface winbind
         [out,ref] wbint_Validation *validation
         );
 
+    typedef [public] struct {
+        uint16 level;
+        [switch_is(level)] netr_Validation *validation;
+    } wbint_PamAuthCrapValidation;
+
+    NTSTATUS wbint_PamAuthCrap(
+        [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 *domain,
+        [in, string,charset(UTF8)] char *workstation,
+        [in] DATA_BLOB lm_resp,
+        [in] DATA_BLOB nt_resp,
+        [in] DATA_BLOB chal,
+        [in] uint32 logon_parameters,
+        [in] wbint_SidArray *require_membership_of_sid,
+        [out,ref] uint8 *authoritative,
+        [out,ref] wbint_PamAuthCrapValidation *validation
+        );
+
   /* Public methods available via IRPC */
 
     typedef [switch_type(uint16)] union netr_LogonLevel netr_LogonLevel;
index 6f85d0779a0a702253ebf2e480f5a2e2569a8887..80df55a5819783211b5054ee4b61386949b16ab8 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           = "AUTH_CRAP",
-               .struct_cmd     = WINBINDD_PAM_AUTH_CRAP,
-               .struct_fn      = winbindd_dual_pam_auth_crap,
        },{
                .name           = "PAM_LOGOFF",
                .struct_cmd     = WINBINDD_PAM_LOGOFF,
index 878e169b7614821853165c1ae05c74b54306e773..cbcc96595d7ed9400a0b7ae0566fe62033d71cf9 100644 (file)
@@ -2115,7 +2115,7 @@ done:
  * @brief build a tsocket_address for the remote address of the supplied socket
  *
  */
-static struct tsocket_address *get_remote_address(TALLOC_CTX *mem_ctx, int sock)
+_UNUSED_ static struct tsocket_address *get_remote_address(TALLOC_CTX *mem_ctx, int sock)
 {
        struct sockaddr_storage st = {0};
        struct sockaddr *sar = (struct sockaddr *)&st;
@@ -2141,7 +2141,7 @@ static struct tsocket_address *get_remote_address(TALLOC_CTX *mem_ctx, int sock)
  * @brief build a tsocket_address for the local address of the supplied socket
  *
  */
-static struct tsocket_address *get_local_address(TALLOC_CTX *mem_ctx, int sock)
+_UNUSED_ static struct tsocket_address *get_local_address(TALLOC_CTX *mem_ctx, int sock)
 {
        struct sockaddr_storage st = {0};
        struct sockaddr *sar = (struct sockaddr *)&st;
@@ -2836,71 +2836,52 @@ done:
        return NT_STATUS_OK;
 }
 
-enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
-                                                struct winbindd_cli_state *state)
+NTSTATUS _wbint_PamAuthCrap(struct pipes_struct *p, struct wbint_PamAuthCrap *r)
 {
+       struct winbindd_domain *domain = wb_child_domain();
        NTSTATUS result;
-       const char *name_user = NULL;
-       const char *name_domain = NULL;
-       const char *workstation;
        uint64_t logon_id = 0;
        uint8_t authoritative = 1;
        uint32_t flags = 0;
        uint16_t validation_level = UINT16_MAX;
        union netr_Validation *validation = NULL;
-       DATA_BLOB lm_resp = { 0 }, nt_resp = { 0 };
-       DATA_BLOB chal = data_blob_null;
        const struct timeval start_time = timeval_current();
        const struct tsocket_address *remote = NULL;
        const struct tsocket_address *local = NULL;
        struct netr_SamInfo3 *info3 = NULL;
-       struct wbint_SidArray *sid_array = NULL;
+       pid_t client_pid;
 
-       /* This is child-only, so no check for privileged access is needed
-          anymore */
+       if (domain == NULL) {
+               return NT_STATUS_REQUEST_NOT_ACCEPTED;
+       }
 
-       /* Ensure null termination */
-       state->request->data.auth_crap.user[sizeof(state->request->data.auth_crap.user)-1]=0;
-       state->request->data.auth_crap.domain[sizeof(state->request->data.auth_crap.domain)-1]=0;
+       /* 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;
+       }
 
-       name_user = state->request->data.auth_crap.user;
-       name_domain = state->request->data.auth_crap.domain;
-       workstation = state->request->data.auth_crap.workstation;
        logon_id = generate_random_u64();
-       remote = get_remote_address(state->mem_ctx, state->sock);
-       local = get_local_address(state->mem_ctx, state->sock);
-
-       DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid,
-                 name_domain, name_user));
+       remote = dcesrv_connection_get_remote_address(p->dce_call->conn);
+       local = dcesrv_connection_get_local_address(p->dce_call->conn);
 
-       lm_resp = data_blob_talloc(state->mem_ctx, state->request->data.auth_crap.lm_resp,
-                                       state->request->data.auth_crap.lm_resp_len);
-
-       if (state->request->flags & WBFLAG_BIG_NTLMV2_BLOB) {
-               nt_resp = data_blob_talloc(state->mem_ctx,
-                                          state->request->extra_data.data,
-                                          state->request->data.auth_crap.nt_resp_len);
-       } else {
-               nt_resp = data_blob_talloc(state->mem_ctx,
-                                          state->request->data.auth_crap.nt_resp,
-                                          state->request->data.auth_crap.nt_resp_len);
-       }
-       chal = data_blob_const(state->request->data.auth_crap.chal, 8);
+       DBG_NOTICE("[%"PRIu32"]: pam auth crap domain: %s user: %s\n",
+                  client_pid, r->in.domain, r->in.user);
 
        result = winbind_dual_SamLogon(domain,
-                                      state->mem_ctx,
+                                      p->mem_ctx,
                                       false, /* interactive */
-                                      state->request->data.auth_crap.logon_parameters,
-                                      name_user,
-                                      name_domain,
-                                      /* Bug #3248 - found by Stefan Burkei. */
-                                      workstation, /* We carefully set this above so use it... */
+                                      r->in.logon_parameters,
+                                      r->in.user,
+                                      r->in.domain,
+                                      r->in.workstation,
                                       logon_id,
-                                      state->request->client_name,
-                                      state->request->pid,
-                                      chal,
-                                      lm_resp,
-                                      nt_resp,
+                                      r->in.client_name,
+                                      client_pid,
+                                      r->in.chal,
+                                      r->in.lm_resp,
+                                      r->in.nt_resp,
                                       remote,
                                       local,
                                       &authoritative,
@@ -2912,7 +2893,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                goto done;
        }
 
-       result = map_validation_to_info3(state->mem_ctx,
+       result = map_validation_to_info3(p->mem_ctx,
                                         validation_level,
                                         validation,
                                         &info3);
@@ -2920,32 +2901,19 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                goto done;
        }
 
-       result = extra_data_to_sid_array(
-               state->request->data.auth_crap.require_membership_of_sid,
-               state->mem_ctx,
-               &sid_array);
-       if (!NT_STATUS_IS_OK(result)) {
-               DBG_ERR("Failed to parse '%s' into a sid array: %s\n",
-                       state->request->data.auth_crap.require_membership_of_sid,
-                       nt_errstr(result));
-               goto done;
-       }
-
        /* Check if the user is in the right group */
-       result = check_info3_in_group(info3, sid_array);
+       result = check_info3_in_group(info3, r->in.require_membership_of_sid);
        if (!NT_STATUS_IS_OK(result)) {
-               char *s = NDR_PRINT_STRUCT_STRING(state->mem_ctx,
+               char *s = NDR_PRINT_STRUCT_STRING(p->mem_ctx,
                                                  wbint_SidArray,
-                                                 sid_array);
+                                                 r->in.require_membership_of_sid);
                DBG_NOTICE("User %s is not in the required groups:\n",
-                          state->request->data.auth_crap.user);
+                          r->in.user);
                DEBUGADD(DBGLVL_NOTICE, ("%s", s));
                DEBUGADD(DBGLVL_NOTICE,
                         ("CRAP authentication is rejected\n"));
-               TALLOC_FREE(sid_array);
                goto done;
        }
-       TALLOC_FREE(sid_array);
 
        if (!is_allowed_domain(info3->base.logon_domain.string)) {
                DBG_NOTICE("Authentication failed for user [%s] "
@@ -2956,45 +2924,48 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                goto done;
        }
 
-       result = append_auth_data(state->mem_ctx, state->response,
-                                 state->request->flags,
-                                 validation_level,
-                                 validation,
-                                 name_domain, name_user);
+       r->out.validation = talloc_zero(p->mem_ctx,
+                                       struct wbint_PamAuthCrapValidation);
+       if (r->out.validation == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
+       r->out.validation->level = validation_level;
+       r->out.validation->validation = talloc_move(r->out.validation,
+                                                   &validation);
 done:
 
-       if (state->request->flags & WBFLAG_PAM_NT_STATUS_SQUASH) {
+       if (r->in.flags & WBFLAG_PAM_NT_STATUS_SQUASH) {
                result = nt_status_squash(result);
        }
 
-       set_auth_errors(state->response, result);
-       state->response->data.auth.authoritative = authoritative;
+       *r->out.authoritative = authoritative;
 
        /*
         * Log the winbind pam authentication, the logon_id will tie this to
         * any of the logons invoked from this request.
         */
        log_authentication(
-           state->mem_ctx,
+           p->mem_ctx,
            domain,
-           state->request->client_name,
-           state->pid,
-           validation_level,
-           validation,
+           r->in.client_name,
+           client_pid,
+           r->out.validation->level,
+           r->out.validation->validation,
            start_time,
            logon_id,
            "NTLM_AUTH",
-           name_user,
-           name_domain,
-           workstation,
-           lm_resp,
-            nt_resp,
+           r->in.user,
+           r->in.domain,
+           r->in.workstation,
+           r->in.lm_resp,
+           r->in.nt_resp,
            remote,
            local,
            result);
 
-       return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
+       return result;
 }
 
 enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain,
index 1a945c55ee36926a3396c45fa8eaf8c09810fb3b..6120522ce3cff9754cf25711425ba5a067087d36 100644 (file)
 #include "libcli/security/dom_sid.h"
 #include "lib/util/string_wrappers.h"
 #include "lib/global_contexts.h"
+#include "librpc/gen_ndr/ndr_winbind_c.h"
 
 struct winbindd_pam_auth_crap_state {
-       struct winbindd_response *response;
        uint8_t authoritative;
        uint32_t flags;
        bool pac_is_trusted;
-       uint16_t validation_level;
-       union netr_Validation *validation;
+       char *domain;
+       char *user;
+       struct wbint_PamAuthCrapValidation validation;
+       NTSTATUS result;
 };
 
 static void winbindd_pam_auth_crap_done(struct tevent_req *subreq);
@@ -45,6 +47,11 @@ struct tevent_req *winbindd_pam_auth_crap_send(
        struct winbindd_pam_auth_crap_state *state;
        struct winbindd_domain *domain;
        const char *auth_domain = NULL;
+       DATA_BLOB lm_resp = data_blob_null;
+       DATA_BLOB nt_resp = data_blob_null;
+       DATA_BLOB chal = data_blob_null;
+       struct wbint_SidArray *require_membership_of_sid = NULL;
+       NTSTATUS status;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct winbindd_pam_auth_crap_state);
@@ -55,14 +62,12 @@ struct tevent_req *winbindd_pam_auth_crap_send(
        state->flags = request->flags;
 
        if (state->flags & WBFLAG_PAM_AUTH_PAC) {
-               NTSTATUS status;
-
-               status = winbindd_pam_auth_pac_verify(cli,
-                                                     state,
-                                                     &state->pac_is_trusted,
-                                                     &state->validation_level,
-                                                     &state->validation);
-               if (tevent_req_nterror(req, status)) {
+               state->result = winbindd_pam_auth_pac_verify(cli,
+                               state,
+                               &state->pac_is_trusted,
+                               &state->validation.level,
+                               &state->validation.validation);
+               if (tevent_req_nterror(req, state->result)) {
                        return tevent_req_post(req, ev);
                }
 
@@ -78,10 +83,12 @@ struct tevent_req *winbindd_pam_auth_crap_send(
        request->data.auth_crap.workstation[
                sizeof(request->data.auth_crap.workstation)-1] = '\0';
 
-       DEBUG(3, ("[%5lu]: pam auth crap domain: [%s] user: %s\n",
-                 (unsigned long)cli->pid,
-                 request->data.auth_crap.domain,
-                 request->data.auth_crap.user));
+       DBG_NOTICE("[%5lu]: pam auth crap domain: [%s] user: [%s] "
+                  "workstation: [%s]\n",
+                  (unsigned long)cli->pid,
+                  request->data.auth_crap.domain,
+                  request->data.auth_crap.user,
+                  request->data.auth_crap.workstation);
 
        if (!check_request_flags(request->flags)) {
                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
@@ -120,8 +127,67 @@ struct tevent_req *winbindd_pam_auth_crap_send(
                }
        }
 
-       subreq = wb_domain_request_send(state, global_event_context(), domain,
-                                       request);
+       state->domain = talloc_strdup(state, request->data.auth_crap.domain);
+       if (tevent_req_nomem(state->domain, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       state->user = talloc_strdup(state, request->data.auth_crap.user);
+       if (tevent_req_nomem(state->user, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       status = extra_data_to_sid_array(
+                       request->data.auth_crap.require_membership_of_sid,
+                       state,
+                       &require_membership_of_sid);
+       if (tevent_req_nterror(req, status)) {
+               return tevent_req_post(req, ev);
+       }
+
+       lm_resp = data_blob_talloc(state,
+                                  request->data.auth_crap.lm_resp,
+                                  request->data.auth_crap.lm_resp_len);
+       if (tevent_req_nomem(lm_resp.data, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       if (request->flags & WBFLAG_BIG_NTLMV2_BLOB) {
+               nt_resp = data_blob_talloc(state,
+                               request->extra_data.data,
+                               request->data.auth_crap.nt_resp_len);
+       } else {
+               nt_resp = data_blob_talloc(state,
+                               request->data.auth_crap.nt_resp,
+                               request->data.auth_crap.nt_resp_len);
+       }
+       if (tevent_req_nomem(nt_resp.data, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       chal = data_blob_talloc(state,
+                               request->data.auth_crap.chal,
+                               8);
+       if (tevent_req_nomem(chal.data, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       subreq = dcerpc_wbint_PamAuthCrap_send(state,
+                               global_event_context(),
+                               dom_child_handle(domain),
+                               request->client_name,
+                               request->pid,
+                               request->flags,
+                               request->data.auth_crap.user,
+                               request->data.auth_crap.domain,
+                               request->data.auth_crap.workstation,
+                               lm_resp,
+                               nt_resp,
+                               chal,
+                               request->data.auth_crap.logon_parameters,
+                               require_membership_of_sid,
+                               &state->authoritative,
+                               &state->validation);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -135,12 +201,11 @@ static void winbindd_pam_auth_crap_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct winbindd_pam_auth_crap_state *state = tevent_req_data(
                req, struct winbindd_pam_auth_crap_state);
-       int res, err;
+       NTSTATUS status;
 
-       res = wb_domain_request_recv(subreq, state, &state->response, &err);
+       status = dcerpc_wbint_PamAuthCrap_recv(subreq, state, &state->result);
        TALLOC_FREE(subreq);
-       if (res == -1) {
-               tevent_req_nterror(req, map_nt_error_from_unix(err));
+       if (tevent_req_nterror(req, status)) {
                return;
        }
 
@@ -155,52 +220,40 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req,
        NTSTATUS status;
 
        if (tevent_req_is_nterror(req, &status)) {
-               set_auth_errors(response, status);
-               response->data.auth.authoritative = state->authoritative;
-               return status;
+               goto out;
        }
 
-       if (state->flags & WBFLAG_PAM_AUTH_PAC) {
-               state->response = talloc_zero(state,
-                                             struct winbindd_response);
-               if (state->response == NULL) {
-                       status = NT_STATUS_NO_MEMORY;
-                       set_auth_errors(response, status);
-                       response->data.auth.authoritative = state->authoritative;
-                       return status;
-               }
-               state->response->result = WINBINDD_PENDING;
-               state->response->length = sizeof(struct winbindd_response);
-
-               status = append_auth_data(state->response,
-                                         state->response,
-                                         state->flags,
-                                         state->validation_level,
-                                         state->validation,
-                                         NULL, NULL);
-               if (NT_STATUS_IS_ERR(status)) {
-                       set_auth_errors(response, status);
-                       response->data.auth.authoritative = state->authoritative;
-                       return status;
-               }
+       if (NT_STATUS_IS_ERR(state->result)) {
+               status = state->result;
+               goto out;
+       }
 
-               if (!state->pac_is_trusted) {
-                       /*
-                        * Clear the flag in state to do no add the domain
-                        * from auth below.
-                        */
-                       state->flags &= ~WBFLAG_PAM_INFO3_TEXT;
-               }
+       status = append_auth_data(response,
+                                 response,
+                                 state->flags,
+                                 state->validation.level,
+                                 state->validation.validation,
+                                 state->domain,
+                                 state->user);
+       if (NT_STATUS_IS_ERR(status)) {
+               goto out;
        }
 
-       if (NT_STATUS_IS_OK(NT_STATUS(state->response->data.auth.nt_status)) &&
-           (state->flags & WBFLAG_PAM_INFO3_TEXT)) {
+       if (state->flags & WBFLAG_PAM_AUTH_PAC && !state->pac_is_trusted) {
+               /*
+                * Clear the flag just in state to do no add the domain
+                * from auth below.
+                */
+               state->flags &= ~WBFLAG_PAM_INFO3_TEXT;
+       }
+
+       if (state->flags & WBFLAG_PAM_INFO3_TEXT) {
                bool ok;
 
                ok = add_trusted_domain_from_auth(
-                       state->response->data.auth.validation_level,
-                       &state->response->data.auth.info3,
-                       &state->response->data.auth.info6);
+                       response->data.auth.validation_level,
+                       &response->data.auth.info3,
+                       &response->data.auth.info6);
                if (!ok) {
                        status = NT_STATUS_LOGON_FAILURE;
                        DBG_ERR("add_trusted_domain_from_auth failed\n");
@@ -211,8 +264,11 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req,
                }
        }
 
-       *response = *state->response;
+       status = NT_STATUS_OK;
+
+out:
+       set_auth_errors(response, status);
+       response->data.auth.authoritative = state->authoritative;
        response->result = WINBINDD_PENDING;
-       state->response = talloc_move(response, &state->response);
        return NT_STATUS(response->data.auth.nt_status);
 }
index b80ba72d5e279521fa282fec7d0230d12311a5ad..2641101ee0ceae18dd3792303cf75cafabb4f833 100644 (file)
@@ -441,8 +441,8 @@ struct pipes_struct;
 struct wbint_PamAuth;
 NTSTATUS _wbint_PamAuth(struct pipes_struct *p,
                        struct wbint_PamAuth *r);
-enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
-                                                struct winbindd_cli_state *state) ;
+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,