root/source4/smb_server/smb/reply.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. reply_simple_send
  2. smbsrv_reply_tcon
  3. smbsrv_reply_tcon_and_X
  4. smbsrv_reply_unknown
  5. reply_ioctl_send
  6. smbsrv_reply_ioctl
  7. smbsrv_reply_chkpth
  8. reply_getatr_send
  9. smbsrv_reply_getatr
  10. smbsrv_reply_setatr
  11. reply_dskattr_send
  12. smbsrv_reply_dskattr
  13. reply_open_send
  14. smbsrv_reply_open
  15. reply_open_and_X_send
  16. smbsrv_reply_open_and_X
  17. reply_mknew_send
  18. smbsrv_reply_mknew
  19. reply_ctemp_send
  20. smbsrv_reply_ctemp
  21. smbsrv_reply_unlink
  22. smbsrv_reply_readbraw
  23. reply_lockread_send
  24. smbsrv_reply_lockread
  25. reply_read_send
  26. smbsrv_reply_read
  27. reply_read_and_X_send
  28. smbsrv_reply_read_and_X
  29. smbsrv_reply_writebraw
  30. reply_writeunlock_send
  31. smbsrv_reply_writeunlock
  32. reply_write_send
  33. smbsrv_reply_write
  34. reply_write_and_X_send
  35. smbsrv_reply_write_and_X
  36. reply_lseek_send
  37. smbsrv_reply_lseek
  38. smbsrv_reply_flush
  39. smbsrv_reply_close
  40. reply_writeclose_send
  41. smbsrv_reply_writeclose
  42. smbsrv_reply_lock
  43. smbsrv_reply_unlock
  44. smbsrv_reply_tdis
  45. smbsrv_reply_echo
  46. reply_printopen_send
  47. smbsrv_reply_printopen
  48. smbsrv_reply_printclose
  49. reply_printqueue_send
  50. smbsrv_reply_printqueue
  51. smbsrv_reply_printwrite
  52. smbsrv_reply_mkdir
  53. smbsrv_reply_rmdir
  54. smbsrv_reply_mv
  55. smbsrv_reply_ntrename
  56. reply_copy_send
  57. smbsrv_reply_copy
  58. reply_lockingX_send
  59. smbsrv_reply_lockingX
  60. smbsrv_reply_readbmpx
  61. smbsrv_reply_setattrE
  62. smbsrv_reply_writebmpx
  63. smbsrv_reply_writebs
  64. reply_getattrE_send
  65. smbsrv_reply_getattrE
  66. smbsrv_reply_sesssetup_send
  67. reply_sesssetup_old
  68. reply_sesssetup_nt1
  69. reply_sesssetup_spnego
  70. smbsrv_reply_sesssetup
  71. smbsrv_reply_exit
  72. smbsrv_reply_ulogoffX
  73. smbsrv_reply_findclose
  74. smbsrv_reply_findnclose
  75. reply_ntcreate_and_X_send
  76. smbsrv_reply_ntcreate_and_X
  77. smbsrv_reply_ntcancel
  78. parse_session_request
  79. smbsrv_reply_special

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

/* [<][>][^][v][top][bottom][index][help] */