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