LCOV - code coverage report
Current view: top level - libcli/smb - smb2cli_read.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 77 88 87.5 %
Date: 2024-04-21 15:09:00 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    smb2 lib
       4             :    Copyright (C) Volker Lendecke 2011
       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 "system/network.h"
      22             : #include "lib/util/tevent_ntstatus.h"
      23             : #include "smb_common.h"
      24             : #include "smbXcli_base.h"
      25             : 
      26             : struct smb2cli_read_state {
      27             :         uint8_t fixed[48];
      28             :         uint8_t dyn_pad[1];
      29             :         struct iovec *recv_iov;
      30             :         uint8_t *data;
      31             :         uint32_t data_length;
      32             :         bool out_valid;
      33             : };
      34             : 
      35             : static void smb2cli_read_done(struct tevent_req *subreq);
      36             : 
      37       11953 : struct tevent_req *smb2cli_read_send(TALLOC_CTX *mem_ctx,
      38             :                                      struct tevent_context *ev,
      39             :                                      struct smbXcli_conn *conn,
      40             :                                      uint32_t timeout_msec,
      41             :                                      struct smbXcli_session *session,
      42             :                                      struct smbXcli_tcon *tcon,
      43             :                                      uint32_t length,
      44             :                                      uint64_t offset,
      45             :                                      uint64_t fid_persistent,
      46             :                                      uint64_t fid_volatile,
      47             :                                      uint64_t minimum_count,
      48             :                                      uint64_t remaining_bytes)
      49             : {
      50          48 :         struct tevent_req *req, *subreq;
      51          48 :         struct smb2cli_read_state *state;
      52          48 :         uint8_t *fixed;
      53             : 
      54       11953 :         req = tevent_req_create(mem_ctx, &state,
      55             :                                 struct smb2cli_read_state);
      56       11953 :         if (req == NULL) {
      57           0 :                 return NULL;
      58             :         }
      59             : 
      60       11953 :         fixed = state->fixed;
      61             : 
      62       11953 :         SSVAL(fixed, 0, 49);
      63       11953 :         SIVAL(fixed, 4, length);
      64       11953 :         SBVAL(fixed, 8, offset);
      65       11953 :         SBVAL(fixed, 16, fid_persistent);
      66       11953 :         SBVAL(fixed, 24, fid_volatile);
      67       11953 :         SBVAL(fixed, 32, minimum_count);
      68       11953 :         SBVAL(fixed, 40, remaining_bytes);
      69             : 
      70       12001 :         subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_READ,
      71             :                                   0, 0, /* flags */
      72             :                                   timeout_msec,
      73             :                                   tcon,
      74             :                                   session,
      75       11953 :                                   state->fixed, sizeof(state->fixed),
      76       11953 :                                   state->dyn_pad, sizeof(state->dyn_pad),
      77             :                                   length); /* max_dyn_len */
      78       11953 :         if (tevent_req_nomem(subreq, req)) {
      79           0 :                 return tevent_req_post(req, ev);
      80             :         }
      81       11953 :         tevent_req_set_callback(subreq, smb2cli_read_done, req);
      82       11953 :         return req;
      83             : }
      84             : 
      85       11951 : static void smb2cli_read_done(struct tevent_req *subreq)
      86             : {
      87       11951 :         struct tevent_req *req = tevent_req_callback_data(
      88             :                 subreq, struct tevent_req);
      89          48 :         struct smb2cli_read_state *state =
      90       11951 :                 tevent_req_data(req,
      91             :                 struct smb2cli_read_state);
      92          48 :         NTSTATUS status;
      93          48 :         NTSTATUS error;
      94          48 :         struct iovec *iov;
      95       11951 :         const uint8_t dyn_ofs = SMB2_HDR_BODY + 0x10;
      96       11951 :         DATA_BLOB dyn_buffer = data_blob_null;
      97          48 :         uint8_t data_offset;
      98       11951 :         DATA_BLOB data_buffer = data_blob_null;
      99       11951 :         uint32_t next_offset = 0; /* this variable is completely ignored */
     100          48 :         static const struct smb2cli_req_expected_response expected[] = {
     101             :         {
     102             :                 .status = STATUS_BUFFER_OVERFLOW,
     103             :                 .body_size = 0x11
     104             :         },
     105             :         {
     106             :                 .status = NT_STATUS_OK,
     107             :                 .body_size = 0x11
     108             :         }
     109             :         };
     110             : 
     111       11951 :         status = smb2cli_req_recv(subreq, state, &iov,
     112             :                                   expected, ARRAY_SIZE(expected));
     113       11951 :         TALLOC_FREE(subreq);
     114       11951 :         if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
     115             :                 /* no error */
     116             :         } else {
     117       11951 :                 if (tevent_req_nterror(req, status)) {
     118         337 :                         return;
     119             :                 }
     120             :         }
     121             : 
     122       11614 :         data_offset = CVAL(iov[1].iov_base, 2);
     123       11614 :         state->data_length = IVAL(iov[1].iov_base, 4);
     124             : 
     125       11614 :         dyn_buffer = data_blob_const((uint8_t *)iov[2].iov_base,
     126       11566 :                                      iov[2].iov_len);
     127             : 
     128       11614 :         error = smb2cli_parse_dyn_buffer(dyn_ofs,
     129             :                                          dyn_buffer,
     130             :                                          dyn_ofs, /* min_offset */
     131             :                                          data_offset,
     132             :                                          state->data_length,
     133       11566 :                                          dyn_buffer.length, /* max_length */
     134             :                                          &next_offset,
     135             :                                          &data_buffer);
     136       11614 :         if (tevent_req_nterror(req, error)) {
     137           0 :                 return;
     138             :         }
     139             : 
     140       11614 :         state->recv_iov = iov;
     141       11614 :         state->data = data_buffer.data;
     142             : 
     143       11614 :         state->out_valid = true;
     144             : 
     145       11614 :         if (tevent_req_nterror(req, status)) {
     146           0 :                 return;
     147             :         }
     148             : 
     149       11614 :         tevent_req_done(req);
     150             : }
     151             : 
     152       11951 : NTSTATUS smb2cli_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     153             :                            uint8_t **data, uint32_t *data_length)
     154             : {
     155          48 :         struct smb2cli_read_state *state =
     156       11951 :                 tevent_req_data(req,
     157             :                 struct smb2cli_read_state);
     158       11951 :         NTSTATUS status = NT_STATUS_OK;
     159             : 
     160       11951 :         if (tevent_req_is_nterror(req, &status) && !state->out_valid) {
     161         337 :                 *data_length = 0;
     162         337 :                 *data = NULL;
     163         337 :                 tevent_req_received(req);
     164         337 :                 return status;
     165             :         }
     166       11614 :         talloc_steal(mem_ctx, state->recv_iov);
     167       11614 :         *data_length = state->data_length;
     168       11614 :         *data = state->data;
     169       11614 :         tevent_req_received(req);
     170       11614 :         return status;
     171             : }
     172             : 
     173          38 : NTSTATUS smb2cli_read(struct smbXcli_conn *conn,
     174             :                       uint32_t timeout_msec,
     175             :                       struct smbXcli_session *session,
     176             :                       struct smbXcli_tcon *tcon,
     177             :                       uint32_t length,
     178             :                       uint64_t offset,
     179             :                       uint64_t fid_persistent,
     180             :                       uint64_t fid_volatile,
     181             :                       uint64_t minimum_count,
     182             :                       uint64_t remaining_bytes,
     183             :                       TALLOC_CTX *mem_ctx,
     184             :                       uint8_t **data,
     185             :                       uint32_t *data_length)
     186             : {
     187          38 :         TALLOC_CTX *frame = talloc_stackframe();
     188           0 :         struct tevent_context *ev;
     189           0 :         struct tevent_req *req;
     190          38 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     191             : 
     192          38 :         if (smbXcli_conn_has_async_calls(conn)) {
     193             :                 /*
     194             :                  * Can't use sync call while an async call is in flight
     195             :                  */
     196           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     197           0 :                 goto fail;
     198             :         }
     199          38 :         ev = samba_tevent_context_init(frame);
     200          38 :         if (ev == NULL) {
     201           0 :                 goto fail;
     202             :         }
     203          38 :         req = smb2cli_read_send(frame, ev,
     204             :                                 conn, timeout_msec, session, tcon,
     205             :                                 length, offset,
     206             :                                 fid_persistent, fid_volatile,
     207             :                                 minimum_count, remaining_bytes);
     208          38 :         if (req == NULL) {
     209           0 :                 goto fail;
     210             :         }
     211          38 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     212           0 :                 goto fail;
     213             :         }
     214          38 :         status = smb2cli_read_recv(req, mem_ctx, data, data_length);
     215          38 :  fail:
     216          38 :         TALLOC_FREE(frame);
     217          38 :         return status;
     218             : }

Generated by: LCOV version 1.14