LCOV - code coverage report
Current view: top level - source3/smbd - smb2_ioctl_named_pipe.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 46 74 62.2 %
Date: 2021-09-23 10:06:22 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Core SMB2 server
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbd/smbd.h"
      23             : #include "smbd/globals.h"
      24             : #include "../libcli/smb/smb_common.h"
      25             : #include "../lib/util/tevent_ntstatus.h"
      26             : #include "rpc_server/srv_pipe_hnd.h"
      27             : #include "include/ntioctl.h"
      28             : #include "smb2_ioctl_private.h"
      29             : 
      30             : #undef DBGC_CLASS
      31             : #define DBGC_CLASS DBGC_SMB2
      32             : 
      33             : static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq);
      34             : static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq);
      35             : 
      36      294562 : struct tevent_req *smb2_ioctl_named_pipe(uint32_t ctl_code,
      37             :                                          struct tevent_context *ev,
      38             :                                          struct tevent_req *req,
      39             :                                          struct smbd_smb2_ioctl_state *state)
      40             : {
      41             :         NTSTATUS status;
      42      294562 :         uint8_t *out_data = NULL;
      43      294562 :         uint32_t out_data_len = 0;
      44             : 
      45      294562 :         if (ctl_code == FSCTL_PIPE_TRANSCEIVE) {
      46             :                 struct tevent_req *subreq;
      47             : 
      48      294562 :                 if (!IS_IPC(state->smbreq->conn)) {
      49           0 :                         tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
      50           0 :                         return tevent_req_post(req, ev);
      51             :                 }
      52             : 
      53      294562 :                 if (state->fsp == NULL) {
      54           0 :                         tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
      55           0 :                         return tevent_req_post(req, ev);
      56             :                 }
      57             : 
      58      294562 :                 if (!fsp_is_np(state->fsp)) {
      59           0 :                         tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
      60           0 :                         return tevent_req_post(req, ev);
      61             :                 }
      62             : 
      63      294562 :                 DEBUG(10,("smbd_smb2_ioctl_send: np_write_send of size %u\n",
      64             :                         (unsigned int)state->in_input.length ));
      65             : 
      66      542285 :                 subreq = np_write_send(state, ev,
      67      294562 :                                        state->fsp->fake_file_handle,
      68      294562 :                                        state->in_input.data,
      69             :                                        state->in_input.length);
      70      294562 :                 if (tevent_req_nomem(subreq, req)) {
      71           0 :                         return tevent_req_post(req, ev);
      72             :                 }
      73      294562 :                 tevent_req_set_callback(subreq,
      74             :                                         smbd_smb2_ioctl_pipe_write_done,
      75             :                                         req);
      76      294562 :                 return req;
      77             :         }
      78             : 
      79           0 :         if (state->fsp == NULL) {
      80           0 :                 status = NT_STATUS_NOT_SUPPORTED;
      81             :         } else {
      82           0 :                 status = SMB_VFS_FSCTL(state->fsp,
      83             :                                        state,
      84             :                                        ctl_code,
      85             :                                        state->smbreq->flags2,
      86             :                                        state->in_input.data,
      87             :                                        state->in_input.length,
      88             :                                        &out_data,
      89             :                                        state->in_max_output,
      90             :                                        &out_data_len);
      91           0 :                 state->out_output = data_blob_const(out_data, out_data_len);
      92           0 :                 if (NT_STATUS_IS_OK(status)) {
      93           0 :                         tevent_req_done(req);
      94           0 :                         return tevent_req_post(req, ev);
      95             :                 }
      96             :         }
      97             : 
      98           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
      99           0 :                 if (IS_IPC(state->smbreq->conn)) {
     100           0 :                         status = NT_STATUS_FS_DRIVER_REQUIRED;
     101             :                 } else {
     102           0 :                         status = NT_STATUS_INVALID_DEVICE_REQUEST;
     103             :                 }
     104             :         }
     105             : 
     106           0 :         tevent_req_nterror(req, status);
     107           0 :         return tevent_req_post(req, ev);
     108             : }
     109             : 
     110      294562 : static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq)
     111             : {
     112      294562 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     113             :                                  struct tevent_req);
     114      294562 :         struct smbd_smb2_ioctl_state *state = tevent_req_data(req,
     115             :                                               struct smbd_smb2_ioctl_state);
     116             :         NTSTATUS status;
     117      294562 :         ssize_t nwritten = -1;
     118             : 
     119      294562 :         status = np_write_recv(subreq, &nwritten);
     120             : 
     121      294562 :         DEBUG(10,("smbd_smb2_ioctl_pipe_write_done: received %ld\n",
     122             :                 (long int)nwritten ));
     123             : 
     124      294562 :         TALLOC_FREE(subreq);
     125      294562 :         if (!NT_STATUS_IS_OK(status)) {
     126           0 :                 tevent_req_nterror(req, status);
     127           0 :                 return;
     128             :         }
     129             : 
     130      294562 :         if (nwritten != state->in_input.length) {
     131           0 :                 tevent_req_nterror(req, NT_STATUS_PIPE_NOT_AVAILABLE);
     132           0 :                 return;
     133             :         }
     134             : 
     135      294562 :         state->out_output = data_blob_talloc(state, NULL, state->in_max_output);
     136      589124 :         if (state->in_max_output > 0 &&
     137      294562 :             tevent_req_nomem(state->out_output.data, req)) {
     138           0 :                 return;
     139             :         }
     140             : 
     141      294562 :         DEBUG(10,("smbd_smb2_ioctl_pipe_write_done: issuing np_read_send "
     142             :                 "of size %u\n",
     143             :                 (unsigned int)state->out_output.length ));
     144             : 
     145      790008 :         subreq = np_read_send(state->smbreq->conn,
     146      294562 :                               state->smb2req->sconn->ev_ctx,
     147      294562 :                               state->fsp->fake_file_handle,
     148             :                               state->out_output.data,
     149             :                               state->out_output.length);
     150      294562 :         if (tevent_req_nomem(subreq, req)) {
     151           0 :                 return;
     152             :         }
     153      294562 :         tevent_req_set_callback(subreq, smbd_smb2_ioctl_pipe_read_done, req);
     154             : }
     155             : 
     156      294562 : static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq)
     157             : {
     158      294562 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     159             :                                  struct tevent_req);
     160      294562 :         struct smbd_smb2_ioctl_state *state = tevent_req_data(req,
     161             :                                               struct smbd_smb2_ioctl_state);
     162             :         NTSTATUS status;
     163      294562 :         ssize_t nread = -1;
     164      294562 :         bool is_data_outstanding = false;
     165             : 
     166      294562 :         status = np_read_recv(subreq, &nread, &is_data_outstanding);
     167             : 
     168      294562 :         DEBUG(10,("smbd_smb2_ioctl_pipe_read_done: np_read_recv nread = %d "
     169             :                  "is_data_outstanding = %d, status = %s\n",
     170             :                 (int)nread,
     171             :                 (int)is_data_outstanding,
     172             :                 nt_errstr(status) ));
     173             : 
     174      294562 :         TALLOC_FREE(subreq);
     175      294562 :         if (!NT_STATUS_IS_OK(status)) {
     176          12 :                 tevent_req_nterror(req, status);
     177          12 :                 return;
     178             :         }
     179             : 
     180      294550 :         state->out_output.length = nread;
     181             : 
     182      294550 :         if (is_data_outstanding) {
     183           0 :                 tevent_req_nterror(req, STATUS_BUFFER_OVERFLOW);
     184           0 :                 return;
     185             :         }
     186             : 
     187      294550 :         tevent_req_done(req);
     188             : }

Generated by: LCOV version 1.13