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