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
);