LCOV - code coverage report
Current view: top level - source4/smb_server/smb - reply.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 824 1046 78.8 %
Date: 2024-06-13 04:01:37 Functions: 65 81 80.2 %

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

Generated by: LCOV version 1.13