LCOV - code coverage report
Current view: top level - source3/libsmb - async_smb.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 97 114 85.1 %
Date: 2024-06-13 04:01:37 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Infrastructure for async SMB client requests
       4             :    Copyright (C) Volker Lendecke 2008
       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 "libsmb/libsmb.h"
      22             : #include "../lib/util/tevent_ntstatus.h"
      23             : #include "async_smb.h"
      24             : #include "../libcli/smb/smbXcli_base.h"
      25             : 
      26             : struct cli_smb_req_state {
      27             :         struct cli_state *cli;
      28             :         uint8_t smb_command;
      29             :         struct tevent_req *req;
      30             :         struct cli_smb_req_state **ptr;
      31             : };
      32             : 
      33           0 : static int cli_smb_req_state_destructor(struct cli_smb_req_state *state)
      34             : {
      35           0 :         talloc_set_destructor(state->ptr, NULL);
      36           0 :         talloc_free(state->ptr);
      37           0 :         return 0;
      38             : }
      39             : 
      40       68936 : static int cli_smb_req_state_ptr_destructor(struct cli_smb_req_state **ptr)
      41             : {
      42       68936 :         struct cli_smb_req_state *state = *ptr;
      43       68936 :         void *parent = talloc_parent(state);
      44             : 
      45       68936 :         talloc_set_destructor(state, NULL);
      46             : 
      47       68936 :         talloc_reparent(state, parent, state->req);
      48       68936 :         talloc_free(state);
      49       68936 :         return 0;
      50             : }
      51             : 
      52        2997 : struct tevent_req *cli_smb_req_create(TALLOC_CTX *mem_ctx,
      53             :                                       struct tevent_context *ev,
      54             :                                       struct cli_state *cli,
      55             :                                       uint8_t smb_command,
      56             :                                       uint8_t additional_flags,
      57             :                                       uint16_t additional_flags2,
      58             :                                       uint8_t wct, uint16_t *vwv,
      59             :                                       int iov_count,
      60             :                                       struct iovec *bytes_iov)
      61             : {
      62             :         struct cli_smb_req_state *state;
      63        2997 :         uint8_t clear_flags = 0;
      64        2997 :         uint16_t clear_flags2 = 0;
      65             : 
      66        2997 :         state = talloc_zero(mem_ctx, struct cli_smb_req_state);
      67        2997 :         if (state == NULL) {
      68           0 :                 return NULL;
      69             :         }
      70        2997 :         state->cli = cli;
      71        2997 :         state->smb_command = smb_command;
      72        2997 :         state->ptr = talloc(state, struct cli_smb_req_state *);
      73        2997 :         if (state->ptr == NULL) {
      74           0 :                 talloc_free(state);
      75           0 :                 return NULL;
      76             :         }
      77        2997 :         *state->ptr = state;
      78             : 
      79        5994 :         state->req = smb1cli_req_create(state, ev, cli->conn, smb_command,
      80             :                                         additional_flags, clear_flags,
      81             :                                         additional_flags2, clear_flags2,
      82        2997 :                                         cli->timeout,
      83             :                                         cli->smb1.pid,
      84             :                                         cli->smb1.tcon,
      85             :                                         cli->smb1.session,
      86             :                                         wct, vwv, iov_count, bytes_iov);
      87        2997 :         if (state->req == NULL) {
      88           0 :                 talloc_free(state);
      89           0 :                 return NULL;
      90             :         }
      91             : 
      92        2997 :         talloc_reparent(state, state->req, state->ptr);
      93        2997 :         talloc_set_destructor(state, cli_smb_req_state_destructor);
      94        2997 :         talloc_set_destructor(state->ptr, cli_smb_req_state_ptr_destructor);
      95             : 
      96        2997 :         return state->req;
      97             : }
      98             : 
      99       65939 : struct tevent_req *cli_smb_send(TALLOC_CTX *mem_ctx,
     100             :                                 struct tevent_context *ev,
     101             :                                 struct cli_state *cli,
     102             :                                 uint8_t smb_command,
     103             :                                 uint8_t additional_flags,
     104             :                                 uint16_t additional_flags2,
     105             :                                 uint8_t wct, uint16_t *vwv,
     106             :                                 uint32_t num_bytes,
     107             :                                 const uint8_t *bytes)
     108             : {
     109             :         struct cli_smb_req_state *state;
     110       65939 :         uint8_t clear_flags = 0;
     111       65939 :         uint16_t clear_flags2 = 0;
     112             : 
     113       65939 :         state = talloc_zero(mem_ctx, struct cli_smb_req_state);
     114       65939 :         if (state == NULL) {
     115           0 :                 return NULL;
     116             :         }
     117       65939 :         state->cli = cli;
     118       65939 :         state->smb_command = smb_command;
     119       65939 :         state->ptr = talloc(state, struct cli_smb_req_state *);
     120       65939 :         if (state->ptr == NULL) {
     121           0 :                 talloc_free(state);
     122           0 :                 return NULL;
     123             :         }
     124       65939 :         *state->ptr = state;
     125             : 
     126      131878 :         state->req = smb1cli_req_send(state, ev, cli->conn, smb_command,
     127             :                                 additional_flags, clear_flags,
     128             :                                 additional_flags2, clear_flags2,
     129       65939 :                                 cli->timeout,
     130             :                                 cli->smb1.pid,
     131             :                                 cli->smb1.tcon,
     132             :                                 cli->smb1.session,
     133             :                                 wct, vwv, num_bytes, bytes);
     134       65939 :         if (state->req == NULL) {
     135           0 :                 talloc_free(state);
     136           0 :                 return NULL;
     137             :         }
     138             : 
     139       65939 :         talloc_reparent(state, state->req, state->ptr);
     140       65939 :         talloc_set_destructor(state, cli_smb_req_state_destructor);
     141       65939 :         talloc_set_destructor(state->ptr, cli_smb_req_state_ptr_destructor);
     142             : 
     143       65939 :         return state->req;
     144             : }
     145             : 
     146       68936 : NTSTATUS cli_smb_recv(struct tevent_req *req,
     147             :                       TALLOC_CTX *mem_ctx, uint8_t **pinbuf,
     148             :                       uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv,
     149             :                       uint32_t *pnum_bytes, uint8_t **pbytes)
     150             : {
     151             :         NTSTATUS status;
     152       68936 :         void *parent = talloc_parent(req);
     153       68914 :         struct cli_smb_req_state *state =
     154          22 :                 talloc_get_type(parent,
     155             :                 struct cli_smb_req_state);
     156       68936 :         struct iovec *recv_iov = NULL;
     157       68936 :         uint8_t wct = 0;
     158       68936 :         uint16_t *vwv = NULL;
     159             :         uint32_t num_bytes;
     160       68936 :         uint8_t *bytes = NULL;
     161             :         uint8_t *inbuf;
     162       68936 :         bool is_expected = false;
     163       68936 :         bool map_dos_errors = true;
     164             : 
     165       68936 :         if (pinbuf != NULL) {
     166         460 :                 *pinbuf = NULL;
     167             :         }
     168       68936 :         if (pwct != NULL) {
     169        1975 :                 *pwct = 0;
     170             :         }
     171       68936 :         if (pvwv != NULL) {
     172        1985 :                 *pvwv = NULL;
     173             :         }
     174       68936 :         if (pnum_bytes != NULL) {
     175         526 :                 *pnum_bytes = 0;
     176             :         }
     177       68936 :         if (pbytes != NULL) {
     178         526 :                 *pbytes = NULL;
     179             :         }
     180             : 
     181       68936 :         status = smb1cli_req_recv(req, req,
     182             :                                   &recv_iov,
     183             :                                   NULL, /* phdr */
     184             :                                   &wct,
     185             :                                   &vwv,
     186             :                                   NULL, /* pvwv_offset */
     187             :                                   &num_bytes,
     188             :                                   &bytes,
     189             :                                   NULL, /* pbytes_offset */
     190             :                                   &inbuf,
     191             :                                   NULL, 0); /* expected */
     192             : 
     193       68936 :         if (state) {
     194       68937 :                 if ((state->smb_command == SMBsesssetupX) &&
     195           1 :                      NT_STATUS_EQUAL(status,
     196             :                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     197             :                         /*
     198             :                          * NT_STATUS_MORE_PROCESSING_REQUIRED is a
     199             :                          * valid return code for session setup
     200             :                          */
     201           0 :                         is_expected = true;
     202             :                 }
     203             : 
     204       68936 :                 map_dos_errors = state->cli->map_dos_errors;
     205       68936 :                 state->cli->raw_status = status;
     206       68936 :                 talloc_free(state->ptr);
     207       68936 :                 state = NULL;
     208             :         }
     209             : 
     210       68936 :         if (NT_STATUS_IS_DOS(status) && map_dos_errors) {
     211       65543 :                 uint8_t eclass = NT_STATUS_DOS_CLASS(status);
     212       65543 :                 uint16_t ecode = NT_STATUS_DOS_CODE(status);
     213             :                 /*
     214             :                  * TODO: is it really a good idea to do a mapping here?
     215             :                  *
     216             :                  * The old cli_pull_error() also does it, so I do not change
     217             :                  * the behavior yet.
     218             :                  */
     219       65543 :                 status = dos_to_ntstatus(eclass, ecode);
     220             :         }
     221             : 
     222       68936 :         if (!NT_STATUS_IS_ERR(status)) {
     223        2851 :                 is_expected = true;
     224             :         }
     225             : 
     226       68936 :         if (!is_expected) {
     227       66085 :                 TALLOC_FREE(recv_iov);
     228       66085 :                 return status;
     229             :         }
     230             : 
     231        2851 :         if (wct < min_wct) {
     232           0 :                 TALLOC_FREE(recv_iov);
     233           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     234             :         }
     235             : 
     236        2851 :         if (pwct != NULL) {
     237        1926 :                 *pwct = wct;
     238             :         }
     239        2851 :         if (pvwv != NULL) {
     240        1935 :                 *pvwv = vwv;
     241             :         }
     242        2851 :         if (pnum_bytes != NULL) {
     243         503 :                 *pnum_bytes = num_bytes;
     244             :         }
     245        2851 :         if (pbytes != NULL) {
     246         503 :                 *pbytes = bytes;
     247             :         }
     248             : 
     249        2851 :         if (pinbuf != NULL && mem_ctx != NULL) {
     250         887 :                 if (talloc_reference_count(inbuf) == 0) {
     251         447 :                         *pinbuf = talloc_move(mem_ctx, &inbuf);
     252         447 :                         TALLOC_FREE(recv_iov);
     253             :                 } else {
     254           1 :                         *pinbuf = inbuf;
     255             :                 }
     256        2403 :         } else if (mem_ctx != NULL) {
     257        1478 :                 if (talloc_reference_count(inbuf) == 0) {
     258        1474 :                         (void)talloc_move(mem_ctx, &inbuf);
     259        1474 :                         TALLOC_FREE(recv_iov);
     260             :                 }
     261             :         }
     262             : 
     263        2851 :         return status;
     264             : }

Generated by: LCOV version 1.13