2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2021
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.
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.
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/>.
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"
32 #define DBGC_CLASS DBGC_SMB2
34 struct async_sleep_state {
35 struct smbd_server_connection *sconn;
39 static void smbd_fsctl_torture_async_sleep_done(struct tevent_req *subreq);
41 static struct tevent_req *smbd_fsctl_torture_async_sleep_send(
43 struct tevent_context *ev,
47 struct async_sleep_state *state = NULL;
48 struct tevent_req *subreq = NULL;
51 subreq = tevent_req_create(mem_ctx,
53 struct async_sleep_state);
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.
64 state->sconn = fsp->conn->sconn;
68 * Just wait for the specified number of micro seconds,
69 * to allow the client time to close fsp.
71 ok = tevent_req_set_endtime(subreq,
73 timeval_current_ofs(0, msecs));
75 tevent_req_nterror(subreq, NT_STATUS_NO_MEMORY);
76 return tevent_req_post(subreq, ev);
82 static files_struct *find_my_fsp(struct files_struct *fsp,
85 struct files_struct *myfsp = (struct files_struct *)private_data;
93 static bool smbd_fsctl_torture_async_sleep_recv(struct tevent_req *subreq)
95 tevent_req_received(subreq);
99 static void smbd_fsctl_torture_async_sleep_done(struct tevent_req *subreq)
101 struct files_struct *found_fsp;
102 struct tevent_req *req = tevent_req_callback_data(
105 struct async_sleep_state *state = tevent_req_data(
107 struct async_sleep_state);
109 /* Does state->fsp still exist on state->sconn ? */
110 found_fsp = files_forall(state->sconn,
114 smbd_fsctl_torture_async_sleep_recv(subreq);
117 if (found_fsp == NULL) {
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
124 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14769
126 * This request should block file closure until it
129 tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
132 tevent_req_done(req);
135 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)
143 ok = lp_parm_bool(-1, "smbd", "FSCTL_SMBTORTURE", false);
149 case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
150 if (state->in_input.length != 0) {
151 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
152 return tevent_req_post(req, ev);
155 state->smb2req->xconn->ack.force_unacked_timeout = true;
156 tevent_req_done(req);
157 return tevent_req_post(req, ev);
159 case FSCTL_SMBTORTURE_IOCTL_RESPONSE_BODY_PADDING8:
160 if (state->in_input.length != 0) {
161 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
162 return tevent_req_post(req, ev);
165 if (state->in_max_output > 0) {
166 uint32_t size = state->in_max_output;
168 state->out_output = data_blob_talloc(state, NULL, size);
169 if (tevent_req_nomem(state->out_output.data, req)) {
170 return tevent_req_post(req, ev);
172 memset(state->out_output.data, 8, size);
175 state->body_padding = 8;
176 tevent_req_done(req);
177 return tevent_req_post(req, ev);
179 case FSCTL_SMBTORTURE_GLOBAL_READ_RESPONSE_BODY_PADDING8:
180 if (state->in_input.length != 0) {
181 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
182 return tevent_req_post(req, ev);
185 state->smb2req->xconn->smb2.smbtorture.read_body_padding = 8;
186 tevent_req_done(req);
187 return tevent_req_post(req, ev);
189 case FSCTL_SMBTORTURE_FSP_ASYNC_SLEEP: {
190 struct tevent_req *subreq = NULL;
192 /* Data is 1 byte of CVAL stored seconds to delay for. */
193 if (state->in_input.length != 1) {
194 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
195 return tevent_req_post(req, ev);
197 if (state->fsp == NULL) {
198 tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
199 return tevent_req_post(req, ev);
202 subreq = smbd_fsctl_torture_async_sleep_send(
206 CVAL(state->in_input.data,0));
207 if (subreq == NULL) {
208 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
209 return tevent_req_post(req, ev);
211 tevent_req_set_callback(subreq,
212 smbd_fsctl_torture_async_sleep_done,
222 if (IS_IPC(state->smbreq->conn)) {
223 status = NT_STATUS_FS_DRIVER_REQUIRED;
225 status = NT_STATUS_INVALID_DEVICE_REQUEST;
228 tevent_req_nterror(req, status);
229 return tevent_req_post(req, ev);