LCOV - code coverage report
Current view: top level - source3/smbd - smb2_ioctl_smbtorture.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 59 87 67.8 %
Date: 2021-09-23 10:06:22 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Core SMB2 server
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             :    Copyright (C) Jeremy Allison 2021
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "smbd/smbd.h"
      24             : #include "smbd/globals.h"
      25             : #include "../libcli/smb/smb_common.h"
      26             : #include "../lib/util/tevent_ntstatus.h"
      27             : #include "include/ntioctl.h"
      28             : #include "smb2_ioctl_private.h"
      29             : #include "librpc/gen_ndr/ioctl.h"
      30             : 
      31             : #undef DBGC_CLASS
      32             : #define DBGC_CLASS DBGC_SMB2
      33             : 
      34             : struct async_sleep_state {
      35             :         struct smbd_server_connection *sconn;
      36             :         files_struct *fsp;
      37             : };
      38             : 
      39             : static void smbd_fsctl_torture_async_sleep_done(struct tevent_req *subreq);
      40             : 
      41           6 : static struct tevent_req *smbd_fsctl_torture_async_sleep_send(
      42             :                                 TALLOC_CTX *mem_ctx,
      43             :                                 struct tevent_context *ev,
      44             :                                 files_struct *fsp,
      45             :                                 uint8_t msecs)
      46             : {
      47           6 :         struct async_sleep_state *state = NULL;
      48           6 :         struct tevent_req *subreq = NULL;
      49             :         bool ok;
      50             : 
      51           6 :         subreq = tevent_req_create(mem_ctx,
      52             :                                 &state,
      53             :                                 struct async_sleep_state);
      54           6 :         if (!subreq) {
      55           0 :                 return NULL;
      56             :         }
      57             : 
      58             :         /*
      59             :          * Store the conn separately, as the test is to
      60             :          * see if fsp is still a valid pointer, so we can't
      61             :          * do anything other than test it for entry in the
      62             :          * open files on this server connection.
      63             :          */
      64           6 :         state->sconn = fsp->conn->sconn;
      65           6 :         state->fsp = fsp;
      66             : 
      67             :         /*
      68             :          * Just wait for the specified number of micro seconds,
      69             :          * to allow the client time to close fsp.
      70             :          */
      71           6 :         ok = tevent_req_set_endtime(subreq,
      72             :                                     ev,
      73             :                                     timeval_current_ofs(0, msecs));
      74           6 :         if (!ok) {
      75           0 :                 tevent_req_nterror(subreq, NT_STATUS_NO_MEMORY);
      76           0 :                 return tevent_req_post(subreq, ev);
      77             :         }
      78             : 
      79           6 :         return subreq;
      80             : }
      81             : 
      82           6 : static files_struct *find_my_fsp(struct files_struct *fsp,
      83             :                                  void *private_data)
      84             : {
      85           6 :         struct files_struct *myfsp = (struct files_struct *)private_data;
      86             : 
      87           6 :         if (fsp == myfsp) {
      88           6 :                 return myfsp;
      89             :         }
      90           0 :         return NULL;
      91             : }
      92             : 
      93           6 : static bool smbd_fsctl_torture_async_sleep_recv(struct tevent_req *subreq)
      94             : {
      95           6 :         tevent_req_received(subreq);
      96           6 :         return true;
      97             : }
      98             : 
      99           6 : static void smbd_fsctl_torture_async_sleep_done(struct tevent_req *subreq)
     100             : {
     101             :         struct files_struct *found_fsp;
     102           6 :         struct tevent_req *req = tevent_req_callback_data(
     103             :                                         subreq,
     104             :                                         struct tevent_req);
     105           6 :         struct async_sleep_state *state = tevent_req_data(
     106             :                                         subreq,
     107             :                                         struct async_sleep_state);
     108             : 
     109             :         /* Does state->fsp still exist on state->sconn ? */
     110           6 :         found_fsp = files_forall(state->sconn,
     111             :                                  find_my_fsp,
     112           6 :                                  state->fsp);
     113             : 
     114           6 :         smbd_fsctl_torture_async_sleep_recv(subreq);
     115           6 :         TALLOC_FREE(subreq);
     116             : 
     117           6 :         if (found_fsp == NULL) {
     118             :                 /*
     119             :                  * We didn't find it - return an error to the
     120             :                  * smb2 ioctl request. Use NT_STATUS_FILE_CLOSED so
     121             :                  * the client can tell the difference between
     122             :                  * a bad fsp handle and
     123             :                  *
     124             :                  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14769
     125             :                  *
     126             :                  * This request should block file closure until it
     127             :                  * has completed.
     128             :                  */
     129           0 :                 tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
     130           0 :                 return;
     131             :         }
     132           6 :         tevent_req_done(req);
     133             : }
     134             : 
     135         344 : struct tevent_req *smb2_ioctl_smbtorture(uint32_t ctl_code,
     136             :                                          struct tevent_context *ev,
     137             :                                          struct tevent_req *req,
     138             :                                          struct smbd_smb2_ioctl_state *state)
     139             : {
     140             :         NTSTATUS status;
     141             :         bool ok;
     142             : 
     143         344 :         ok = lp_parm_bool(-1, "smbd", "FSCTL_SMBTORTURE", false);
     144         344 :         if (!ok) {
     145           0 :                 goto not_supported;
     146             :         }
     147             : 
     148         344 :         switch (ctl_code) {
     149         328 :         case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
     150         328 :                 if (state->in_input.length != 0) {
     151           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     152           0 :                         return tevent_req_post(req, ev);
     153             :                 }
     154             : 
     155         328 :                 state->smb2req->xconn->ack.force_unacked_timeout = true;
     156         328 :                 tevent_req_done(req);
     157         328 :                 return tevent_req_post(req, ev);
     158             : 
     159           6 :         case FSCTL_SMBTORTURE_IOCTL_RESPONSE_BODY_PADDING8:
     160           6 :                 if (state->in_input.length != 0) {
     161           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     162           0 :                         return tevent_req_post(req, ev);
     163             :                 }
     164             : 
     165           6 :                 if (state->in_max_output > 0) {
     166           6 :                         uint32_t size = state->in_max_output;
     167             : 
     168           6 :                         state->out_output = data_blob_talloc(state, NULL, size);
     169           6 :                         if (tevent_req_nomem(state->out_output.data, req)) {
     170           0 :                                 return tevent_req_post(req, ev);
     171             :                         }
     172           6 :                         memset(state->out_output.data, 8, size);
     173             :                 }
     174             : 
     175           6 :                 state->body_padding = 8;
     176           6 :                 tevent_req_done(req);
     177           6 :                 return tevent_req_post(req, ev);
     178             : 
     179           4 :         case FSCTL_SMBTORTURE_GLOBAL_READ_RESPONSE_BODY_PADDING8:
     180           4 :                 if (state->in_input.length != 0) {
     181           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     182           0 :                         return tevent_req_post(req, ev);
     183             :                 }
     184             : 
     185           4 :                 state->smb2req->xconn->smb2.smbtorture.read_body_padding = 8;
     186           4 :                 tevent_req_done(req);
     187           4 :                 return tevent_req_post(req, ev);
     188             : 
     189           6 :         case FSCTL_SMBTORTURE_FSP_ASYNC_SLEEP: {
     190           6 :                 struct tevent_req *subreq = NULL;
     191             : 
     192             :                 /* Data is 1 byte of CVAL stored seconds to delay for. */
     193           6 :                 if (state->in_input.length != 1) {
     194           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     195           0 :                         return tevent_req_post(req, ev);
     196             :                 }
     197           6 :                 if (state->fsp == NULL) {
     198           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
     199           0 :                         return tevent_req_post(req, ev);
     200             :                 }
     201             : 
     202           6 :                 subreq = smbd_fsctl_torture_async_sleep_send(
     203             :                                                 req,
     204             :                                                 ev,
     205             :                                                 state->fsp,
     206           6 :                                                 CVAL(state->in_input.data,0));
     207           6 :                 if (subreq == NULL) {
     208           0 :                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     209           0 :                         return tevent_req_post(req, ev);
     210             :                 }
     211           6 :                 tevent_req_set_callback(subreq,
     212             :                                         smbd_fsctl_torture_async_sleep_done,
     213             :                                         req);
     214           6 :                 return req;
     215             :         }
     216             : 
     217           0 :         default:
     218           0 :                 goto not_supported;
     219             :         }
     220             : 
     221           0 : not_supported:
     222           0 :         if (IS_IPC(state->smbreq->conn)) {
     223           0 :                 status = NT_STATUS_FS_DRIVER_REQUIRED;
     224             :         } else {
     225           0 :                 status = NT_STATUS_INVALID_DEVICE_REQUEST;
     226             :         }
     227             : 
     228           0 :         tevent_req_nterror(req, status);
     229           0 :         return tevent_req_post(req, ev);
     230             : }

Generated by: LCOV version 1.13