LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_pam_auth_crap.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 100 132 75.8 %
Date: 2023-11-21 12:31:41 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    async implementation of WINBINDD_PAM_AUTH_CRAP
       4             :    Copyright (C) Volker Lendecke 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "winbindd.h"
      22             : #include "rpc_client/util_netlogon.h"
      23             : #include "libcli/security/dom_sid.h"
      24             : #include "lib/util/string_wrappers.h"
      25             : #include "lib/global_contexts.h"
      26             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      27             : 
      28             : struct winbindd_pam_auth_crap_state {
      29             :         uint8_t authoritative;
      30             :         uint32_t flags;
      31             :         bool pac_is_trusted;
      32             :         char *domain;
      33             :         char *user;
      34             :         struct wbint_PamAuthCrapValidation validation;
      35             :         NTSTATUS result;
      36             : };
      37             : 
      38             : static void winbindd_pam_auth_crap_done(struct tevent_req *subreq);
      39             : 
      40        4379 : struct tevent_req *winbindd_pam_auth_crap_send(
      41             :         TALLOC_CTX *mem_ctx,
      42             :         struct tevent_context *ev,
      43             :         struct winbindd_cli_state *cli,
      44             :         struct winbindd_request *request)
      45             : {
      46           0 :         struct tevent_req *req, *subreq;
      47           0 :         struct winbindd_pam_auth_crap_state *state;
      48           0 :         struct winbindd_domain *domain;
      49        4379 :         const char *auth_domain = NULL;
      50        4379 :         DATA_BLOB lm_resp = data_blob_null;
      51        4379 :         DATA_BLOB nt_resp = data_blob_null;
      52        4379 :         DATA_BLOB chal = data_blob_null;
      53        4379 :         struct wbint_SidArray *require_membership_of_sid = NULL;
      54           0 :         NTSTATUS status;
      55        4379 :         bool lmlength_ok = false;
      56        4379 :         bool ntlength_ok = false;
      57        4379 :         bool pwlength_ok = false;
      58             : 
      59        4379 :         req = tevent_req_create(mem_ctx, &state,
      60             :                                 struct winbindd_pam_auth_crap_state);
      61        4379 :         if (req == NULL) {
      62           0 :                 return NULL;
      63             :         }
      64        4379 :         state->authoritative = 1;
      65        4379 :         state->flags = request->flags;
      66             : 
      67        4379 :         if (state->flags & WBFLAG_PAM_AUTH_PAC) {
      68         869 :                 state->result = winbindd_pam_auth_pac_verify(cli,
      69             :                                 state,
      70         869 :                                 &state->pac_is_trusted,
      71         869 :                                 &state->validation.level,
      72         869 :                                 &state->validation.validation);
      73         869 :                 if (tevent_req_nterror(req, state->result)) {
      74           2 :                         return tevent_req_post(req, ev);
      75             :                 }
      76             : 
      77         867 :                 tevent_req_done(req);
      78         867 :                 return tevent_req_post(req, ev);
      79             :         }
      80             : 
      81             :         /* Ensure null termination */
      82           0 :         request->data.auth_crap.user[
      83        3510 :                 sizeof(request->data.auth_crap.user)-1] = '\0';
      84           0 :         request->data.auth_crap.domain[
      85        3510 :                 sizeof(request->data.auth_crap.domain)-1] = '\0';
      86           0 :         request->data.auth_crap.workstation[
      87        3510 :                 sizeof(request->data.auth_crap.workstation)-1] = '\0';
      88             : 
      89        3510 :         DBG_NOTICE("[%5lu]: pam auth crap domain: [%s] user: [%s] "
      90             :                    "workstation: [%s]\n",
      91             :                    (unsigned long)cli->pid,
      92             :                    request->data.auth_crap.domain,
      93             :                    request->data.auth_crap.user,
      94             :                    request->data.auth_crap.workstation);
      95             : 
      96        3510 :         if (!check_request_flags(request->flags)) {
      97           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
      98           0 :                 return tevent_req_post(req, ev);
      99             :         }
     100             : 
     101        3510 :         auth_domain = request->data.auth_crap.domain;
     102        3510 :         if (auth_domain[0] == '\0') {
     103         108 :                 auth_domain = lp_workgroup();
     104             :         }
     105             : 
     106        3510 :         domain = find_auth_domain(request->flags, auth_domain);
     107        3510 :         if (domain == NULL) {
     108             :                 /*
     109             :                  * We don't know the domain so
     110             :                  * we're not authoritative
     111             :                  */
     112        2782 :                 state->authoritative = 0;
     113        2782 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
     114        2782 :                 return tevent_req_post(req, ev);
     115             :         }
     116             : 
     117         728 :         if (request->data.auth_crap.workstation[0] == '\0') {
     118         300 :                 fstrcpy(request->data.auth_crap.workstation, lp_netbios_name());
     119             :         }
     120             : 
     121         728 :         lmlength_ok = (request->data.auth_crap.lm_resp_len <=
     122             :                        sizeof(request->data.auth_crap.lm_resp));
     123             : 
     124         728 :         ntlength_ok = (request->data.auth_crap.nt_resp_len <=
     125             :                        sizeof(request->data.auth_crap.nt_resp));
     126             : 
     127        1456 :         ntlength_ok |=
     128        1148 :                 ((request->flags & WBFLAG_BIG_NTLMV2_BLOB) &&
     129         420 :                  (request->extra_len == request->data.auth_crap.nt_resp_len));
     130             : 
     131         728 :         pwlength_ok = lmlength_ok && ntlength_ok;
     132             : 
     133         728 :         if (!pwlength_ok) {
     134           0 :                 DBG_ERR("Invalid password length %u/%u\n",
     135             :                         request->data.auth_crap.lm_resp_len,
     136             :                         request->data.auth_crap.nt_resp_len);
     137           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     138           0 :                 return tevent_req_post(req, ev);
     139             :         }
     140             : 
     141         728 :         state->domain = talloc_strdup(state, request->data.auth_crap.domain);
     142         728 :         if (tevent_req_nomem(state->domain, req)) {
     143           0 :                 return tevent_req_post(req, ev);
     144             :         }
     145             : 
     146         728 :         state->user = talloc_strdup(state, request->data.auth_crap.user);
     147         728 :         if (tevent_req_nomem(state->user, req)) {
     148           0 :                 return tevent_req_post(req, ev);
     149             :         }
     150             : 
     151         728 :         status = extra_data_to_sid_array(
     152         728 :                         request->data.auth_crap.require_membership_of_sid,
     153             :                         state,
     154             :                         &require_membership_of_sid);
     155         728 :         if (tevent_req_nterror(req, status)) {
     156           0 :                 return tevent_req_post(req, ev);
     157             :         }
     158             : 
     159         728 :         lm_resp = data_blob_talloc(state,
     160             :                                    request->data.auth_crap.lm_resp,
     161             :                                    request->data.auth_crap.lm_resp_len);
     162         728 :         if (tevent_req_nomem(lm_resp.data, req)) {
     163           0 :                 return tevent_req_post(req, ev);
     164             :         }
     165             : 
     166         728 :         if (request->flags & WBFLAG_BIG_NTLMV2_BLOB) {
     167         420 :                 nt_resp = data_blob_talloc(state,
     168             :                                 request->extra_data.data,
     169             :                                 request->data.auth_crap.nt_resp_len);
     170             :         } else {
     171         308 :                 nt_resp = data_blob_talloc(state,
     172             :                                 request->data.auth_crap.nt_resp,
     173             :                                 request->data.auth_crap.nt_resp_len);
     174             :         }
     175         728 :         if (tevent_req_nomem(nt_resp.data, req)) {
     176           0 :                 return tevent_req_post(req, ev);
     177             :         }
     178             : 
     179         728 :         chal = data_blob_talloc(state,
     180             :                                 request->data.auth_crap.chal,
     181             :                                 8);
     182         728 :         if (tevent_req_nomem(chal.data, req)) {
     183           0 :                 return tevent_req_post(req, ev);
     184             :         }
     185             : 
     186         728 :         subreq = dcerpc_wbint_PamAuthCrap_send(state,
     187             :                                 global_event_context(),
     188             :                                 dom_child_handle(domain),
     189         728 :                                 request->client_name,
     190         728 :                                 request->pid,
     191             :                                 request->flags,
     192         728 :                                 request->data.auth_crap.user,
     193         728 :                                 request->data.auth_crap.domain,
     194         728 :                                 request->data.auth_crap.workstation,
     195             :                                 lm_resp,
     196             :                                 nt_resp,
     197             :                                 chal,
     198             :                                 request->data.auth_crap.logon_parameters,
     199             :                                 require_membership_of_sid,
     200         728 :                                 &state->authoritative,
     201         728 :                                 &state->validation);
     202         728 :         if (tevent_req_nomem(subreq, req)) {
     203           0 :                 return tevent_req_post(req, ev);
     204             :         }
     205         728 :         tevent_req_set_callback(subreq, winbindd_pam_auth_crap_done, req);
     206         728 :         return req;
     207             : }
     208             : 
     209         728 : static void winbindd_pam_auth_crap_done(struct tevent_req *subreq)
     210             : {
     211         728 :         struct tevent_req *req = tevent_req_callback_data(
     212             :                 subreq, struct tevent_req);
     213         728 :         struct winbindd_pam_auth_crap_state *state = tevent_req_data(
     214             :                 req, struct winbindd_pam_auth_crap_state);
     215           0 :         NTSTATUS status;
     216             : 
     217         728 :         status = dcerpc_wbint_PamAuthCrap_recv(subreq, state, &state->result);
     218         728 :         TALLOC_FREE(subreq);
     219         728 :         if (tevent_req_nterror(req, status)) {
     220           0 :                 return;
     221             :         }
     222             : 
     223         728 :         tevent_req_done(req);
     224             : }
     225             : 
     226        4379 : NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req,
     227             :                                      struct winbindd_response *response)
     228             : {
     229        4379 :         struct winbindd_pam_auth_crap_state *state = tevent_req_data(
     230             :                 req, struct winbindd_pam_auth_crap_state);
     231           0 :         NTSTATUS status;
     232             : 
     233        4379 :         if (tevent_req_is_nterror(req, &status)) {
     234        2784 :                 goto out;
     235             :         }
     236             : 
     237        1595 :         if (NT_STATUS_IS_ERR(state->result)) {
     238         238 :                 status = state->result;
     239         238 :                 goto out;
     240             :         }
     241             : 
     242        1357 :         status = append_auth_data(response,
     243             :                                   response,
     244             :                                   state->flags,
     245        1357 :                                   state->validation.level,
     246             :                                   state->validation.validation,
     247        1357 :                                   state->domain,
     248        1357 :                                   state->user);
     249        1357 :         if (NT_STATUS_IS_ERR(status)) {
     250           0 :                 goto out;
     251             :         }
     252             : 
     253        1357 :         if (state->flags & WBFLAG_PAM_AUTH_PAC && !state->pac_is_trusted) {
     254             :                 /*
     255             :                  * Clear the flag just in state to do no add the domain
     256             :                  * from auth below.
     257             :                  */
     258           0 :                 state->flags &= ~WBFLAG_PAM_INFO3_TEXT;
     259             :         }
     260             : 
     261        1357 :         if (state->flags & WBFLAG_PAM_INFO3_TEXT) {
     262           0 :                 bool ok;
     263             : 
     264        1155 :                 ok = add_trusted_domain_from_auth(
     265        1155 :                         response->data.auth.validation_level,
     266             :                         &response->data.auth.info3,
     267             :                         &response->data.auth.info6);
     268        1155 :                 if (!ok) {
     269           0 :                         status = NT_STATUS_LOGON_FAILURE;
     270           0 :                         DBG_ERR("add_trusted_domain_from_auth failed\n");
     271           0 :                         set_auth_errors(response, status);
     272           0 :                         response->data.auth.authoritative =
     273           0 :                                 state->authoritative;
     274           0 :                         return status;
     275             :                 }
     276             :         }
     277             : 
     278        1357 :         status = NT_STATUS_OK;
     279             : 
     280        4379 : out:
     281        4379 :         set_auth_errors(response, status);
     282        4379 :         response->data.auth.authoritative = state->authoritative;
     283        4379 :         response->result = WINBINDD_PENDING;
     284        4379 :         return NT_STATUS(response->data.auth.nt_status);
     285             : }

Generated by: LCOV version 1.14