/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- reply_simple_send
- smbsrv_reply_tcon
- smbsrv_reply_tcon_and_X
- smbsrv_reply_unknown
- reply_ioctl_send
- smbsrv_reply_ioctl
- smbsrv_reply_chkpth
- reply_getatr_send
- smbsrv_reply_getatr
- smbsrv_reply_setatr
- reply_dskattr_send
- smbsrv_reply_dskattr
- reply_open_send
- smbsrv_reply_open
- reply_open_and_X_send
- smbsrv_reply_open_and_X
- reply_mknew_send
- smbsrv_reply_mknew
- reply_ctemp_send
- smbsrv_reply_ctemp
- smbsrv_reply_unlink
- smbsrv_reply_readbraw
- reply_lockread_send
- smbsrv_reply_lockread
- reply_read_send
- smbsrv_reply_read
- reply_read_and_X_send
- smbsrv_reply_read_and_X
- smbsrv_reply_writebraw
- reply_writeunlock_send
- smbsrv_reply_writeunlock
- reply_write_send
- smbsrv_reply_write
- reply_write_and_X_send
- smbsrv_reply_write_and_X
- reply_lseek_send
- smbsrv_reply_lseek
- smbsrv_reply_flush
- smbsrv_reply_close
- reply_writeclose_send
- smbsrv_reply_writeclose
- smbsrv_reply_lock
- smbsrv_reply_unlock
- smbsrv_reply_tdis
- smbsrv_reply_echo
- reply_printopen_send
- smbsrv_reply_printopen
- smbsrv_reply_printclose
- reply_printqueue_send
- smbsrv_reply_printqueue
- smbsrv_reply_printwrite
- smbsrv_reply_mkdir
- smbsrv_reply_rmdir
- smbsrv_reply_mv
- smbsrv_reply_ntrename
- reply_copy_send
- smbsrv_reply_copy
- reply_lockingX_send
- smbsrv_reply_lockingX
- smbsrv_reply_readbmpx
- smbsrv_reply_setattrE
- smbsrv_reply_writebmpx
- smbsrv_reply_writebs
- reply_getattrE_send
- smbsrv_reply_getattrE
- smbsrv_reply_sesssetup_send
- reply_sesssetup_old
- reply_sesssetup_nt1
- reply_sesssetup_spnego
- smbsrv_reply_sesssetup
- smbsrv_reply_exit
- smbsrv_reply_ulogoffX
- smbsrv_reply_findclose
- smbsrv_reply_findnclose
- reply_ntcreate_and_X_send
- smbsrv_reply_ntcreate_and_X
- smbsrv_reply_ntcancel
- parse_session_request
- smbsrv_reply_special
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-2003
5 Copyright (C) James J Myers 2003 <myersjj@samba.org>
6 Copyright (C) Stefan Metzmacher 2006
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 This file handles most of the reply_ calls that the server
23 makes to handle specific SMB commands
24 */
25
26 #include "includes.h"
27 #include "smb_server/smb_server.h"
28 #include "ntvfs/ntvfs.h"
29 #include "librpc/gen_ndr/ndr_nbt.h"
30
31
32 /****************************************************************************
33 Reply to a simple request (async send)
34 ****************************************************************************/
35 static void reply_simple_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
36 {
37 struct smbsrv_request *req;
38
39 SMBSRV_CHECK_ASYNC_STATUS_SIMPLE;
40
41 smbsrv_setup_reply(req, 0, 0);
42 smbsrv_send_reply(req);
43 }
44
45
46 /****************************************************************************
47 Reply to a tcon.
48 ****************************************************************************/
49 void smbsrv_reply_tcon(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
50 {
51 union smb_tcon con;
52 NTSTATUS status;
53 uint8_t *p;
54
55 /* parse request */
56 SMBSRV_CHECK_WCT(req, 0);
57
58 con.tcon.level = RAW_TCON_TCON;
59
60 p = req->in.data;
61 p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.service, p, STR_TERMINATE);
62 p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.password, p, STR_TERMINATE);
63 p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.dev, p, STR_TERMINATE);
64
65 if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
66 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
67 return;
68 }
69
70 /* call backend */
71 status = smbsrv_tcon_backend(req, &con);
72
73 if (!NT_STATUS_IS_OK(status)) {
74 smbsrv_send_error(req, status);
75 return;
76 }
77
78 /* construct reply */
79 smbsrv_setup_reply(req, 2, 0);
80
81 SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
82 SSVAL(req->out.vwv, VWV(1), con.tcon.out.tid);
83 SSVAL(req->out.hdr, HDR_TID, req->tcon->tid);
84
85 smbsrv_send_reply(req);
86 }
87
88
89 /****************************************************************************
90 Reply to a tcon and X.
91 ****************************************************************************/
92 void smbsrv_reply_tcon_and_X(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
93 {
94 NTSTATUS status;
95 union smb_tcon con;
96 uint8_t *p;
97 uint16_t passlen;
98
99 con.tconx.level = RAW_TCON_TCONX;
100
101 /* parse request */
102 SMBSRV_CHECK_WCT(req, 4);
103
104 con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
105 passlen = SVAL(req->in.vwv, VWV(3));
106
107 p = req->in.data;
108
109 if (!req_pull_blob(&req->in.bufinfo, p, passlen, &con.tconx.in.password)) {
110 smbsrv_send_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
111 return;
112 }
113 p += passlen;
114
115 p += req_pull_string(&req->in.bufinfo, &con.tconx.in.path, p, -1, STR_TERMINATE);
116 p += req_pull_string(&req->in.bufinfo, &con.tconx.in.device, p, -1, STR_ASCII);
117
118 if (!con.tconx.in.path || !con.tconx.in.device) {
119 smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE);
120 return;
121 }
122
123 /* call backend */
124 status = smbsrv_tcon_backend(req, &con);
125
126 if (!NT_STATUS_IS_OK(status)) {
127 smbsrv_send_error(req, status);
128 return;
129 }
130
131 /* construct reply - two variants */
132 if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
133 smbsrv_setup_reply(req, 2, 0);
134
135 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
136 SSVAL(req->out.vwv, VWV(1), 0);
137
138 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
139 } else {
140 smbsrv_setup_reply(req, 3, 0);
141
142 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
143 SSVAL(req->out.vwv, VWV(1), 0);
144 SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
145
146 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
147 req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
148 }
149
150 /* set the incoming and outgoing tid to the just created one */
151 SSVAL(req->in.hdr, HDR_TID, con.tconx.out.tid);
152 SSVAL(req->out.hdr,HDR_TID, con.tconx.out.tid);
153
154 smbsrv_chain_reply(req);
155 }
156
157
158 /****************************************************************************
159 Reply to an unknown request
160 ****************************************************************************/
161 void smbsrv_reply_unknown(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
162 {
163 int type;
164
165 type = CVAL(req->in.hdr, HDR_COM);
166
167 DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
168
169 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRunknownsmb));
170 }
171
172
173 /****************************************************************************
174 Reply to an ioctl (async reply)
175 ****************************************************************************/
176 static void reply_ioctl_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
177 {
178 struct smbsrv_request *req;
179 union smb_ioctl *io;
180
181 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_ioctl);
182
183 /* the +1 is for nicer alignment */
184 smbsrv_setup_reply(req, 8, io->ioctl.out.blob.length+1);
185 SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
186 SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
187 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
188
189 memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
190
191 smbsrv_send_reply(req);
192 }
193
194 /****************************************************************************
195 Reply to an ioctl.
196 ****************************************************************************/
197 void smbsrv_reply_ioctl(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
198 {
199 union smb_ioctl *io;
200
201 /* parse request */
202 SMBSRV_CHECK_WCT(req, 3);
203 SMBSRV_TALLOC_IO_PTR(io, union smb_ioctl);
204 SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
205
206 io->ioctl.level = RAW_IOCTL_IOCTL;
207 io->ioctl.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
208 io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
209
210 SMBSRV_CHECK_FILE_HANDLE_ERROR(io->ioctl.in.file.ntvfs,
211 NT_STATUS_DOS(ERRSRV, ERRerror));
212 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));
213 }
214
215
216 /****************************************************************************
217 Reply to a chkpth.
218 ****************************************************************************/
219 void smbsrv_reply_chkpth(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
220 {
221 union smb_chkpath *io;
222
223 SMBSRV_TALLOC_IO_PTR(io, union smb_chkpath);
224 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
225
226 req_pull_ascii4(&req->in.bufinfo, &io->chkpath.in.path, req->in.data, STR_TERMINATE);
227
228 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_chkpath(req->ntvfs, io));
229 }
230
231 /****************************************************************************
232 Reply to a getatr (async reply)
233 ****************************************************************************/
234 static void reply_getatr_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
235 {
236 struct smbsrv_request *req;
237 union smb_fileinfo *st;
238
239 SMBSRV_CHECK_ASYNC_STATUS(st, union smb_fileinfo);
240
241 /* construct reply */
242 smbsrv_setup_reply(req, 10, 0);
243
244 SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
245 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
246 SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
247
248 SMBSRV_VWV_RESERVED(5, 5);
249
250 smbsrv_send_reply(req);
251 }
252
253
254 /****************************************************************************
255 Reply to a getatr.
256 ****************************************************************************/
257 void smbsrv_reply_getatr(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
258 {
259 union smb_fileinfo *st;
260
261 SMBSRV_TALLOC_IO_PTR(st, union smb_fileinfo);
262 SMBSRV_SETUP_NTVFS_REQUEST(reply_getatr_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
263
264 st->getattr.level = RAW_FILEINFO_GETATTR;
265
266 /* parse request */
267 req_pull_ascii4(&req->in.bufinfo, &st->getattr.in.file.path, req->in.data, STR_TERMINATE);
268 if (!st->getattr.in.file.path) {
269 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
270 return;
271 }
272
273 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qpathinfo(req->ntvfs, st));
274 }
275
276
277 /****************************************************************************
278 Reply to a setatr.
279 ****************************************************************************/
280 void smbsrv_reply_setatr(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
281 {
282 union smb_setfileinfo *st;
283
284 /* parse request */
285 SMBSRV_CHECK_WCT(req, 8);
286 SMBSRV_TALLOC_IO_PTR(st, union smb_setfileinfo);
287 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
288
289 st->setattr.level = RAW_SFILEINFO_SETATTR;
290 st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
291 st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
292
293 req_pull_ascii4(&req->in.bufinfo, &st->setattr.in.file.path, req->in.data, STR_TERMINATE);
294
295 if (!st->setattr.in.file.path) {
296 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
297 return;
298 }
299
300 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setpathinfo(req->ntvfs, st));
301 }
302
303
304 /****************************************************************************
305 Reply to a dskattr (async reply)
306 ****************************************************************************/
307 static void reply_dskattr_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
308 {
309 struct smbsrv_request *req;
310 union smb_fsinfo *fs;
311
312 SMBSRV_CHECK_ASYNC_STATUS(fs, union smb_fsinfo);
313
314 /* construct reply */
315 smbsrv_setup_reply(req, 5, 0);
316
317 SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
318 SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
319 SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
320 SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
321
322 SMBSRV_VWV_RESERVED(4, 1);
323
324 smbsrv_send_reply(req);
325 }
326
327
328 /****************************************************************************
329 Reply to a dskattr.
330 ****************************************************************************/
331 void smbsrv_reply_dskattr(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
332 {
333 union smb_fsinfo *fs;
334
335 SMBSRV_TALLOC_IO_PTR(fs, union smb_fsinfo);
336 SMBSRV_SETUP_NTVFS_REQUEST(reply_dskattr_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
337
338 fs->dskattr.level = RAW_QFS_DSKATTR;
339
340 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_fsinfo(req->ntvfs, fs));
341 }
342
343
344 /****************************************************************************
345 Reply to an open (async reply)
346 ****************************************************************************/
347 static void reply_open_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
348 {
349 struct smbsrv_request *req;
350 union smb_open *oi;
351
352 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
353
354 /* construct reply */
355 smbsrv_setup_reply(req, 7, 0);
356
357 smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs);
358 SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
359 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
360 SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
361 SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
362
363 smbsrv_send_reply(req);
364 }
365
366 /****************************************************************************
367 Reply to an open.
368 ****************************************************************************/
369 void smbsrv_reply_open(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
370 {
371 union smb_open *oi;
372
373 /* parse request */
374 SMBSRV_CHECK_WCT(req, 2);
375 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
376 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
377
378 oi->openold.level = RAW_OPEN_OPEN;
379 oi->openold.in.open_mode = SVAL(req->in.vwv, VWV(0));
380 oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
381
382 req_pull_ascii4(&req->in.bufinfo, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
383
384 if (!oi->openold.in.fname) {
385 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
386 return;
387 }
388
389 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
390 }
391
392
393 /****************************************************************************
394 Reply to an open and X (async reply)
395 ****************************************************************************/
396 static void reply_open_and_X_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
397 {
398 struct smbsrv_request *req;
399 union smb_open *oi;
400
401 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
402
403 /* build the reply */
404 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
405 smbsrv_setup_reply(req, 19, 0);
406 } else {
407 smbsrv_setup_reply(req, 15, 0);
408 }
409
410 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
411 SSVAL(req->out.vwv, VWV(1), 0);
412 smbsrv_push_fnum(req->out.vwv, VWV(2), oi->openx.out.file.ntvfs);
413 SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
414 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
415 SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
416 SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
417 SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
418 SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
419 SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
420 SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
421 SSVAL(req->out.vwv, VWV(14),0); /* reserved */
422 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
423 SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
424 SMBSRV_VWV_RESERVED(17, 2);
425 }
426
427 req->chained_fnum = SVAL(req->out.vwv, VWV(2));
428
429 smbsrv_chain_reply(req);
430 }
431
432
433 /****************************************************************************
434 Reply to an open and X.
435 ****************************************************************************/
436 void smbsrv_reply_open_and_X(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
437 {
438 union smb_open *oi;
439
440 /* parse the request */
441 SMBSRV_CHECK_WCT(req, 15);
442 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
443 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
444
445 oi->openx.level = RAW_OPEN_OPENX;
446 oi->openx.in.flags = SVAL(req->in.vwv, VWV(2));
447 oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
448 oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
449 oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
450 oi->openx.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
451 oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
452 oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
453 oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
454
455 req_pull_ascii4(&req->in.bufinfo, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
456
457 if (!oi->openx.in.fname) {
458 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
459 return;
460 }
461
462 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
463 }
464
465
466 /****************************************************************************
467 Reply to a mknew or a create.
468 ****************************************************************************/
469 static void reply_mknew_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
470 {
471 struct smbsrv_request *req;
472 union smb_open *oi;
473
474 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
475
476 /* build the reply */
477 smbsrv_setup_reply(req, 1, 0);
478
479 smbsrv_push_fnum(req->out.vwv, VWV(0), oi->mknew.out.file.ntvfs);
480
481 smbsrv_send_reply(req);
482 }
483
484
485 /****************************************************************************
486 Reply to a mknew or a create.
487 ****************************************************************************/
488 void smbsrv_reply_mknew(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
489 {
490 union smb_open *oi;
491
492 /* parse the request */
493 SMBSRV_CHECK_WCT(req, 3);
494 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
495 SMBSRV_SETUP_NTVFS_REQUEST(reply_mknew_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
496
497 if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
498 oi->mknew.level = RAW_OPEN_MKNEW;
499 } else {
500 oi->mknew.level = RAW_OPEN_CREATE;
501 }
502 oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
503 oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
504
505 req_pull_ascii4(&req->in.bufinfo, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
506
507 if (!oi->mknew.in.fname) {
508 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
509 return;
510 }
511
512 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
513 }
514
515 /****************************************************************************
516 Reply to a create temporary file (async reply)
517 ****************************************************************************/
518 static void reply_ctemp_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
519 {
520 struct smbsrv_request *req;
521 union smb_open *oi;
522
523 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
524
525 /* build the reply */
526 smbsrv_setup_reply(req, 1, 0);
527
528 smbsrv_push_fnum(req->out.vwv, VWV(0), oi->ctemp.out.file.ntvfs);
529
530 /* the returned filename is relative to the directory */
531 req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
532
533 smbsrv_send_reply(req);
534 }
535
536 /****************************************************************************
537 Reply to a create temporary file.
538 ****************************************************************************/
539 void smbsrv_reply_ctemp(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
540 {
541 union smb_open *oi;
542
543 /* parse the request */
544 SMBSRV_CHECK_WCT(req, 3);
545 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
546 SMBSRV_SETUP_NTVFS_REQUEST(reply_ctemp_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
547
548 oi->ctemp.level = RAW_OPEN_CTEMP;
549 oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
550 oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
551
552 /* the filename is actually a directory name, the server provides a filename
553 in that directory */
554 req_pull_ascii4(&req->in.bufinfo, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
555
556 if (!oi->ctemp.in.directory) {
557 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
558 return;
559 }
560
561 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
562 }
563
564
565 /****************************************************************************
566 Reply to a unlink
567 ****************************************************************************/
568 void smbsrv_reply_unlink(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
569 {
570 union smb_unlink *unl;
571
572 /* parse the request */
573 SMBSRV_CHECK_WCT(req, 1);
574 SMBSRV_TALLOC_IO_PTR(unl, union smb_unlink);
575 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
576
577 unl->unlink.in.attrib = SVAL(req->in.vwv, VWV(0));
578
579 req_pull_ascii4(&req->in.bufinfo, &unl->unlink.in.pattern, req->in.data, STR_TERMINATE);
580
581 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_unlink(req->ntvfs, unl));
582 }
583
584
585 /****************************************************************************
586 Reply to a readbraw (core+ protocol).
587 this is a strange packet because it doesn't use a standard SMB header in the reply,
588 only the 4 byte NBT header
589 This command must be replied to synchronously
590 ****************************************************************************/
591 void smbsrv_reply_readbraw(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
592 {
593 NTSTATUS status;
594 union smb_read io;
595
596 io.readbraw.level = RAW_READ_READBRAW;
597
598 /* there are two variants, one with 10 and one with 8 command words */
599 if (req->in.wct < 8) {
600 goto failed;
601 }
602
603 io.readbraw.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
604 io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
605 io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
606 io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
607 io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
608
609 if (!io.readbraw.in.file.ntvfs) {
610 goto failed;
611 }
612
613 /* the 64 bit variant */
614 if (req->in.wct == 10) {
615 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
616 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
617 }
618
619 /* before calling the backend we setup the raw buffer. This
620 * saves a copy later */
621 req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
622 req->out.buffer = talloc_size(req, req->out.size);
623 if (req->out.buffer == NULL) {
624 goto failed;
625 }
626 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
627
628 /* tell the backend where to put the data */
629 io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
630
631 /* prepare the ntvfs request */
632 req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req,
633 req->session->session_info,
634 SVAL(req->in.hdr,HDR_PID),
635 req->request_time,
636 req, NULL, 0);
637 if (!req->ntvfs) {
638 goto failed;
639 }
640
641 /* call the backend */
642 status = ntvfs_read(req->ntvfs, &io);
643 if (!NT_STATUS_IS_OK(status)) {
644 goto failed;
645 }
646
647 req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
648
649 smbsrv_send_reply_nosign(req);
650 return;
651
652 failed:
653 /* any failure in readbraw is equivalent to reading zero bytes */
654 req->out.size = 4;
655 req->out.buffer = talloc_size(req, req->out.size);
656 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
657
658 smbsrv_send_reply_nosign(req);
659 }
660
661
662 /****************************************************************************
663 Reply to a lockread (async reply)
664 ****************************************************************************/
665 static void reply_lockread_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
666 {
667 struct smbsrv_request *req;
668 union smb_read *io;
669
670 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
671
672 /* trim packet */
673 io->lockread.out.nread = MIN(io->lockread.out.nread,
674 req_max_data(req) - 3);
675 req_grow_data(req, 3 + io->lockread.out.nread);
676
677 /* construct reply */
678 SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
679 SMBSRV_VWV_RESERVED(1, 4);
680
681 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
682 SSVAL(req->out.data, 1, io->lockread.out.nread);
683
684 smbsrv_send_reply(req);
685 }
686
687
688 /****************************************************************************
689 Reply to a lockread (core+ protocol).
690 note that the lock is a write lock, not a read lock!
691 ****************************************************************************/
692 void smbsrv_reply_lockread(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
693 {
694 union smb_read *io;
695
696 /* parse request */
697 SMBSRV_CHECK_WCT(req, 5);
698 SMBSRV_TALLOC_IO_PTR(io, union smb_read);
699 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
700
701 io->lockread.level = RAW_READ_LOCKREAD;
702 io->lockread.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
703 io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
704 io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
705 io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
706
707 /* setup the reply packet assuming the maximum possible read */
708 smbsrv_setup_reply(req, 5, 3 + io->lockread.in.count);
709
710 /* tell the backend where to put the data */
711 io->lockread.out.data = req->out.data + 3;
712
713 SMBSRV_CHECK_FILE_HANDLE(io->lockread.in.file.ntvfs);
714 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
715 }
716
717
718
719 /****************************************************************************
720 Reply to a read (async reply)
721 ****************************************************************************/
722 static void reply_read_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
723 {
724 struct smbsrv_request *req;
725 union smb_read *io;
726
727 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
728
729 /* trim packet */
730 io->read.out.nread = MIN(io->read.out.nread,
731 req_max_data(req) - 3);
732 req_grow_data(req, 3 + io->read.out.nread);
733
734 /* construct reply */
735 SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
736 SMBSRV_VWV_RESERVED(1, 4);
737
738 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
739 SSVAL(req->out.data, 1, io->read.out.nread);
740
741 smbsrv_send_reply(req);
742 }
743
744 /****************************************************************************
745 Reply to a read.
746 ****************************************************************************/
747 void smbsrv_reply_read(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
748 {
749 union smb_read *io;
750
751 /* parse request */
752 SMBSRV_CHECK_WCT(req, 5);
753 SMBSRV_TALLOC_IO_PTR(io, union smb_read);
754 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
755
756 io->read.level = RAW_READ_READ;
757 io->read.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
758 io->read.in.count = SVAL(req->in.vwv, VWV(1));
759 io->read.in.offset = IVAL(req->in.vwv, VWV(2));
760 io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
761
762 /* setup the reply packet assuming the maximum possible read */
763 smbsrv_setup_reply(req, 5, 3 + io->read.in.count);
764
765 /* tell the backend where to put the data */
766 io->read.out.data = req->out.data + 3;
767
768 SMBSRV_CHECK_FILE_HANDLE(io->read.in.file.ntvfs);
769 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
770 }
771
772 /****************************************************************************
773 Reply to a read and X (async reply)
774 ****************************************************************************/
775 static void reply_read_and_X_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
776 {
777 struct smbsrv_request *req;
778 union smb_read *io;
779
780 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
781
782 /* readx reply packets can be over-sized */
783 req->control_flags |= SMBSRV_REQ_CONTROL_LARGE;
784 if (io->readx.in.maxcnt != 0xFFFF &&
785 io->readx.in.mincnt != 0xFFFF) {
786 req_grow_data(req, 1 + io->readx.out.nread);
787 SCVAL(req->out.data, 0, 0); /* padding */
788 } else {
789 req_grow_data(req, io->readx.out.nread);
790 }
791
792 /* construct reply */
793 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
794 SSVAL(req->out.vwv, VWV(1), 0);
795 SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
796 SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
797 SMBSRV_VWV_RESERVED(4, 1);
798 SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
799 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
800 SMBSRV_VWV_RESERVED(7, 5);
801
802 smbsrv_chain_reply(req);
803 }
804
805 /****************************************************************************
806 Reply to a read and X.
807 ****************************************************************************/
808 void smbsrv_reply_read_and_X(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
809 {
810 union smb_read *io;
811
812 /* parse request */
813 if (req->in.wct != 12) {
814 SMBSRV_CHECK_WCT(req, 10);
815 }
816
817 SMBSRV_TALLOC_IO_PTR(io, union smb_read);
818 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
819
820 io->readx.level = RAW_READ_READX;
821 io->readx.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(2));
822 io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
823 io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
824 io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
825 io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
826 if (req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) {
827 io->readx.in.read_for_execute = true;
828 } else {
829 io->readx.in.read_for_execute = false;
830 }
831
832 if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
833 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
834 if (high_part == 1) {
835 io->readx.in.maxcnt |= high_part << 16;
836 }
837 }
838
839 /* the 64 bit variant */
840 if (req->in.wct == 12) {
841 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
842 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
843 }
844
845 /* setup the reply packet assuming the maximum possible read */
846 smbsrv_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
847
848 /* tell the backend where to put the data. Notice the pad byte. */
849 if (io->readx.in.maxcnt != 0xFFFF &&
850 io->readx.in.mincnt != 0xFFFF) {
851 io->readx.out.data = req->out.data + 1;
852 } else {
853 io->readx.out.data = req->out.data;
854 }
855
856 SMBSRV_CHECK_FILE_HANDLE(io->readx.in.file.ntvfs);
857 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
858 }
859
860
861 /****************************************************************************
862 Reply to a writebraw (core+ or LANMAN1.0 protocol).
863 ****************************************************************************/
864 void smbsrv_reply_writebraw(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
865 {
866 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
867 }
868
869
870 /****************************************************************************
871 Reply to a writeunlock (async reply)
872 ****************************************************************************/
873 static void reply_writeunlock_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
874 {
875 struct smbsrv_request *req;
876 union smb_write *io;
877
878 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
879
880 /* construct reply */
881 smbsrv_setup_reply(req, 1, 0);
882
883 SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
884
885 smbsrv_send_reply(req);
886 }
887
888 /****************************************************************************
889 Reply to a writeunlock (core+).
890 ****************************************************************************/
891 void smbsrv_reply_writeunlock(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
892 {
893 union smb_write *io;
894
895 SMBSRV_CHECK_WCT(req, 5);
896 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
897 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
898
899 io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
900 io->writeunlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
901 io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
902 io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
903 io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
904 io->writeunlock.in.data = req->in.data + 3;
905
906 /* make sure they gave us the data they promised */
907 if (io->writeunlock.in.count+3 > req->in.data_size) {
908 smbsrv_send_error(req, NT_STATUS_FOOBAR);
909 return;
910 }
911
912 /* make sure the data block is big enough */
913 if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
914 smbsrv_send_error(req, NT_STATUS_FOOBAR);
915 return;
916 }
917
918 SMBSRV_CHECK_FILE_HANDLE(io->writeunlock.in.file.ntvfs);
919 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
920 }
921
922
923
924 /****************************************************************************
925 Reply to a write (async reply)
926 ****************************************************************************/
927 static void reply_write_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
928 {
929 struct smbsrv_request *req;
930 union smb_write *io;
931
932 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
933
934 /* construct reply */
935 smbsrv_setup_reply(req, 1, 0);
936
937 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
938
939 smbsrv_send_reply(req);
940 }
941
942 /****************************************************************************
943 Reply to a write
944 ****************************************************************************/
945 void smbsrv_reply_write(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
946 {
947 union smb_write *io;
948
949 SMBSRV_CHECK_WCT(req, 5);
950 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
951 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
952
953 io->write.level = RAW_WRITE_WRITE;
954 io->write.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
955 io->write.in.count = SVAL(req->in.vwv, VWV(1));
956 io->write.in.offset = IVAL(req->in.vwv, VWV(2));
957 io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
958 io->write.in.data = req->in.data + 3;
959
960 /* make sure they gave us the data they promised */
961 if (req_data_oob(&req->in.bufinfo, io->write.in.data, io->write.in.count)) {
962 smbsrv_send_error(req, NT_STATUS_FOOBAR);
963 return;
964 }
965
966 /* make sure the data block is big enough */
967 if (SVAL(req->in.data, 1) < io->write.in.count) {
968 smbsrv_send_error(req, NT_STATUS_FOOBAR);
969 return;
970 }
971
972 SMBSRV_CHECK_FILE_HANDLE(io->write.in.file.ntvfs);
973 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
974 }
975
976
977 /****************************************************************************
978 Reply to a write and X (async reply)
979 ****************************************************************************/
980 static void reply_write_and_X_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
981 {
982 struct smbsrv_request *req;
983 union smb_write *io;
984
985 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
986
987 /* construct reply */
988 smbsrv_setup_reply(req, 6, 0);
989
990 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
991 SSVAL(req->out.vwv, VWV(1), 0);
992 SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
993 SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
994 SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
995 SMBSRV_VWV_RESERVED(5, 1);
996
997 smbsrv_chain_reply(req);
998 }
999
1000 /****************************************************************************
1001 Reply to a write and X.
1002 ****************************************************************************/
1003 void smbsrv_reply_write_and_X(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1004 {
1005 union smb_write *io;
1006
1007 if (req->in.wct != 14) {
1008 SMBSRV_CHECK_WCT(req, 12);
1009 }
1010
1011 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1012 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1013
1014 io->writex.level = RAW_WRITE_WRITEX;
1015 io->writex.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2));
1016 io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
1017 io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
1018 io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1019 io->writex.in.count = SVAL(req->in.vwv, VWV(10));
1020 io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1021
1022 if (req->in.wct == 14) {
1023 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1024 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1025 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1026 io->writex.in.count |= ((uint32_t)count_high) << 16;
1027 }
1028
1029 /* make sure the data is in bounds */
1030 if (req_data_oob(&req->in.bufinfo, io->writex.in.data, io->writex.in.count)) {
1031 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1032 return;
1033 }
1034
1035 SMBSRV_CHECK_FILE_HANDLE(io->writex.in.file.ntvfs);
1036 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1037 }
1038
1039
1040 /****************************************************************************
1041 Reply to a lseek (async reply)
1042 ****************************************************************************/
1043 static void reply_lseek_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
1044 {
1045 struct smbsrv_request *req;
1046 union smb_seek *io;
1047
1048 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_seek);
1049
1050 /* construct reply */
1051 smbsrv_setup_reply(req, 2, 0);
1052
1053 SIVALS(req->out.vwv, VWV(0), io->lseek.out.offset);
1054
1055 smbsrv_send_reply(req);
1056 }
1057
1058 /****************************************************************************
1059 Reply to a lseek.
1060 ****************************************************************************/
1061 void smbsrv_reply_lseek(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1062 {
1063 union smb_seek *io;
1064
1065 SMBSRV_CHECK_WCT(req, 4);
1066 SMBSRV_TALLOC_IO_PTR(io, union smb_seek);
1067 SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1068
1069 io->lseek.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1070 io->lseek.in.mode = SVAL(req->in.vwv, VWV(1));
1071 io->lseek.in.offset = IVALS(req->in.vwv, VWV(2));
1072
1073 SMBSRV_CHECK_FILE_HANDLE(io->lseek.in.file.ntvfs);
1074 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req->ntvfs, io));
1075 }
1076
1077 /****************************************************************************
1078 Reply to a flush.
1079 ****************************************************************************/
1080 void smbsrv_reply_flush(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1081 {
1082 union smb_flush *io;
1083 uint16_t fnum;
1084
1085 /* parse request */
1086 SMBSRV_CHECK_WCT(req, 1);
1087 SMBSRV_TALLOC_IO_PTR(io, union smb_flush);
1088 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1089
1090 fnum = SVAL(req->in.vwv, VWV(0));
1091 if (fnum == 0xFFFF) {
1092 io->flush_all.level = RAW_FLUSH_ALL;
1093 } else {
1094 io->flush.level = RAW_FLUSH_FLUSH;
1095 io->flush.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1096 SMBSRV_CHECK_FILE_HANDLE(io->flush.in.file.ntvfs);
1097 }
1098
1099 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req->ntvfs, io));
1100 }
1101
1102 /****************************************************************************
1103 Reply to a close
1104
1105 Note that this has to deal with closing a directory opened by NT SMB's.
1106 ****************************************************************************/
1107 void smbsrv_reply_close(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1108 {
1109 union smb_close *io;
1110
1111 /* parse request */
1112 SMBSRV_CHECK_WCT(req, 3);
1113 SMBSRV_TALLOC_IO_PTR(io, union smb_close);
1114 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1115
1116 io->close.level = RAW_CLOSE_CLOSE;
1117 io->close.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1118 io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1119
1120 SMBSRV_CHECK_FILE_HANDLE(io->close.in.file.ntvfs);
1121 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
1122 }
1123
1124
1125 /****************************************************************************
1126 Reply to a writeclose (async reply)
1127 ****************************************************************************/
1128 static void reply_writeclose_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
1129 {
1130 struct smbsrv_request *req;
1131 union smb_write *io;
1132
1133 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
1134
1135 /* construct reply */
1136 smbsrv_setup_reply(req, 1, 0);
1137
1138 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1139
1140 smbsrv_send_reply(req);
1141 }
1142
1143 /****************************************************************************
1144 Reply to a writeclose (Core+ protocol).
1145 ****************************************************************************/
1146 void smbsrv_reply_writeclose(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1147 {
1148 union smb_write *io;
1149
1150 /* this one is pretty weird - the wct can be 6 or 12 */
1151 if (req->in.wct != 12) {
1152 SMBSRV_CHECK_WCT(req, 6);
1153 }
1154
1155 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1156 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1157
1158 io->writeclose.level = RAW_WRITE_WRITECLOSE;
1159 io->writeclose.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1160 io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
1161 io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1162 io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1163 io->writeclose.in.data = req->in.data + 1;
1164
1165 /* make sure they gave us the data they promised */
1166 if (req_data_oob(&req->in.bufinfo, io->writeclose.in.data, io->writeclose.in.count)) {
1167 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1168 return;
1169 }
1170
1171 SMBSRV_CHECK_FILE_HANDLE(io->writeclose.in.file.ntvfs);
1172 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1173 }
1174
1175 /****************************************************************************
1176 Reply to a lock.
1177 ****************************************************************************/
1178 void smbsrv_reply_lock(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1179 {
1180 union smb_lock *lck;
1181
1182 /* parse request */
1183 SMBSRV_CHECK_WCT(req, 5);
1184 SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1185 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1186
1187 lck->lock.level = RAW_LOCK_LOCK;
1188 lck->lock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1189 lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
1190 lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1191
1192 SMBSRV_CHECK_FILE_HANDLE(lck->lock.in.file.ntvfs);
1193 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1194 }
1195
1196
1197 /****************************************************************************
1198 Reply to a unlock.
1199 ****************************************************************************/
1200 void smbsrv_reply_unlock(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1201 {
1202 union smb_lock *lck;
1203
1204 /* parse request */
1205 SMBSRV_CHECK_WCT(req, 5);
1206 SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1207 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1208
1209 lck->unlock.level = RAW_LOCK_UNLOCK;
1210 lck->unlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1211 lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
1212 lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1213
1214 SMBSRV_CHECK_FILE_HANDLE(lck->unlock.in.file.ntvfs);
1215 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1216 }
1217
1218
1219 /****************************************************************************
1220 Reply to a tdis.
1221 ****************************************************************************/
1222 void smbsrv_reply_tdis(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1223 {
1224 struct smbsrv_handle *h, *nh;
1225
1226 SMBSRV_CHECK_WCT(req, 0);
1227
1228 /*
1229 * TODO: cancel all pending requests on this tcon
1230 */
1231
1232 /*
1233 * close all handles on this tcon
1234 */
1235 for (h=req->tcon->handles.list; h; h=nh) {
1236 nh = h->next;
1237 talloc_free(h);
1238 }
1239
1240 /* finally destroy the tcon */
1241 talloc_free(req->tcon);
1242 req->tcon = NULL;
1243
1244 smbsrv_setup_reply(req, 0, 0);
1245 smbsrv_send_reply(req);
1246 }
1247
1248
1249 /****************************************************************************
1250 Reply to a echo. This is one of the few calls that is handled directly (the
1251 backends don't see it at all)
1252 ****************************************************************************/
1253 void smbsrv_reply_echo(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1254 {
1255 uint16_t count;
1256 int i;
1257
1258 SMBSRV_CHECK_WCT(req, 1);
1259
1260 count = SVAL(req->in.vwv, VWV(0));
1261
1262 smbsrv_setup_reply(req, 1, req->in.data_size);
1263
1264 memcpy(req->out.data, req->in.data, req->in.data_size);
1265
1266 for (i=1; i <= count;i++) {
1267 struct smbsrv_request *this_req;
1268
1269 if (i != count) {
1270 this_req = smbsrv_setup_secondary_request(req);
1271 } else {
1272 this_req = req;
1273 }
1274
1275 SSVAL(this_req->out.vwv, VWV(0), i);
1276 smbsrv_send_reply(this_req);
1277 }
1278 }
1279
1280
1281
1282 /****************************************************************************
1283 Reply to a printopen (async reply)
1284 ****************************************************************************/
1285 static void reply_printopen_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
1286 {
1287 struct smbsrv_request *req;
1288 union smb_open *oi;
1289
1290 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
1291
1292 /* construct reply */
1293 smbsrv_setup_reply(req, 1, 0);
1294
1295 smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs);
1296
1297 smbsrv_send_reply(req);
1298 }
1299
1300 /****************************************************************************
1301 Reply to a printopen.
1302 ****************************************************************************/
1303 void smbsrv_reply_printopen(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1304 {
1305 union smb_open *oi;
1306
1307 /* parse request */
1308 SMBSRV_CHECK_WCT(req, 2);
1309 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
1310 SMBSRV_SETUP_NTVFS_REQUEST(reply_printopen_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1311
1312 oi->splopen.level = RAW_OPEN_SPLOPEN;
1313 oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1314 oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
1315
1316 req_pull_ascii4(&req->in.bufinfo, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1317
1318 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
1319 }
1320
1321 /****************************************************************************
1322 Reply to a printclose.
1323 ****************************************************************************/
1324 void smbsrv_reply_printclose(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1325 {
1326 union smb_close *io;
1327
1328 /* parse request */
1329 SMBSRV_CHECK_WCT(req, 3);
1330 SMBSRV_TALLOC_IO_PTR(io, union smb_close);
1331 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1332
1333 io->splclose.level = RAW_CLOSE_SPLCLOSE;
1334 io->splclose.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1335
1336 SMBSRV_CHECK_FILE_HANDLE(io->splclose.in.file.ntvfs);
1337 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
1338 }
1339
1340 /****************************************************************************
1341 Reply to a printqueue.
1342 ****************************************************************************/
1343 static void reply_printqueue_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
1344 {
1345 struct smbsrv_request *req;
1346 union smb_lpq *lpq;
1347 int i, maxcount;
1348 const uint_t el_size = 28;
1349
1350 SMBSRV_CHECK_ASYNC_STATUS(lpq,union smb_lpq);
1351
1352 /* construct reply */
1353 smbsrv_setup_reply(req, 2, 0);
1354
1355 /* truncate the returned list to fit in the negotiated buffer size */
1356 maxcount = (req_max_data(req) - 3) / el_size;
1357 if (maxcount < lpq->retq.out.count) {
1358 lpq->retq.out.count = maxcount;
1359 }
1360
1361 /* setup enough space in the reply */
1362 req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1363
1364 /* and fill it in */
1365 SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1366 SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1367
1368 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1369 SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1370
1371 req->out.ptr = req->out.data + 3;
1372
1373 for (i=0;i<lpq->retq.out.count;i++) {
1374 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1375 SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
1376 SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
1377 SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
1378 SCVAL(req->out.ptr, 11, 0); /* reserved */
1379 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1380 req->out.ptr += el_size;
1381 }
1382
1383 smbsrv_send_reply(req);
1384 }
1385
1386 /****************************************************************************
1387 Reply to a printqueue.
1388 ****************************************************************************/
1389 void smbsrv_reply_printqueue(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1390 {
1391 union smb_lpq *lpq;
1392
1393 /* parse request */
1394 SMBSRV_CHECK_WCT(req, 2);
1395 SMBSRV_TALLOC_IO_PTR(lpq, union smb_lpq);
1396 SMBSRV_SETUP_NTVFS_REQUEST(reply_printqueue_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1397
1398 lpq->retq.level = RAW_LPQ_RETQ;
1399 lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
1400 lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
1401
1402 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lpq(req->ntvfs, lpq));
1403 }
1404
1405
1406 /****************************************************************************
1407 Reply to a printwrite.
1408 ****************************************************************************/
1409 void smbsrv_reply_printwrite(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1410 {
1411 union smb_write *io;
1412
1413 /* parse request */
1414 SMBSRV_CHECK_WCT(req, 1);
1415 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1416 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1417
1418 if (req->in.data_size < 3) {
1419 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1420 return;
1421 }
1422
1423 io->splwrite.level = RAW_WRITE_SPLWRITE;
1424 io->splwrite.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1425 io->splwrite.in.count = SVAL(req->in.data, 1);
1426 io->splwrite.in.data = req->in.data + 3;
1427
1428 /* make sure they gave us the data they promised */
1429 if (req_data_oob(&req->in.bufinfo, io->splwrite.in.data, io->splwrite.in.count)) {
1430 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1431 return;
1432 }
1433
1434 SMBSRV_CHECK_FILE_HANDLE(io->splwrite.in.file.ntvfs);
1435 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1436 }
1437
1438
1439 /****************************************************************************
1440 Reply to a mkdir.
1441 ****************************************************************************/
1442 void smbsrv_reply_mkdir(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1443 {
1444 union smb_mkdir *io;
1445
1446 /* parse the request */
1447 SMBSRV_CHECK_WCT(req, 0);
1448 SMBSRV_TALLOC_IO_PTR(io, union smb_mkdir);
1449 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1450
1451 io->generic.level = RAW_MKDIR_MKDIR;
1452 req_pull_ascii4(&req->in.bufinfo, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1453
1454 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_mkdir(req->ntvfs, io));
1455 }
1456
1457
1458 /****************************************************************************
1459 Reply to a rmdir.
1460 ****************************************************************************/
1461 void smbsrv_reply_rmdir(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1462 {
1463 struct smb_rmdir *io;
1464
1465 /* parse the request */
1466 SMBSRV_CHECK_WCT(req, 0);
1467 SMBSRV_TALLOC_IO_PTR(io, struct smb_rmdir);
1468 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1469
1470 req_pull_ascii4(&req->in.bufinfo, &io->in.path, req->in.data, STR_TERMINATE);
1471
1472 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rmdir(req->ntvfs, io));
1473 }
1474
1475
1476 /****************************************************************************
1477 Reply to a mv.
1478 ****************************************************************************/
1479 void smbsrv_reply_mv(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1480 {
1481 union smb_rename *io;
1482 uint8_t *p;
1483
1484 /* parse the request */
1485 SMBSRV_CHECK_WCT(req, 1);
1486 SMBSRV_TALLOC_IO_PTR(io, union smb_rename);
1487 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1488
1489 io->generic.level = RAW_RENAME_RENAME;
1490 io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1491
1492 p = req->in.data;
1493 p += req_pull_ascii4(&req->in.bufinfo, &io->rename.in.pattern1, p, STR_TERMINATE);
1494 p += req_pull_ascii4(&req->in.bufinfo, &io->rename.in.pattern2, p, STR_TERMINATE);
1495
1496 if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1497 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1498 return;
1499 }
1500
1501 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req->ntvfs, io));
1502 }
1503
1504
1505 /****************************************************************************
1506 Reply to an NT rename.
1507 ****************************************************************************/
1508 void smbsrv_reply_ntrename(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1509 {
1510 union smb_rename *io;
1511 uint8_t *p;
1512
1513 /* parse the request */
1514 SMBSRV_CHECK_WCT(req, 4);
1515 SMBSRV_TALLOC_IO_PTR(io, union smb_rename);
1516 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1517
1518 io->generic.level = RAW_RENAME_NTRENAME;
1519 io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
1520 io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
1521 io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1522
1523 p = req->in.data;
1524 p += req_pull_ascii4(&req->in.bufinfo, &io->ntrename.in.old_name, p, STR_TERMINATE);
1525 p += req_pull_ascii4(&req->in.bufinfo, &io->ntrename.in.new_name, p, STR_TERMINATE);
1526
1527 if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1528 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1529 return;
1530 }
1531
1532 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req->ntvfs, io));
1533 }
1534
1535 /****************************************************************************
1536 Reply to a file copy (async reply)
1537 ****************************************************************************/
1538 static void reply_copy_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
1539 {
1540 struct smbsrv_request *req;
1541 struct smb_copy *cp;
1542
1543 SMBSRV_CHECK_ASYNC_STATUS(cp, struct smb_copy);
1544
1545 /* build the reply */
1546 smbsrv_setup_reply(req, 1, 0);
1547
1548 SSVAL(req->out.vwv, VWV(0), cp->out.count);
1549
1550 smbsrv_send_reply(req);
1551 }
1552
1553 /****************************************************************************
1554 Reply to a file copy.
1555 ****************************************************************************/
1556 void smbsrv_reply_copy(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1557 {
1558 struct smb_copy *cp;
1559 uint8_t *p;
1560
1561 /* parse request */
1562 SMBSRV_CHECK_WCT(req, 3);
1563 SMBSRV_TALLOC_IO_PTR(cp, struct smb_copy);
1564 SMBSRV_SETUP_NTVFS_REQUEST(reply_copy_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1565
1566 cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
1567 cp->in.ofun = SVAL(req->in.vwv, VWV(1));
1568 cp->in.flags = SVAL(req->in.vwv, VWV(2));
1569
1570 p = req->in.data;
1571 p += req_pull_ascii4(&req->in.bufinfo, &cp->in.path1, p, STR_TERMINATE);
1572 p += req_pull_ascii4(&req->in.bufinfo, &cp->in.path2, p, STR_TERMINATE);
1573
1574 if (!cp->in.path1 || !cp->in.path2) {
1575 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1576 return;
1577 }
1578
1579 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_copy(req->ntvfs, cp));
1580 }
1581
1582 /****************************************************************************
1583 Reply to a lockingX request (async send)
1584 ****************************************************************************/
1585 static void reply_lockingX_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
1586 {
1587 struct smbsrv_request *req;
1588 union smb_lock *lck;
1589
1590 SMBSRV_CHECK_ASYNC_STATUS(lck, union smb_lock);
1591
1592 /* if it was an oplock break ack then we only send a reply if
1593 there was an error */
1594 if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1595 talloc_free(req);
1596 return;
1597 }
1598
1599 /* construct reply */
1600 smbsrv_setup_reply(req, 2, 0);
1601
1602 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1603 SSVAL(req->out.vwv, VWV(1), 0);
1604
1605 smbsrv_chain_reply(req);
1606 }
1607
1608
1609 /****************************************************************************
1610 Reply to a lockingX request.
1611 ****************************************************************************/
1612 void smbsrv_reply_lockingX(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1613 {
1614 union smb_lock *lck;
1615 uint_t total_locks, i;
1616 uint_t lck_size;
1617 uint8_t *p;
1618
1619 /* parse request */
1620 SMBSRV_CHECK_WCT(req, 8);
1621 SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1622 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1623
1624 lck->lockx.level = RAW_LOCK_LOCKX;
1625 lck->lockx.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2));
1626 lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
1627 lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
1628 lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1629 lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
1630
1631 total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1632
1633 /* there are two variants, one with 64 bit offsets and counts */
1634 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1635 lck_size = 20;
1636 } else {
1637 lck_size = 10;
1638 }
1639
1640 /* make sure we got the promised data */
1641 if (req_data_oob(&req->in.bufinfo, req->in.data, total_locks * lck_size)) {
1642 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1643 return;
1644 }
1645
1646 /* allocate the locks array */
1647 if (total_locks) {
1648 lck->lockx.in.locks = talloc_array(req, struct smb_lock_entry,
1649 total_locks);
1650 if (lck->lockx.in.locks == NULL) {
1651 smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1652 return;
1653 }
1654 }
1655
1656 p = req->in.data;
1657
1658 /* construct the locks array */
1659 for (i=0;i<total_locks;i++) {
1660 uint32_t ofs_high=0, count_high=0;
1661
1662 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1663
1664 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1665 ofs_high = IVAL(p, 4);
1666 lck->lockx.in.locks[i].offset = IVAL(p, 8);
1667 count_high = IVAL(p, 12);
1668 lck->lockx.in.locks[i].count = IVAL(p, 16);
1669 } else {
1670 lck->lockx.in.locks[i].offset = IVAL(p, 2);
1671 lck->lockx.in.locks[i].count = IVAL(p, 6);
1672 }
1673 if (ofs_high != 0 || count_high != 0) {
1674 lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
1675 lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1676 }
1677 p += lck_size;
1678 }
1679
1680 SMBSRV_CHECK_FILE_HANDLE(lck->lockx.in.file.ntvfs);
1681 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1682 }
1683
1684 /****************************************************************************
1685 Reply to a SMBreadbmpx (read block multiplex) request.
1686 ****************************************************************************/
1687 void smbsrv_reply_readbmpx(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1688 {
1689 /* tell the client to not use a multiplexed read - its too broken to use */
1690 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1691 }
1692
1693
1694 /****************************************************************************
1695 Reply to a SMBsetattrE.
1696 ****************************************************************************/
1697 void smbsrv_reply_setattrE(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1698 {
1699 union smb_setfileinfo *info;
1700
1701 /* parse request */
1702 SMBSRV_CHECK_WCT(req, 7);
1703 SMBSRV_TALLOC_IO_PTR(info, union smb_setfileinfo);
1704 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1705
1706 info->setattre.level = RAW_SFILEINFO_SETATTRE;
1707 info->setattre.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1708 info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1709 info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1710 info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1711
1712 SMBSRV_CHECK_FILE_HANDLE(info->setattre.in.file.ntvfs);
1713 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req->ntvfs, info));
1714 }
1715
1716
1717 /****************************************************************************
1718 Reply to a SMBwritebmpx (write block multiplex primary) request.
1719 ****************************************************************************/
1720 void smbsrv_reply_writebmpx(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1721 {
1722 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1723 }
1724
1725
1726 /****************************************************************************
1727 Reply to a SMBwritebs (write block multiplex secondary) request.
1728 ****************************************************************************/
1729 void smbsrv_reply_writebs(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1730 {
1731 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1732 }
1733
1734
1735
1736 /****************************************************************************
1737 Reply to a SMBgetattrE (async reply)
1738 ****************************************************************************/
1739 static void reply_getattrE_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
1740 {
1741 struct smbsrv_request *req;
1742 union smb_fileinfo *info;
1743
1744 SMBSRV_CHECK_ASYNC_STATUS(info, union smb_fileinfo);
1745
1746 /* setup reply */
1747 smbsrv_setup_reply(req, 11, 0);
1748
1749 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1750 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1751 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1752 SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
1753 SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
1754 SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
1755
1756 smbsrv_send_reply(req);
1757 }
1758
1759 /****************************************************************************
1760 Reply to a SMBgetattrE.
1761 ****************************************************************************/
1762 void smbsrv_reply_getattrE(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1763 {
1764 union smb_fileinfo *info;
1765
1766 /* parse request */
1767 SMBSRV_CHECK_WCT(req, 1);
1768 SMBSRV_TALLOC_IO_PTR(info, union smb_fileinfo);
1769 SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1770
1771 info->getattr.level = RAW_FILEINFO_GETATTRE;
1772 info->getattr.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
1773
1774 SMBSRV_CHECK_FILE_HANDLE(info->getattr.in.file.ntvfs);
1775 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req->ntvfs, info));
1776 }
1777
1778 void smbsrv_reply_sesssetup_send(struct smbsrv_request *req,
/* [<][>][^][v][top][bottom][index][help] */
1779 union smb_sesssetup *io,
1780 NTSTATUS status)
1781 {
1782 switch (io->old.level) {
1783 case RAW_SESSSETUP_OLD:
1784 if (!NT_STATUS_IS_OK(status)) {
1785 smbsrv_send_error(req, status);
1786 return;
1787 }
1788
1789 /* construct reply */
1790 smbsrv_setup_reply(req, 3, 0);
1791
1792 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1793 SSVAL(req->out.vwv, VWV(1), 0);
1794 SSVAL(req->out.vwv, VWV(2), io->old.out.action);
1795
1796 SSVAL(req->out.hdr, HDR_UID, io->old.out.vuid);
1797
1798 smbsrv_chain_reply(req);
1799 return;
1800
1801 case RAW_SESSSETUP_NT1:
1802 if (!NT_STATUS_IS_OK(status)) {
1803 smbsrv_send_error(req, status);
1804 return;
1805 }
1806
1807 /* construct reply */
1808 smbsrv_setup_reply(req, 3, 0);
1809
1810 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1811 SSVAL(req->out.vwv, VWV(1), 0);
1812 SSVAL(req->out.vwv, VWV(2), io->nt1.out.action);
1813
1814 SSVAL(req->out.hdr, HDR_UID, io->nt1.out.vuid);
1815
1816 req_push_str(req, NULL, io->nt1.out.os, -1, STR_TERMINATE);
1817 req_push_str(req, NULL, io->nt1.out.lanman, -1, STR_TERMINATE);
1818 req_push_str(req, NULL, io->nt1.out.domain, -1, STR_TERMINATE);
1819
1820 smbsrv_chain_reply(req);
1821 return;
1822
1823 case RAW_SESSSETUP_SPNEGO:
1824 if (!NT_STATUS_IS_OK(status) &&
1825 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1826 smbsrv_send_error(req, status);
1827 return;
1828 }
1829
1830 /* construct reply */
1831 smbsrv_setup_reply(req, 4, io->spnego.out.secblob.length);
1832
1833 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1834 smbsrv_setup_error(req, status);
1835 }
1836
1837 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1838 SSVAL(req->out.vwv, VWV(1), 0);
1839 SSVAL(req->out.vwv, VWV(2), io->spnego.out.action);
1840 SSVAL(req->out.vwv, VWV(3), io->spnego.out.secblob.length);
1841
1842 SSVAL(req->out.hdr, HDR_UID, io->spnego.out.vuid);
1843
1844 memcpy(req->out.data, io->spnego.out.secblob.data, io->spnego.out.secblob.length);
1845 req_push_str(req, NULL, io->spnego.out.os, -1, STR_TERMINATE);
1846 req_push_str(req, NULL, io->spnego.out.lanman, -1, STR_TERMINATE);
1847 req_push_str(req, NULL, io->spnego.out.workgroup, -1, STR_TERMINATE);
1848
1849 smbsrv_chain_reply(req);
1850 return;
1851
1852 case RAW_SESSSETUP_SMB2:
1853 break;
1854 }
1855
1856 smbsrv_send_error(req, NT_STATUS_INTERNAL_ERROR);
1857 }
1858
1859 /****************************************************************************
1860 reply to an old style session setup command
1861 ****************************************************************************/
1862 static void reply_sesssetup_old(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1863 {
1864 uint8_t *p;
1865 uint16_t passlen;
1866 union smb_sesssetup *io;
1867
1868 SMBSRV_TALLOC_IO_PTR(io, union smb_sesssetup);
1869
1870 io->old.level = RAW_SESSSETUP_OLD;
1871
1872 /* parse request */
1873 io->old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1874 io->old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1875 io->old.in.vc_num = SVAL(req->in.vwv, VWV(4));
1876 io->old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1877 passlen = SVAL(req->in.vwv, VWV(7));
1878
1879 /* check the request isn't malformed */
1880 if (req_data_oob(&req->in.bufinfo, req->in.data, passlen)) {
1881 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1882 return;
1883 }
1884
1885 p = req->in.data;
1886 if (!req_pull_blob(&req->in.bufinfo, p, passlen, &io->old.in.password)) {
1887 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1888 return;
1889 }
1890 p += passlen;
1891
1892 p += req_pull_string(&req->in.bufinfo, &io->old.in.user, p, -1, STR_TERMINATE);
1893 p += req_pull_string(&req->in.bufinfo, &io->old.in.domain, p, -1, STR_TERMINATE);
1894 p += req_pull_string(&req->in.bufinfo, &io->old.in.os, p, -1, STR_TERMINATE);
1895 p += req_pull_string(&req->in.bufinfo, &io->old.in.lanman, p, -1, STR_TERMINATE);
1896
1897 /* call the generic handler */
1898 smbsrv_sesssetup_backend(req, io);
1899 }
1900
1901 /****************************************************************************
1902 reply to an NT1 style session setup command
1903 ****************************************************************************/
1904 static void reply_sesssetup_nt1(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1905 {
1906 uint8_t *p;
1907 uint16_t passlen1, passlen2;
1908 union smb_sesssetup *io;
1909
1910 SMBSRV_TALLOC_IO_PTR(io, union smb_sesssetup);
1911
1912 io->nt1.level = RAW_SESSSETUP_NT1;
1913
1914 /* parse request */
1915 io->nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
1916 io->nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1917 io->nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
1918 io->nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
1919 passlen1 = SVAL(req->in.vwv, VWV(7));
1920 passlen2 = SVAL(req->in.vwv, VWV(8));
1921 io->nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
1922
1923 /* check the request isn't malformed */
1924 if (req_data_oob(&req->in.bufinfo, req->in.data, passlen1) ||
1925 req_data_oob(&req->in.bufinfo, req->in.data + passlen1, passlen2)) {
1926 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1927 return;
1928 }
1929
1930 p = req->in.data;
1931 if (!req_pull_blob(&req->in.bufinfo, p, passlen1, &io->nt1.in.password1)) {
1932 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1933 return;
1934 }
1935 p += passlen1;
1936 if (!req_pull_blob(&req->in.bufinfo, p, passlen2, &io->nt1.in.password2)) {
1937 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1938 return;
1939 }
1940 p += passlen2;
1941
1942 p += req_pull_string(&req->in.bufinfo, &io->nt1.in.user, p, -1, STR_TERMINATE);
1943 p += req_pull_string(&req->in.bufinfo, &io->nt1.in.domain, p, -1, STR_TERMINATE);
1944 p += req_pull_string(&req->in.bufinfo, &io->nt1.in.os, p, -1, STR_TERMINATE);
1945 p += req_pull_string(&req->in.bufinfo, &io->nt1.in.lanman, p, -1, STR_TERMINATE);
1946
1947 /* call the generic handler */
1948 smbsrv_sesssetup_backend(req, io);
1949 }
1950
1951
1952 /****************************************************************************
1953 reply to an SPNEGO style session setup command
1954 ****************************************************************************/
1955 static void reply_sesssetup_spnego(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1956 {
1957 uint8_t *p;
1958 uint16_t blob_len;
1959 union smb_sesssetup *io;
1960
1961 SMBSRV_TALLOC_IO_PTR(io, union smb_sesssetup);
1962
1963 io->spnego.level = RAW_SESSSETUP_SPNEGO;
1964
1965 /* parse request */
1966 io->spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
1967 io->spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1968 io->spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
1969 io->spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
1970 blob_len = SVAL(req->in.vwv, VWV(7));
1971 io->spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
1972
1973 p = req->in.data;
1974 if (!req_pull_blob(&req->in.bufinfo, p, blob_len, &io->spnego.in.secblob)) {
1975 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1976 return;
1977 }
1978 p += blob_len;
1979
1980 p += req_pull_string(&req->in.bufinfo, &io->spnego.in.os, p, -1, STR_TERMINATE);
1981 p += req_pull_string(&req->in.bufinfo, &io->spnego.in.lanman, p, -1, STR_TERMINATE);
1982 p += req_pull_string(&req->in.bufinfo, &io->spnego.in.workgroup, p, -1, STR_TERMINATE);
1983
1984 /* call the generic handler */
1985 smbsrv_sesssetup_backend(req, io);
1986 }
1987
1988
1989 /****************************************************************************
1990 reply to a session setup command
1991 ****************************************************************************/
1992 void smbsrv_reply_sesssetup(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1993 {
1994 switch (req->in.wct) {
1995 case 10:
1996 /* a pre-NT1 call */
1997 reply_sesssetup_old(req);
1998 return;
1999 case 13:
2000 /* a NT1 call */
2001 reply_sesssetup_nt1(req);
2002 return;
2003 case 12:
2004 /* a SPNEGO call */
2005 reply_sesssetup_spnego(req);
2006 return;
2007 }
2008
2009 /* unsupported variant */
2010 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2011 }
2012
2013 /****************************************************************************
2014 Reply to a exit. This closes all files open by a smbpid
2015 ****************************************************************************/
2016 void smbsrv_reply_exit(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2017 {
2018 struct smbsrv_handle_session_item *i, *ni;
2019 struct smbsrv_handle *h;
2020 struct smbsrv_tcon *tcon;
2021 uint16_t smbpid;
2022
2023 SMBSRV_CHECK_WCT(req, 0);
2024
2025 smbpid = SVAL(req->in.hdr,HDR_PID);
2026
2027 /* first destroy all handles, which have the same PID as the request */
2028 for (i=req->session->handles; i; i=ni) {
2029 ni = i->next;
2030 h = i->handle;
2031 if (h->smbpid != smbpid) continue;
2032
2033 talloc_free(h);
2034 }
2035
2036 /*
2037 * then let the ntvfs backends proxy the call if they want to,
2038 * but we didn't check the return value of the backends,
2039 * as for the SMB client the call succeed
2040 */
2041 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
2042 req->tcon = tcon;
2043 SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
2044 ntvfs_exit(req->ntvfs);
2045 talloc_free(req->ntvfs);
2046 req->ntvfs = NULL;
2047 req->tcon = NULL;
2048 }
2049
2050 smbsrv_setup_reply(req, 0, 0);
2051 smbsrv_send_reply(req);
2052 }
2053
2054 /****************************************************************************
2055 Reply to a SMBulogoffX.
2056 ****************************************************************************/
2057 void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2058 {
2059 struct smbsrv_handle_session_item *i, *ni;
2060 struct smbsrv_handle *h;
2061 struct smbsrv_tcon *tcon;
2062
2063 SMBSRV_CHECK_WCT(req, 2);
2064
2065 /*
2066 * TODO: cancel all pending requests
2067 */
2068
2069
2070 /* destroy all handles */
2071 for (i=req->session->handles; i; i=ni) {
2072 ni = i->next;
2073 h = i->handle;
2074 talloc_free(h);
2075 }
2076
2077 /*
2078 * then let the ntvfs backends proxy the call if they want to,
2079 * but we didn't check the return value of the backends,
2080 * as for the SMB client the call succeed
2081 */
2082 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
2083 req->tcon = tcon;
2084 SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
2085 ntvfs_logoff(req->ntvfs);
2086 talloc_free(req->ntvfs);
2087 req->ntvfs = NULL;
2088 req->tcon = NULL;
2089 }
2090
2091 talloc_free(req->session);
2092 req->session = NULL; /* it is now invalid, don't use on
2093 any chained packets */
2094
2095 smbsrv_setup_reply(req, 2, 0);
2096
2097 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2098 SSVAL(req->out.vwv, VWV(1), 0);
2099
2100 smbsrv_chain_reply(req);
2101 }
2102
2103 /****************************************************************************
2104 Reply to an SMBfindclose request
2105 ****************************************************************************/
2106 void smbsrv_reply_findclose(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2107 {
2108 union smb_search_close *io;
2109
2110 /* parse request */
2111 SMBSRV_CHECK_WCT(req, 1);
2112 SMBSRV_TALLOC_IO_PTR(io, union smb_search_close);
2113 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
2114
2115 io->findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2116 io->findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2117
2118 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_close(req->ntvfs, io));
2119 }
2120
2121 /****************************************************************************
2122 Reply to an SMBfindnclose request
2123 ****************************************************************************/
2124 void smbsrv_reply_findnclose(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2125 {
2126 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2127 }
2128
2129
2130 /****************************************************************************
2131 Reply to an SMBntcreateX request (async send)
2132 ****************************************************************************/
2133 static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs)
/* [<][>][^][v][top][bottom][index][help] */
2134 {
2135 struct smbsrv_request *req;
2136 union smb_open *io;
2137
2138 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_open);
2139
2140 /* construct reply */
2141 smbsrv_setup_reply(req, 34, 0);
2142
2143 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2144 SSVAL(req->out.vwv, VWV(1), 0);
2145 SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2146
2147 /* the rest of the parameters are not aligned! */
2148 smbsrv_push_fnum(req->out.vwv, 5, io->ntcreatex.out.file.ntvfs);
2149 SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
2150 push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2151 push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2152 push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2153 push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2154 SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
2155 SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
2156 SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
2157 SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
2158 SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
2159 SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
2160
2161 req->chained_fnum = SVAL(req->out.vwv, 5);
2162
2163 smbsrv_chain_reply(req);
2164 }
2165
2166 /****************************************************************************
2167 Reply to an SMBntcreateX request
2168 ****************************************************************************/
2169 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2170 {
2171 union smb_open *io;
2172 uint16_t fname_len;
2173
2174 /* parse the request */
2175 SMBSRV_CHECK_WCT(req, 24);
2176 SMBSRV_TALLOC_IO_PTR(io, union smb_open);
2177 SMBSRV_SETUP_NTVFS_REQUEST(reply_ntcreate_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
2178
2179 io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2180
2181 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2182 fname_len = SVAL(req->in.vwv, 5);
2183 io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
2184 io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
2185 io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
2186 io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
2187 io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
2188 io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
2189 io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2190 io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
2191 io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
2192 io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
2193 io->ntcreatex.in.ea_list = NULL;
2194 io->ntcreatex.in.sec_desc = NULL;
2195 io->ntcreatex.in.query_maximal_access = false;
2196
2197 /* we use a couple of bits of the create options internally */
2198 if (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_PRIVATE_MASK) {
2199 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
2200 return;
2201 }
2202
2203 /* we need a neater way to handle this alignment */
2204 if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
2205 ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2206 fname_len++;
2207 }
2208
2209 req_pull_string(&req->in.bufinfo, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2210 if (!io->ntcreatex.in.fname) {
2211 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2212 return;
2213 }
2214
2215 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
2216 }
2217
2218
2219 /****************************************************************************
2220 Reply to an SMBntcancel request
2221 ****************************************************************************/
2222 void smbsrv_reply_ntcancel(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2223 {
2224 struct smbsrv_request *r;
2225 uint16_t tid = SVAL(req->in.hdr,HDR_TID);
2226 uint16_t uid = SVAL(req->in.hdr,HDR_UID);
2227 uint16_t mid = SVAL(req->in.hdr,HDR_MID);
2228 uint16_t pid = SVAL(req->in.hdr,HDR_PID);
2229
2230 for (r = req->smb_conn->requests; r; r = r->next) {
2231 if (tid != SVAL(r->in.hdr,HDR_TID)) continue;
2232 if (uid != SVAL(r->in.hdr,HDR_UID)) continue;
2233 if (mid != SVAL(r->in.hdr,HDR_MID)) continue;
2234 if (pid != SVAL(r->in.hdr,HDR_PID)) continue;
2235
2236 SMBSRV_CHECK(ntvfs_cancel(r->ntvfs));
2237
2238 /* NOTE: this request does not generate a reply */
2239 talloc_free(req);
2240 return;
2241 }
2242
2243 /* TODO: workout the correct error code,
2244 * until we know how the smb signing works
2245 * for ntcancel replies, don't send an error
2246 */
2247 /*smbsrv_send_error(req, NT_STATUS_FOOBAR);*/
2248 talloc_free(req);
2249 }
2250
2251 /*
2252 parse the called/calling names from session request
2253 */
2254 static NTSTATUS parse_session_request(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2255 {
2256 DATA_BLOB blob;
2257 NTSTATUS status;
2258
2259 blob.data = req->in.buffer + 4;
2260 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2261 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2262
2263 req->smb_conn->negotiate.called_name = talloc(req->smb_conn, struct nbt_name);
2264 req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2265 if (req->smb_conn->negotiate.called_name == NULL ||
2266 req->smb_conn->negotiate.calling_name == NULL) {
2267 return NT_STATUS_NO_MEMORY;
2268 }
2269
2270 status = nbt_name_from_blob(req->smb_conn, &blob,
2271 req->smb_conn->negotiate.called_name);
2272 NT_STATUS_NOT_OK_RETURN(status);
2273
2274 blob.data += blob.length;
2275 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2276 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2277
2278 status = nbt_name_from_blob(req->smb_conn, &blob,
2279 req->smb_conn->negotiate.calling_name);
2280 NT_STATUS_NOT_OK_RETURN(status);
2281
2282 req->smb_conn->negotiate.done_nbt_session = true;
2283
2284 return NT_STATUS_OK;
2285 }
2286
2287
2288
2289 /****************************************************************************
2290 Reply to a special message - a SMB packet with non zero NBT message type
2291 ****************************************************************************/
2292 void smbsrv_reply_special(struct smbsrv_request *req)
/* [<][>][^][v][top][bottom][index][help] */
2293 {
2294 uint8_t msg_type;
2295 uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2296
2297 msg_type = CVAL(req->in.buffer,0);
2298
2299 SIVAL(buf, 0, 0);
2300
2301 switch (msg_type) {
2302 case 0x81: /* session request */
2303 if (req->smb_conn->negotiate.done_nbt_session) {
2304 DEBUG(0,("Warning: ignoring secondary session request\n"));
2305 return;
2306 }
2307
2308 SCVAL(buf,0,0x82);
2309 SCVAL(buf,3,0);
2310
2311 /* we don't check the status - samba always accepts session
2312 requests for any name */
2313 parse_session_request(req);
2314
2315 req->out.buffer = buf;
2316 req->out.size = 4;
2317 smbsrv_send_reply_nosign(req);
2318 return;
2319
2320 case 0x89: /* session keepalive request
2321 (some old clients produce this?) */
2322 SCVAL(buf, 0, SMBkeepalive);
2323 SCVAL(buf, 3, 0);
2324 req->out.buffer = buf;
2325 req->out.size = 4;
2326 smbsrv_send_reply_nosign(req);
2327 return;
2328
2329 case SMBkeepalive:
2330 /* session keepalive - swallow it */
2331 talloc_free(req);
2332 return;
2333 }
2334
2335 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));
2336 talloc_free(req);
2337 }