source: trunk/server/source4/smb_server/smb/reply.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

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