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