LCOV - code coverage report
Current view: top level - source3/libsmb - async_smb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 98 122 80.3 %
Date: 2024-04-21 15:09:00 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      379936 : static int cli_smb_req_state_ptr_destructor(struct cli_smb_req_state **ptr)
      41             : {
      42      379936 :         struct cli_smb_req_state *state = *ptr;
      43      379936 :         void *parent = talloc_parent(state);
      44             : 
      45      379936 :         talloc_set_destructor(state, NULL);
      46             : 
      47      379936 :         talloc_reparent(state, parent, state->req);
      48      379936 :         talloc_free(state);
      49      379936 :         return 0;
      50             : }
      51             : 
      52       35763 : 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           0 :         struct cli_smb_req_state *state;
      63       35763 :         uint8_t clear_flags = 0;
      64       35763 :         uint16_t clear_flags2 = 0;
      65             : 
      66       35763 :         state = talloc_zero(mem_ctx, struct cli_smb_req_state);
      67       35763 :         if (state == NULL) {
      68           0 :                 return NULL;
      69             :         }
      70       35763 :         state->cli = cli;
      71       35763 :         state->smb_command = smb_command;
      72       35763 :         state->ptr = talloc(state, struct cli_smb_req_state *);
      73       35763 :         if (state->ptr == NULL) {
      74           0 :                 talloc_free(state);
      75           0 :                 return NULL;
      76             :         }
      77       35763 :         *state->ptr = state;
      78             : 
      79       71526 :         state->req = smb1cli_req_create(state, ev, cli->conn, smb_command,
      80             :                                         additional_flags, clear_flags,
      81             :                                         additional_flags2, clear_flags2,
      82       35763 :                                         cli->timeout,
      83             :                                         cli->smb1.pid,
      84             :                                         cli->smb1.tcon,
      85             :                                         cli->smb1.session,
      86             :                                         wct, vwv, iov_count, bytes_iov);
      87       35763 :         if (state->req == NULL) {
      88           0 :                 talloc_free(state);
      89           0 :                 return NULL;
      90             :         }
      91             : 
      92       35763 :         talloc_reparent(state, state->req, state->ptr);
      93       35763 :         talloc_set_destructor(state, cli_smb_req_state_destructor);
      94       35763 :         talloc_set_destructor(state->ptr, cli_smb_req_state_ptr_destructor);
      95             : 
      96       35763 :         return state->req;
      97             : }
      98             : 
      99      344173 : 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           0 :         struct cli_smb_req_state *state;
     110      344173 :         uint8_t clear_flags = 0;
     111      344173 :         uint16_t clear_flags2 = 0;
     112             : 
     113      344173 :         state = talloc_zero(mem_ctx, struct cli_smb_req_state);
     114      344173 :         if (state == NULL) {
     115           0 :                 return NULL;
     116             :         }
     117      344173 :         state->cli = cli;
     118      344173 :         state->smb_command = smb_command;
     119      344173 :         state->ptr = talloc(state, struct cli_smb_req_state *);
     120      344173 :         if (state->ptr == NULL) {
     121           0 :                 talloc_free(state);
     122           0 :                 return NULL;
     123             :         }
     124      344173 :         *state->ptr = state;
     125             : 
     126      688346 :         state->req = smb1cli_req_send(state, ev, cli->conn, smb_command,
     127             :                                 additional_flags, clear_flags,
     128             :                                 additional_flags2, clear_flags2,
     129      344173 :                                 cli->timeout,
     130             :                                 cli->smb1.pid,
     131             :                                 cli->smb1.tcon,
     132             :                                 cli->smb1.session,
     133             :                                 wct, vwv, num_bytes, bytes);
     134      344173 :         if (state->req == NULL) {
     135           0 :                 talloc_free(state);
     136           0 :                 return NULL;
     137             :         }
     138             : 
     139      344173 :         talloc_reparent(state, state->req, state->ptr);
     140      344173 :         talloc_set_destructor(state, cli_smb_req_state_destructor);
     141      344173 :         talloc_set_destructor(state->ptr, cli_smb_req_state_ptr_destructor);
     142             : 
     143      344173 :         return state->req;
     144             : }
     145             : 
     146      379936 : 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           0 :         NTSTATUS status;
     152      379936 :         void *parent = talloc_parent(req);
     153           0 :         struct cli_smb_req_state *state =
     154      379936 :                 talloc_get_type(parent,
     155             :                 struct cli_smb_req_state);
     156      379936 :         struct iovec *recv_iov = NULL;
     157      379936 :         uint8_t wct = 0;
     158      379936 :         uint16_t *vwv = NULL;
     159           0 :         uint32_t num_bytes;
     160      379936 :         uint8_t *bytes = NULL;
     161           0 :         uint8_t *inbuf;
     162      379936 :         bool is_expected = false;
     163      379936 :         bool map_dos_errors = true;
     164             : 
     165      379936 :         if (pinbuf != NULL) {
     166       14667 :                 *pinbuf = NULL;
     167             :         }
     168      379936 :         if (pwct != NULL) {
     169       31921 :                 *pwct = 0;
     170             :         }
     171      379936 :         if (pvwv != NULL) {
     172       32037 :                 *pvwv = NULL;
     173             :         }
     174      379936 :         if (pnum_bytes != NULL) {
     175       18541 :                 *pnum_bytes = 0;
     176             :         }
     177      379936 :         if (pbytes != NULL) {
     178       18541 :                 *pbytes = NULL;
     179             :         }
     180             : 
     181      379936 :         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      379936 :         if (state) {
     194      379936 :                 if ((state->smb_command == SMBsesssetupX) &&
     195           5 :                      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      379936 :                 if ((state->smb_command == SMBntcreateX) &&
     205        3863 :                     NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
     206           0 :                         min_wct = 0;
     207             :                 }
     208             : 
     209      379936 :                 map_dos_errors = state->cli->map_dos_errors;
     210      379936 :                 state->cli->raw_status = status;
     211      379936 :                 talloc_free(state->ptr);
     212      379936 :                 state = NULL;
     213             :         }
     214             : 
     215      379936 :         if (NT_STATUS_IS_DOS(status) && map_dos_errors) {
     216      327721 :                 uint8_t eclass = NT_STATUS_DOS_CLASS(status);
     217      327721 :                 uint16_t ecode = NT_STATUS_DOS_CODE(status);
     218             :                 /*
     219             :                  * TODO: is it really a good idea to do a mapping here?
     220             :                  *
     221             :                  * The old cli_pull_error() also does it, so I do not change
     222             :                  * the behavior yet.
     223             :                  */
     224      327721 :                 status = dos_to_ntstatus(eclass, ecode);
     225             :         }
     226             : 
     227      379936 :         if (!NT_STATUS_IS_ERR(status)) {
     228       48508 :                 is_expected = true;
     229             :         }
     230             : 
     231      379936 :         if (!is_expected) {
     232      331428 :                 TALLOC_FREE(recv_iov);
     233      331428 :                 return status;
     234             :         }
     235             : 
     236       48508 :         if (wct < min_wct) {
     237           0 :                 TALLOC_FREE(recv_iov);
     238           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     239             :         }
     240             : 
     241       48508 :         if (pwct != NULL) {
     242       31231 :                 *pwct = wct;
     243             :         }
     244       48508 :         if (pvwv != NULL) {
     245       31340 :                 *pvwv = vwv;
     246             :         }
     247       48508 :         if (pnum_bytes != NULL) {
     248       17981 :                 *pnum_bytes = num_bytes;
     249             :         }
     250       48508 :         if (pbytes != NULL) {
     251       17981 :                 *pbytes = bytes;
     252             :         }
     253             : 
     254       48508 :         if (pinbuf != NULL && mem_ctx != NULL) {
     255       14614 :                 if (talloc_reference_count(inbuf) == 0) {
     256       14592 :                         *pinbuf = talloc_move(mem_ctx, &inbuf);
     257       14592 :                         TALLOC_FREE(recv_iov);
     258             :                 } else {
     259           5 :                         *pinbuf = inbuf;
     260             :                 }
     261       33911 :         } else if (mem_ctx != NULL) {
     262       16632 :                 if (talloc_reference_count(inbuf) == 0) {
     263       16612 :                         (void)talloc_move(mem_ctx, &inbuf);
     264       16612 :                         TALLOC_FREE(recv_iov);
     265             :                 }
     266             :         }
     267             : 
     268       48508 :         return status;
     269             : }

Generated by: LCOV version 1.14