r4100: fix drsuapi_DsReplicaObjMetaData2() idl
[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         uint8_t *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         uint8_t *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         if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
560                 oi->mknew.level = RAW_OPEN_MKNEW;
561         } else {
562                 oi->mknew.level = RAW_OPEN_CREATE;
563         }
564         oi->mknew.in.attrib  = SVAL(req->in.vwv, VWV(0));
565         oi->mknew.in.write_time  = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
566
567         req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
568
569         if (!oi->mknew.in.fname) {
570                 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
571                 return;
572         }
573
574         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
575         req->async_states->send_fn = reply_mknew_send;
576         req->async_states->private_data = oi;
577
578         /* call the backend */
579         req->async_states->status = ntvfs_openfile(req, oi);
580
581         REQ_ASYNC_TAIL;
582 }
583
584 /****************************************************************************
585  Reply to a create temporary file (async reply)
586 ****************************************************************************/
587 static void reply_ctemp_send(struct smbsrv_request *req)
588 {
589         union smb_open *oi = req->async_states->private_data;
590
591         CHECK_ASYNC_STATUS;
592
593         /* build the reply */
594         req_setup_reply(req, 1, 0);
595
596         SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
597
598         /* the returned filename is relative to the directory */
599         req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
600
601         req_send_reply(req);
602 }
603
604 /****************************************************************************
605  Reply to a create temporary file.
606 ****************************************************************************/
607 void reply_ctemp(struct smbsrv_request *req)
608 {
609         union smb_open *oi;
610
611         /* parse the request */
612         REQ_CHECK_WCT(req, 3);
613         REQ_TALLOC(oi, sizeof(*oi));
614
615         oi->ctemp.level = RAW_OPEN_CTEMP;
616         oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
617         oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
618
619         /* the filename is actually a directory name, the server provides a filename
620            in that directory */
621         req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
622
623         if (!oi->ctemp.in.directory) {
624                 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
625                 return;
626         }
627
628         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
629         req->async_states->send_fn = reply_ctemp_send;
630         req->async_states->private_data = oi;
631
632         /* call the backend */
633         req->async_states->status = ntvfs_openfile(req, oi);
634
635         REQ_ASYNC_TAIL;
636 }
637
638
639 /****************************************************************************
640  Reply to a unlink
641 ****************************************************************************/
642 void reply_unlink(struct smbsrv_request *req)
643 {
644         struct smb_unlink *unl;
645
646         /* parse the request */
647         REQ_CHECK_WCT(req, 1);
648         REQ_TALLOC(unl, sizeof(*unl));
649         
650         unl->in.attrib = SVAL(req->in.vwv, VWV(0));
651
652         req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
653         
654         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
655         req->async_states->send_fn = reply_simple_send;
656
657         /* call backend */
658         req->async_states->status = ntvfs_unlink(req, unl);
659
660         REQ_ASYNC_TAIL;
661 }
662
663
664 /****************************************************************************
665  Reply to a readbraw (core+ protocol).
666  this is a strange packet because it doesn't use a standard SMB header in the reply,
667  only the 4 byte NBT header
668  This command must be replied to synchronously
669 ****************************************************************************/
670 void reply_readbraw(struct smbsrv_request *req)
671 {
672         NTSTATUS status;
673         union smb_read io;
674
675         io.readbraw.level = RAW_READ_READBRAW;
676
677         /* there are two variants, one with 10 and one with 8 command words */
678         if (req->in.wct < 8) {
679                 goto failed;
680         }
681
682         io.readbraw.in.fnum    = req_fnum(req, req->in.vwv, VWV(0));
683         io.readbraw.in.offset  = IVAL(req->in.vwv, VWV(1));
684         io.readbraw.in.maxcnt  = SVAL(req->in.vwv, VWV(3));
685         io.readbraw.in.mincnt  = SVAL(req->in.vwv, VWV(4));
686         io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
687
688         /* the 64 bit variant */
689         if (req->in.wct == 10) {
690                 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
691                 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
692         }
693
694         /* before calling the backend we setup the raw buffer. This
695          * saves a copy later */
696         req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
697         req->out.buffer = talloc(req, req->out.size);
698         if (req->out.buffer == NULL) {
699                 goto failed;
700         }
701         SIVAL(req->out.buffer, 0, 0); /* init NBT header */
702
703         /* tell the backend where to put the data */
704         io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
705
706         /* call the backend */
707         status = ntvfs_read(req, &io);
708
709         if (!NT_STATUS_IS_OK(status)) {
710                 goto failed;
711         }
712
713         req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
714
715         req_send_reply_nosign(req);
716         return;
717
718 failed:
719         /* any failure in readbraw is equivalent to reading zero bytes */
720         req->out.size = 4;
721         req->out.buffer = talloc(req, req->out.size);
722         SIVAL(req->out.buffer, 0, 0); /* init NBT header */
723
724         req_send_reply_nosign(req);
725 }
726
727
728 /****************************************************************************
729  Reply to a lockread (async reply)
730 ****************************************************************************/
731 static void reply_lockread_send(struct smbsrv_request *req)
732 {
733         union smb_read *io = req->async_states->private_data;
734
735         CHECK_ASYNC_STATUS;
736
737         /* trim packet */
738         io->lockread.out.nread = MIN(io->lockread.out.nread,
739                 req_max_data(req) - 3);
740         req_grow_data(req, 3 + io->lockread.out.nread);
741
742         /* construct reply */
743         SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
744         REQ_VWV_RESERVED(1, 4);
745
746         SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
747         SSVAL(req->out.data, 1, io->lockread.out.nread);
748
749         req_send_reply(req);
750 }
751
752
753 /****************************************************************************
754  Reply to a lockread (core+ protocol).
755  note that the lock is a write lock, not a read lock!
756 ****************************************************************************/
757 void reply_lockread(struct smbsrv_request *req)
758 {
759         union smb_read *io;
760         
761         /* parse request */
762         REQ_CHECK_WCT(req, 5);
763         REQ_TALLOC(io, sizeof(*io));
764
765         io->lockread.level = RAW_READ_LOCKREAD;
766         io->lockread.in.fnum      = req_fnum(req, req->in.vwv, VWV(0));
767         io->lockread.in.count     = SVAL(req->in.vwv, VWV(1));
768         io->lockread.in.offset    = IVAL(req->in.vwv, VWV(2));
769         io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
770         
771         /* setup the reply packet assuming the maximum possible read */
772         req_setup_reply(req, 5, 3 + io->lockread.in.count);
773
774         /* tell the backend where to put the data */
775         io->lockread.out.data = req->out.data + 3;
776
777         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
778         req->async_states->send_fn = reply_lockread_send;
779         req->async_states->private_data = io;
780
781         /* call backend */
782         req->async_states->status = ntvfs_read(req, io);
783
784         REQ_ASYNC_TAIL;
785 }
786
787
788
789 /****************************************************************************
790  Reply to a read (async reply)
791 ****************************************************************************/
792 static void reply_read_send(struct smbsrv_request *req)
793 {
794         union smb_read *io = req->async_states->private_data;
795
796         CHECK_ASYNC_STATUS;
797
798         /* trim packet */
799         io->read.out.nread = MIN(io->read.out.nread,
800                 req_max_data(req) - 3);
801         req_grow_data(req, 3 + io->read.out.nread);
802
803         /* construct reply */
804         SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
805         REQ_VWV_RESERVED(1, 4);
806
807         SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
808         SSVAL(req->out.data, 1, io->read.out.nread);
809
810         req_send_reply(req);
811 }
812
813 /****************************************************************************
814  Reply to a read.
815 ****************************************************************************/
816 void reply_read(struct smbsrv_request *req)
817 {
818         union smb_read *io;
819
820         /* parse request */
821         REQ_CHECK_WCT(req, 5);
822         REQ_TALLOC(io, sizeof(*io));
823         
824         io->read.level = RAW_READ_READ;
825         io->read.in.fnum          = req_fnum(req, req->in.vwv, VWV(0));
826         io->read.in.count         = SVAL(req->in.vwv, VWV(1));
827         io->read.in.offset        = IVAL(req->in.vwv, VWV(2));
828         io->read.in.remaining     = SVAL(req->in.vwv, VWV(4));
829         
830         /* setup the reply packet assuming the maximum possible read */
831         req_setup_reply(req, 5, 3 + io->read.in.count);
832
833         /* tell the backend where to put the data */
834         io->read.out.data = req->out.data + 3;
835
836         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
837         req->async_states->send_fn = reply_read_send;
838         req->async_states->private_data = io;
839
840         /* call backend */
841         req->async_states->status = ntvfs_read(req, io);
842
843         REQ_ASYNC_TAIL;
844 }
845
846
847
848 /****************************************************************************
849  Reply to a read and X (async reply)
850 ****************************************************************************/
851 static void reply_read_and_X_send(struct smbsrv_request *req)
852 {
853         union smb_read *io = req->async_states->private_data;
854
855         CHECK_ASYNC_STATUS;
856
857         /* readx reply packets can be over-sized */
858         req->control_flags |= REQ_CONTROL_LARGE;
859         if (io->readx.in.maxcnt != 0xFFFF &&
860             io->readx.in.mincnt != 0xFFFF) {
861                 req_grow_data(req, 1 + io->readx.out.nread);
862                 SCVAL(req->out.data, 0, 0); /* padding */
863         } else {
864                 req_grow_data(req, io->readx.out.nread);
865         }
866
867         /* construct reply */
868         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
869         SSVAL(req->out.vwv, VWV(1), 0);
870         SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
871         SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
872         REQ_VWV_RESERVED(4, 1);
873         SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
874         SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
875         REQ_VWV_RESERVED(7, 5);
876
877         chain_reply(req);
878 }
879
880 /****************************************************************************
881  Reply to a read and X.
882 ****************************************************************************/
883 void reply_read_and_X(struct smbsrv_request *req)
884 {
885         union smb_read *io;
886
887         /* parse request */
888         if (req->in.wct != 12) {
889                 REQ_CHECK_WCT(req, 10);
890         }
891
892         REQ_TALLOC(io, sizeof(*io));
893
894         io->readx.level = RAW_READ_READX;
895         io->readx.in.fnum          = req_fnum(req, req->in.vwv, VWV(2));
896         io->readx.in.offset        = IVAL(req->in.vwv, VWV(3));
897         io->readx.in.maxcnt        = SVAL(req->in.vwv, VWV(5));
898         io->readx.in.mincnt        = SVAL(req->in.vwv, VWV(6));
899         io->readx.in.remaining     = SVAL(req->in.vwv, VWV(9));
900
901         if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
902                 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
903                 if (high_part == 1) {
904                         io->readx.in.maxcnt |= high_part << 16;
905                 }
906         }
907         
908         /* the 64 bit variant */
909         if (req->in.wct == 12) {
910                 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
911                 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
912         }
913
914         /* setup the reply packet assuming the maximum possible read */
915         req_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
916
917         /* tell the backend where to put the data. Notice the pad byte. */
918         if (io->readx.in.maxcnt != 0xFFFF &&
919             io->readx.in.mincnt != 0xFFFF) {
920                 io->readx.out.data = req->out.data + 1;
921         } else {
922                 io->readx.out.data = req->out.data;
923         }
924
925         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
926         req->async_states->send_fn = reply_read_and_X_send;
927         req->async_states->private_data = io;
928
929         /* call backend */
930         req->async_states->status = ntvfs_read(req, io);
931
932         REQ_ASYNC_TAIL;
933 }
934
935
936 /****************************************************************************
937  Reply to a writebraw (core+ or LANMAN1.0 protocol).
938 ****************************************************************************/
939 void reply_writebraw(struct smbsrv_request *req)
940 {
941         /* this one is damn complex - put it off for now */
942         req_reply_error(req, NT_STATUS_FOOBAR);
943 }
944
945
946 /****************************************************************************
947  Reply to a writeunlock (async reply)
948 ****************************************************************************/
949 static void reply_writeunlock_send(struct smbsrv_request *req)
950 {
951         union smb_write *io = req->async_states->private_data;
952
953         CHECK_ASYNC_STATUS;
954
955         /* construct reply */
956         req_setup_reply(req, 1, 0);
957
958         SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
959
960         req_send_reply(req);
961 }
962
963 /****************************************************************************
964  Reply to a writeunlock (core+).
965 ****************************************************************************/
966 void reply_writeunlock(struct smbsrv_request *req)
967 {
968         union smb_write *io;
969
970         REQ_CHECK_WCT(req, 5);
971         REQ_TALLOC(io, sizeof(*io));
972
973         io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
974         io->writeunlock.in.fnum        = req_fnum(req, req->in.vwv, VWV(0));
975         io->writeunlock.in.count       = SVAL(req->in.vwv, VWV(1));
976         io->writeunlock.in.offset      = IVAL(req->in.vwv, VWV(2));
977         io->writeunlock.in.remaining   = SVAL(req->in.vwv, VWV(4));
978         io->writeunlock.in.data        = req->in.data + 3;
979
980         /* make sure they gave us the data they promised */
981         if (io->writeunlock.in.count+3 > req->in.data_size) {
982                 req_reply_error(req, NT_STATUS_FOOBAR);
983                 return;
984         }
985
986         /* make sure the data block is big enough */
987         if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
988                 req_reply_error(req, NT_STATUS_FOOBAR);
989                 return;
990         }
991
992         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
993         req->async_states->send_fn = reply_writeunlock_send;
994         req->async_states->private_data = io;
995
996         /* call backend */
997         req->async_states->status = ntvfs_write(req, io);
998
999         REQ_ASYNC_TAIL;
1000 }
1001
1002
1003
1004 /****************************************************************************
1005  Reply to a write (async reply)
1006 ****************************************************************************/
1007 static void reply_write_send(struct smbsrv_request *req)
1008 {
1009         union smb_write *io = req->async_states->private_data;
1010         
1011         CHECK_ASYNC_STATUS;
1012
1013         /* construct reply */
1014         req_setup_reply(req, 1, 0);
1015
1016         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1017
1018         req_send_reply(req);
1019 }
1020
1021 /****************************************************************************
1022  Reply to a write
1023 ****************************************************************************/
1024 void reply_write(struct smbsrv_request *req)
1025 {
1026         union smb_write *io;
1027
1028         REQ_CHECK_WCT(req, 5);
1029         REQ_TALLOC(io, sizeof(*io));
1030
1031         io->write.level = RAW_WRITE_WRITE;
1032         io->write.in.fnum        = req_fnum(req, req->in.vwv, VWV(0));
1033         io->write.in.count       = SVAL(req->in.vwv, VWV(1));
1034         io->write.in.offset      = IVAL(req->in.vwv, VWV(2));
1035         io->write.in.remaining   = SVAL(req->in.vwv, VWV(4));
1036         io->write.in.data        = req->in.data + 3;
1037
1038         /* make sure they gave us the data they promised */
1039         if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
1040                 req_reply_error(req, NT_STATUS_FOOBAR);
1041                 return;
1042         }
1043
1044         /* make sure the data block is big enough */
1045         if (SVAL(req->in.data, 1) < io->write.in.count) {
1046                 req_reply_error(req, NT_STATUS_FOOBAR);
1047                 return;
1048         }
1049
1050         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1051         req->async_states->send_fn = reply_write_send;
1052         req->async_states->private_data = io;
1053
1054         /* call backend */
1055         req->async_states->status = ntvfs_write(req, io);
1056
1057         REQ_ASYNC_TAIL;
1058 }
1059
1060
1061 /****************************************************************************
1062  Reply to a write and X (async reply)
1063 ****************************************************************************/
1064 static void reply_write_and_X_send(struct smbsrv_request *req)
1065 {
1066         union smb_write *io = req->async_states->private_data;
1067
1068         CHECK_ASYNC_STATUS;
1069
1070         /* construct reply */
1071         req_setup_reply(req, 6, 0);
1072
1073         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1074         SSVAL(req->out.vwv, VWV(1), 0);
1075         SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
1076         SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
1077         SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
1078         REQ_VWV_RESERVED(5, 1);
1079
1080         chain_reply(req);
1081 }
1082
1083 /****************************************************************************
1084  Reply to a write and X.
1085 ****************************************************************************/
1086 void reply_write_and_X(struct smbsrv_request *req)
1087 {
1088         union smb_write *io;
1089         
1090         if (req->in.wct != 14) {
1091                 REQ_CHECK_WCT(req, 12);
1092         }
1093
1094         REQ_TALLOC(io, sizeof(*io));
1095
1096         io->writex.level = RAW_WRITE_WRITEX;
1097         io->writex.in.fnum      = req_fnum(req, req->in.vwv, VWV(2));
1098         io->writex.in.offset    = IVAL(req->in.vwv, VWV(3));
1099         io->writex.in.wmode     = SVAL(req->in.vwv, VWV(7));
1100         io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1101         io->writex.in.count     = SVAL(req->in.vwv, VWV(10));
1102         io->writex.in.data      = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1103
1104         if (req->in.wct == 14) {
1105                 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1106                 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1107                 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1108                 io->writex.in.count |= ((uint32_t)count_high) << 16;
1109         }
1110
1111         /* make sure the data is in bounds */
1112         if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1113                 req_reply_error(req, NT_STATUS_FOOBAR);
1114                 return;
1115         } 
1116
1117         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1118         req->async_states->send_fn = reply_write_and_X_send;
1119         req->async_states->private_data = io;
1120
1121         /* call backend */
1122         req->async_states->status = ntvfs_write(req, io);
1123
1124         REQ_ASYNC_TAIL;
1125 }
1126
1127
1128 /****************************************************************************
1129  Reply to a lseek (async reply)
1130 ****************************************************************************/
1131 static void reply_lseek_send(struct smbsrv_request *req)
1132 {
1133         struct smb_seek *io = req->async_states->private_data;
1134
1135         CHECK_ASYNC_STATUS;
1136
1137         /* construct reply */
1138         req_setup_reply(req, 2, 0);
1139
1140         SIVALS(req->out.vwv, VWV(0), io->out.offset);
1141
1142         req_send_reply(req);
1143 }
1144
1145 /****************************************************************************
1146  Reply to a lseek.
1147 ****************************************************************************/
1148 void reply_lseek(struct smbsrv_request *req)
1149 {
1150         struct smb_seek *io;
1151
1152         REQ_CHECK_WCT(req, 4);
1153         REQ_TALLOC(io, sizeof(*io));
1154
1155         io->in.fnum   = req_fnum(req, req->in.vwv,  VWV(0));
1156         io->in.mode   = SVAL(req->in.vwv,  VWV(1));
1157         io->in.offset = IVALS(req->in.vwv, VWV(2));
1158
1159         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1160         req->async_states->send_fn = reply_lseek_send;
1161         req->async_states->private_data = io;
1162         
1163         /* call backend */
1164         req->async_states->status = ntvfs_seek(req, io);
1165
1166         REQ_ASYNC_TAIL;
1167 }
1168
1169 /****************************************************************************
1170  Reply to a flush.
1171 ****************************************************************************/
1172 void reply_flush(struct smbsrv_request *req)
1173 {
1174         struct smb_flush *io;
1175
1176         /* parse request */
1177         REQ_CHECK_WCT(req, 1);
1178         REQ_TALLOC(io, sizeof(*io));
1179
1180         io->in.fnum   = req_fnum(req, req->in.vwv,  VWV(0));
1181         
1182         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1183         req->async_states->send_fn = reply_simple_send;
1184
1185         /* call backend */
1186         req->async_states->status = ntvfs_flush(req, io);
1187         
1188         REQ_ASYNC_TAIL;
1189 }
1190
1191
1192 /****************************************************************************
1193  Reply to a exit. This closes all files open by a smbpid
1194 ****************************************************************************/
1195 void reply_exit(struct smbsrv_request *req)
1196 {
1197         NTSTATUS status;
1198         struct smbsrv_tcon *tcon;
1199         REQ_CHECK_WCT(req, 0);
1200
1201         for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
1202                 req->tcon = tcon;
1203                 status = ntvfs_exit(req);
1204                 req->tcon = NULL;
1205                 if (!NT_STATUS_IS_OK(status)) {
1206                         req_reply_error(req, status);
1207                         return;
1208                 }
1209         }
1210
1211         req_setup_reply(req, 0, 0);
1212         req_send_reply(req);
1213 }
1214
1215
1216 /****************************************************************************
1217  Reply to a close 
1218
1219  Note that this has to deal with closing a directory opened by NT SMB's.
1220 ****************************************************************************/
1221 void reply_close(struct smbsrv_request *req)
1222 {
1223         union smb_close *io;
1224
1225         /* parse request */
1226         REQ_CHECK_WCT(req, 3);
1227         REQ_TALLOC(io, sizeof(*io));
1228
1229         io->close.level = RAW_CLOSE_CLOSE;
1230         io->close.in.fnum  = req_fnum(req, req->in.vwv,  VWV(0));
1231         io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1232
1233         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1234         req->async_states->send_fn = reply_simple_send;
1235
1236         /* call backend */
1237         req->async_states->status = ntvfs_close(req, io);
1238
1239         REQ_ASYNC_TAIL;
1240 }
1241
1242
1243
1244 /****************************************************************************
1245  Reply to a writeclose (async reply)
1246 ****************************************************************************/
1247 static void reply_writeclose_send(struct smbsrv_request *req)
1248 {
1249         union smb_write *io = req->async_states->private_data;
1250
1251         CHECK_ASYNC_STATUS;
1252
1253         /* construct reply */
1254         req_setup_reply(req, 1, 0);
1255
1256         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1257
1258         req_send_reply(req);
1259 }
1260
1261 /****************************************************************************
1262  Reply to a writeclose (Core+ protocol).
1263 ****************************************************************************/
1264 void reply_writeclose(struct smbsrv_request *req)
1265 {
1266         union smb_write *io;
1267
1268         /* this one is pretty weird - the wct can be 6 or 12 */
1269         if (req->in.wct != 12) {
1270                 REQ_CHECK_WCT(req, 6);
1271         }
1272
1273         REQ_TALLOC(io, sizeof(*io));
1274
1275         io->writeclose.level = RAW_WRITE_WRITECLOSE;
1276         io->writeclose.in.fnum   = req_fnum(req, req->in.vwv, VWV(0));
1277         io->writeclose.in.count  = SVAL(req->in.vwv, VWV(1));
1278         io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1279         io->writeclose.in.mtime  = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1280         io->writeclose.in.data   = req->in.data + 1;
1281
1282         /* make sure they gave us the data they promised */
1283         if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1284                 req_reply_error(req, NT_STATUS_FOOBAR);
1285                 return;
1286         }
1287
1288         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1289         req->async_states->send_fn = reply_writeclose_send;
1290         req->async_states->private_data = io;
1291
1292         /* call backend */
1293         req->async_states->status = ntvfs_write(req, io);
1294
1295         REQ_ASYNC_TAIL;
1296 }
1297
1298 /****************************************************************************
1299  Reply to a lock.
1300 ****************************************************************************/
1301 void reply_lock(struct smbsrv_request *req)
1302 {
1303         union smb_lock *lck;
1304
1305         /* parse request */
1306         REQ_CHECK_WCT(req, 5);
1307         REQ_TALLOC(lck, sizeof(*lck));
1308
1309         lck->lock.level     = RAW_LOCK_LOCK;
1310         lck->lock.in.fnum   = req_fnum(req, req->in.vwv, VWV(0));
1311         lck->lock.in.count  = IVAL(req->in.vwv, VWV(1));
1312         lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1313
1314         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1315         req->async_states->send_fn = reply_simple_send;
1316
1317         /* call backend */
1318         req->async_states->status = ntvfs_lock(req, lck);
1319
1320         REQ_ASYNC_TAIL;
1321 }
1322
1323
1324 /****************************************************************************
1325  Reply to a unlock.
1326 ****************************************************************************/
1327 void reply_unlock(struct smbsrv_request *req)
1328 {
1329         union smb_lock *lck;
1330
1331         /* parse request */
1332         REQ_CHECK_WCT(req, 5);
1333         REQ_TALLOC(lck, sizeof(*lck));
1334
1335         lck->unlock.level = RAW_LOCK_UNLOCK;
1336         lck->unlock.in.fnum   = req_fnum(req, req->in.vwv, VWV(0));
1337         lck->unlock.in.count  = IVAL(req->in.vwv, VWV(1));
1338         lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1339
1340         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1341         req->async_states->send_fn = reply_simple_send;
1342
1343         /* call backend */
1344         req->async_states->status = ntvfs_lock(req, lck);
1345
1346         REQ_ASYNC_TAIL;
1347 }
1348
1349
1350 /****************************************************************************
1351  Reply to a tdis.
1352 ****************************************************************************/
1353 void reply_tdis(struct smbsrv_request *req)
1354 {
1355         REQ_CHECK_WCT(req, 0);
1356
1357         close_cnum(req->tcon);
1358
1359         /* construct reply */
1360         req_setup_reply(req, 0, 0);
1361
1362         req_send_reply(req);
1363 }
1364
1365
1366 /****************************************************************************
1367  Reply to a echo. This is one of the few calls that is handled directly (the
1368  backends don't see it at all)
1369 ****************************************************************************/
1370 void reply_echo(struct smbsrv_request *req)
1371 {
1372         uint16_t count;
1373         int i;
1374
1375         REQ_CHECK_WCT(req, 0);
1376
1377         count = SVAL(req->in.vwv, VWV(0));
1378
1379         req_setup_reply(req, 1, req->in.data_size);
1380
1381         memcpy(req->out.data, req->in.data, req->in.data_size);
1382
1383         for (i=1; i <= count;i++) {
1384                 struct smbsrv_request *this_req;
1385                 
1386                 if (i != count) {
1387                         this_req = req_setup_secondary(req);
1388                 } else {
1389                         this_req = req;
1390                 }
1391
1392                 SSVAL(this_req->out.vwv, VWV(0), i);
1393                 req_send_reply(this_req);
1394         }
1395 }
1396
1397
1398
1399 /****************************************************************************
1400  Reply to a printopen (async reply)
1401 ****************************************************************************/
1402 static void reply_printopen_send(struct smbsrv_request *req)
1403 {
1404         union smb_open *oi = req->async_states->private_data;
1405
1406         CHECK_ASYNC_STATUS;
1407
1408         /* construct reply */
1409         req_setup_reply(req, 1, 0);
1410
1411         SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
1412
1413         req_send_reply(req);
1414 }
1415
1416 /****************************************************************************
1417  Reply to a printopen.
1418 ****************************************************************************/
1419 void reply_printopen(struct smbsrv_request *req)
1420 {
1421         union smb_open *oi;
1422
1423         /* parse request */
1424         REQ_CHECK_WCT(req, 2);
1425         REQ_TALLOC(oi, sizeof(*oi));
1426
1427         oi->splopen.level = RAW_OPEN_SPLOPEN;
1428         oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1429         oi->splopen.in.mode         = SVAL(req->in.vwv, VWV(1));
1430
1431         req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1432
1433         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1434         req->async_states->send_fn = reply_printopen_send;
1435         req->async_states->private_data = oi;
1436
1437         /* call backend */
1438         req->async_states->status = ntvfs_openfile(req, oi);
1439
1440         REQ_ASYNC_TAIL;
1441 }
1442
1443 /****************************************************************************
1444  Reply to a printclose.
1445 ****************************************************************************/
1446 void reply_printclose(struct smbsrv_request *req)
1447 {
1448         union smb_close *io;
1449
1450         /* parse request */
1451         REQ_CHECK_WCT(req, 3);
1452         REQ_TALLOC(io, sizeof(*io));
1453
1454         io->splclose.level = RAW_CLOSE_SPLCLOSE;
1455         io->splclose.in.fnum = req_fnum(req, req->in.vwv,  VWV(0));
1456
1457         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1458         req->async_states->send_fn = reply_simple_send;
1459
1460         /* call backend */
1461         req->async_states->status = ntvfs_close(req, io);
1462
1463         REQ_ASYNC_TAIL;
1464 }
1465
1466 /****************************************************************************
1467  Reply to a printqueue.
1468 ****************************************************************************/
1469 void reply_printqueue_send(struct smbsrv_request *req)
1470 {
1471         union smb_lpq *lpq = req->async_states->private_data;
1472         int i, maxcount;
1473         const uint_t el_size = 28;      
1474
1475         CHECK_ASYNC_STATUS;
1476
1477         /* construct reply */
1478         req_setup_reply(req, 2, 0);
1479
1480         /* truncate the returned list to fit in the negotiated buffer size */
1481         maxcount = (req_max_data(req) - 3) / el_size;
1482         if (maxcount < lpq->retq.out.count) {
1483                 lpq->retq.out.count = maxcount;
1484         }
1485
1486         /* setup enough space in the reply */
1487         req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1488         
1489         /* and fill it in */
1490         SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1491         SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1492
1493         SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1494         SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1495
1496         req->out.ptr = req->out.data + 3;
1497
1498         for (i=0;i<lpq->retq.out.count;i++) {
1499                 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1500                 SCVAL(req->out.ptr,  4, lpq->retq.out.queue[i].status);
1501                 SSVAL(req->out.ptr,  5, lpq->retq.out.queue[i].job);
1502                 SIVAL(req->out.ptr,  7, lpq->retq.out.queue[i].size);
1503                 SCVAL(req->out.ptr, 11, 0); /* reserved */
1504                 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1505                 req->out.ptr += el_size;
1506         }
1507
1508         req_send_reply(req);
1509 }
1510
1511 /****************************************************************************
1512  Reply to a printqueue.
1513 ****************************************************************************/
1514 void reply_printqueue(struct smbsrv_request *req)
1515 {
1516         union smb_lpq *lpq;
1517
1518         /* parse request */
1519         REQ_CHECK_WCT(req, 2);
1520         REQ_TALLOC(lpq, sizeof(*lpq));
1521
1522         lpq->retq.level = RAW_LPQ_RETQ;
1523         lpq->retq.in.maxcount = SVAL(req->in.vwv,  VWV(0));
1524         lpq->retq.in.startidx = SVAL(req->in.vwv,  VWV(1));
1525
1526         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1527         req->async_states->send_fn = reply_printqueue_send;
1528         req->async_states->private_data = lpq;
1529
1530         /* call backend */
1531         req->async_states->status = ntvfs_lpq(req, lpq);
1532
1533         REQ_ASYNC_TAIL;
1534 }
1535
1536
1537 /****************************************************************************
1538  Reply to a printwrite.
1539 ****************************************************************************/
1540 void reply_printwrite(struct smbsrv_request *req)
1541 {
1542         union smb_write *io;
1543
1544         /* parse request */
1545         REQ_CHECK_WCT(req, 1);
1546         REQ_TALLOC(io, sizeof(*io));
1547
1548         io->splwrite.level = RAW_WRITE_SPLWRITE;
1549
1550         if (req->in.data_size < 3) {
1551                 req_reply_error(req, NT_STATUS_FOOBAR);
1552                 return;
1553         }
1554
1555         io->splwrite.in.fnum  = req_fnum(req, req->in.vwv, VWV(0));
1556         io->splwrite.in.count = SVAL(req->in.data, 1);
1557         io->splwrite.in.data  = req->in.data + 3;
1558
1559         /* make sure they gave us the data they promised */
1560         if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1561                 req_reply_error(req, NT_STATUS_FOOBAR);
1562                 return;
1563         }
1564
1565         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1566         req->async_states->send_fn = reply_simple_send;
1567
1568         /* call backend */
1569         req->async_states->status = ntvfs_write(req, io);
1570
1571         REQ_ASYNC_TAIL;
1572 }
1573
1574
1575 /****************************************************************************
1576  Reply to a mkdir.
1577 ****************************************************************************/
1578 void reply_mkdir(struct smbsrv_request *req)
1579 {
1580         union smb_mkdir *io;
1581
1582         /* parse the request */
1583         REQ_CHECK_WCT(req, 0);
1584         REQ_TALLOC(io, sizeof(*io));
1585
1586         io->generic.level = RAW_MKDIR_MKDIR;
1587         req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1588
1589         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1590         req->async_states->send_fn = reply_simple_send;
1591
1592         /* call backend */
1593         req->async_states->status = ntvfs_mkdir(req, io);
1594
1595         REQ_ASYNC_TAIL;
1596 }
1597
1598
1599 /****************************************************************************
1600  Reply to a rmdir.
1601 ****************************************************************************/
1602 void reply_rmdir(struct smbsrv_request *req)
1603 {
1604         struct smb_rmdir *io;
1605  
1606         /* parse the request */
1607         REQ_CHECK_WCT(req, 0);
1608         REQ_TALLOC(io, sizeof(*io));
1609
1610         req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1611
1612         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1613         req->async_states->send_fn = reply_simple_send;
1614
1615         /* call backend */
1616         req->async_states->status = ntvfs_rmdir(req, io);
1617
1618         REQ_ASYNC_TAIL;
1619 }
1620
1621
1622 /****************************************************************************
1623  Reply to a mv.
1624 ****************************************************************************/
1625 void reply_mv(struct smbsrv_request *req)
1626 {
1627         union smb_rename *io;
1628         uint8_t *p;
1629  
1630         /* parse the request */
1631         REQ_CHECK_WCT(req, 1);
1632         REQ_TALLOC(io, sizeof(*io));
1633
1634         io->generic.level = RAW_RENAME_RENAME;
1635         io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1636
1637         p = req->in.data;
1638         p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1639         p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1640
1641         if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1642                 req_reply_error(req, NT_STATUS_FOOBAR);
1643                 return;
1644         }
1645
1646         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1647         req->async_states->send_fn = reply_simple_send;
1648
1649         /* call backend */
1650         req->async_states->status = ntvfs_rename(req, io);
1651
1652         REQ_ASYNC_TAIL;
1653 }
1654
1655
1656 /****************************************************************************
1657  Reply to an NT rename.
1658 ****************************************************************************/
1659 void reply_ntrename(struct smbsrv_request *req)
1660 {
1661         union smb_rename *io;
1662         uint8_t *p;
1663  
1664         /* parse the request */
1665         REQ_CHECK_WCT(req, 4);
1666         REQ_TALLOC(io, sizeof(*io));
1667
1668         io->generic.level = RAW_RENAME_NTRENAME;
1669         io->ntrename.in.attrib  = SVAL(req->in.vwv, VWV(0));
1670         io->ntrename.in.flags   = SVAL(req->in.vwv, VWV(1));
1671         io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1672
1673         p = req->in.data;
1674         p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1675         p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1676
1677         if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1678                 req_reply_error(req, NT_STATUS_FOOBAR);
1679                 return;
1680         }
1681
1682         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1683         req->async_states->send_fn = reply_simple_send;
1684
1685         /* call backend */
1686         req->async_states->status = ntvfs_rename(req, io);
1687
1688         REQ_ASYNC_TAIL;
1689 }
1690
1691 /****************************************************************************
1692  Reply to a file copy (async reply)
1693 ****************************************************************************/
1694 static void reply_copy_send(struct smbsrv_request *req)
1695 {
1696         struct smb_copy *cp = req->async_states->private_data;
1697
1698         CHECK_ASYNC_STATUS;
1699
1700         /* build the reply */
1701         req_setup_reply(req, 1, 0);
1702
1703         SSVAL(req->out.vwv, VWV(0), cp->out.count);
1704
1705         req_send_reply(req);
1706 }
1707
1708 /****************************************************************************
1709  Reply to a file copy.
1710 ****************************************************************************/
1711 void reply_copy(struct smbsrv_request *req)
1712 {
1713         struct smb_copy *cp;
1714         uint8_t *p;
1715
1716         /* parse request */
1717         REQ_CHECK_WCT(req, 3);
1718         REQ_TALLOC(cp, sizeof(*cp));
1719
1720         cp->in.tid2  = SVAL(req->in.vwv, VWV(0));
1721         cp->in.ofun  = SVAL(req->in.vwv, VWV(1));
1722         cp->in.flags = SVAL(req->in.vwv, VWV(2));
1723
1724         p = req->in.data;
1725         p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1726         p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1727
1728         if (!cp->in.path1 || !cp->in.path2) {
1729                 req_reply_error(req, NT_STATUS_FOOBAR);
1730                 return;
1731         }
1732
1733         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1734         req->async_states->send_fn = reply_copy_send;
1735         req->async_states->private_data = cp;
1736
1737         /* call backend */
1738         req->async_states->status = ntvfs_copy(req, cp);
1739
1740         REQ_ASYNC_TAIL;
1741 }
1742
1743 /****************************************************************************
1744  Reply to a lockingX request (async send)
1745 ****************************************************************************/
1746 static void reply_lockingX_send(struct smbsrv_request *req)
1747 {
1748         union smb_lock *lck = req->async_states->private_data;
1749
1750         CHECK_ASYNC_STATUS;
1751
1752         /* if it was an oplock break ack then we only send a reply if
1753            there was an error */
1754         if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1755                 req_destroy(req);
1756                 return;
1757         }
1758
1759         /* construct reply */
1760         req_setup_reply(req, 2, 0);
1761         
1762         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1763         SSVAL(req->out.vwv, VWV(1), 0);
1764
1765         chain_reply(req);
1766 }
1767
1768
1769 /****************************************************************************
1770  Reply to a lockingX request.
1771 ****************************************************************************/
1772 void reply_lockingX(struct smbsrv_request *req)
1773 {
1774         union smb_lock *lck;
1775         uint_t total_locks, i;
1776         uint_t lck_size;
1777         uint8_t *p;
1778
1779         /* parse request */
1780         REQ_CHECK_WCT(req, 8);
1781         REQ_TALLOC(lck, sizeof(*lck));
1782
1783         lck->lockx.level = RAW_LOCK_LOCKX;
1784         lck->lockx.in.fnum      = req_fnum(req, req->in.vwv, VWV(2));
1785         lck->lockx.in.mode      = SVAL(req->in.vwv, VWV(3));
1786         lck->lockx.in.timeout   = IVAL(req->in.vwv, VWV(4));
1787         lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1788         lck->lockx.in.lock_cnt  = SVAL(req->in.vwv, VWV(7));
1789
1790         total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1791
1792         /* there are two variants, one with 64 bit offsets and counts */
1793         if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1794                 lck_size = 20;
1795         } else {
1796                 lck_size = 10;          
1797         }
1798
1799         /* make sure we got the promised data */
1800         if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1801                 req_reply_error(req, NT_STATUS_FOOBAR);
1802                 return;
1803         }
1804
1805         /* allocate the locks array */
1806         if (total_locks) {
1807                 REQ_TALLOC(lck->lockx.in.locks, total_locks * sizeof(lck->lockx.in.locks[0]));
1808         }
1809
1810         p = req->in.data;
1811
1812         /* construct the locks array */
1813         for (i=0;i<total_locks;i++) {
1814                 uint32_t ofs_high=0, count_high=0;
1815
1816                 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1817
1818                 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1819                         ofs_high   = IVAL(p, 4);
1820                         lck->lockx.in.locks[i].offset = IVAL(p, 8);
1821                         count_high = IVAL(p, 12);
1822                         lck->lockx.in.locks[i].count  = IVAL(p, 16);
1823                 } else {
1824                         lck->lockx.in.locks[i].offset = IVAL(p, 2);
1825                         lck->lockx.in.locks[i].count  = IVAL(p, 6);
1826                 }
1827                 if (ofs_high != 0 || count_high != 0) {
1828                         lck->lockx.in.locks[i].count  |= ((uint64_t)count_high) << 32;
1829                         lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1830                 }
1831                 p += lck_size;
1832         }
1833
1834         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1835         req->async_states->send_fn = reply_lockingX_send;
1836         req->async_states->private_data = lck;
1837
1838         /* call backend */
1839         req->async_states->status = ntvfs_lock(req, lck);
1840
1841         REQ_ASYNC_TAIL;
1842 }
1843
1844 /****************************************************************************
1845  Reply to a SMBreadbmpx (read block multiplex) request.
1846 ****************************************************************************/
1847 void reply_readbmpx(struct smbsrv_request *req)
1848 {
1849         /* tell the client to not use a multiplexed read - its too broken to use */
1850         req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1851 }
1852
1853
1854 /****************************************************************************
1855  Reply to a SMBsetattrE.
1856 ****************************************************************************/
1857 void reply_setattrE(struct smbsrv_request *req)
1858 {
1859         union smb_setfileinfo *info;
1860
1861         /* parse request */
1862         REQ_CHECK_WCT(req, 7);
1863         REQ_TALLOC(info, sizeof(*info));
1864
1865         info->setattre.level = RAW_SFILEINFO_SETATTRE;
1866         info->setattre.file.fnum =      req_fnum(req, req->in.vwv,    VWV(0));
1867         info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1868         info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1869         info->setattre.in.write_time  = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1870
1871         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1872         req->async_states->send_fn = reply_simple_send;
1873
1874         /* call backend */
1875         req->async_states->status = ntvfs_setfileinfo(req, info);
1876
1877         REQ_ASYNC_TAIL;
1878 }
1879
1880
1881 /****************************************************************************
1882  Reply to a SMBwritebmpx (write block multiplex primary) request.
1883 ****************************************************************************/
1884 void reply_writebmpx(struct smbsrv_request *req)
1885 {
1886         req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1887 }
1888
1889
1890 /****************************************************************************
1891  Reply to a SMBwritebs (write block multiplex secondary) request.
1892 ****************************************************************************/
1893 void reply_writebs(struct smbsrv_request *req)
1894 {
1895         req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1896 }
1897
1898
1899
1900 /****************************************************************************
1901  Reply to a SMBgetattrE (async reply)
1902 ****************************************************************************/
1903 static void reply_getattrE_send(struct smbsrv_request *req)
1904 {
1905         union smb_fileinfo *info = req->async_states->private_data;
1906
1907         CHECK_ASYNC_STATUS;
1908
1909         /* setup reply */
1910         req_setup_reply(req, 11, 0);
1911
1912         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1913         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1914         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1915         SIVAL(req->out.vwv,         VWV(6), info->getattre.out.size);
1916         SIVAL(req->out.vwv,         VWV(8), info->getattre.out.alloc_size);
1917         SSVAL(req->out.vwv,        VWV(10), info->getattre.out.attrib);
1918
1919         req_send_reply(req);
1920 }
1921
1922 /****************************************************************************
1923  Reply to a SMBgetattrE.
1924 ****************************************************************************/
1925 void reply_getattrE(struct smbsrv_request *req)
1926 {
1927         union smb_fileinfo *info;
1928
1929         /* parse request */
1930         REQ_CHECK_WCT(req, 1);
1931         REQ_TALLOC(info, sizeof(*info));
1932
1933         info->getattr.level = RAW_FILEINFO_GETATTRE;
1934         info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1935
1936         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1937         req->async_states->send_fn = reply_getattrE_send;
1938         req->async_states->private_data = info;
1939
1940         /* call backend */
1941         req->async_states->status = ntvfs_qfileinfo(req, info);
1942
1943         REQ_ASYNC_TAIL;
1944 }
1945
1946
1947 /****************************************************************************
1948 reply to an old style session setup command
1949 ****************************************************************************/
1950 static void reply_sesssetup_old(struct smbsrv_request *req)
1951 {
1952         NTSTATUS status;
1953         union smb_sesssetup sess;
1954         uint8_t *p;
1955         uint16_t passlen;
1956
1957         sess.old.level = RAW_SESSSETUP_OLD;
1958
1959         /* parse request */
1960         sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1961         sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1962         sess.old.in.vc_num  = SVAL(req->in.vwv, VWV(4));
1963         sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1964         passlen             = SVAL(req->in.vwv, VWV(7));
1965
1966         /* check the request isn't malformed */
1967         if (req_data_oob(req, req->in.data, passlen)) {
1968                 req_reply_error(req, NT_STATUS_FOOBAR);
1969                 return;
1970         }
1971         
1972         p = req->in.data;
1973         if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1974                 req_reply_error(req, NT_STATUS_FOOBAR);
1975                 return;
1976         }
1977         p += passlen;
1978         
1979         p += req_pull_string(req, &sess.old.in.user,   p, -1, STR_TERMINATE);
1980         p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1981         p += req_pull_string(req, &sess.old.in.os,     p, -1, STR_TERMINATE);
1982         p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1983
1984         /* call the generic handler */
1985         status = sesssetup_backend(req, &sess);
1986
1987         if (!NT_STATUS_IS_OK(status)) {
1988                 req_reply_error(req, status);
1989                 return;
1990         }
1991
1992         /* construct reply */
1993         req_setup_reply(req, 3, 0);
1994
1995         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1996         SSVAL(req->out.vwv, VWV(1), 0);
1997         SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
1998
1999         SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
2000
2001         chain_reply(req);
2002 }
2003
2004
2005 /****************************************************************************
2006 reply to an NT1 style session setup command
2007 ****************************************************************************/
2008 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2009 {
2010         NTSTATUS status;
2011         union smb_sesssetup sess;
2012         uint8_t *p;
2013         uint16_t passlen1, passlen2;
2014
2015         sess.nt1.level = RAW_SESSSETUP_NT1;
2016
2017         /* parse request */
2018         sess.nt1.in.bufsize      = SVAL(req->in.vwv, VWV(2));
2019         sess.nt1.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
2020         sess.nt1.in.vc_num       = SVAL(req->in.vwv, VWV(4));
2021         sess.nt1.in.sesskey      = IVAL(req->in.vwv, VWV(5));
2022         passlen1                 = SVAL(req->in.vwv, VWV(7));
2023         passlen2                 = SVAL(req->in.vwv, VWV(8));
2024         sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2025
2026         /* check the request isn't malformed */
2027         if (req_data_oob(req, req->in.data, passlen1) ||
2028             req_data_oob(req, req->in.data + passlen1, passlen2)) {
2029                 req_reply_error(req, NT_STATUS_FOOBAR);
2030                 return;
2031         }
2032         
2033         p = req->in.data;
2034         if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2035                 req_reply_error(req, NT_STATUS_FOOBAR);
2036                 return;
2037         }
2038         p += passlen1;
2039         if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2040                 req_reply_error(req, NT_STATUS_FOOBAR);
2041                 return;
2042         }
2043         p += passlen2;
2044         
2045         p += req_pull_string(req, &sess.nt1.in.user,   p, -1, STR_TERMINATE);
2046         p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2047         p += req_pull_string(req, &sess.nt1.in.os,     p, -1, STR_TERMINATE);
2048         p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2049
2050         /* call the generic handler */
2051         status = sesssetup_backend(req, &sess);
2052
2053         if (!NT_STATUS_IS_OK(status)) {
2054                 req_reply_error(req, status);
2055                 return;
2056         }
2057
2058         /* construct reply */
2059         req_setup_reply(req, 3, 0);
2060
2061         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2062         SSVAL(req->out.vwv, VWV(1), 0);
2063         SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2064
2065         SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2066
2067         req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2068         req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2069         req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2070
2071         chain_reply(req);
2072 }
2073
2074
2075 /****************************************************************************
2076 reply to an SPNEGO style session setup command
2077 ****************************************************************************/
2078 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2079 {
2080         NTSTATUS status;
2081         union smb_sesssetup sess;
2082         uint8_t *p;
2083         uint16_t blob_len;
2084
2085         sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2086
2087         /* parse request */
2088         sess.spnego.in.bufsize      = SVAL(req->in.vwv, VWV(2));
2089         sess.spnego.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
2090         sess.spnego.in.vc_num       = SVAL(req->in.vwv, VWV(4));
2091         sess.spnego.in.sesskey      = IVAL(req->in.vwv, VWV(5));
2092         blob_len                    = SVAL(req->in.vwv, VWV(7));
2093         sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2094
2095         p = req->in.data;
2096         if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2097                 req_reply_error(req, NT_STATUS_FOOBAR);
2098                 return;
2099         }
2100         p += blob_len;
2101         
2102         p += req_pull_string(req, &sess.spnego.in.os,     p, -1, STR_TERMINATE);
2103         p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
2104         p += req_pull_string(req, &sess.spnego.in.domain, p, -1, STR_TERMINATE);
2105
2106         /* call the generic handler */
2107         status = sesssetup_backend(req, &sess);
2108
2109         if (!NT_STATUS_IS_OK(status) && 
2110             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2111                 req_reply_error(req, status);
2112                 return;
2113         }
2114
2115         /* construct reply */
2116         req_setup_reply(req, 4, sess.spnego.out.secblob.length);
2117
2118         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2119                 req_setup_error(req, status);
2120         }
2121
2122         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2123         SSVAL(req->out.vwv, VWV(1), 0);
2124         SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2125         SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2126
2127         SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2128
2129         memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2130         req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
2131         req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
2132         req_push_str(req, NULL, sess.spnego.out.domain, -1, STR_TERMINATE);
2133
2134         chain_reply(req);
2135 }
2136
2137
2138 /****************************************************************************
2139 reply to a session setup command
2140 ****************************************************************************/
2141 void reply_sesssetup(struct smbsrv_request *req)
2142 {
2143         switch (req->in.wct) {
2144         case 10:
2145                 /* a pre-NT1 call */
2146                 reply_sesssetup_old(req);
2147                 return;
2148         case 13:
2149                 /* a NT1 call */
2150                 reply_sesssetup_nt1(req);
2151                 return;
2152         case 12:
2153                 /* a SPNEGO call */
2154                 reply_sesssetup_spnego(req);
2155                 return;
2156         }
2157
2158         /* unsupported variant */
2159         req_reply_error(req, NT_STATUS_FOOBAR);
2160 }
2161
2162 /****************************************************************************
2163  Reply to a SMBulogoffX.
2164 ****************************************************************************/
2165 void reply_ulogoffX(struct smbsrv_request *req)
2166 {
2167         struct smbsrv_tcon *tcon;
2168         uint16_t vuid;
2169         NTSTATUS status;
2170
2171         vuid = SVAL(req->in.hdr, HDR_UID);
2172
2173         /* in user level security we are supposed to close any files
2174            open by this user on all open tree connects */
2175         if ((vuid != 0) && (lp_security() != SEC_SHARE)) {
2176                 for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
2177                         req->tcon = tcon;
2178                         status = ntvfs_logoff(req);
2179                         req->tcon = NULL;
2180                         if (!NT_STATUS_IS_OK(status)) {
2181                                 req_reply_error(req, status);
2182                                 return;
2183                         }
2184                 }
2185         }
2186
2187         smbsrv_invalidate_vuid(req->smb_conn, vuid);
2188
2189         req_setup_reply(req, 2, 0);
2190
2191         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2192         SSVAL(req->out.vwv, VWV(1), 0); 
2193         
2194         chain_reply(req);
2195 }
2196
2197
2198 /****************************************************************************
2199  Reply to an SMBfindclose request
2200 ****************************************************************************/
2201 void reply_findclose(struct smbsrv_request *req)
2202 {
2203         NTSTATUS status;
2204         union smb_search_close io;
2205
2206         io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2207
2208         /* parse request */
2209         REQ_CHECK_WCT(req, 1);
2210
2211         io.findclose.in.handle  = SVAL(req->in.vwv, VWV(0));
2212         
2213         /* call backend */
2214         status = ntvfs_search_close(req, &io);
2215
2216         if (!NT_STATUS_IS_OK(status)) {
2217                 req_reply_error(req, status);
2218                 return;
2219         }
2220
2221         /* construct reply */
2222         req_setup_reply(req, 0, 0);
2223
2224         req_send_reply(req);    
2225 }
2226
2227 /****************************************************************************
2228  Reply to an SMBfindnclose request
2229 ****************************************************************************/
2230 void reply_findnclose(struct smbsrv_request *req)
2231 {
2232         req_reply_error(req, NT_STATUS_FOOBAR);
2233 }
2234
2235
2236 /****************************************************************************
2237  Reply to an SMBntcreateX request (async send)
2238 ****************************************************************************/
2239 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2240 {
2241         union smb_open *io = req->async_states->private_data;
2242
2243         CHECK_ASYNC_STATUS;
2244
2245         /* construct reply */
2246         req_setup_reply(req, 34, 0);
2247
2248         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2249         SSVAL(req->out.vwv, VWV(1), 0); 
2250         SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2251
2252         /* the rest of the parameters are not aligned! */
2253         SSVAL(req->out.vwv,        5, io->ntcreatex.out.fnum);
2254         SIVAL(req->out.vwv,        7, io->ntcreatex.out.create_action);
2255         push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2256         push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2257         push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2258         push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2259         SIVAL(req->out.vwv,       43, io->ntcreatex.out.attrib);
2260         SBVAL(req->out.vwv,       47, io->ntcreatex.out.alloc_size);
2261         SBVAL(req->out.vwv,       55, io->ntcreatex.out.size);
2262         SSVAL(req->out.vwv,       63, io->ntcreatex.out.file_type);
2263         SSVAL(req->out.vwv,       65, io->ntcreatex.out.ipc_state);
2264         SCVAL(req->out.vwv,       67, io->ntcreatex.out.is_directory);
2265
2266         chain_reply(req);
2267 }
2268
2269 /****************************************************************************
2270  Reply to an SMBntcreateX request
2271 ****************************************************************************/
2272 void reply_ntcreate_and_X(struct smbsrv_request *req)
2273 {
2274         union smb_open *io;
2275         uint16_t fname_len;
2276
2277         /* parse the request */
2278         REQ_CHECK_WCT(req, 24);
2279         REQ_TALLOC(io, sizeof(*io));
2280
2281         io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2282
2283         /* notice that the word parameters are not word aligned, so we don't use VWV() */
2284         fname_len =                         SVAL(req->in.vwv, 5);
2285         io->ntcreatex.in.flags =            IVAL(req->in.vwv, 7);
2286         io->ntcreatex.in.root_fid =         IVAL(req->in.vwv, 11);
2287         io->ntcreatex.in.access_mask =      IVAL(req->in.vwv, 15);
2288         io->ntcreatex.in.alloc_size =       BVAL(req->in.vwv, 19);
2289         io->ntcreatex.in.file_attr =        IVAL(req->in.vwv, 27);
2290         io->ntcreatex.in.share_access =     IVAL(req->in.vwv, 31);
2291         io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2292         io->ntcreatex.in.create_options =   IVAL(req->in.vwv, 39);
2293         io->ntcreatex.in.impersonation =    IVAL(req->in.vwv, 43);
2294         io->ntcreatex.in.security_flags =   CVAL(req->in.vwv, 47);
2295         io->ntcreatex.in.ea_list          = NULL;
2296         io->ntcreatex.in.sec_desc         = NULL;
2297
2298         /* we need a neater way to handle this alignment */
2299         if ((req->flags2 & FLAGS2_UNICODE_STRINGS) && 
2300             ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2301                 fname_len++;
2302         }
2303
2304         req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2305         if (!io->ntcreatex.in.fname) {
2306                 req_reply_error(req, NT_STATUS_FOOBAR);
2307                 return;
2308         }
2309
2310         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2311         req->async_states->send_fn = reply_ntcreate_and_X_send;
2312         req->async_states->private_data = io;
2313
2314         /* call the backend */
2315         req->async_states->status = ntvfs_openfile(req, io);
2316
2317         REQ_ASYNC_TAIL;
2318 }
2319
2320
2321 /****************************************************************************
2322  Reply to an SMBntcancel request
2323 ****************************************************************************/
2324 void reply_ntcancel(struct smbsrv_request *req)
2325 {
2326         /* NOTE: this request does not generate a reply */
2327         req_signing_no_reply(req);
2328         ntvfs_cancel(req);
2329         req_destroy(req);
2330 }
2331
2332 /****************************************************************************
2333  Reply to an SMBsends request
2334 ****************************************************************************/
2335 void reply_sends(struct smbsrv_request *req)
2336 {
2337         req_reply_error(req, NT_STATUS_FOOBAR);
2338 }
2339
2340 /****************************************************************************
2341  Reply to an SMBsendstrt request
2342 ****************************************************************************/
2343 void reply_sendstrt(struct smbsrv_request *req)
2344 {
2345         req_reply_error(req, NT_STATUS_FOOBAR);
2346 }
2347
2348 /****************************************************************************
2349  Reply to an SMBsendend request
2350 ****************************************************************************/
2351 void reply_sendend(struct smbsrv_request *req)
2352 {
2353         req_reply_error(req, NT_STATUS_FOOBAR);
2354 }
2355
2356 /****************************************************************************
2357  Reply to an SMBsendtxt request
2358 ****************************************************************************/
2359 void reply_sendtxt(struct smbsrv_request *req)
2360 {
2361         req_reply_error(req, NT_STATUS_FOOBAR);
2362 }
2363
2364
2365
2366 /****************************************************************************
2367  Reply to a special message - a SMB packet with non zero NBT message type
2368 ****************************************************************************/
2369 void reply_special(struct smbsrv_request *req)
2370 {
2371         uint8_t msg_type;
2372         uint8_t *buf = talloc_zero_array_p(req, uint8_t, 4);
2373         
2374         msg_type = CVAL(req->in.buffer,0);
2375
2376         SIVAL(buf, 0, 0);
2377         
2378         switch (msg_type) {
2379         case 0x81: /* session request */
2380                 if (req->smb_conn->negotiate.done_nbt_session) {
2381                         smbsrv_terminate_connection(req->smb_conn, 
2382                                                     "multiple session request not permitted");
2383                         return;
2384                 }
2385                 
2386                 SCVAL(buf,0,0x82);
2387                 SCVAL(buf,3,0);
2388                 
2389                 DEBUG(0,("REWRITE: not parsing netbios names in NBT session request!\n"));
2390                 /* TODO: store the name for the session setup 'remote
2391                    machine' code, as well as smbstatus */
2392
2393                 req->smb_conn->negotiate.done_nbt_session = True;
2394                 
2395                 req->out.buffer = buf;
2396                 req->out.size = 4;
2397                 req_send_reply_nosign(req);
2398                 return;
2399                 
2400         case 0x89: /* session keepalive request 
2401                       (some old clients produce this?) */
2402                 SCVAL(buf, 0, SMBkeepalive);
2403                 SCVAL(buf, 3, 0);
2404                 req->out.buffer = buf;
2405                 req->out.size = 4;
2406                 req_send_reply_nosign(req);
2407                 return;
2408                 
2409         case SMBkeepalive: 
2410                 /* session keepalive - swallow it */
2411                 req_destroy(req);
2412                 return;
2413         }
2414
2415         DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));
2416         req_destroy(req);
2417 }