LCOV - code coverage report
Current view: top level - source3/libsmb - clitrans.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 57 74 77.0 %
Date: 2021-09-23 10:06:22 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    client transaction calls
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       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_trans_state {
      27             :         struct cli_state *cli;
      28             :         struct tevent_req *subreq;
      29             :         uint16_t recv_flags2;
      30             :         uint16_t *setup;
      31             :         uint8_t num_setup;
      32             :         uint8_t *param;
      33             :         uint32_t num_param;
      34             :         uint8_t *data;
      35             :         uint32_t num_data;
      36             : };
      37             : 
      38             : static void cli_trans_done(struct tevent_req *subreq);
      39             : static bool cli_trans_cancel(struct tevent_req *req);
      40             : 
      41       15059 : struct tevent_req *cli_trans_send(
      42             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
      43             :         struct cli_state *cli, uint16_t additional_flags2, uint8_t cmd,
      44             :         const char *pipe_name, uint16_t fid, uint16_t function, int flags,
      45             :         uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
      46             :         uint8_t *param, uint32_t num_param, uint32_t max_param,
      47             :         uint8_t *data, uint32_t num_data, uint32_t max_data)
      48             : {
      49             :         struct tevent_req *req;
      50             :         struct cli_trans_state *state;
      51       15059 :         uint8_t additional_flags = 0;
      52       15059 :         uint8_t clear_flags = 0;
      53       15059 :         uint16_t clear_flags2 = 0;
      54             : 
      55       15059 :         req = tevent_req_create(mem_ctx, &state, struct cli_trans_state);
      56       15059 :         if (req == NULL) {
      57           0 :                 return NULL;
      58             :         }
      59       15059 :         state->cli = cli;
      60             : 
      61       30118 :         state->subreq = smb1cli_trans_send(state, ev,
      62             :                                            cli->conn, cmd,
      63             :                                            additional_flags, clear_flags,
      64             :                                            additional_flags2, clear_flags2,
      65       15059 :                                            cli->timeout,
      66             :                                            cli->smb1.pid,
      67             :                                            cli->smb1.tcon,
      68             :                                            cli->smb1.session,
      69             :                                            pipe_name, fid, function, flags,
      70             :                                            setup, num_setup, max_setup,
      71             :                                            param, num_param, max_param,
      72             :                                            data, num_data, max_data);
      73       15059 :         if (tevent_req_nomem(state->subreq, req)) {
      74           0 :                 return tevent_req_post(req, ev);
      75             :         }
      76       15059 :         tevent_req_set_callback(state->subreq, cli_trans_done, req);
      77       15059 :         tevent_req_set_cancel_fn(req, cli_trans_cancel);
      78       15059 :         return req;
      79             : }
      80             : 
      81           0 : static bool cli_trans_cancel(struct tevent_req *req)
      82             : {
      83           0 :         struct cli_trans_state *state = tevent_req_data(
      84             :                 req, struct cli_trans_state);
      85             :         bool ok;
      86             : 
      87           0 :         ok = tevent_req_cancel(state->subreq);
      88           0 :         return ok;
      89             : }
      90             : 
      91       15059 : static void cli_trans_done(struct tevent_req *subreq)
      92             : {
      93       15059 :         struct tevent_req *req = tevent_req_callback_data(
      94             :                 subreq, struct tevent_req);
      95       15059 :         struct cli_trans_state *state = tevent_req_data(
      96             :                 req, struct cli_trans_state);
      97             :         NTSTATUS status;
      98             : 
      99       15059 :         status = smb1cli_trans_recv(
     100             :                 subreq,
     101             :                 state,
     102             :                 &state->recv_flags2,
     103             :                 &state->setup, 0, &state->num_setup,
     104             :                 &state->param, 0, &state->num_param,
     105             :                 &state->data, 0, &state->num_data);
     106       15059 :         TALLOC_FREE(subreq);
     107       15059 :         if (tevent_req_nterror(req, status)) {
     108        3951 :                 return;
     109             :         }
     110       11108 :         tevent_req_done(req);
     111             : }
     112             : 
     113       15059 : NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     114             :                         uint16_t *recv_flags2,
     115             :                         uint16_t **setup, uint8_t min_setup,
     116             :                         uint8_t *num_setup,
     117             :                         uint8_t **param, uint32_t min_param,
     118             :                         uint32_t *num_param,
     119             :                         uint8_t **data, uint32_t min_data,
     120             :                         uint32_t *num_data)
     121             : {
     122       15059 :         struct cli_trans_state *state = tevent_req_data(
     123             :                 req, struct cli_trans_state);
     124       15059 :         NTSTATUS status = NT_STATUS_OK;
     125       15059 :         bool map_dos_errors = true;
     126             : 
     127       15059 :         if (tevent_req_is_nterror(req, &status)) {
     128        3951 :                 goto map_error;
     129             :         }
     130             : 
     131       22214 :         if ((state->num_setup < min_setup) ||
     132       22214 :             (state->num_param < min_param) ||
     133       11108 :             (state->num_data < min_data)) {
     134           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     135             :         }
     136             : 
     137       11108 :         if (recv_flags2 != NULL) {
     138        1718 :                 *recv_flags2 = state->recv_flags2;
     139             :         }
     140       11108 :         if (setup != NULL) {
     141           0 :                 *setup = talloc_move(mem_ctx, &state->setup);
     142           0 :                 *num_setup = state->num_setup;
     143             :         }
     144       11108 :         if (param != NULL) {
     145        1345 :                 *param = talloc_move(mem_ctx, &state->param);
     146        1345 :                 *num_param = state->num_param;
     147             :         }
     148       11108 :         if (data != NULL) {
     149       10366 :                 *data = talloc_move(mem_ctx, &state->data);
     150       10366 :                 *num_data = state->num_data;
     151             :         }
     152             : 
     153       15787 : map_error:
     154       15059 :         map_dos_errors = state->cli->map_dos_errors;
     155       15059 :         state->cli->raw_status = status;
     156             : 
     157       15059 :         if (NT_STATUS_IS_DOS(status) && map_dos_errors) {
     158           0 :                 uint8_t eclass = NT_STATUS_DOS_CLASS(status);
     159           0 :                 uint16_t ecode = NT_STATUS_DOS_CODE(status);
     160             :                 /*
     161             :                  * TODO: is it really a good idea to do a mapping here?
     162             :                  *
     163             :                  * The old cli_pull_error() also does it, so I do not change
     164             :                  * the behavior yet.
     165             :                  */
     166           0 :                 status = dos_to_ntstatus(eclass, ecode);
     167             :         }
     168             : 
     169       15059 :         return status;
     170             : }
     171             : 
     172        2799 : NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     173             :                    uint8_t trans_cmd,
     174             :                    const char *pipe_name, uint16_t fid, uint16_t function,
     175             :                    int flags,
     176             :                    uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
     177             :                    uint8_t *param, uint32_t num_param, uint32_t max_param,
     178             :                    uint8_t *data, uint32_t num_data, uint32_t max_data,
     179             :                    uint16_t *recv_flags2,
     180             :                    uint16_t **rsetup, uint8_t min_rsetup, uint8_t *num_rsetup,
     181             :                    uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam,
     182             :                    uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata)
     183             : {
     184        2799 :         TALLOC_CTX *frame = talloc_stackframe();
     185             :         struct tevent_context *ev;
     186             :         struct tevent_req *req;
     187        2799 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     188             : 
     189        2799 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     190             :                 /*
     191             :                  * Can't use sync call while an async call is in flight
     192             :                  */
     193           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     194           0 :                 goto fail;
     195             :         }
     196        2799 :         ev = samba_tevent_context_init(frame);
     197        2799 :         if (ev == NULL) {
     198           0 :                 goto fail;
     199             :         }
     200        2799 :         req = cli_trans_send(
     201             :                 frame,          /* mem_ctx */
     202             :                 ev,             /* ev */
     203             :                 cli,            /* cli */
     204             :                 0,              /* additional_flags2 */
     205             :                 trans_cmd,      /* cmd */
     206             :                 pipe_name, fid, function, flags,
     207             :                 setup, num_setup, max_setup,
     208             :                 param, num_param, max_param,
     209             :                 data, num_data, max_data);
     210        2799 :         if (req == NULL) {
     211           0 :                 goto fail;
     212             :         }
     213        2799 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     214           0 :                 goto fail;
     215             :         }
     216        2799 :         status = cli_trans_recv(
     217             :                 req, mem_ctx, recv_flags2,
     218             :                 rsetup, min_rsetup, num_rsetup,
     219             :                 rparam, min_rparam, num_rparam,
     220             :                 rdata, min_rdata, num_rdata);
     221        2799 : fail:
     222        2799 :         TALLOC_FREE(frame);
     223        2799 :         return status;
     224             : }

Generated by: LCOV version 1.13