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