LCOV - code coverage report
Current view: top level - source3/smbd - smb1_reply.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 137 3123 4.4 %
Date: 2024-02-14 10:14:15 Functions: 6 87 6.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Main SMB reply routines
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Andrew Bartlett      2001
       6             :    Copyright (C) Jeremy Allison 1992-2007.
       7             :    Copyright (C) Volker Lendecke 2007
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : /*
      23             :    This file handles most of the reply_ calls that the server
      24             :    makes to handle specific protocols
      25             : */
      26             : 
      27             : #include "includes.h"
      28             : #include "libsmb/namequery.h"
      29             : #include "system/filesys.h"
      30             : #include "printing.h"
      31             : #include "locking/share_mode_lock.h"
      32             : #include "smbd/smbd.h"
      33             : #include "smbd/globals.h"
      34             : #include "smbd/smbXsrv_open.h"
      35             : #include "fake_file.h"
      36             : #include "rpc_client/rpc_client.h"
      37             : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
      38             : #include "rpc_client/cli_spoolss.h"
      39             : #include "rpc_client/init_spoolss.h"
      40             : #include "rpc_server/rpc_ncacn_np.h"
      41             : #include "libcli/security/security.h"
      42             : #include "libsmb/nmblib.h"
      43             : #include "auth.h"
      44             : #include "smbprofile.h"
      45             : #include "../lib/tsocket/tsocket.h"
      46             : #include "lib/util/tevent_ntstatus.h"
      47             : #include "libcli/smb/smb_signing.h"
      48             : #include "lib/util/sys_rw_data.h"
      49             : #include "librpc/gen_ndr/open_files.h"
      50             : #include "libcli/smb/smb2_posix.h"
      51             : #include "lib/util/string_wrappers.h"
      52             : #include "source3/printing/rap_jobid.h"
      53             : #include "source3/lib/substitute.h"
      54             : 
      55             : /****************************************************************************
      56             :  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
      57             : ****************************************************************************/
      58             : 
      59           0 : bool check_fsp_open(connection_struct *conn, struct smb_request *req,
      60             :                     files_struct *fsp)
      61             : {
      62           0 :         if ((fsp == NULL) || (conn == NULL)) {
      63           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
      64           0 :                 return false;
      65             :         }
      66           0 :         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
      67           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
      68           0 :                 return false;
      69             :         }
      70           0 :         return true;
      71             : }
      72             : 
      73             : /****************************************************************************
      74             :  Check if we have a correct fsp pointing to a file.
      75             : ****************************************************************************/
      76             : 
      77           0 : bool check_fsp(connection_struct *conn, struct smb_request *req,
      78             :                files_struct *fsp)
      79             : {
      80           0 :         if (!check_fsp_open(conn, req, fsp)) {
      81           0 :                 return false;
      82             :         }
      83           0 :         if (fsp->fsp_flags.is_directory) {
      84           0 :                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
      85           0 :                 return false;
      86             :         }
      87           0 :         if (fsp_get_pathref_fd(fsp) == -1) {
      88           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
      89           0 :                 return false;
      90             :         }
      91           0 :         fsp->num_smb_operations++;
      92           0 :         return true;
      93             : }
      94             : 
      95             : /****************************************************************************
      96             :  Reply to a tcon.
      97             :  conn POINTER CAN BE NULL HERE !
      98             : ****************************************************************************/
      99             : 
     100           0 : void reply_tcon(struct smb_request *req)
     101             : {
     102           0 :         connection_struct *conn = req->conn;
     103             :         const char *service;
     104           0 :         char *service_buf = NULL;
     105           0 :         char *password = NULL;
     106           0 :         char *dev = NULL;
     107           0 :         int pwlen=0;
     108             :         NTSTATUS nt_status;
     109             :         const uint8_t *p;
     110             :         const char *p2;
     111           0 :         TALLOC_CTX *ctx = talloc_tos();
     112           0 :         struct smbXsrv_connection *xconn = req->xconn;
     113           0 :         NTTIME now = timeval_to_nttime(&req->request_time);
     114             : 
     115           0 :         START_PROFILE(SMBtcon);
     116             : 
     117           0 :         if (req->buflen < 4) {
     118           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     119           0 :                 END_PROFILE(SMBtcon);
     120           0 :                 return;
     121             :         }
     122             : 
     123           0 :         p = req->buf + 1;
     124           0 :         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
     125           0 :         p += 1;
     126           0 :         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
     127           0 :         p += pwlen+1;
     128           0 :         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
     129           0 :         p += 1;
     130             : 
     131           0 :         if (service_buf == NULL || password == NULL || dev == NULL) {
     132           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     133           0 :                 END_PROFILE(SMBtcon);
     134           0 :                 return;
     135             :         }
     136           0 :         p2 = strrchr_m(service_buf,'\\');
     137           0 :         if (p2) {
     138           0 :                 service = p2+1;
     139             :         } else {
     140           0 :                 service = service_buf;
     141             :         }
     142             : 
     143           0 :         conn = make_connection(req, now, service, dev,
     144             :                                req->vuid,&nt_status);
     145           0 :         req->conn = conn;
     146             : 
     147           0 :         if (!conn) {
     148           0 :                 reply_nterror(req, nt_status);
     149           0 :                 END_PROFILE(SMBtcon);
     150           0 :                 return;
     151             :         }
     152             : 
     153           0 :         reply_smb1_outbuf(req, 2, 0);
     154           0 :         SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
     155           0 :         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
     156           0 :         SSVAL(req->outbuf,smb_tid,conn->cnum);
     157             : 
     158           0 :         DEBUG(3,("tcon service=%s cnum=%d\n",
     159             :                  service, conn->cnum));
     160             : 
     161           0 :         END_PROFILE(SMBtcon);
     162           0 :         return;
     163             : }
     164             : 
     165             : /****************************************************************************
     166             :  Reply to a tcon and X.
     167             :  conn POINTER CAN BE NULL HERE !
     168             : ****************************************************************************/
     169             : 
     170          28 : void reply_tcon_and_X(struct smb_request *req)
     171             : {
     172             :         const struct loadparm_substitution *lp_sub =
     173          28 :                 loadparm_s3_global_substitution();
     174          28 :         connection_struct *conn = req->conn;
     175          28 :         const char *service = NULL;
     176          28 :         TALLOC_CTX *ctx = talloc_tos();
     177             :         /* what the client thinks the device is */
     178          28 :         char *client_devicetype = NULL;
     179             :         /* what the server tells the client the share represents */
     180             :         const char *server_devicetype;
     181             :         NTSTATUS nt_status;
     182             :         int passlen;
     183          28 :         char *path = NULL;
     184             :         const uint8_t *p;
     185             :         const char *q;
     186             :         uint16_t tcon_flags;
     187          28 :         struct smbXsrv_session *session = NULL;
     188          28 :         NTTIME now = timeval_to_nttime(&req->request_time);
     189          28 :         bool session_key_updated = false;
     190          28 :         uint16_t optional_support = 0;
     191          28 :         struct smbXsrv_connection *xconn = req->xconn;
     192             : 
     193          28 :         START_PROFILE(SMBtconX);
     194             : 
     195          28 :         if (req->wct < 4) {
     196           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     197           0 :                 END_PROFILE(SMBtconX);
     198           0 :                 return;
     199             :         }
     200             : 
     201          28 :         passlen = SVAL(req->vwv+3, 0);
     202          28 :         tcon_flags = SVAL(req->vwv+2, 0);
     203             : 
     204             :         /* we might have to close an old one */
     205          28 :         if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
     206             :                 struct smbXsrv_tcon *tcon;
     207             :                 NTSTATUS status;
     208             : 
     209           0 :                 tcon = conn->tcon;
     210           0 :                 req->conn = NULL;
     211           0 :                 conn = NULL;
     212             : 
     213             :                 /*
     214             :                  * TODO: cancel all outstanding requests on the tcon
     215             :                  */
     216           0 :                 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
     217           0 :                 if (!NT_STATUS_IS_OK(status)) {
     218           0 :                         DEBUG(0, ("reply_tcon_and_X: "
     219             :                                   "smbXsrv_tcon_disconnect() failed: %s\n",
     220             :                                   nt_errstr(status)));
     221             :                         /*
     222             :                          * If we hit this case, there is something completely
     223             :                          * wrong, so we better disconnect the transport connection.
     224             :                          */
     225           0 :                         END_PROFILE(SMBtconX);
     226           0 :                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
     227             :                         return;
     228             :                 }
     229             : 
     230           0 :                 TALLOC_FREE(tcon);
     231             :                 /*
     232             :                  * This tree id is gone. Make sure we can't re-use it
     233             :                  * by accident.
     234             :                  */
     235           0 :                 req->tid = 0;
     236             :         }
     237             : 
     238          28 :         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
     239           0 :                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
     240           0 :                 END_PROFILE(SMBtconX);
     241           0 :                 return;
     242             :         }
     243             : 
     244          28 :         if (xconn->smb1.negprot.encrypted_passwords) {
     245          28 :                 p = req->buf + passlen;
     246             :         } else {
     247           0 :                 p = req->buf + passlen + 1;
     248             :         }
     249             : 
     250          28 :         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
     251             : 
     252          28 :         if (path == NULL) {
     253           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     254           0 :                 END_PROFILE(SMBtconX);
     255           0 :                 return;
     256             :         }
     257             : 
     258             :         /*
     259             :          * the service name can be either: \\server\share
     260             :          * or share directly like on the DELL PowerVault 705
     261             :          */
     262          28 :         if (*path=='\\') {
     263          28 :                 q = strchr_m(path+2,'\\');
     264          28 :                 if (!q) {
     265           0 :                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
     266           0 :                         END_PROFILE(SMBtconX);
     267           0 :                         return;
     268             :                 }
     269          28 :                 service = q+1;
     270             :         } else {
     271           0 :                 service = path;
     272             :         }
     273             : 
     274          28 :         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
     275             :                                 &client_devicetype, p,
     276             :                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
     277             : 
     278          28 :         if (client_devicetype == NULL) {
     279           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     280           0 :                 END_PROFILE(SMBtconX);
     281           0 :                 return;
     282             :         }
     283             : 
     284          28 :         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
     285             : 
     286          28 :         nt_status = smb1srv_session_lookup(xconn,
     287          28 :                                            req->vuid, now, &session);
     288          28 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
     289           0 :                 reply_force_doserror(req, ERRSRV, ERRbaduid);
     290           0 :                 END_PROFILE(SMBtconX);
     291           0 :                 return;
     292             :         }
     293          28 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
     294           0 :                 reply_nterror(req, nt_status);
     295           0 :                 END_PROFILE(SMBtconX);
     296           0 :                 return;
     297             :         }
     298          28 :         if (!NT_STATUS_IS_OK(nt_status)) {
     299           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     300           0 :                 END_PROFILE(SMBtconX);
     301           0 :                 return;
     302             :         }
     303             : 
     304          28 :         if (session->global->auth_session_info == NULL) {
     305           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     306           0 :                 END_PROFILE(SMBtconX);
     307           0 :                 return;
     308             :         }
     309             : 
     310             :         /*
     311             :          * If there is no application key defined yet
     312             :          * we create one.
     313             :          *
     314             :          * This means we setup the application key on the
     315             :          * first tcon that happens via the given session.
     316             :          *
     317             :          * Once the application key is defined, it does not
     318             :          * change any more.
     319             :          */
     320          56 :         if (session->global->application_key_blob.length == 0 &&
     321          28 :             smb2_signing_key_valid(session->global->signing_key))
     322             :         {
     323          28 :                 struct smbXsrv_session *x = session;
     324          28 :                 struct auth_session_info *session_info =
     325          28 :                         session->global->auth_session_info;
     326             :                 uint8_t session_key[16];
     327             : 
     328          28 :                 ZERO_STRUCT(session_key);
     329          28 :                 memcpy(session_key, x->global->signing_key->blob.data,
     330          28 :                        MIN(x->global->signing_key->blob.length, sizeof(session_key)));
     331             : 
     332             :                 /*
     333             :                  * The application key is truncated/padded to 16 bytes
     334             :                  */
     335          28 :                 x->global->application_key_blob = data_blob_talloc(x->global,
     336             :                                                              session_key,
     337             :                                                              sizeof(session_key));
     338          28 :                 ZERO_STRUCT(session_key);
     339          28 :                 if (x->global->application_key_blob.data == NULL) {
     340           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     341           0 :                         END_PROFILE(SMBtconX);
     342           0 :                         return;
     343             :                 }
     344          28 :                 talloc_keep_secret(x->global->application_key_blob.data);
     345             : 
     346          28 :                 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
     347             :                         NTSTATUS status;
     348             : 
     349          28 :                         status = smb1_key_derivation(x->global->application_key_blob.data,
     350          28 :                                                     x->global->application_key_blob.length,
     351          28 :                                                     x->global->application_key_blob.data);
     352          28 :                         if (!NT_STATUS_IS_OK(status)) {
     353           0 :                                 DBG_ERR("smb1_key_derivation failed: %s\n",
     354             :                                         nt_errstr(status));
     355           0 :                                 END_PROFILE(SMBtconX);
     356           0 :                                 return;
     357             :                         }
     358          28 :                         optional_support |= SMB_EXTENDED_SIGNATURES;
     359             :                 }
     360             : 
     361             :                 /*
     362             :                  * Place the application key into the session_info
     363             :                  */
     364          28 :                 data_blob_clear_free(&session_info->session_key);
     365          28 :                 session_info->session_key = data_blob_dup_talloc(session_info,
     366             :                                                 x->global->application_key_blob);
     367          28 :                 if (session_info->session_key.data == NULL) {
     368           0 :                         data_blob_clear_free(&x->global->application_key_blob);
     369           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     370           0 :                         END_PROFILE(SMBtconX);
     371           0 :                         return;
     372             :                 }
     373          28 :                 talloc_keep_secret(session_info->session_key.data);
     374          28 :                 session_key_updated = true;
     375             :         }
     376             : 
     377          28 :         conn = make_connection(req, now, service, client_devicetype,
     378             :                                req->vuid, &nt_status);
     379          28 :         req->conn =conn;
     380             : 
     381          28 :         if (!conn) {
     382           0 :                 if (session_key_updated) {
     383           0 :                         struct smbXsrv_session *x = session;
     384           0 :                         struct auth_session_info *session_info =
     385           0 :                                 session->global->auth_session_info;
     386           0 :                         data_blob_clear_free(&x->global->application_key_blob);
     387           0 :                         data_blob_clear_free(&session_info->session_key);
     388             :                 }
     389           0 :                 reply_nterror(req, nt_status);
     390           0 :                 END_PROFILE(SMBtconX);
     391           0 :                 return;
     392             :         }
     393             : 
     394          28 :         if ( IS_IPC(conn) )
     395          20 :                 server_devicetype = "IPC";
     396           8 :         else if ( IS_PRINT(conn) )
     397           0 :                 server_devicetype = "LPT1:";
     398             :         else
     399           8 :                 server_devicetype = "A:";
     400             : 
     401          28 :         if (get_Protocol() < PROTOCOL_NT1) {
     402           0 :                 reply_smb1_outbuf(req, 2, 0);
     403           0 :                 if (message_push_string(&req->outbuf, server_devicetype,
     404             :                                         STR_TERMINATE|STR_ASCII) == -1) {
     405           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     406           0 :                         END_PROFILE(SMBtconX);
     407           0 :                         return;
     408             :                 }
     409             :         } else {
     410             :                 /* NT sets the fstype of IPC$ to the null string */
     411          28 :                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
     412             : 
     413          28 :                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
     414             :                         /* Return permissions. */
     415          28 :                         uint32_t perm1 = 0;
     416          28 :                         uint32_t perm2 = 0;
     417             : 
     418          28 :                         reply_smb1_outbuf(req, 7, 0);
     419             : 
     420          28 :                         if (IS_IPC(conn)) {
     421          20 :                                 perm1 = FILE_ALL_ACCESS;
     422          20 :                                 perm2 = FILE_ALL_ACCESS;
     423             :                         } else {
     424           8 :                                 perm1 = conn->share_access;
     425             :                         }
     426             : 
     427          28 :                         SIVAL(req->outbuf, smb_vwv3, perm1);
     428          28 :                         SIVAL(req->outbuf, smb_vwv5, perm2);
     429             :                 } else {
     430           0 :                         reply_smb1_outbuf(req, 3, 0);
     431             :                 }
     432             : 
     433          28 :                 if ((message_push_string(&req->outbuf, server_devicetype,
     434             :                                          STR_TERMINATE|STR_ASCII) == -1)
     435          28 :                     || (message_push_string(&req->outbuf, fstype,
     436             :                                             STR_TERMINATE) == -1)) {
     437           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     438           0 :                         END_PROFILE(SMBtconX);
     439           0 :                         return;
     440             :                 }
     441             : 
     442             :                 /* what does setting this bit do? It is set by NT4 and
     443             :                    may affect the ability to autorun mounted cdroms */
     444          28 :                 optional_support |= SMB_SUPPORT_SEARCH_BITS;
     445          28 :                 optional_support |=
     446          28 :                         (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
     447             : 
     448          28 :                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
     449           0 :                         DEBUG(2,("Serving %s as a Dfs root\n",
     450             :                                  lp_servicename(ctx, lp_sub, SNUM(conn)) ));
     451           0 :                         optional_support |= SMB_SHARE_IN_DFS;
     452             :                 }
     453             : 
     454          28 :                 SSVAL(req->outbuf, smb_vwv2, optional_support);
     455             :         }
     456             : 
     457          28 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
     458          28 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
     459             : 
     460          28 :         DEBUG(3,("tconX service=%s \n",
     461             :                  service));
     462             : 
     463             :         /* set the incoming and outgoing tid to the just created one */
     464          28 :         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
     465          28 :         SSVAL(req->outbuf,smb_tid,conn->cnum);
     466             : 
     467          28 :         END_PROFILE(SMBtconX);
     468             : 
     469          28 :         req->tid = conn->cnum;
     470             : }
     471             : 
     472             : /****************************************************************************
     473             :  Reply to an unknown type.
     474             : ****************************************************************************/
     475             : 
     476           0 : void reply_unknown_new(struct smb_request *req, uint8_t type)
     477             : {
     478           0 :         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
     479             :                   smb_fn_name(type), type, type));
     480           0 :         reply_force_doserror(req, ERRSRV, ERRunknownsmb);
     481           0 :         return;
     482             : }
     483             : 
     484             : /****************************************************************************
     485             :  Reply to an ioctl.
     486             :  conn POINTER CAN BE NULL HERE !
     487             : ****************************************************************************/
     488             : 
     489           0 : void reply_ioctl(struct smb_request *req)
     490             : {
     491             :         const struct loadparm_substitution *lp_sub =
     492           0 :                 loadparm_s3_global_substitution();
     493           0 :         connection_struct *conn = req->conn;
     494             :         uint16_t device;
     495             :         uint16_t function;
     496             :         uint32_t ioctl_code;
     497             :         int replysize;
     498             :         char *p;
     499             : 
     500           0 :         START_PROFILE(SMBioctl);
     501             : 
     502           0 :         if (req->wct < 3) {
     503           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     504           0 :                 END_PROFILE(SMBioctl);
     505           0 :                 return;
     506             :         }
     507             : 
     508           0 :         device     = SVAL(req->vwv+1, 0);
     509           0 :         function   = SVAL(req->vwv+2, 0);
     510           0 :         ioctl_code = (device << 16) + function;
     511             : 
     512           0 :         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
     513             : 
     514           0 :         switch (ioctl_code) {
     515           0 :             case IOCTL_QUERY_JOB_INFO:
     516           0 :                     replysize = 32;
     517           0 :                     break;
     518           0 :             default:
     519           0 :                     reply_force_doserror(req, ERRSRV, ERRnosupport);
     520           0 :                     END_PROFILE(SMBioctl);
     521           0 :                     return;
     522             :         }
     523             : 
     524           0 :         reply_smb1_outbuf(req, 8, replysize+1);
     525           0 :         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
     526           0 :         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
     527           0 :         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
     528           0 :         p = smb_buf(req->outbuf);
     529           0 :         memset(p, '\0', replysize+1); /* valgrind-safe. */
     530           0 :         p += 1;          /* Allow for alignment */
     531             : 
     532           0 :         switch (ioctl_code) {
     533           0 :                 case IOCTL_QUERY_JOB_INFO:                  
     534             :                 {
     535             :                         NTSTATUS status;
     536           0 :                         size_t len = 0;
     537           0 :                         files_struct *fsp = file_fsp(
     538           0 :                                 req, SVAL(req->vwv+0, 0));
     539           0 :                         if (!fsp) {
     540           0 :                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     541           0 :                                 END_PROFILE(SMBioctl);
     542           0 :                                 return;
     543             :                         }
     544             :                         /* Job number */
     545           0 :                         SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
     546             : 
     547           0 :                         status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
     548             :                                     lp_netbios_name(), 15,
     549             :                                     STR_TERMINATE|STR_ASCII, &len);
     550           0 :                         if (!NT_STATUS_IS_OK(status)) {
     551           0 :                                 reply_nterror(req, status);
     552           0 :                                 END_PROFILE(SMBioctl);
     553           0 :                                 return;
     554             :                         }
     555           0 :                         if (conn) {
     556           0 :                                 status = srvstr_push((char *)req->outbuf, req->flags2,
     557             :                                             p+18,
     558             :                                             lp_servicename(talloc_tos(),
     559             :                                                            lp_sub,
     560             :                                                            SNUM(conn)),
     561             :                                             13, STR_TERMINATE|STR_ASCII, &len);
     562           0 :                                 if (!NT_STATUS_IS_OK(status)) {
     563           0 :                                         reply_nterror(req, status);
     564           0 :                                         END_PROFILE(SMBioctl);
     565           0 :                                         return;
     566             :                                 }
     567             :                         } else {
     568           0 :                                 memset(p+18, 0, 13);
     569             :                         }
     570           0 :                         break;
     571             :                 }
     572             :         }
     573             : 
     574           0 :         END_PROFILE(SMBioctl);
     575           0 :         return;
     576             : }
     577             : 
     578             : /****************************************************************************
     579             :  Strange checkpath NTSTATUS mapping.
     580             : ****************************************************************************/
     581             : 
     582           0 : static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
     583             : {
     584             :         /* Strange DOS error code semantics only for checkpath... */
     585           0 :         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
     586           0 :                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
     587             :                         /* We need to map to ERRbadpath */
     588           0 :                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     589             :                 }
     590             :         }
     591           0 :         return status;
     592             : }
     593             : 
     594             : /****************************************************************************
     595             :  Reply to a checkpath.
     596             : ****************************************************************************/
     597             : 
     598           0 : void reply_checkpath(struct smb_request *req)
     599             : {
     600           0 :         connection_struct *conn = req->conn;
     601           0 :         struct smb_filename *smb_fname = NULL;
     602           0 :         char *name = NULL;
     603             :         NTSTATUS status;
     604           0 :         struct files_struct *dirfsp = NULL;
     605           0 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
     606           0 :         NTTIME twrp = 0;
     607           0 :         TALLOC_CTX *ctx = talloc_tos();
     608             : 
     609           0 :         START_PROFILE(SMBcheckpath);
     610             : 
     611           0 :         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
     612             :                             STR_TERMINATE, &status);
     613             : 
     614           0 :         if (!NT_STATUS_IS_OK(status)) {
     615           0 :                 status = map_checkpath_error(req->flags2, status);
     616           0 :                 reply_nterror(req, status);
     617           0 :                 END_PROFILE(SMBcheckpath);
     618           0 :                 return;
     619             :         }
     620             : 
     621           0 :         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
     622             : 
     623           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
     624           0 :                 extract_snapshot_token(name, &twrp);
     625             :         }
     626           0 :         status = filename_convert_dirfsp(ctx,
     627             :                                          conn,
     628             :                                          name,
     629             :                                          ucf_flags,
     630             :                                          twrp,
     631             :                                          &dirfsp,
     632             :                                          &smb_fname);
     633           0 :         if (!NT_STATUS_IS_OK(status)) {
     634           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
     635           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
     636             :                                         ERRSRV, ERRbadpath);
     637           0 :                         END_PROFILE(SMBcheckpath);
     638           0 :                         return;
     639             :                 }
     640           0 :                 goto path_err;
     641             :         }
     642             : 
     643           0 :         if (!VALID_STAT(smb_fname->st) &&
     644           0 :             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
     645           0 :                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
     646             :                         smb_fname_str_dbg(smb_fname), strerror(errno)));
     647           0 :                 status = map_nt_error_from_unix(errno);
     648           0 :                 goto path_err;
     649             :         }
     650             : 
     651           0 :         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
     652           0 :                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
     653             :                                 ERRDOS, ERRbadpath);
     654           0 :                 goto out;
     655             :         }
     656             : 
     657           0 :         reply_smb1_outbuf(req, 0, 0);
     658             : 
     659           0 :  path_err:
     660             :         /* We special case this - as when a Windows machine
     661             :                 is parsing a path is steps through the components
     662             :                 one at a time - if a component fails it expects
     663             :                 ERRbadpath, not ERRbadfile.
     664             :         */
     665           0 :         status = map_checkpath_error(req->flags2, status);
     666           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     667             :                 /*
     668             :                  * Windows returns different error codes if
     669             :                  * the parent directory is valid but not the
     670             :                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
     671             :                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
     672             :                  * if the path is invalid.
     673             :                  */
     674           0 :                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     675             :                                 ERRDOS, ERRbadpath);
     676           0 :                 goto out;
     677             :         }
     678             : 
     679           0 :         reply_nterror(req, status);
     680             : 
     681           0 :  out:
     682           0 :         TALLOC_FREE(smb_fname);
     683           0 :         END_PROFILE(SMBcheckpath);
     684           0 :         return;
     685             : }
     686             : 
     687             : /****************************************************************************
     688             :  Reply to a getatr.
     689             : ****************************************************************************/
     690             : 
     691           0 : void reply_getatr(struct smb_request *req)
     692             : {
     693           0 :         connection_struct *conn = req->conn;
     694           0 :         struct smb_filename *smb_fname = NULL;
     695           0 :         char *fname = NULL;
     696           0 :         int mode=0;
     697           0 :         off_t size=0;
     698           0 :         time_t mtime=0;
     699             :         const char *p;
     700             :         NTSTATUS status;
     701           0 :         TALLOC_CTX *ctx = talloc_tos();
     702             : 
     703           0 :         START_PROFILE(SMBgetatr);
     704             : 
     705           0 :         p = (const char *)req->buf + 1;
     706           0 :         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
     707           0 :         if (!NT_STATUS_IS_OK(status)) {
     708           0 :                 reply_nterror(req, status);
     709           0 :                 goto out;
     710             :         }
     711             : 
     712             :         /*
     713             :          * dos sometimes asks for a stat of "" - it returns a "hidden
     714             :          * directory" under WfWg - weird!
     715             :          */
     716           0 :         if (*fname == '\0') {
     717           0 :                 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
     718           0 :                 if (!CAN_WRITE(conn)) {
     719           0 :                         mode |= FILE_ATTRIBUTE_READONLY;
     720             :                 }
     721           0 :                 size = 0;
     722           0 :                 mtime = 0;
     723             :         } else {
     724           0 :                 struct files_struct *dirfsp = NULL;
     725           0 :                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
     726           0 :                 NTTIME twrp = 0;
     727             :                 bool ask_sharemode;
     728             : 
     729           0 :                 if (ucf_flags & UCF_GMT_PATHNAME) {
     730           0 :                         extract_snapshot_token(fname, &twrp);
     731             :                 }
     732           0 :                 status = filename_convert_dirfsp(ctx,
     733             :                                                  conn,
     734             :                                                  fname,
     735             :                                                  ucf_flags,
     736             :                                                  twrp,
     737             :                                                  &dirfsp,
     738             :                                                  &smb_fname);
     739           0 :                 if (!NT_STATUS_IS_OK(status)) {
     740           0 :                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
     741           0 :                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
     742             :                                                 ERRSRV, ERRbadpath);
     743           0 :                                 goto out;
     744             :                         }
     745           0 :                         reply_nterror(req, status);
     746           0 :                         goto out;
     747             :                 }
     748           0 :                 if (!VALID_STAT(smb_fname->st) &&
     749           0 :                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
     750           0 :                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
     751             :                                  smb_fname_str_dbg(smb_fname),
     752             :                                  strerror(errno)));
     753           0 :                         reply_nterror(req,  map_nt_error_from_unix(errno));
     754           0 :                         goto out;
     755             :                 }
     756             : 
     757           0 :                 mode = fdos_mode(smb_fname->fsp);
     758           0 :                 size = smb_fname->st.st_ex_size;
     759             : 
     760           0 :                 ask_sharemode = fsp_search_ask_sharemode(smb_fname->fsp);
     761           0 :                 if (ask_sharemode) {
     762             :                         struct timespec write_time_ts;
     763             :                         struct file_id fileid;
     764             : 
     765           0 :                         ZERO_STRUCT(write_time_ts);
     766           0 :                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
     767           0 :                         get_file_infos(fileid, 0, NULL, &write_time_ts);
     768           0 :                         if (!is_omit_timespec(&write_time_ts)) {
     769           0 :                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
     770             :                         }
     771             :                 }
     772             : 
     773           0 :                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
     774           0 :                 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
     775           0 :                         size = 0;
     776             :                 }
     777             :         }
     778             : 
     779           0 :         reply_smb1_outbuf(req, 10, 0);
     780             : 
     781           0 :         SSVAL(req->outbuf,smb_vwv0,mode);
     782           0 :         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
     783           0 :                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
     784             :         } else {
     785           0 :                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
     786             :         }
     787           0 :         SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
     788             : 
     789           0 :         if (get_Protocol() >= PROTOCOL_NT1) {
     790           0 :                 SSVAL(req->outbuf, smb_flg2,
     791             :                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
     792             :         }
     793             : 
     794           0 :         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
     795             :                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
     796             : 
     797           0 :  out:
     798           0 :         TALLOC_FREE(smb_fname);
     799           0 :         TALLOC_FREE(fname);
     800           0 :         END_PROFILE(SMBgetatr);
     801           0 :         return;
     802             : }
     803             : 
     804             : /****************************************************************************
     805             :  Reply to a setatr.
     806             : ****************************************************************************/
     807             : 
     808           0 : void reply_setatr(struct smb_request *req)
     809             : {
     810             :         struct smb_file_time ft;
     811           0 :         connection_struct *conn = req->conn;
     812           0 :         struct smb_filename *smb_fname = NULL;
     813           0 :         struct files_struct *dirfsp = NULL;
     814           0 :         char *fname = NULL;
     815             :         int mode;
     816             :         time_t mtime;
     817             :         const char *p;
     818             :         NTSTATUS status;
     819           0 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
     820           0 :         NTTIME twrp = 0;
     821           0 :         TALLOC_CTX *ctx = talloc_tos();
     822             : 
     823           0 :         START_PROFILE(SMBsetatr);
     824           0 :         init_smb_file_time(&ft);
     825             : 
     826           0 :         if (req->wct < 2) {
     827           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     828           0 :                 goto out;
     829             :         }
     830             : 
     831           0 :         p = (const char *)req->buf + 1;
     832           0 :         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
     833           0 :         if (!NT_STATUS_IS_OK(status)) {
     834           0 :                 reply_nterror(req, status);
     835           0 :                 goto out;
     836             :         }
     837             : 
     838           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
     839           0 :                 extract_snapshot_token(fname, &twrp);
     840             :         }
     841           0 :         status = filename_convert_dirfsp(ctx,
     842             :                                          conn,
     843             :                                          fname,
     844             :                                          ucf_flags,
     845             :                                          twrp,
     846             :                                          &dirfsp,
     847             :                                          &smb_fname);
     848           0 :         if (!NT_STATUS_IS_OK(status)) {
     849           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
     850           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
     851             :                                         ERRSRV, ERRbadpath);
     852           0 :                         goto out;
     853             :                 }
     854           0 :                 reply_nterror(req, status);
     855           0 :                 goto out;
     856             :         }
     857             : 
     858           0 :         if (ISDOT(smb_fname->base_name)) {
     859             :                 /*
     860             :                  * Not sure here is the right place to catch this
     861             :                  * condition. Might be moved to somewhere else later -- vl
     862             :                  */
     863           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     864           0 :                 goto out;
     865             :         }
     866             : 
     867           0 :         if (smb_fname->fsp == NULL) {
     868             :                 /* Can't set access rights on a symlink. */
     869           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     870           0 :                 goto out;
     871             :         }
     872             : 
     873           0 :         mode = SVAL(req->vwv+0, 0);
     874           0 :         mtime = srv_make_unix_date3(req->vwv+1);
     875             : 
     876           0 :         if (mode != FILE_ATTRIBUTE_NORMAL) {
     877           0 :                 if (VALID_STAT_OF_DIR(smb_fname->st))
     878           0 :                         mode |= FILE_ATTRIBUTE_DIRECTORY;
     879             :                 else
     880           0 :                         mode &= ~FILE_ATTRIBUTE_DIRECTORY;
     881             : 
     882           0 :                 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
     883           0 :                                         smb_fname->fsp,
     884             :                                         false,
     885             :                                         FILE_WRITE_ATTRIBUTES);
     886           0 :                 if (!NT_STATUS_IS_OK(status)) {
     887           0 :                         reply_nterror(req, status);
     888           0 :                         goto out;
     889             :                 }
     890             : 
     891           0 :                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
     892             :                                      false) != 0) {
     893           0 :                         reply_nterror(req, map_nt_error_from_unix(errno));
     894           0 :                         goto out;
     895             :                 }
     896             :         }
     897             : 
     898           0 :         ft.mtime = time_t_to_full_timespec(mtime);
     899             : 
     900           0 :         status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
     901           0 :         if (!NT_STATUS_IS_OK(status)) {
     902           0 :                 reply_nterror(req, status);
     903           0 :                 goto out;
     904             :         }
     905             : 
     906           0 :         reply_smb1_outbuf(req, 0, 0);
     907             : 
     908           0 :         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
     909             :                  mode));
     910           0 :  out:
     911           0 :         TALLOC_FREE(smb_fname);
     912           0 :         END_PROFILE(SMBsetatr);
     913           0 :         return;
     914             : }
     915             : 
     916             : /****************************************************************************
     917             :  Reply to a dskattr.
     918             : ****************************************************************************/
     919             : 
     920           0 : void reply_dskattr(struct smb_request *req)
     921             : {
     922           0 :         connection_struct *conn = req->conn;
     923             :         uint64_t ret;
     924             :         uint64_t dfree,dsize,bsize;
     925             :         struct smb_filename smb_fname;
     926           0 :         START_PROFILE(SMBdskattr);
     927             : 
     928           0 :         ZERO_STRUCT(smb_fname);
     929           0 :         smb_fname.base_name = discard_const_p(char, ".");
     930             : 
     931           0 :         if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
     932           0 :                 reply_nterror(req, map_nt_error_from_unix(errno));
     933           0 :                 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
     934           0 :                 END_PROFILE(SMBdskattr);
     935           0 :                 return;
     936             :         }
     937             : 
     938           0 :         ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
     939           0 :         if (ret == (uint64_t)-1) {
     940           0 :                 reply_nterror(req, map_nt_error_from_unix(errno));
     941           0 :                 END_PROFILE(SMBdskattr);
     942           0 :                 return;
     943             :         }
     944             : 
     945             :         /*
     946             :          * Force max to fit in 16 bit fields.
     947             :          */
     948           0 :         while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
     949           0 :                 dfree /= 2;
     950           0 :                 dsize /= 2;
     951           0 :                 bsize *= 2;
     952           0 :                 if (bsize > (WORDMAX*512)) {
     953           0 :                         bsize = (WORDMAX*512);
     954           0 :                         if (dsize > WORDMAX)
     955           0 :                                 dsize = WORDMAX;
     956           0 :                         if (dfree >  WORDMAX)
     957           0 :                                 dfree = WORDMAX;
     958           0 :                         break;
     959             :                 }
     960             :         }
     961             : 
     962           0 :         reply_smb1_outbuf(req, 5, 0);
     963             : 
     964           0 :         if (get_Protocol() <= PROTOCOL_LANMAN2) {
     965             :                 double total_space, free_space;
     966             :                 /* we need to scale this to a number that DOS6 can handle. We
     967             :                    use floating point so we can handle large drives on systems
     968             :                    that don't have 64 bit integers 
     969             : 
     970             :                    we end up displaying a maximum of 2G to DOS systems
     971             :                 */
     972           0 :                 total_space = dsize * (double)bsize;
     973           0 :                 free_space = dfree * (double)bsize;
     974             : 
     975           0 :                 dsize = (uint64_t)((total_space+63*512) / (64*512));
     976           0 :                 dfree = (uint64_t)((free_space+63*512) / (64*512));
     977             : 
     978           0 :                 if (dsize > 0xFFFF) dsize = 0xFFFF;
     979           0 :                 if (dfree > 0xFFFF) dfree = 0xFFFF;
     980             : 
     981           0 :                 SSVAL(req->outbuf,smb_vwv0,dsize);
     982           0 :                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
     983           0 :                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
     984           0 :                 SSVAL(req->outbuf,smb_vwv3,dfree);
     985             :         } else {
     986           0 :                 SSVAL(req->outbuf,smb_vwv0,dsize);
     987           0 :                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
     988           0 :                 SSVAL(req->outbuf,smb_vwv2,512);
     989           0 :                 SSVAL(req->outbuf,smb_vwv3,dfree);
     990             :         }
     991             : 
     992           0 :         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
     993             : 
     994           0 :         END_PROFILE(SMBdskattr);
     995           0 :         return;
     996             : }
     997             : 
     998             : /****************************************************************************
     999             :  Make a dir struct.
    1000             : ****************************************************************************/
    1001             : 
    1002           0 : static bool make_dir_struct(TALLOC_CTX *ctx,
    1003             :                             char *buf,
    1004             :                             const char *mask,
    1005             :                             const char *fname,
    1006             :                             off_t size,
    1007             :                             uint32_t mode,
    1008             :                             time_t date,
    1009             :                             bool uc)
    1010             : {
    1011             :         char *p;
    1012           0 :         char *mask2 = talloc_strdup(ctx, mask);
    1013             : 
    1014           0 :         if (!mask2) {
    1015           0 :                 return False;
    1016             :         }
    1017             : 
    1018           0 :         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    1019           0 :                 size = 0;
    1020             :         }
    1021             : 
    1022           0 :         memset(buf+1,' ',11);
    1023           0 :         if ((p = strchr_m(mask2,'.')) != NULL) {
    1024           0 :                 *p = 0;
    1025           0 :                 push_ascii(buf+1,mask2,8, 0);
    1026           0 :                 push_ascii(buf+9,p+1,3, 0);
    1027           0 :                 *p = '.';
    1028             :         } else {
    1029           0 :                 push_ascii(buf+1,mask2,11, 0);
    1030             :         }
    1031             : 
    1032           0 :         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
    1033           0 :         SCVAL(buf,21,mode);
    1034           0 :         srv_put_dos_date(buf,22,date);
    1035           0 :         SSVAL(buf,26,size & 0xFFFF);
    1036           0 :         SSVAL(buf,28,(size >> 16)&0xFFFF);
    1037             :         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
    1038             :            Strange, but verified on W2K3. Needed for OS/2. JRA. */
    1039           0 :         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
    1040           0 :         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
    1041           0 :         return True;
    1042             : }
    1043             : 
    1044             : /****************************************************************************
    1045             :  Reply to a search.
    1046             :  Can be called from SMBsearch, SMBffirst or SMBfunique.
    1047             : ****************************************************************************/
    1048             : 
    1049           0 : void reply_search(struct smb_request *req)
    1050             : {
    1051           0 :         connection_struct *conn = req->conn;
    1052           0 :         char *path = NULL;
    1053           0 :         char *mask = NULL;
    1054           0 :         char *directory = NULL;
    1055           0 :         struct smb_filename *smb_fname = NULL;
    1056           0 :         char *fname = NULL;
    1057             :         off_t size;
    1058             :         uint32_t mode;
    1059             :         struct timespec date;
    1060             :         uint32_t dirtype;
    1061           0 :         unsigned int numentries = 0;
    1062           0 :         unsigned int maxentries = 0;
    1063           0 :         bool finished = False;
    1064             :         const char *p;
    1065             :         int status_len;
    1066             :         char status[21];
    1067           0 :         int dptr_num= -1;
    1068           0 :         bool check_descend = False;
    1069           0 :         bool expect_close = False;
    1070             :         NTSTATUS nt_status;
    1071           0 :         bool mask_contains_wcard = False;
    1072           0 :         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
    1073           0 :         TALLOC_CTX *ctx = talloc_tos();
    1074           0 :         struct smbXsrv_connection *xconn = req->xconn;
    1075           0 :         struct smbd_server_connection *sconn = req->sconn;
    1076           0 :         files_struct *fsp = NULL;
    1077             :         const struct loadparm_substitution *lp_sub =
    1078           0 :                 loadparm_s3_global_substitution();
    1079             : 
    1080           0 :         START_PROFILE(SMBsearch);
    1081             : 
    1082           0 :         if (req->wct < 2) {
    1083           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1084           0 :                 goto out;
    1085             :         }
    1086             : 
    1087           0 :         if (req->posix_pathnames) {
    1088           0 :                 reply_unknown_new(req, req->cmd);
    1089           0 :                 goto out;
    1090             :         }
    1091             : 
    1092             :         /* If we were called as SMBffirst then we must expect close. */
    1093           0 :         if(req->cmd == SMBffirst) {
    1094           0 :                 expect_close = True;
    1095             :         }
    1096             : 
    1097           0 :         reply_smb1_outbuf(req, 1, 3);
    1098           0 :         maxentries = SVAL(req->vwv+0, 0);
    1099           0 :         dirtype = SVAL(req->vwv+1, 0);
    1100           0 :         p = (const char *)req->buf + 1;
    1101           0 :         p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
    1102             :                                        &nt_status);
    1103           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1104           0 :                 reply_nterror(req, nt_status);
    1105           0 :                 goto out;
    1106             :         }
    1107             : 
    1108           0 :         if (smbreq_bufrem(req, p) < 3) {
    1109           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1110           0 :                 goto out;
    1111             :         }
    1112             : 
    1113           0 :         p++;
    1114           0 :         status_len = SVAL(p, 0);
    1115           0 :         p += 2;
    1116             : 
    1117             :         /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
    1118             : 
    1119           0 :         if (status_len == 0) {
    1120             :                 const char *dirpath;
    1121           0 :                 struct files_struct *dirfsp = NULL;
    1122           0 :                 struct smb_filename *smb_dname = NULL;
    1123           0 :                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    1124             : 
    1125           0 :                 nt_status = filename_convert_smb1_search_path(ctx,
    1126             :                                         conn,
    1127             :                                         path,
    1128             :                                         ucf_flags,
    1129             :                                         &dirfsp,
    1130             :                                         &smb_dname,
    1131             :                                         &mask);
    1132             : 
    1133           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1134           0 :                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
    1135           0 :                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    1136             :                                                 ERRSRV, ERRbadpath);
    1137           0 :                                 goto out;
    1138             :                         }
    1139           0 :                         reply_nterror(req, nt_status);
    1140           0 :                         goto out;
    1141             :                 }
    1142             : 
    1143           0 :                 memset((char *)status,'\0',21);
    1144           0 :                 SCVAL(status,0,(dirtype & 0x1F));
    1145             : 
    1146             :                 /*
    1147             :                  * Open an fsp on this directory for the dptr.
    1148             :                  */
    1149           0 :                 nt_status = SMB_VFS_CREATE_FILE(
    1150             :                                 conn, /* conn */
    1151             :                                 req, /* req */
    1152             :                                 dirfsp, /* dirfsp */
    1153             :                                 smb_dname, /* dname */
    1154             :                                 FILE_LIST_DIRECTORY, /* access_mask */
    1155             :                                 FILE_SHARE_READ|
    1156             :                                 FILE_SHARE_WRITE, /* share_access */
    1157             :                                 FILE_OPEN, /* create_disposition*/
    1158             :                                 FILE_DIRECTORY_FILE, /* create_options */
    1159             :                                 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
    1160             :                                 NO_OPLOCK, /* oplock_request */
    1161             :                                 NULL, /* lease */
    1162             :                                 0, /* allocation_size */
    1163             :                                 0, /* private_flags */
    1164             :                                 NULL, /* sd */
    1165             :                                 NULL, /* ea_list */
    1166             :                                 &fsp, /* result */
    1167             :                                 NULL, /* pinfo */
    1168             :                                 NULL, /* in_context */
    1169             :                                 NULL);/* out_context */
    1170             : 
    1171           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1172           0 :                         DBG_ERR("failed to open directory %s\n",
    1173             :                                 smb_fname_str_dbg(smb_dname));
    1174           0 :                         reply_nterror(req, nt_status);
    1175           0 :                         goto out;
    1176             :                 }
    1177             : 
    1178           0 :                 nt_status = dptr_create(conn,
    1179             :                                         NULL, /* req */
    1180             :                                         fsp, /* fsp */
    1181             :                                         True,
    1182             :                                         expect_close,
    1183           0 :                                         req->smbpid,
    1184             :                                         mask,
    1185             :                                         dirtype,
    1186           0 :                                         &fsp->dptr);
    1187             : 
    1188           0 :                 TALLOC_FREE(smb_dname);
    1189             : 
    1190           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1191             :                         /*
    1192             :                          * Use NULL here for the first parameter (req)
    1193             :                          * as this is not a client visible handle so
    1194             :                          * can'tbe part of an SMB1 chain.
    1195             :                          */
    1196           0 :                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1197           0 :                         reply_nterror(req, nt_status);
    1198           0 :                         goto out;
    1199             :                 }
    1200             : 
    1201           0 :                 dptr_num = dptr_dnum(fsp->dptr);
    1202           0 :                 dirpath = dptr_path(sconn, dptr_num);
    1203           0 :                 directory = talloc_strdup(ctx, dirpath);
    1204           0 :                 if (!directory) {
    1205           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1206           0 :                         goto out;
    1207             :                 }
    1208             : 
    1209             :         } else {
    1210             :                 int status_dirtype;
    1211             :                 const char *dirpath;
    1212             : 
    1213           0 :                 if (smbreq_bufrem(req, p) < 21) {
    1214           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1215           0 :                         goto out;
    1216             :                 }
    1217             : 
    1218           0 :                 memcpy(status,p,21);
    1219           0 :                 status_dirtype = CVAL(status,0) & 0x1F;
    1220           0 :                 if (status_dirtype != (dirtype & 0x1F)) {
    1221           0 :                         dirtype = status_dirtype;
    1222             :                 }
    1223             : 
    1224           0 :                 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
    1225           0 :                 if (fsp == NULL) {
    1226           0 :                         goto SearchEmpty;
    1227             :                 }
    1228           0 :                 dirpath = dptr_path(sconn, dptr_num);
    1229           0 :                 directory = talloc_strdup(ctx, dirpath);
    1230           0 :                 if (!directory) {
    1231           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1232           0 :                         goto out;
    1233             :                 }
    1234             : 
    1235           0 :                 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
    1236           0 :                 if (!mask) {
    1237           0 :                         goto SearchEmpty;
    1238             :                 }
    1239           0 :                 dirtype = dptr_attr(sconn, dptr_num);
    1240             :         }
    1241             : 
    1242           0 :         mask_contains_wcard = dptr_has_wild(fsp->dptr);
    1243             : 
    1244           0 :         DEBUG(4,("dptr_num is %d\n",dptr_num));
    1245             : 
    1246           0 :         if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
    1247             :                 char buf[DIR_STRUCT_SIZE];
    1248           0 :                 memcpy(buf,status,21);
    1249           0 :                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
    1250           0 :                                 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
    1251           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1252           0 :                         goto out;
    1253             :                 }
    1254           0 :                 dptr_fill(sconn, buf+12,dptr_num);
    1255           0 :                 if (dptr_zero(buf+12) && (status_len==0)) {
    1256           0 :                         numentries = 1;
    1257             :                 } else {
    1258           0 :                         numentries = 0;
    1259             :                 }
    1260           0 :                 if (message_push_blob(&req->outbuf,
    1261             :                                       data_blob_const(buf, sizeof(buf)))
    1262             :                     == -1) {
    1263           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1264           0 :                         goto out;
    1265             :                 }
    1266             :         } else {
    1267             :                 unsigned int i;
    1268           0 :                 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
    1269           0 :                 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
    1270             :                 bool ask_sharemode;
    1271             : 
    1272           0 :                 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
    1273             : 
    1274           0 :                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
    1275             :                          directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
    1276           0 :                 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
    1277           0 :                         check_descend = True;
    1278             :                 }
    1279             : 
    1280           0 :                 ask_sharemode = fsp_search_ask_sharemode(fsp);
    1281             : 
    1282           0 :                 for (i=numentries;(i<maxentries) && !finished;i++) {
    1283           0 :                         finished = !get_dir_entry(ctx,
    1284           0 :                                                   fsp->dptr,
    1285             :                                                   mask,
    1286             :                                                   dirtype,
    1287             :                                                   &fname,
    1288             :                                                   &size,
    1289             :                                                   &mode,
    1290             :                                                   &date,
    1291             :                                                   check_descend,
    1292           0 :                                                   ask_sharemode);
    1293           0 :                         if (!finished) {
    1294             :                                 char buf[DIR_STRUCT_SIZE];
    1295           0 :                                 memcpy(buf,status,21);
    1296           0 :                                 if (!make_dir_struct(ctx,
    1297             :                                                 buf,
    1298             :                                                 mask,
    1299             :                                                 fname,
    1300             :                                                 size,
    1301             :                                                 mode,
    1302             :                                                 convert_timespec_to_time_t(date),
    1303           0 :                                                 !allow_long_path_components)) {
    1304           0 :                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1305           0 :                                         goto out;
    1306             :                                 }
    1307           0 :                                 if (!dptr_fill(sconn, buf+12,dptr_num)) {
    1308           0 :                                         break;
    1309             :                                 }
    1310           0 :                                 if (message_push_blob(&req->outbuf,
    1311             :                                                       data_blob_const(buf, sizeof(buf)))
    1312             :                                     == -1) {
    1313           0 :                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1314           0 :                                         goto out;
    1315             :                                 }
    1316           0 :                                 numentries++;
    1317             :                         }
    1318             :                 }
    1319             :         }
    1320             : 
    1321           0 :   SearchEmpty:
    1322             : 
    1323             :         /* If we were called as SMBffirst with smb_search_id == NULL
    1324             :                 and no entries were found then return error and close fsp->dptr
    1325             :                 (X/Open spec) */
    1326             : 
    1327           0 :         if (numentries == 0) {
    1328           0 :                 dptr_num = -1;
    1329           0 :                 if (fsp != NULL) {
    1330           0 :                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1331             :                 }
    1332           0 :         } else if(expect_close && status_len == 0) {
    1333             :                 /* Close the dptr - we know it's gone */
    1334           0 :                 dptr_num = -1;
    1335           0 :                 if (fsp != NULL) {
    1336           0 :                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1337             :                 }
    1338             :         }
    1339             : 
    1340             :         /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
    1341           0 :         if(dptr_num >= 0 && req->cmd == SMBfunique) {
    1342           0 :                 dptr_num = -1;
    1343             :                 /* fsp may have been closed above. */
    1344           0 :                 if (fsp != NULL) {
    1345           0 :                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1346             :                 }
    1347             :         }
    1348             : 
    1349           0 :         if ((numentries == 0) && !mask_contains_wcard) {
    1350           0 :                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
    1351           0 :                 goto out;
    1352             :         }
    1353             : 
    1354           0 :         SSVAL(req->outbuf,smb_vwv0,numentries);
    1355           0 :         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
    1356           0 :         SCVAL(smb_buf(req->outbuf),0,5);
    1357           0 :         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
    1358             : 
    1359             :         /* The replies here are never long name. */
    1360           0 :         SSVAL(req->outbuf, smb_flg2,
    1361             :               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
    1362           0 :         if (!allow_long_path_components) {
    1363           0 :                 SSVAL(req->outbuf, smb_flg2,
    1364             :                       SVAL(req->outbuf, smb_flg2)
    1365             :                       & (~FLAGS2_LONG_PATH_COMPONENTS));
    1366             :         }
    1367             : 
    1368             :         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
    1369           0 :         SSVAL(req->outbuf, smb_flg2,
    1370             :               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
    1371             : 
    1372           0 :         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
    1373             :                 smb_fn_name(req->cmd),
    1374             :                 mask,
    1375             :                 directory,
    1376             :                 dirtype,
    1377             :                 numentries,
    1378             :                 maxentries ));
    1379           0 :  out:
    1380           0 :         TALLOC_FREE(directory);
    1381           0 :         TALLOC_FREE(mask);
    1382           0 :         TALLOC_FREE(smb_fname);
    1383           0 :         END_PROFILE(SMBsearch);
    1384           0 :         return;
    1385             : }
    1386             : 
    1387             : /****************************************************************************
    1388             :  Reply to a fclose (stop directory search).
    1389             : ****************************************************************************/
    1390             : 
    1391           0 : void reply_fclose(struct smb_request *req)
    1392             : {
    1393             :         int status_len;
    1394             :         char status[21];
    1395           0 :         int dptr_num= -2;
    1396             :         const char *p;
    1397           0 :         char *path = NULL;
    1398             :         NTSTATUS err;
    1399           0 :         TALLOC_CTX *ctx = talloc_tos();
    1400           0 :         struct smbd_server_connection *sconn = req->sconn;
    1401           0 :         files_struct *fsp = NULL;
    1402             : 
    1403           0 :         START_PROFILE(SMBfclose);
    1404             : 
    1405           0 :         if (req->posix_pathnames) {
    1406           0 :                 reply_unknown_new(req, req->cmd);
    1407           0 :                 END_PROFILE(SMBfclose);
    1408           0 :                 return;
    1409             :         }
    1410             : 
    1411           0 :         p = (const char *)req->buf + 1;
    1412           0 :         p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
    1413             :                                        &err);
    1414           0 :         if (!NT_STATUS_IS_OK(err)) {
    1415           0 :                 reply_nterror(req, err);
    1416           0 :                 END_PROFILE(SMBfclose);
    1417           0 :                 return;
    1418             :         }
    1419             : 
    1420           0 :         if (smbreq_bufrem(req, p) < 3) {
    1421           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1422           0 :                 END_PROFILE(SMBfclose);
    1423           0 :                 return;
    1424             :         }
    1425             : 
    1426           0 :         p++;
    1427           0 :         status_len = SVAL(p,0);
    1428           0 :         p += 2;
    1429             : 
    1430           0 :         if (status_len == 0) {
    1431           0 :                 reply_force_doserror(req, ERRSRV, ERRsrverror);
    1432           0 :                 END_PROFILE(SMBfclose);
    1433           0 :                 return;
    1434             :         }
    1435             : 
    1436           0 :         if (smbreq_bufrem(req, p) < 21) {
    1437           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1438           0 :                 END_PROFILE(SMBfclose);
    1439           0 :                 return;
    1440             :         }
    1441             : 
    1442           0 :         memcpy(status,p,21);
    1443             : 
    1444           0 :         fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
    1445           0 :         if(fsp != NULL) {
    1446             :                 /*  Close the file - we know it's gone */
    1447           0 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1448           0 :                 dptr_num = -1;
    1449             :         }
    1450             : 
    1451           0 :         reply_smb1_outbuf(req, 1, 0);
    1452           0 :         SSVAL(req->outbuf,smb_vwv0,0);
    1453             : 
    1454           0 :         DEBUG(3,("search close\n"));
    1455             : 
    1456           0 :         END_PROFILE(SMBfclose);
    1457           0 :         return;
    1458             : }
    1459             : 
    1460             : /****************************************************************************
    1461             :  Reply to an open.
    1462             : ****************************************************************************/
    1463             : 
    1464           0 : void reply_open(struct smb_request *req)
    1465             : {
    1466           0 :         connection_struct *conn = req->conn;
    1467           0 :         struct smb_filename *smb_fname = NULL;
    1468           0 :         char *fname = NULL;
    1469           0 :         uint32_t fattr=0;
    1470           0 :         off_t size = 0;
    1471           0 :         time_t mtime=0;
    1472             :         int info;
    1473           0 :         struct files_struct *dirfsp = NULL;
    1474             :         files_struct *fsp;
    1475             :         int oplock_request;
    1476             :         int deny_mode;
    1477             :         uint32_t dos_attr;
    1478             :         uint32_t access_mask;
    1479             :         uint32_t share_mode;
    1480             :         uint32_t create_disposition;
    1481           0 :         uint32_t create_options = 0;
    1482           0 :         uint32_t private_flags = 0;
    1483             :         NTSTATUS status;
    1484             :         uint32_t ucf_flags;
    1485           0 :         NTTIME twrp = 0;
    1486           0 :         TALLOC_CTX *ctx = talloc_tos();
    1487             : 
    1488           0 :         START_PROFILE(SMBopen);
    1489             : 
    1490           0 :         if (req->wct < 2) {
    1491           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1492           0 :                 goto out;
    1493             :         }
    1494             : 
    1495           0 :         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
    1496           0 :         deny_mode = SVAL(req->vwv+0, 0);
    1497           0 :         dos_attr = SVAL(req->vwv+1, 0);
    1498             : 
    1499           0 :         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
    1500             :                             STR_TERMINATE, &status);
    1501           0 :         if (!NT_STATUS_IS_OK(status)) {
    1502           0 :                 reply_nterror(req, status);
    1503           0 :                 goto out;
    1504             :         }
    1505             : 
    1506           0 :         if (!map_open_params_to_ntcreate(fname, deny_mode,
    1507             :                                          OPENX_FILE_EXISTS_OPEN, &access_mask,
    1508             :                                          &share_mode, &create_disposition,
    1509             :                                          &create_options, &private_flags)) {
    1510           0 :                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
    1511           0 :                 goto out;
    1512             :         }
    1513             : 
    1514           0 :         ucf_flags = filename_create_ucf_flags(req, create_disposition);
    1515             : 
    1516           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    1517           0 :                 extract_snapshot_token(fname, &twrp);
    1518             :         }
    1519           0 :         status = filename_convert_dirfsp(ctx,
    1520             :                                          conn,
    1521             :                                          fname,
    1522             :                                          ucf_flags,
    1523             :                                          twrp,
    1524             :                                          &dirfsp,
    1525             :                                          &smb_fname);
    1526           0 :         if (!NT_STATUS_IS_OK(status)) {
    1527           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    1528           0 :                         reply_botherror(req,
    1529             :                                         NT_STATUS_PATH_NOT_COVERED,
    1530             :                                         ERRSRV, ERRbadpath);
    1531           0 :                         goto out;
    1532             :                 }
    1533           0 :                 reply_nterror(req, status);
    1534           0 :                 goto out;
    1535             :         }
    1536             : 
    1537           0 :         status = SMB_VFS_CREATE_FILE(
    1538             :                 conn,                                   /* conn */
    1539             :                 req,                                    /* req */
    1540             :                 dirfsp,                                 /* dirfsp */
    1541             :                 smb_fname,                              /* fname */
    1542             :                 access_mask,                            /* access_mask */
    1543             :                 share_mode,                             /* share_access */
    1544             :                 create_disposition,                     /* create_disposition*/
    1545             :                 create_options,                         /* create_options */
    1546             :                 dos_attr,                               /* file_attributes */
    1547             :                 oplock_request,                         /* oplock_request */
    1548             :                 NULL,                                   /* lease */
    1549             :                 0,                                      /* allocation_size */
    1550             :                 private_flags,
    1551             :                 NULL,                                   /* sd */
    1552             :                 NULL,                                   /* ea_list */
    1553             :                 &fsp,                                       /* result */
    1554             :                 &info,                                      /* pinfo */
    1555             :                 NULL, NULL);                            /* create context */
    1556             : 
    1557           0 :         if (!NT_STATUS_IS_OK(status)) {
    1558           0 :                 if (open_was_deferred(req->xconn, req->mid)) {
    1559             :                         /* We have re-scheduled this call. */
    1560           0 :                         goto out;
    1561             :                 }
    1562             : 
    1563           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    1564           0 :                         reply_openerror(req, status);
    1565           0 :                         goto out;
    1566             :                 }
    1567             : 
    1568           0 :                 fsp = fcb_or_dos_open(
    1569             :                         req,
    1570             :                         smb_fname,
    1571             :                         access_mask,
    1572             :                         create_options,
    1573             :                         private_flags);
    1574           0 :                 if (fsp == NULL) {
    1575           0 :                         bool ok = defer_smb1_sharing_violation(req);
    1576           0 :                         if (ok) {
    1577           0 :                                 goto out;
    1578             :                         }
    1579           0 :                         reply_openerror(req, status);
    1580           0 :                         goto out;
    1581             :                 }
    1582             :         }
    1583             : 
    1584             :         /* Ensure we're pointing at the correct stat struct. */
    1585           0 :         TALLOC_FREE(smb_fname);
    1586           0 :         smb_fname = fsp->fsp_name;
    1587             : 
    1588           0 :         size = smb_fname->st.st_ex_size;
    1589           0 :         fattr = fdos_mode(fsp);
    1590             : 
    1591           0 :         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
    1592             : 
    1593           0 :         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
    1594           0 :                 DEBUG(3,("attempt to open a directory %s\n",
    1595             :                          fsp_str_dbg(fsp)));
    1596           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
    1597           0 :                 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
    1598             :                         ERRDOS, ERRnoaccess);
    1599           0 :                 goto out;
    1600             :         }
    1601             : 
    1602           0 :         reply_smb1_outbuf(req, 7, 0);
    1603           0 :         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
    1604           0 :         SSVAL(req->outbuf,smb_vwv1,fattr);
    1605           0 :         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
    1606           0 :                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
    1607             :         } else {
    1608           0 :                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
    1609             :         }
    1610           0 :         SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
    1611           0 :         SSVAL(req->outbuf,smb_vwv6,deny_mode);
    1612             : 
    1613           0 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    1614           0 :                 SCVAL(req->outbuf,smb_flg,
    1615             :                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    1616             :         }
    1617             : 
    1618           0 :         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    1619           0 :                 SCVAL(req->outbuf,smb_flg,
    1620             :                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    1621             :         }
    1622           0 :  out:
    1623           0 :         END_PROFILE(SMBopen);
    1624           0 :         return;
    1625             : }
    1626             : 
    1627             : /****************************************************************************
    1628             :  Reply to an open and X.
    1629             : ****************************************************************************/
    1630             : 
    1631           0 : void reply_open_and_X(struct smb_request *req)
    1632             : {
    1633           0 :         connection_struct *conn = req->conn;
    1634           0 :         struct smb_filename *smb_fname = NULL;
    1635           0 :         char *fname = NULL;
    1636             :         uint16_t open_flags;
    1637             :         int deny_mode;
    1638             :         uint32_t smb_attr;
    1639             :         /* Breakout the oplock request bits so we can set the
    1640             :                 reply bits separately. */
    1641             :         int ex_oplock_request;
    1642             :         int core_oplock_request;
    1643             :         int oplock_request;
    1644             : #if 0
    1645             :         int smb_sattr = SVAL(req->vwv+4, 0);
    1646             :         uint32_t smb_time = make_unix_date3(req->vwv+6);
    1647             : #endif
    1648             :         int smb_ofun;
    1649           0 :         uint32_t fattr=0;
    1650           0 :         int mtime=0;
    1651           0 :         int smb_action = 0;
    1652           0 :         struct files_struct *dirfsp = NULL;
    1653             :         files_struct *fsp;
    1654             :         NTSTATUS status;
    1655             :         uint64_t allocation_size;
    1656           0 :         ssize_t retval = -1;
    1657             :         uint32_t access_mask;
    1658             :         uint32_t share_mode;
    1659             :         uint32_t create_disposition;
    1660           0 :         uint32_t create_options = 0;
    1661           0 :         uint32_t private_flags = 0;
    1662             :         uint32_t ucf_flags;
    1663           0 :         NTTIME twrp = 0;
    1664           0 :         TALLOC_CTX *ctx = talloc_tos();
    1665             : 
    1666           0 :         START_PROFILE(SMBopenX);
    1667             : 
    1668           0 :         if (req->wct < 15) {
    1669           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1670           0 :                 goto out;
    1671             :         }
    1672             : 
    1673           0 :         open_flags = SVAL(req->vwv+2, 0);
    1674           0 :         deny_mode = SVAL(req->vwv+3, 0);
    1675           0 :         smb_attr = SVAL(req->vwv+5, 0);
    1676           0 :         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
    1677           0 :         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
    1678           0 :         oplock_request = ex_oplock_request | core_oplock_request;
    1679           0 :         smb_ofun = SVAL(req->vwv+8, 0);
    1680           0 :         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
    1681             : 
    1682             :         /* If it's an IPC, pass off the pipe handler. */
    1683           0 :         if (IS_IPC(conn)) {
    1684           0 :                 if (lp_nt_pipe_support()) {
    1685           0 :                         reply_open_pipe_and_X(conn, req);
    1686             :                 } else {
    1687           0 :                         reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
    1688             :                 }
    1689           0 :                 goto out;
    1690             :         }
    1691             : 
    1692             :         /* XXXX we need to handle passed times, sattr and flags */
    1693           0 :         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
    1694             :                         STR_TERMINATE, &status);
    1695           0 :         if (!NT_STATUS_IS_OK(status)) {
    1696           0 :                 reply_nterror(req, status);
    1697           0 :                 goto out;
    1698             :         }
    1699             : 
    1700           0 :         if (!map_open_params_to_ntcreate(fname, deny_mode,
    1701             :                                          smb_ofun,
    1702             :                                          &access_mask, &share_mode,
    1703             :                                          &create_disposition,
    1704             :                                          &create_options,
    1705             :                                          &private_flags)) {
    1706           0 :                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
    1707           0 :                 goto out;
    1708             :         }
    1709             : 
    1710           0 :         ucf_flags = filename_create_ucf_flags(req, create_disposition);
    1711             : 
    1712           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    1713           0 :                 extract_snapshot_token(fname, &twrp);
    1714             :         }
    1715             : 
    1716           0 :         status = filename_convert_dirfsp(ctx,
    1717             :                                          conn,
    1718             :                                          fname,
    1719             :                                          ucf_flags,
    1720             :                                          twrp,
    1721             :                                          &dirfsp,
    1722             :                                          &smb_fname);
    1723           0 :         if (!NT_STATUS_IS_OK(status)) {
    1724           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    1725           0 :                         reply_botherror(req,
    1726             :                                         NT_STATUS_PATH_NOT_COVERED,
    1727             :                                         ERRSRV, ERRbadpath);
    1728           0 :                         goto out;
    1729             :                 }
    1730           0 :                 reply_nterror(req, status);
    1731           0 :                 goto out;
    1732             :         }
    1733             : 
    1734           0 :         status = SMB_VFS_CREATE_FILE(
    1735             :                 conn,                                   /* conn */
    1736             :                 req,                                    /* req */
    1737             :                 dirfsp,                                 /* dirfsp */
    1738             :                 smb_fname,                              /* fname */
    1739             :                 access_mask,                            /* access_mask */
    1740             :                 share_mode,                             /* share_access */
    1741             :                 create_disposition,                     /* create_disposition*/
    1742             :                 create_options,                         /* create_options */
    1743             :                 smb_attr,                               /* file_attributes */
    1744             :                 oplock_request,                         /* oplock_request */
    1745             :                 NULL,                                   /* lease */
    1746             :                 0,                                      /* allocation_size */
    1747             :                 private_flags,
    1748             :                 NULL,                                   /* sd */
    1749             :                 NULL,                                   /* ea_list */
    1750             :                 &fsp,                                       /* result */
    1751             :                 &smb_action,                                /* pinfo */
    1752             :                 NULL, NULL);                            /* create context */
    1753             : 
    1754           0 :         if (!NT_STATUS_IS_OK(status)) {
    1755           0 :                 if (open_was_deferred(req->xconn, req->mid)) {
    1756             :                         /* We have re-scheduled this call. */
    1757           0 :                         goto out;
    1758             :                 }
    1759             : 
    1760           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    1761           0 :                         reply_openerror(req, status);
    1762           0 :                         goto out;
    1763             :                 }
    1764             : 
    1765           0 :                 fsp = fcb_or_dos_open(
    1766             :                         req,
    1767             :                         smb_fname,
    1768             :                         access_mask,
    1769             :                         create_options,
    1770             :                         private_flags);
    1771           0 :                 if (fsp == NULL) {
    1772           0 :                         bool ok = defer_smb1_sharing_violation(req);
    1773           0 :                         if (ok) {
    1774           0 :                                 goto out;
    1775             :                         }
    1776           0 :                         reply_openerror(req, status);
    1777           0 :                         goto out;
    1778             :                 }
    1779             : 
    1780             : 
    1781           0 :                 smb_action = FILE_WAS_OPENED;
    1782             :         }
    1783             : 
    1784             :         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
    1785             :            if the file is truncated or created. */
    1786           0 :         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
    1787           0 :                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
    1788           0 :                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
    1789           0 :                         close_file_free(req, &fsp, ERROR_CLOSE);
    1790           0 :                         reply_nterror(req, NT_STATUS_DISK_FULL);
    1791           0 :                         goto out;
    1792             :                 }
    1793           0 :                 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
    1794           0 :                 if (retval < 0) {
    1795           0 :                         close_file_free(req, &fsp, ERROR_CLOSE);
    1796           0 :                         reply_nterror(req, NT_STATUS_DISK_FULL);
    1797           0 :                         goto out;
    1798             :                 }
    1799           0 :                 status = vfs_stat_fsp(fsp);
    1800           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1801           0 :                         close_file_free(req, &fsp, ERROR_CLOSE);
    1802           0 :                         reply_nterror(req, status);
    1803           0 :                         goto out;
    1804             :                 }
    1805             :         }
    1806             : 
    1807           0 :         fattr = fdos_mode(fsp);
    1808           0 :         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
    1809           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
    1810           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1811           0 :                 goto out;
    1812             :         }
    1813           0 :         mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
    1814             : 
    1815             :         /* If the caller set the extended oplock request bit
    1816             :                 and we granted one (by whatever means) - set the
    1817             :                 correct bit for extended oplock reply.
    1818             :         */
    1819             : 
    1820           0 :         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
    1821           0 :                 smb_action |= EXTENDED_OPLOCK_GRANTED;
    1822             :         }
    1823             : 
    1824           0 :         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    1825           0 :                 smb_action |= EXTENDED_OPLOCK_GRANTED;
    1826             :         }
    1827             : 
    1828             :         /* If the caller set the core oplock request bit
    1829             :                 and we granted one (by whatever means) - set the
    1830             :                 correct bit for core oplock reply.
    1831             :         */
    1832             : 
    1833           0 :         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
    1834           0 :                 reply_smb1_outbuf(req, 19, 0);
    1835             :         } else {
    1836           0 :                 reply_smb1_outbuf(req, 15, 0);
    1837             :         }
    1838             : 
    1839           0 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
    1840           0 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
    1841             : 
    1842           0 :         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
    1843           0 :                 SCVAL(req->outbuf, smb_flg,
    1844             :                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    1845             :         }
    1846             : 
    1847           0 :         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    1848           0 :                 SCVAL(req->outbuf, smb_flg,
    1849             :                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    1850             :         }
    1851             : 
    1852           0 :         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
    1853           0 :         SSVAL(req->outbuf,smb_vwv3,fattr);
    1854           0 :         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
    1855           0 :                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
    1856             :         } else {
    1857           0 :                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
    1858             :         }
    1859           0 :         SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
    1860           0 :         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
    1861           0 :         SSVAL(req->outbuf,smb_vwv11,smb_action);
    1862             : 
    1863           0 :         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
    1864           0 :                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
    1865             :         }
    1866             : 
    1867           0 :  out:
    1868           0 :         TALLOC_FREE(smb_fname);
    1869           0 :         END_PROFILE(SMBopenX);
    1870           0 :         return;
    1871             : }
    1872             : 
    1873             : /****************************************************************************
    1874             :  Reply to a SMBulogoffX.
    1875             : ****************************************************************************/
    1876             : 
    1877             : static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
    1878             :                                 struct smbXsrv_session *session);
    1879             : static void reply_ulogoffX_done(struct tevent_req *req);
    1880             : 
    1881           0 : void reply_ulogoffX(struct smb_request *smb1req)
    1882             : {
    1883           0 :         struct timeval now = timeval_current();
    1884           0 :         struct smbXsrv_session *session = NULL;
    1885             :         struct tevent_req *req;
    1886             :         NTSTATUS status;
    1887             : 
    1888             :         /*
    1889             :          * Don't setup the profile charge here, take
    1890             :          * it in reply_ulogoffX_done(). Not strictly correct
    1891             :          * but better than the other SMB1 async
    1892             :          * code that double-charges at the moment.
    1893             :          */
    1894             : 
    1895           0 :         status = smb1srv_session_lookup(smb1req->xconn,
    1896           0 :                                         smb1req->vuid,
    1897             :                                         timeval_to_nttime(&now),
    1898             :                                         &session);
    1899           0 :         if (!NT_STATUS_IS_OK(status)) {
    1900             :                 /* Not going async, profile here. */
    1901           0 :                 START_PROFILE(SMBulogoffX);
    1902           0 :                 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
    1903             :                          (unsigned long long)smb1req->vuid);
    1904             : 
    1905           0 :                 smb1req->vuid = UID_FIELD_INVALID;
    1906           0 :                 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
    1907           0 :                 END_PROFILE(SMBulogoffX);
    1908           0 :                 return;
    1909             :         }
    1910             : 
    1911           0 :         req = reply_ulogoffX_send(smb1req, session);
    1912           0 :         if (req == NULL) {
    1913             :                 /* Not going async, profile here. */
    1914           0 :                 START_PROFILE(SMBulogoffX);
    1915           0 :                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
    1916           0 :                 END_PROFILE(SMBulogoffX);
    1917           0 :                 return;
    1918             :         }
    1919             : 
    1920             :         /* We're async. This will complete later. */
    1921           0 :         tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
    1922           0 :         return;
    1923             : }
    1924             : 
    1925             : struct reply_ulogoffX_state {
    1926             :         struct tevent_queue *wait_queue;
    1927             :         struct smbXsrv_session *session;
    1928             : };
    1929             : 
    1930             : static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
    1931             : 
    1932             : /****************************************************************************
    1933             :  Async SMB1 ulogoffX.
    1934             :  Note, on failure here we deallocate and return NULL to allow the caller to
    1935             :  SMB1 return an error of ERRnomem immediately.
    1936             : ****************************************************************************/
    1937             : 
    1938           0 : static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
    1939             :                                         struct smbXsrv_session *session)
    1940             : {
    1941             :         struct tevent_req *req;
    1942             :         struct reply_ulogoffX_state *state;
    1943             :         struct tevent_req *subreq;
    1944             :         files_struct *fsp;
    1945           0 :         struct smbd_server_connection *sconn = session->client->sconn;
    1946           0 :         uint64_t vuid = session->global->session_wire_id;
    1947             : 
    1948           0 :         req = tevent_req_create(smb1req, &state,
    1949             :                         struct reply_ulogoffX_state);
    1950           0 :         if (req == NULL) {
    1951           0 :                 return NULL;
    1952             :         }
    1953           0 :         state->wait_queue = tevent_queue_create(state,
    1954             :                                 "reply_ulogoffX_wait_queue");
    1955           0 :         if (tevent_req_nomem(state->wait_queue, req)) {
    1956           0 :                 TALLOC_FREE(req);
    1957           0 :                 return NULL;
    1958             :         }
    1959           0 :         state->session = session;
    1960             : 
    1961             :         /*
    1962             :          * Make sure that no new request will be able to use this session.
    1963             :          * This ensures that once all outstanding fsp->aio_requests
    1964             :          * on this session are done, we are safe to close it.
    1965             :          */
    1966           0 :         session->status = NT_STATUS_USER_SESSION_DELETED;
    1967             : 
    1968           0 :         for (fsp = sconn->files; fsp; fsp = fsp->next) {
    1969           0 :                 if (fsp->vuid != vuid) {
    1970           0 :                         continue;
    1971             :                 }
    1972             :                 /*
    1973             :                  * Flag the file as close in progress.
    1974             :                  * This will prevent any more IO being
    1975             :                  * done on it.
    1976             :                  */
    1977           0 :                 fsp->fsp_flags.closing = true;
    1978             : 
    1979           0 :                 if (fsp->num_aio_requests > 0) {
    1980             :                         /*
    1981             :                          * Now wait until all aio requests on this fsp are
    1982             :                          * finished.
    1983             :                          *
    1984             :                          * We don't set a callback, as we just want to block the
    1985             :                          * wait queue and the talloc_free() of fsp->aio_request
    1986             :                          * will remove the item from the wait queue.
    1987             :                          */
    1988           0 :                         subreq = tevent_queue_wait_send(fsp->aio_requests,
    1989             :                                                 sconn->ev_ctx,
    1990           0 :                                                 state->wait_queue);
    1991           0 :                         if (tevent_req_nomem(subreq, req)) {
    1992           0 :                                 TALLOC_FREE(req);
    1993           0 :                                 return NULL;
    1994             :                         }
    1995             :                 }
    1996             :         }
    1997             : 
    1998             :         /*
    1999             :          * Now we add our own waiter to the end of the queue,
    2000             :          * this way we get notified when all pending requests are finished
    2001             :          * and reply to the outstanding SMB1 request.
    2002             :          */
    2003           0 :         subreq = tevent_queue_wait_send(state,
    2004             :                                 sconn->ev_ctx,
    2005           0 :                                 state->wait_queue);
    2006           0 :         if (tevent_req_nomem(subreq, req)) {
    2007           0 :                 TALLOC_FREE(req);
    2008           0 :                 return NULL;
    2009             :         }
    2010             : 
    2011             :         /*
    2012             :          * We're really going async - move the SMB1 request from
    2013             :          * a talloc stackframe above us to the sconn talloc-context.
    2014             :          * We need this to stick around until the wait_done
    2015             :          * callback is invoked.
    2016             :          */
    2017           0 :         smb1req = talloc_move(sconn, &smb1req);
    2018             : 
    2019           0 :         tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
    2020             : 
    2021           0 :         return req;
    2022             : }
    2023             : 
    2024           0 : static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
    2025             : {
    2026           0 :         struct tevent_req *req = tevent_req_callback_data(
    2027             :                 subreq, struct tevent_req);
    2028             : 
    2029           0 :         tevent_queue_wait_recv(subreq);
    2030           0 :         TALLOC_FREE(subreq);
    2031           0 :         tevent_req_done(req);
    2032           0 : }
    2033             : 
    2034           0 : static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
    2035             : {
    2036           0 :         return tevent_req_simple_recv_ntstatus(req);
    2037             : }
    2038             : 
    2039           0 : static void reply_ulogoffX_done(struct tevent_req *req)
    2040             : {
    2041           0 :         struct smb_request *smb1req = tevent_req_callback_data(
    2042             :                 req, struct smb_request);
    2043           0 :         struct reply_ulogoffX_state *state = tevent_req_data(req,
    2044             :                                                 struct reply_ulogoffX_state);
    2045           0 :         struct smbXsrv_session *session = state->session;
    2046             :         NTSTATUS status;
    2047             : 
    2048             :         /*
    2049             :          * Take the profile charge here. Not strictly
    2050             :          * correct but better than the other SMB1 async
    2051             :          * code that double-charges at the moment.
    2052             :          */
    2053           0 :         START_PROFILE(SMBulogoffX);
    2054             : 
    2055           0 :         status = reply_ulogoffX_recv(req);
    2056           0 :         TALLOC_FREE(req);
    2057           0 :         if (!NT_STATUS_IS_OK(status)) {
    2058           0 :                 TALLOC_FREE(smb1req);
    2059           0 :                 END_PROFILE(SMBulogoffX);
    2060           0 :                 exit_server(__location__ ": reply_ulogoffX_recv failed");
    2061             :                 return;
    2062             :         }
    2063             : 
    2064           0 :         status = smbXsrv_session_logoff(session);
    2065           0 :         if (!NT_STATUS_IS_OK(status)) {
    2066           0 :                 TALLOC_FREE(smb1req);
    2067           0 :                 END_PROFILE(SMBulogoffX);
    2068           0 :                 exit_server(__location__ ": smbXsrv_session_logoff failed");
    2069             :                 return;
    2070             :         }
    2071             : 
    2072           0 :         TALLOC_FREE(session);
    2073             : 
    2074           0 :         reply_smb1_outbuf(smb1req, 2, 0);
    2075           0 :         SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
    2076           0 :         SSVAL(smb1req->outbuf, smb_vwv1, 0);    /* no andx offset */
    2077             : 
    2078           0 :         DBG_NOTICE("ulogoffX vuid=%llu\n",
    2079             :                   (unsigned long long)smb1req->vuid);
    2080             : 
    2081           0 :         smb1req->vuid = UID_FIELD_INVALID;
    2082             :         /*
    2083             :          * The following call is needed to push the
    2084             :          * reply data back out the socket after async
    2085             :          * return. Plus it frees smb1req.
    2086             :          */
    2087           0 :         smb_request_done(smb1req);
    2088           0 :         END_PROFILE(SMBulogoffX);
    2089             : }
    2090             : 
    2091             : /****************************************************************************
    2092             :  Reply to a mknew or a create.
    2093             : ****************************************************************************/
    2094             : 
    2095           0 : void reply_mknew(struct smb_request *req)
    2096             : {
    2097           0 :         connection_struct *conn = req->conn;
    2098           0 :         struct smb_filename *smb_fname = NULL;
    2099           0 :         char *fname = NULL;
    2100           0 :         uint32_t fattr = 0;
    2101             :         struct smb_file_time ft;
    2102           0 :         struct files_struct *dirfsp = NULL;
    2103             :         files_struct *fsp;
    2104           0 :         int oplock_request = 0;
    2105             :         NTSTATUS status;
    2106           0 :         uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
    2107           0 :         uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
    2108             :         uint32_t create_disposition;
    2109           0 :         uint32_t create_options = 0;
    2110             :         uint32_t ucf_flags;
    2111           0 :         NTTIME twrp = 0;
    2112           0 :         TALLOC_CTX *ctx = talloc_tos();
    2113             : 
    2114           0 :         START_PROFILE(SMBcreate);
    2115           0 :         init_smb_file_time(&ft);
    2116             : 
    2117           0 :         if (req->wct < 3) {
    2118           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2119           0 :                 goto out;
    2120             :         }
    2121             : 
    2122           0 :         fattr = SVAL(req->vwv+0, 0);
    2123           0 :         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
    2124             : 
    2125           0 :         if (req->cmd == SMBmknew) {
    2126             :                 /* We should fail if file exists. */
    2127           0 :                 create_disposition = FILE_CREATE;
    2128             :         } else {
    2129             :                 /* Create if file doesn't exist, truncate if it does. */
    2130           0 :                 create_disposition = FILE_OVERWRITE_IF;
    2131             :         }
    2132             : 
    2133             :         /* mtime. */
    2134           0 :         ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
    2135             : 
    2136           0 :         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
    2137             :                             STR_TERMINATE, &status);
    2138           0 :         if (!NT_STATUS_IS_OK(status)) {
    2139           0 :                 reply_nterror(req, status);
    2140           0 :                 goto out;
    2141             :         }
    2142             : 
    2143           0 :         ucf_flags = filename_create_ucf_flags(req, create_disposition);
    2144           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    2145           0 :                 extract_snapshot_token(fname, &twrp);
    2146             :         }
    2147             : 
    2148           0 :         status = filename_convert_dirfsp(ctx,
    2149             :                                          conn,
    2150             :                                          fname,
    2151             :                                          ucf_flags,
    2152             :                                          twrp,
    2153             :                                          &dirfsp,
    2154             :                                          &smb_fname);
    2155           0 :         if (!NT_STATUS_IS_OK(status)) {
    2156           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    2157           0 :                         reply_botherror(req,
    2158             :                                         NT_STATUS_PATH_NOT_COVERED,
    2159             :                                         ERRSRV, ERRbadpath);
    2160           0 :                         goto out;
    2161             :                 }
    2162           0 :                 reply_nterror(req, status);
    2163           0 :                 goto out;
    2164             :         }
    2165             : 
    2166           0 :         if (fattr & FILE_ATTRIBUTE_VOLUME) {
    2167           0 :                 DEBUG(0,("Attempt to create file (%s) with volid set - "
    2168             :                          "please report this\n",
    2169             :                          smb_fname_str_dbg(smb_fname)));
    2170             :         }
    2171             : 
    2172           0 :         status = SMB_VFS_CREATE_FILE(
    2173             :                 conn,                                   /* conn */
    2174             :                 req,                                    /* req */
    2175             :                 dirfsp,                                 /* dirfsp */
    2176             :                 smb_fname,                              /* fname */
    2177             :                 access_mask,                            /* access_mask */
    2178             :                 share_mode,                             /* share_access */
    2179             :                 create_disposition,                     /* create_disposition*/
    2180             :                 create_options,                         /* create_options */
    2181             :                 fattr,                                  /* file_attributes */
    2182             :                 oplock_request,                         /* oplock_request */
    2183             :                 NULL,                                   /* lease */
    2184             :                 0,                                      /* allocation_size */
    2185             :                 0,                                      /* private_flags */
    2186             :                 NULL,                                   /* sd */
    2187             :                 NULL,                                   /* ea_list */
    2188             :                 &fsp,                                       /* result */
    2189             :                 NULL,                                   /* pinfo */
    2190             :                 NULL, NULL);                            /* create context */
    2191             : 
    2192           0 :         if (!NT_STATUS_IS_OK(status)) {
    2193           0 :                 if (open_was_deferred(req->xconn, req->mid)) {
    2194             :                         /* We have re-scheduled this call. */
    2195           0 :                         goto out;
    2196             :                 }
    2197           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    2198           0 :                         bool ok = defer_smb1_sharing_violation(req);
    2199           0 :                         if (ok) {
    2200           0 :                                 goto out;
    2201             :                         }
    2202             :                 }
    2203           0 :                 reply_openerror(req, status);
    2204           0 :                 goto out;
    2205             :         }
    2206             : 
    2207           0 :         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
    2208           0 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    2209           0 :         if (!NT_STATUS_IS_OK(status)) {
    2210           0 :                 END_PROFILE(SMBcreate);
    2211           0 :                 goto out;
    2212             :         }
    2213             : 
    2214           0 :         reply_smb1_outbuf(req, 1, 0);
    2215           0 :         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
    2216             : 
    2217           0 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    2218           0 :                 SCVAL(req->outbuf,smb_flg,
    2219             :                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    2220             :         }
    2221             : 
    2222           0 :         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    2223           0 :                 SCVAL(req->outbuf,smb_flg,
    2224             :                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    2225             :         }
    2226             : 
    2227           0 :         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
    2228           0 :         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
    2229             :                   smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
    2230             :                   (unsigned int)fattr));
    2231             : 
    2232           0 :  out:
    2233           0 :         TALLOC_FREE(smb_fname);
    2234           0 :         END_PROFILE(SMBcreate);
    2235           0 :         return;
    2236             : }
    2237             : 
    2238             : /****************************************************************************
    2239             :  Reply to a create temporary file.
    2240             : ****************************************************************************/
    2241             : 
    2242           0 : void reply_ctemp(struct smb_request *req)
    2243             : {
    2244           0 :         connection_struct *conn = req->conn;
    2245           0 :         struct smb_filename *smb_fname = NULL;
    2246           0 :         char *wire_name = NULL;
    2247           0 :         char *fname = NULL;
    2248             :         uint32_t fattr;
    2249           0 :         struct files_struct *dirfsp = NULL;
    2250             :         files_struct *fsp;
    2251             :         int oplock_request;
    2252             :         char *s;
    2253             :         NTSTATUS status;
    2254             :         int i;
    2255             :         uint32_t ucf_flags;
    2256           0 :         NTTIME twrp = 0;
    2257           0 :         TALLOC_CTX *ctx = talloc_tos();
    2258             : 
    2259           0 :         START_PROFILE(SMBctemp);
    2260             : 
    2261           0 :         if (req->wct < 3) {
    2262           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2263           0 :                 goto out;
    2264             :         }
    2265             : 
    2266           0 :         fattr = SVAL(req->vwv+0, 0);
    2267           0 :         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
    2268             : 
    2269           0 :         srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
    2270             :                             STR_TERMINATE, &status);
    2271           0 :         if (!NT_STATUS_IS_OK(status)) {
    2272           0 :                 reply_nterror(req, status);
    2273           0 :                 goto out;
    2274             :         }
    2275             : 
    2276           0 :         for (i = 0; i < 10; i++) {
    2277           0 :                 if (*wire_name) {
    2278           0 :                         fname = talloc_asprintf(ctx,
    2279             :                                         "%s/TMP%s",
    2280             :                                         wire_name,
    2281             :                                         generate_random_str_list(ctx, 5, "0123456789"));
    2282             :                 } else {
    2283           0 :                         fname = talloc_asprintf(ctx,
    2284             :                                         "TMP%s",
    2285             :                                         generate_random_str_list(ctx, 5, "0123456789"));
    2286             :                 }
    2287             : 
    2288           0 :                 if (!fname) {
    2289           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    2290           0 :                         goto out;
    2291             :                 }
    2292             : 
    2293           0 :                 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
    2294           0 :                 if (ucf_flags & UCF_GMT_PATHNAME) {
    2295           0 :                         extract_snapshot_token(fname, &twrp);
    2296             :                 }
    2297           0 :                 status = filename_convert_dirfsp(ctx,
    2298             :                                                  conn,
    2299             :                                                  fname,
    2300             :                                                  ucf_flags,
    2301             :                                                  twrp,
    2302             :                                                  &dirfsp,
    2303             :                                                  &smb_fname);
    2304           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2305           0 :                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    2306           0 :                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    2307             :                                         ERRSRV, ERRbadpath);
    2308           0 :                                 goto out;
    2309             :                         }
    2310           0 :                         reply_nterror(req, status);
    2311           0 :                         goto out;
    2312             :                 }
    2313             : 
    2314             :                 /* Create the file. */
    2315           0 :                 status = SMB_VFS_CREATE_FILE(
    2316             :                         conn,                                   /* conn */
    2317             :                         req,                                    /* req */
    2318             :                         dirfsp,                                 /* dirfsp */
    2319             :                         smb_fname,                              /* fname */
    2320             :                         FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
    2321             :                         FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
    2322             :                         FILE_CREATE,                            /* create_disposition*/
    2323             :                         0,                                      /* create_options */
    2324             :                         fattr,                                  /* file_attributes */
    2325             :                         oplock_request,                         /* oplock_request */
    2326             :                         NULL,                                   /* lease */
    2327             :                         0,                                      /* allocation_size */
    2328             :                         0,                                      /* private_flags */
    2329             :                         NULL,                                   /* sd */
    2330             :                         NULL,                                   /* ea_list */
    2331             :                         &fsp,                                       /* result */
    2332             :                         NULL,                                   /* pinfo */
    2333             :                         NULL, NULL);                            /* create context */
    2334             : 
    2335           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    2336           0 :                         TALLOC_FREE(fname);
    2337           0 :                         TALLOC_FREE(dirfsp);
    2338           0 :                         TALLOC_FREE(smb_fname);
    2339           0 :                         continue;
    2340             :                 }
    2341             : 
    2342           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2343           0 :                         if (open_was_deferred(req->xconn, req->mid)) {
    2344             :                                 /* We have re-scheduled this call. */
    2345           0 :                                 goto out;
    2346             :                         }
    2347           0 :                         if (NT_STATUS_EQUAL(
    2348             :                                     status, NT_STATUS_SHARING_VIOLATION)) {
    2349           0 :                                 bool ok = defer_smb1_sharing_violation(req);
    2350           0 :                                 if (ok) {
    2351           0 :                                         goto out;
    2352             :                                 }
    2353             :                         }
    2354           0 :                         reply_openerror(req, status);
    2355           0 :                         goto out;
    2356             :                 }
    2357             : 
    2358           0 :                 break;
    2359             :         }
    2360             : 
    2361           0 :         if (i == 10) {
    2362             :                 /* Collision after 10 times... */
    2363           0 :                 reply_nterror(req, status);
    2364           0 :                 goto out;
    2365             :         }
    2366             : 
    2367           0 :         reply_smb1_outbuf(req, 1, 0);
    2368           0 :         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
    2369             : 
    2370             :         /* the returned filename is relative to the directory */
    2371           0 :         s = strrchr_m(fsp->fsp_name->base_name, '/');
    2372           0 :         if (!s) {
    2373           0 :                 s = fsp->fsp_name->base_name;
    2374             :         } else {
    2375           0 :                 s++;
    2376             :         }
    2377             : 
    2378             : #if 0
    2379             :         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
    2380             :            thing in the byte section. JRA */
    2381             :         SSVALS(p, 0, -1); /* what is this? not in spec */
    2382             : #endif
    2383           0 :         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
    2384             :             == -1) {
    2385           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2386           0 :                 goto out;
    2387             :         }
    2388             : 
    2389           0 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    2390           0 :                 SCVAL(req->outbuf, smb_flg,
    2391             :                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    2392             :         }
    2393             : 
    2394           0 :         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    2395           0 :                 SCVAL(req->outbuf, smb_flg,
    2396             :                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
    2397             :         }
    2398             : 
    2399           0 :         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
    2400           0 :         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
    2401             :                     fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
    2402           0 :  out:
    2403           0 :         TALLOC_FREE(smb_fname);
    2404           0 :         TALLOC_FREE(wire_name);
    2405           0 :         END_PROFILE(SMBctemp);
    2406           0 :         return;
    2407             : }
    2408             : 
    2409             : /****************************************************************************
    2410             :  Reply to a unlink
    2411             : ****************************************************************************/
    2412             : 
    2413           0 : void reply_unlink(struct smb_request *req)
    2414             : {
    2415           0 :         connection_struct *conn = req->conn;
    2416           0 :         char *name = NULL;
    2417           0 :         struct files_struct *dirfsp = NULL;
    2418           0 :         struct smb_filename *smb_fname = NULL;
    2419             :         uint32_t dirtype;
    2420             :         NTSTATUS status;
    2421           0 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    2422           0 :         NTTIME twrp = 0;
    2423           0 :         TALLOC_CTX *ctx = talloc_tos();
    2424             : 
    2425           0 :         START_PROFILE(SMBunlink);
    2426             : 
    2427           0 :         if (req->wct < 1) {
    2428           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2429           0 :                 goto out;
    2430             :         }
    2431             : 
    2432           0 :         dirtype = SVAL(req->vwv+0, 0);
    2433             : 
    2434           0 :         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
    2435             :                                   STR_TERMINATE, &status);
    2436           0 :         if (!NT_STATUS_IS_OK(status)) {
    2437           0 :                 reply_nterror(req, status);
    2438           0 :                 goto out;
    2439             :         }
    2440             : 
    2441           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    2442           0 :                 extract_snapshot_token(name, &twrp);
    2443             :         }
    2444           0 :         status = filename_convert_dirfsp(ctx,
    2445             :                                          conn,
    2446             :                                          name,
    2447             :                                          ucf_flags,
    2448             :                                          twrp,
    2449             :                                          &dirfsp,
    2450             :                                          &smb_fname);
    2451           0 :         if (!NT_STATUS_IS_OK(status)) {
    2452           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    2453           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    2454             :                                         ERRSRV, ERRbadpath);
    2455           0 :                         goto out;
    2456             :                 }
    2457           0 :                 reply_nterror(req, status);
    2458           0 :                 goto out;
    2459             :         }
    2460             : 
    2461           0 :         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
    2462             : 
    2463           0 :         status = unlink_internals(conn, req, dirtype, dirfsp, smb_fname);
    2464           0 :         if (!NT_STATUS_IS_OK(status)) {
    2465           0 :                 if (open_was_deferred(req->xconn, req->mid)) {
    2466             :                         /* We have re-scheduled this call. */
    2467           0 :                         goto out;
    2468             :                 }
    2469           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    2470           0 :                         bool ok = defer_smb1_sharing_violation(req);
    2471           0 :                         if (ok) {
    2472           0 :                                 goto out;
    2473             :                         }
    2474             :                 }
    2475           0 :                 reply_nterror(req, status);
    2476           0 :                 goto out;
    2477             :         }
    2478             : 
    2479           0 :         reply_smb1_outbuf(req, 0, 0);
    2480           0 :  out:
    2481           0 :         TALLOC_FREE(smb_fname);
    2482           0 :         END_PROFILE(SMBunlink);
    2483           0 :         return;
    2484             : }
    2485             : 
    2486             : /****************************************************************************
    2487             :  Fail for readbraw.
    2488             : ****************************************************************************/
    2489             : 
    2490           0 : static void fail_readraw(void)
    2491             : {
    2492           0 :         const char *errstr = talloc_asprintf(talloc_tos(),
    2493             :                         "FAIL ! reply_readbraw: socket write fail (%s)",
    2494           0 :                         strerror(errno));
    2495           0 :         if (!errstr) {
    2496           0 :                 errstr = "";
    2497             :         }
    2498           0 :         exit_server_cleanly(errstr);
    2499             : }
    2500             : 
    2501             : /****************************************************************************
    2502             :  Return a readbraw error (4 bytes of zero).
    2503             : ****************************************************************************/
    2504             : 
    2505           0 : static void reply_readbraw_error(struct smbXsrv_connection *xconn)
    2506             : {
    2507             :         char header[4];
    2508             : 
    2509           0 :         SIVAL(header,0,0);
    2510             : 
    2511           0 :         smbd_lock_socket(xconn);
    2512           0 :         if (write_data(xconn->transport.sock,header,4) != 4) {
    2513           0 :                 int saved_errno = errno;
    2514             :                 /*
    2515             :                  * Try and give an error message saying what
    2516             :                  * client failed.
    2517             :                  */
    2518           0 :                 DEBUG(0, ("write_data failed for client %s. "
    2519             :                           "Error %s\n",
    2520             :                           smbXsrv_connection_dbg(xconn),
    2521             :                           strerror(saved_errno)));
    2522           0 :                 errno = saved_errno;
    2523             : 
    2524           0 :                 fail_readraw();
    2525             :         }
    2526           0 :         smbd_unlock_socket(xconn);
    2527           0 : }
    2528             : 
    2529             : /*******************************************************************
    2530             :  Ensure we don't use sendfile if server smb signing is active.
    2531             : ********************************************************************/
    2532             : 
    2533           0 : static bool lp_use_sendfile(int snum, struct smb1_signing_state *signing_state)
    2534             : {
    2535           0 :         bool sign_active = false;
    2536             : 
    2537             :         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
    2538           0 :         if (get_Protocol() < PROTOCOL_NT1) {
    2539           0 :                 return false;
    2540             :         }
    2541           0 :         if (signing_state) {
    2542           0 :                 sign_active = smb1_signing_is_active(signing_state);
    2543             :         }
    2544           0 :         return (lp__use_sendfile(snum) &&
    2545           0 :                         (get_remote_arch() != RA_WIN95) &&
    2546           0 :                         !sign_active);
    2547             : }
    2548             : /****************************************************************************
    2549             :  Use sendfile in readbraw.
    2550             : ****************************************************************************/
    2551             : 
    2552           0 : static void send_file_readbraw(connection_struct *conn,
    2553             :                                struct smb_request *req,
    2554             :                                files_struct *fsp,
    2555             :                                off_t startpos,
    2556             :                                size_t nread,
    2557             :                                ssize_t mincount)
    2558             : {
    2559           0 :         struct smbXsrv_connection *xconn = req->xconn;
    2560           0 :         char *outbuf = NULL;
    2561           0 :         ssize_t ret=0;
    2562             : 
    2563             :         /*
    2564             :          * We can only use sendfile on a non-chained packet 
    2565             :          * but we can use on a non-oplocked file. tridge proved this
    2566             :          * on a train in Germany :-). JRA.
    2567             :          * reply_readbraw has already checked the length.
    2568             :          */
    2569             : 
    2570           0 :         if ( !req_is_in_chain(req) &&
    2571           0 :              (nread > 0) &&
    2572           0 :              !fsp_is_alternate_stream(fsp) &&
    2573           0 :              lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
    2574           0 :                 ssize_t sendfile_read = -1;
    2575             :                 char header[4];
    2576             :                 DATA_BLOB header_blob;
    2577             : 
    2578           0 :                 _smb_setlen(header,nread);
    2579           0 :                 header_blob = data_blob_const(header, 4);
    2580             : 
    2581           0 :                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
    2582             :                                                  &header_blob, startpos,
    2583             :                                                  nread);
    2584           0 :                 if (sendfile_read == -1) {
    2585             :                         /* Returning ENOSYS means no data at all was sent.
    2586             :                          * Do this as a normal read. */
    2587           0 :                         if (errno == ENOSYS) {
    2588           0 :                                 goto normal_readbraw;
    2589             :                         }
    2590             : 
    2591             :                         /*
    2592             :                          * Special hack for broken Linux with no working sendfile. If we
    2593             :                          * return EINTR we sent the header but not the rest of the data.
    2594             :                          * Fake this up by doing read/write calls.
    2595             :                          */
    2596           0 :                         if (errno == EINTR) {
    2597             :                                 /* Ensure we don't do this again. */
    2598           0 :                                 set_use_sendfile(SNUM(conn), False);
    2599           0 :                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
    2600             : 
    2601           0 :                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
    2602           0 :                                         DEBUG(0,("send_file_readbraw: "
    2603             :                                                  "fake_sendfile failed for "
    2604             :                                                  "file %s (%s).\n",
    2605             :                                                  fsp_str_dbg(fsp),
    2606             :                                                  strerror(errno)));
    2607           0 :                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
    2608             :                                 }
    2609           0 :                                 return;
    2610             :                         }
    2611             : 
    2612           0 :                         DEBUG(0,("send_file_readbraw: sendfile failed for "
    2613             :                                  "file %s (%s). Terminating\n",
    2614             :                                  fsp_str_dbg(fsp), strerror(errno)));
    2615           0 :                         exit_server_cleanly("send_file_readbraw sendfile failed");
    2616           0 :                 } else if (sendfile_read == 0) {
    2617             :                         /*
    2618             :                          * Some sendfile implementations return 0 to indicate
    2619             :                          * that there was a short read, but nothing was
    2620             :                          * actually written to the socket.  In this case,
    2621             :                          * fallback to the normal read path so the header gets
    2622             :                          * the correct byte count.
    2623             :                          */
    2624           0 :                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
    2625             :                                   "bytes falling back to the normal read: "
    2626             :                                   "%s\n", fsp_str_dbg(fsp)));
    2627           0 :                         goto normal_readbraw;
    2628             :                 }
    2629             : 
    2630             :                 /* Deal with possible short send. */
    2631           0 :                 if (sendfile_read != 4+nread) {
    2632           0 :                         ret = sendfile_short_send(xconn, fsp,
    2633             :                                                   sendfile_read, 4, nread);
    2634           0 :                         if (ret == -1) {
    2635           0 :                                 fail_readraw();
    2636             :                         }
    2637             :                 }
    2638           0 :                 return;
    2639             :         }
    2640             : 
    2641           0 : normal_readbraw:
    2642             : 
    2643           0 :         outbuf = talloc_array(NULL, char, nread+4);
    2644           0 :         if (!outbuf) {
    2645           0 :                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
    2646             :                         (unsigned)(nread+4)));
    2647           0 :                 reply_readbraw_error(xconn);
    2648           0 :                 return;
    2649             :         }
    2650             : 
    2651           0 :         if (nread > 0) {
    2652           0 :                 ret = read_file(fsp,outbuf+4,startpos,nread);
    2653             : #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
    2654             :                 if (ret < mincount)
    2655             :                         ret = 0;
    2656             : #else
    2657           0 :                 if (ret < nread)
    2658           0 :                         ret = 0;
    2659             : #endif
    2660             :         }
    2661             : 
    2662           0 :         _smb_setlen(outbuf,ret);
    2663           0 :         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
    2664           0 :                 int saved_errno = errno;
    2665             :                 /*
    2666             :                  * Try and give an error message saying what
    2667             :                  * client failed.
    2668             :                  */
    2669           0 :                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
    2670             :                           smbXsrv_connection_dbg(xconn),
    2671             :                           strerror(saved_errno)));
    2672           0 :                 errno = saved_errno;
    2673             : 
    2674           0 :                 fail_readraw();
    2675             :         }
    2676             : 
    2677           0 :         TALLOC_FREE(outbuf);
    2678             : }
    2679             : 
    2680             : /****************************************************************************
    2681             :  Reply to a readbraw (core+ protocol).
    2682             : ****************************************************************************/
    2683             : 
    2684           0 : void reply_readbraw(struct smb_request *req)
    2685             : {
    2686           0 :         connection_struct *conn = req->conn;
    2687           0 :         struct smbXsrv_connection *xconn = req->xconn;
    2688             :         ssize_t maxcount,mincount;
    2689           0 :         size_t nread = 0;
    2690             :         off_t startpos;
    2691             :         files_struct *fsp;
    2692             :         struct lock_struct lock;
    2693           0 :         off_t size = 0;
    2694             :         NTSTATUS status;
    2695             : 
    2696           0 :         START_PROFILE(SMBreadbraw);
    2697             : 
    2698           0 :         if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
    2699           0 :                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
    2700             :                         "raw reads/writes are disallowed.");
    2701             :         }
    2702             : 
    2703           0 :         if (req->wct < 8) {
    2704           0 :                 reply_readbraw_error(xconn);
    2705           0 :                 END_PROFILE(SMBreadbraw);
    2706           0 :                 return;
    2707             :         }
    2708             : 
    2709           0 :         if (xconn->smb1.echo_handler.trusted_fde) {
    2710           0 :                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
    2711             :                          "'async smb echo handler = yes'\n"));
    2712           0 :                 reply_readbraw_error(xconn);
    2713           0 :                 END_PROFILE(SMBreadbraw);
    2714           0 :                 return;
    2715             :         }
    2716             : 
    2717             :         /*
    2718             :          * Special check if an oplock break has been issued
    2719             :          * and the readraw request croses on the wire, we must
    2720             :          * return a zero length response here.
    2721             :          */
    2722             : 
    2723           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    2724             : 
    2725             :         /*
    2726             :          * We have to do a check_fsp by hand here, as
    2727             :          * we must always return 4 zero bytes on error,
    2728             :          * not a NTSTATUS.
    2729             :          */
    2730             : 
    2731           0 :         if (fsp == NULL ||
    2732           0 :             conn == NULL ||
    2733           0 :             conn != fsp->conn ||
    2734           0 :             req->vuid != fsp->vuid ||
    2735           0 :             fsp->fsp_flags.is_directory ||
    2736           0 :             fsp_get_io_fd(fsp) == -1)
    2737             :         {
    2738             :                 /*
    2739             :                  * fsp could be NULL here so use the value from the packet. JRA.
    2740             :                  */
    2741           0 :                 DEBUG(3,("reply_readbraw: fnum %d not valid "
    2742             :                         "- cache prime?\n",
    2743             :                         (int)SVAL(req->vwv+0, 0)));
    2744           0 :                 reply_readbraw_error(xconn);
    2745           0 :                 END_PROFILE(SMBreadbraw);
    2746           0 :                 return;
    2747             :         }
    2748             : 
    2749             :         /* Do a "by hand" version of CHECK_READ. */
    2750           0 :         if (!(fsp->fsp_flags.can_read ||
    2751           0 :                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
    2752           0 :                                 (fsp->access_mask & FILE_EXECUTE)))) {
    2753           0 :                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
    2754             :                                 (int)SVAL(req->vwv+0, 0)));
    2755           0 :                 reply_readbraw_error(xconn);
    2756           0 :                 END_PROFILE(SMBreadbraw);
    2757           0 :                 return;
    2758             :         }
    2759             : 
    2760           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
    2761           0 :         if(req->wct == 10) {
    2762             :                 /*
    2763             :                  * This is a large offset (64 bit) read.
    2764             :                  */
    2765             : 
    2766           0 :                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
    2767             : 
    2768           0 :                 if(startpos < 0) {
    2769           0 :                         DEBUG(0,("reply_readbraw: negative 64 bit "
    2770             :                                 "readraw offset (%.0f) !\n",
    2771             :                                 (double)startpos ));
    2772           0 :                         reply_readbraw_error(xconn);
    2773           0 :                         END_PROFILE(SMBreadbraw);
    2774           0 :                         return;
    2775             :                 }
    2776             :         }
    2777             : 
    2778           0 :         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
    2779           0 :         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
    2780             : 
    2781             :         /* ensure we don't overrun the packet size */
    2782           0 :         maxcount = MIN(65535,maxcount);
    2783             : 
    2784           0 :         init_strict_lock_struct(fsp,
    2785           0 :                         (uint64_t)req->smbpid,
    2786             :                         (uint64_t)startpos,
    2787             :                         (uint64_t)maxcount,
    2788             :                         READ_LOCK,
    2789             :                         lp_posix_cifsu_locktype(fsp),
    2790             :                         &lock);
    2791             : 
    2792           0 :         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    2793           0 :                 reply_readbraw_error(xconn);
    2794           0 :                 END_PROFILE(SMBreadbraw);
    2795           0 :                 return;
    2796             :         }
    2797             : 
    2798           0 :         status = vfs_stat_fsp(fsp);
    2799           0 :         if (NT_STATUS_IS_OK(status)) {
    2800           0 :                 size = fsp->fsp_name->st.st_ex_size;
    2801             :         }
    2802             : 
    2803           0 :         if (startpos >= size) {
    2804           0 :                 nread = 0;
    2805             :         } else {
    2806           0 :                 nread = MIN(maxcount,(size - startpos));
    2807             :         }
    2808             : 
    2809             : #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
    2810             :         if (nread < mincount)
    2811             :                 nread = 0;
    2812             : #endif
    2813             : 
    2814           0 :         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
    2815             :                 "min=%lu nread=%lu\n",
    2816             :                 fsp_fnum_dbg(fsp), (double)startpos,
    2817             :                 (unsigned long)maxcount,
    2818             :                 (unsigned long)mincount,
    2819             :                 (unsigned long)nread ) );
    2820             : 
    2821           0 :         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
    2822             : 
    2823           0 :         DEBUG(5,("reply_readbraw finished\n"));
    2824             : 
    2825           0 :         END_PROFILE(SMBreadbraw);
    2826           0 :         return;
    2827             : }
    2828             : 
    2829             : #undef DBGC_CLASS
    2830             : #define DBGC_CLASS DBGC_LOCKING
    2831             : 
    2832             : /****************************************************************************
    2833             :  Reply to a lockread (core+ protocol).
    2834             : ****************************************************************************/
    2835             : 
    2836             : static void reply_lockread_locked(struct tevent_req *subreq);
    2837             : 
    2838           0 : void reply_lockread(struct smb_request *req)
    2839             : {
    2840           0 :         struct tevent_req *subreq = NULL;
    2841           0 :         connection_struct *conn = req->conn;
    2842             :         files_struct *fsp;
    2843           0 :         struct smbd_lock_element *lck = NULL;
    2844             : 
    2845           0 :         START_PROFILE(SMBlockread);
    2846             : 
    2847           0 :         if (req->wct < 5) {
    2848           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2849           0 :                 END_PROFILE(SMBlockread);
    2850           0 :                 return;
    2851             :         }
    2852             : 
    2853           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    2854             : 
    2855           0 :         if (!check_fsp(conn, req, fsp)) {
    2856           0 :                 END_PROFILE(SMBlockread);
    2857           0 :                 return;
    2858             :         }
    2859             : 
    2860           0 :         if (!CHECK_READ(fsp,req)) {
    2861           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    2862           0 :                 END_PROFILE(SMBlockread);
    2863           0 :                 return;
    2864             :         }
    2865             : 
    2866           0 :         lck = talloc(req, struct smbd_lock_element);
    2867           0 :         if (lck == NULL) {
    2868           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2869           0 :                 END_PROFILE(SMBlockread);
    2870           0 :                 return;
    2871             :         }
    2872             : 
    2873             :         /*
    2874             :          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
    2875             :          * protocol request that predates the read/write lock concept. 
    2876             :          * Thus instead of asking for a read lock here we need to ask
    2877             :          * for a write lock. JRA.
    2878             :          * Note that the requested lock size is unaffected by max_send.
    2879             :          */
    2880             : 
    2881           0 :         *lck = (struct smbd_lock_element) {
    2882           0 :                 .req_guid = smbd_request_guid(req, 0),
    2883           0 :                 .smblctx = req->smbpid,
    2884             :                 .brltype = WRITE_LOCK,
    2885             :                 .lock_flav = WINDOWS_LOCK,
    2886           0 :                 .count = SVAL(req->vwv+1, 0),
    2887           0 :                 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
    2888             :         };
    2889             : 
    2890           0 :         subreq = smbd_smb1_do_locks_send(
    2891             :                 fsp,
    2892           0 :                 req->sconn->ev_ctx,
    2893             :                 &req,
    2894             :                 fsp,
    2895             :                 0,
    2896             :                 false,          /* large_offset */
    2897             :                 1,
    2898             :                 lck);
    2899           0 :         if (subreq == NULL) {
    2900           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2901           0 :                 END_PROFILE(SMBlockread);
    2902           0 :                 return;
    2903             :         }
    2904           0 :         tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
    2905           0 :         END_PROFILE(SMBlockread);
    2906             : }
    2907             : 
    2908           0 : static void reply_lockread_locked(struct tevent_req *subreq)
    2909             : {
    2910           0 :         struct smb_request *req = NULL;
    2911           0 :         ssize_t nread = -1;
    2912           0 :         char *data = NULL;
    2913             :         NTSTATUS status;
    2914             :         bool ok;
    2915             :         off_t startpos;
    2916             :         size_t numtoread, maxtoread;
    2917           0 :         struct files_struct *fsp = NULL;
    2918           0 :         char *p = NULL;
    2919             : 
    2920           0 :         START_PROFILE(SMBlockread);
    2921             : 
    2922           0 :         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
    2923           0 :         SMB_ASSERT(ok);
    2924             : 
    2925           0 :         status = smbd_smb1_do_locks_recv(subreq);
    2926           0 :         TALLOC_FREE(subreq);
    2927             : 
    2928           0 :         if (!NT_STATUS_IS_OK(status)) {
    2929           0 :                 reply_nterror(req, status);
    2930           0 :                 goto send;
    2931             :         }
    2932             : 
    2933           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    2934           0 :         if (fsp == NULL) {
    2935           0 :                 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
    2936           0 :                 goto send;
    2937             :         }
    2938             : 
    2939           0 :         numtoread = SVAL(req->vwv+1, 0);
    2940           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
    2941             : 
    2942             :         /*
    2943             :          * However the requested READ size IS affected by max_send. Insanity.... JRA.
    2944             :          */
    2945           0 :         maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
    2946             : 
    2947           0 :         if (numtoread > maxtoread) {
    2948           0 :                 DBG_WARNING("requested read size (%zu) is greater than "
    2949             :                             "maximum allowed (%zu/%d). "
    2950             :                             "Returning short read of maximum allowed for "
    2951             :                             "compatibility with Windows 2000.\n",
    2952             :                             numtoread,
    2953             :                             maxtoread,
    2954             :                             req->xconn->smb1.sessions.max_send);
    2955           0 :                 numtoread = maxtoread;
    2956             :         }
    2957             : 
    2958           0 :         reply_smb1_outbuf(req, 5, numtoread + 3);
    2959             : 
    2960           0 :         data = smb_buf(req->outbuf) + 3;
    2961             : 
    2962           0 :         nread = read_file(fsp,data,startpos,numtoread);
    2963             : 
    2964           0 :         if (nread < 0) {
    2965           0 :                 reply_nterror(req, map_nt_error_from_unix(errno));
    2966           0 :                 goto send;
    2967             :         }
    2968             : 
    2969           0 :         srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
    2970             : 
    2971           0 :         SSVAL(req->outbuf,smb_vwv0,nread);
    2972           0 :         SSVAL(req->outbuf,smb_vwv5,nread+3);
    2973           0 :         p = smb_buf(req->outbuf);
    2974           0 :         SCVAL(p,0,0); /* pad byte. */
    2975           0 :         SSVAL(p,1,nread);
    2976             : 
    2977           0 :         DEBUG(3,("lockread %s num=%d nread=%d\n",
    2978             :                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
    2979             : 
    2980           0 : send:
    2981           0 :         ok = smb1_srv_send(req->xconn,
    2982           0 :                           (char *)req->outbuf,
    2983             :                           true,
    2984           0 :                           req->seqnum+1,
    2985           0 :                           IS_CONN_ENCRYPTED(req->conn),
    2986             :                           NULL);
    2987           0 :         if (!ok) {
    2988           0 :                 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
    2989             :         }
    2990           0 :         TALLOC_FREE(req);
    2991           0 :         END_PROFILE(SMBlockread);
    2992           0 :         return;
    2993             : }
    2994             : 
    2995             : #undef DBGC_CLASS
    2996             : #define DBGC_CLASS DBGC_ALL
    2997             : 
    2998             : /****************************************************************************
    2999             :  Reply to a read.
    3000             : ****************************************************************************/
    3001             : 
    3002           0 : void reply_read(struct smb_request *req)
    3003             : {
    3004           0 :         connection_struct *conn = req->conn;
    3005             :         size_t numtoread;
    3006             :         size_t maxtoread;
    3007           0 :         ssize_t nread = 0;
    3008             :         char *data;
    3009             :         off_t startpos;
    3010             :         files_struct *fsp;
    3011             :         struct lock_struct lock;
    3012           0 :         struct smbXsrv_connection *xconn = req->xconn;
    3013             : 
    3014           0 :         START_PROFILE(SMBread);
    3015             : 
    3016           0 :         if (req->wct < 3) {
    3017           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3018           0 :                 END_PROFILE(SMBread);
    3019           0 :                 return;
    3020             :         }
    3021             : 
    3022           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    3023             : 
    3024           0 :         if (!check_fsp(conn, req, fsp)) {
    3025           0 :                 END_PROFILE(SMBread);
    3026           0 :                 return;
    3027             :         }
    3028             : 
    3029           0 :         if (!CHECK_READ(fsp,req)) {
    3030           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    3031           0 :                 END_PROFILE(SMBread);
    3032           0 :                 return;
    3033             :         }
    3034             : 
    3035           0 :         numtoread = SVAL(req->vwv+1, 0);
    3036           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
    3037             : 
    3038             :         /*
    3039             :          * The requested read size cannot be greater than max_send. JRA.
    3040             :          */
    3041           0 :         maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
    3042             : 
    3043           0 :         if (numtoread > maxtoread) {
    3044           0 :                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
    3045             : Returning short read of maximum allowed for compatibility with Windows 2000.\n",
    3046             :                         (unsigned int)numtoread, (unsigned int)maxtoread,
    3047             :                         (unsigned int)xconn->smb1.sessions.max_send));
    3048           0 :                 numtoread = maxtoread;
    3049             :         }
    3050             : 
    3051           0 :         reply_smb1_outbuf(req, 5, numtoread+3);
    3052             : 
    3053           0 :         data = smb_buf(req->outbuf) + 3;
    3054             : 
    3055           0 :         init_strict_lock_struct(fsp,
    3056           0 :                         (uint64_t)req->smbpid,
    3057             :                         (uint64_t)startpos,
    3058             :                         (uint64_t)numtoread,
    3059             :                         READ_LOCK,
    3060             :                         lp_posix_cifsu_locktype(fsp),
    3061             :                         &lock);
    3062             : 
    3063           0 :         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    3064           0 :                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    3065           0 :                 END_PROFILE(SMBread);
    3066           0 :                 return;
    3067             :         }
    3068             : 
    3069           0 :         if (numtoread > 0)
    3070           0 :                 nread = read_file(fsp,data,startpos,numtoread);
    3071             : 
    3072           0 :         if (nread < 0) {
    3073           0 :                 reply_nterror(req, map_nt_error_from_unix(errno));
    3074           0 :                 goto out;
    3075             :         }
    3076             : 
    3077           0 :         srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
    3078             : 
    3079           0 :         SSVAL(req->outbuf,smb_vwv0,nread);
    3080           0 :         SSVAL(req->outbuf,smb_vwv5,nread+3);
    3081           0 :         SCVAL(smb_buf(req->outbuf),0,1);
    3082           0 :         SSVAL(smb_buf(req->outbuf),1,nread);
    3083             : 
    3084           0 :         DEBUG(3, ("read %s num=%d nread=%d\n",
    3085             :                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
    3086             : 
    3087           0 : out:
    3088           0 :         END_PROFILE(SMBread);
    3089           0 :         return;
    3090             : }
    3091             : 
    3092             : /****************************************************************************
    3093             :  Setup readX header.
    3094             : ****************************************************************************/
    3095             : 
    3096           0 : size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
    3097             : {
    3098             :         size_t outsize;
    3099             : 
    3100           0 :         outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
    3101             :                                   False);
    3102             : 
    3103           0 :         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
    3104             : 
    3105           0 :         SCVAL(outbuf,smb_vwv0,0xFF);
    3106           0 :         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
    3107           0 :         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
    3108           0 :         SSVAL(outbuf,smb_vwv6,
    3109             :               (smb_wct - 4)     /* offset from smb header to wct */
    3110             :               + 1               /* the wct field */
    3111             :               + 12 * sizeof(uint16_t) /* vwv */
    3112             :               + 2               /* the buflen field */
    3113             :               + 1);             /* padding byte */
    3114           0 :         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
    3115           0 :         SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
    3116             :         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
    3117           0 :         _smb_setlen_large(outbuf,
    3118             :                           smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
    3119           0 :         return outsize;
    3120             : }
    3121             : 
    3122             : /****************************************************************************
    3123             :  Reply to a read and X - possibly using sendfile.
    3124             : ****************************************************************************/
    3125             : 
    3126           0 : static void send_file_readX(connection_struct *conn, struct smb_request *req,
    3127             :                             files_struct *fsp, off_t startpos,
    3128             :                             size_t smb_maxcnt)
    3129             : {
    3130           0 :         struct smbXsrv_connection *xconn = req->xconn;
    3131           0 :         ssize_t nread = -1;
    3132             :         struct lock_struct lock;
    3133           0 :         int saved_errno = 0;
    3134             :         NTSTATUS status;
    3135             : 
    3136           0 :         init_strict_lock_struct(fsp,
    3137           0 :                         (uint64_t)req->smbpid,
    3138             :                         (uint64_t)startpos,
    3139             :                         (uint64_t)smb_maxcnt,
    3140             :                         READ_LOCK,
    3141             :                         lp_posix_cifsu_locktype(fsp),
    3142             :                         &lock);
    3143             : 
    3144           0 :         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    3145           0 :                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    3146           0 :                 return;
    3147             :         }
    3148             : 
    3149             :         /*
    3150             :          * We can only use sendfile on a non-chained packet
    3151             :          * but we can use on a non-oplocked file. tridge proved this
    3152             :          * on a train in Germany :-). JRA.
    3153             :          */
    3154             : 
    3155           0 :         if (!req_is_in_chain(req) &&
    3156           0 :             !req->encrypted &&
    3157           0 :             !fsp_is_alternate_stream(fsp) &&
    3158           0 :             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
    3159             :                 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
    3160             :                 DATA_BLOB header;
    3161             : 
    3162           0 :                 status = vfs_stat_fsp(fsp);
    3163           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3164           0 :                         reply_nterror(req, status);
    3165           0 :                         goto out;
    3166             :                 }
    3167             : 
    3168           0 :                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
    3169           0 :                     (startpos > fsp->fsp_name->st.st_ex_size) ||
    3170           0 :                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
    3171             :                         /*
    3172             :                          * We already know that we would do a short read, so don't
    3173             :                          * try the sendfile() path.
    3174             :                          */
    3175           0 :                         goto nosendfile_read;
    3176             :                 }
    3177             : 
    3178             :                 /*
    3179             :                  * Set up the packet header before send. We
    3180             :                  * assume here the sendfile will work (get the
    3181             :                  * correct amount of data).
    3182             :                  */
    3183             : 
    3184           0 :                 header = data_blob_const(headerbuf, sizeof(headerbuf));
    3185             : 
    3186           0 :                 construct_smb1_reply_common_req(req, (char *)headerbuf);
    3187           0 :                 setup_readX_header((char *)headerbuf, smb_maxcnt);
    3188             : 
    3189           0 :                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
    3190             :                                          startpos, smb_maxcnt);
    3191           0 :                 if (nread == -1) {
    3192           0 :                         saved_errno = errno;
    3193             : 
    3194             :                         /* Returning ENOSYS means no data at all was sent.
    3195             :                            Do this as a normal read. */
    3196           0 :                         if (errno == ENOSYS) {
    3197           0 :                                 goto normal_read;
    3198             :                         }
    3199             : 
    3200             :                         /*
    3201             :                          * Special hack for broken Linux with no working sendfile. If we
    3202             :                          * return EINTR we sent the header but not the rest of the data.
    3203             :                          * Fake this up by doing read/write calls.
    3204             :                          */
    3205             : 
    3206           0 :                         if (errno == EINTR) {
    3207             :                                 /* Ensure we don't do this again. */
    3208           0 :                                 set_use_sendfile(SNUM(conn), False);
    3209           0 :                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
    3210           0 :                                 nread = fake_sendfile(xconn, fsp, startpos,
    3211             :                                                       smb_maxcnt);
    3212           0 :                                 if (nread == -1) {
    3213           0 :                                         saved_errno = errno;
    3214           0 :                                         DEBUG(0,("send_file_readX: "
    3215             :                                                  "fake_sendfile failed for "
    3216             :                                                  "file %s (%s) for client %s. "
    3217             :                                                  "Terminating\n",
    3218             :                                                  fsp_str_dbg(fsp),
    3219             :                                                  smbXsrv_connection_dbg(xconn),
    3220             :                                                  strerror(saved_errno)));
    3221           0 :                                         errno = saved_errno;
    3222           0 :                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
    3223             :                                 }
    3224           0 :                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
    3225             :                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
    3226             :                                 /* No outbuf here means successful sendfile. */
    3227           0 :                                 goto out;
    3228             :                         }
    3229             : 
    3230           0 :                         DEBUG(0,("send_file_readX: sendfile failed for file "
    3231             :                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
    3232             :                                  strerror(errno)));
    3233           0 :                         exit_server_cleanly("send_file_readX sendfile failed");
    3234           0 :                 } else if (nread == 0) {
    3235             :                         /*
    3236             :                          * Some sendfile implementations return 0 to indicate
    3237             :                          * that there was a short read, but nothing was
    3238             :                          * actually written to the socket.  In this case,
    3239             :                          * fallback to the normal read path so the header gets
    3240             :                          * the correct byte count.
    3241             :                          */
    3242           0 :                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
    3243             :                                   "falling back to the normal read: %s\n",
    3244             :                                   fsp_str_dbg(fsp)));
    3245           0 :                         goto normal_read;
    3246             :                 }
    3247             : 
    3248           0 :                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
    3249             :                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
    3250             : 
    3251             :                 /* Deal with possible short send. */
    3252           0 :                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
    3253             :                         ssize_t ret;
    3254             : 
    3255           0 :                         ret = sendfile_short_send(xconn, fsp, nread,
    3256             :                                                   sizeof(headerbuf), smb_maxcnt);
    3257           0 :                         if (ret == -1) {
    3258             :                                 const char *r;
    3259           0 :                                 r = "send_file_readX: sendfile_short_send failed";
    3260           0 :                                 DEBUG(0,("%s for file %s (%s).\n",
    3261             :                                          r, fsp_str_dbg(fsp), strerror(errno)));
    3262           0 :                                 exit_server_cleanly(r);
    3263             :                         }
    3264             :                 }
    3265             :                 /* No outbuf here means successful sendfile. */
    3266           0 :                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
    3267           0 :                 SMB_PERFCOUNT_END(&req->pcd);
    3268           0 :                 goto out;
    3269             :         }
    3270             : 
    3271           0 : normal_read:
    3272             : 
    3273           0 :         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
    3274             :                 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
    3275             :                 ssize_t ret;
    3276             : 
    3277           0 :                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
    3278           0 :                     (startpos > fsp->fsp_name->st.st_ex_size) ||
    3279           0 :                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
    3280             :                         /*
    3281             :                          * We already know that we would do a short
    3282             :                          * read, so don't try the sendfile() path.
    3283             :                          */
    3284           0 :                         goto nosendfile_read;
    3285             :                 }
    3286             : 
    3287           0 :                 construct_smb1_reply_common_req(req, (char *)headerbuf);
    3288           0 :                 setup_readX_header((char *)headerbuf, smb_maxcnt);
    3289             : 
    3290             :                 /* Send out the header. */
    3291           0 :                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
    3292             :                                  sizeof(headerbuf));
    3293           0 :                 if (ret != sizeof(headerbuf)) {
    3294           0 :                         saved_errno = errno;
    3295             :                         /*
    3296             :                          * Try and give an error message saying what
    3297             :                          * client failed.
    3298             :                          */
    3299           0 :                         DEBUG(0,("send_file_readX: write_data failed for file "
    3300             :                                  "%s (%s) for client %s. Terminating\n",
    3301             :                                  fsp_str_dbg(fsp),
    3302             :                                  smbXsrv_connection_dbg(xconn),
    3303             :                                  strerror(saved_errno)));
    3304           0 :                         errno = saved_errno;
    3305           0 :                         exit_server_cleanly("send_file_readX sendfile failed");
    3306             :                 }
    3307           0 :                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
    3308           0 :                 if (nread == -1) {
    3309           0 :                         saved_errno = errno;
    3310           0 :                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
    3311             :                                  "%s (%s) for client %s. Terminating\n",
    3312             :                                  fsp_str_dbg(fsp),
    3313             :                                  smbXsrv_connection_dbg(xconn),
    3314             :                                  strerror(saved_errno)));
    3315           0 :                         errno = saved_errno;
    3316           0 :                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
    3317             :                 }
    3318           0 :                 goto out;
    3319             :         }
    3320             : 
    3321           0 : nosendfile_read:
    3322             : 
    3323           0 :         reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
    3324           0 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
    3325           0 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
    3326             : 
    3327           0 :         nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
    3328             :                           startpos, smb_maxcnt);
    3329           0 :         saved_errno = errno;
    3330             : 
    3331           0 :         if (nread < 0) {
    3332           0 :                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
    3333           0 :                 return;
    3334             :         }
    3335             : 
    3336           0 :         setup_readX_header((char *)req->outbuf, nread);
    3337             : 
    3338           0 :         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
    3339             :                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
    3340           0 :         return;
    3341             : 
    3342           0 : out:
    3343           0 :         TALLOC_FREE(req->outbuf);
    3344           0 :         return;
    3345             : }
    3346             : 
    3347             : /****************************************************************************
    3348             :  Work out how much space we have for a read return.
    3349             : ****************************************************************************/
    3350             : 
    3351           0 : static size_t calc_max_read_pdu(const struct smb_request *req)
    3352             : {
    3353           0 :         struct smbXsrv_connection *xconn = req->xconn;
    3354             : 
    3355           0 :         if (xconn->protocol < PROTOCOL_NT1) {
    3356           0 :                 return xconn->smb1.sessions.max_send;
    3357             :         }
    3358             : 
    3359           0 :         if (!lp_large_readwrite()) {
    3360           0 :                 return xconn->smb1.sessions.max_send;
    3361             :         }
    3362             : 
    3363           0 :         if (req_is_in_chain(req)) {
    3364           0 :                 return xconn->smb1.sessions.max_send;
    3365             :         }
    3366             : 
    3367           0 :         if (req->encrypted) {
    3368             :                 /*
    3369             :                  * Don't take encrypted traffic up to the
    3370             :                  * limit. There are padding considerations
    3371             :                  * that make that tricky.
    3372             :                  */
    3373           0 :                 return xconn->smb1.sessions.max_send;
    3374             :         }
    3375             : 
    3376           0 :         if (smb1_srv_is_signing_active(xconn)) {
    3377           0 :                 return 0x1FFFF;
    3378             :         }
    3379             : 
    3380           0 :         if (!lp_smb1_unix_extensions()) {
    3381           0 :                 return 0x1FFFF;
    3382             :         }
    3383             : 
    3384             :         /*
    3385             :          * We can do ultra-large POSIX reads.
    3386             :          */
    3387           0 :         return 0xFFFFFF;
    3388             : }
    3389             : 
    3390             : /****************************************************************************
    3391             :  Calculate how big a read can be. Copes with all clients. It's always
    3392             :  safe to return a short read - Windows does this.
    3393             : ****************************************************************************/
    3394             : 
    3395           0 : static size_t calc_read_size(const struct smb_request *req,
    3396             :                              size_t upper_size,
    3397             :                              size_t lower_size)
    3398             : {
    3399           0 :         struct smbXsrv_connection *xconn = req->xconn;
    3400           0 :         size_t max_pdu = calc_max_read_pdu(req);
    3401           0 :         size_t total_size = 0;
    3402           0 :         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
    3403           0 :         size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
    3404             : 
    3405             :         /*
    3406             :          * Windows explicitly ignores upper size of 0xFFFF.
    3407             :          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
    3408             :          * We must do the same as these will never fit even in
    3409             :          * an extended size NetBIOS packet.
    3410             :          */
    3411           0 :         if (upper_size == 0xFFFF) {
    3412           0 :                 upper_size = 0;
    3413             :         }
    3414             : 
    3415           0 :         if (xconn->protocol < PROTOCOL_NT1) {
    3416           0 :                 upper_size = 0;
    3417             :         }
    3418             : 
    3419           0 :         total_size = ((upper_size<<16) | lower_size);
    3420             : 
    3421             :         /*
    3422             :          * LARGE_READX test shows it's always safe to return
    3423             :          * a short read. Windows does so.
    3424             :          */
    3425           0 :         return MIN(total_size, max_len);
    3426             : }
    3427             : 
    3428             : /****************************************************************************
    3429             :  Reply to a read and X.
    3430             : ****************************************************************************/
    3431             : 
    3432           0 : void reply_read_and_X(struct smb_request *req)
    3433             : {
    3434           0 :         connection_struct *conn = req->conn;
    3435             :         files_struct *fsp;
    3436             :         off_t startpos;
    3437             :         size_t smb_maxcnt;
    3438             :         size_t upper_size;
    3439           0 :         bool big_readX = False;
    3440             : #if 0
    3441             :         size_t smb_mincnt = SVAL(req->vwv+6, 0);
    3442             : #endif
    3443             : 
    3444           0 :         START_PROFILE(SMBreadX);
    3445             : 
    3446           0 :         if ((req->wct != 10) && (req->wct != 12)) {
    3447           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3448           0 :                 return;
    3449             :         }
    3450             : 
    3451           0 :         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
    3452           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
    3453           0 :         smb_maxcnt = SVAL(req->vwv+5, 0);
    3454             : 
    3455             :         /* If it's an IPC, pass off the pipe handler. */
    3456           0 :         if (IS_IPC(conn)) {
    3457           0 :                 reply_pipe_read_and_X(req);
    3458           0 :                 END_PROFILE(SMBreadX);
    3459           0 :                 return;
    3460             :         }
    3461             : 
    3462           0 :         if (!check_fsp(conn, req, fsp)) {
    3463           0 :                 END_PROFILE(SMBreadX);
    3464           0 :                 return;
    3465             :         }
    3466             : 
    3467           0 :         if (!CHECK_READ(fsp,req)) {
    3468           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    3469           0 :                 END_PROFILE(SMBreadX);
    3470           0 :                 return;
    3471             :         }
    3472             : 
    3473           0 :         upper_size = SVAL(req->vwv+7, 0);
    3474           0 :         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
    3475           0 :         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
    3476             :                 /*
    3477             :                  * This is a heuristic to avoid keeping large
    3478             :                  * outgoing buffers around over long-lived aio
    3479             :                  * requests.
    3480             :                  */
    3481           0 :                 big_readX = True;
    3482             :         }
    3483             : 
    3484           0 :         if (req->wct == 12) {
    3485             :                 /*
    3486             :                  * This is a large offset (64 bit) read.
    3487             :                  */
    3488           0 :                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
    3489             : 
    3490             :         }
    3491             : 
    3492           0 :         if (!big_readX) {
    3493           0 :                 NTSTATUS status = schedule_aio_read_and_X(conn,
    3494             :                                         req,
    3495             :                                         fsp,
    3496             :                                         startpos,
    3497             :                                         smb_maxcnt);
    3498           0 :                 if (NT_STATUS_IS_OK(status)) {
    3499             :                         /* Read scheduled - we're done. */
    3500           0 :                         goto out;
    3501             :                 }
    3502           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
    3503             :                         /* Real error - report to client. */
    3504           0 :                         END_PROFILE(SMBreadX);
    3505           0 :                         reply_nterror(req, status);
    3506           0 :                         return;
    3507             :                 }
    3508             :                 /* NT_STATUS_RETRY - fall back to sync read. */
    3509             :         }
    3510             : 
    3511           0 :         smbd_lock_socket(req->xconn);
    3512           0 :         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
    3513           0 :         smbd_unlock_socket(req->xconn);
    3514             : 
    3515           0 :  out:
    3516           0 :         END_PROFILE(SMBreadX);
    3517           0 :         return;
    3518             : }
    3519             : 
    3520             : /****************************************************************************
    3521             :  Error replies to writebraw must have smb_wct == 1. Fix this up.
    3522             : ****************************************************************************/
    3523             : 
    3524           0 : void error_to_writebrawerr(struct smb_request *req)
    3525             : {
    3526           0 :         uint8_t *old_outbuf = req->outbuf;
    3527             : 
    3528           0 :         reply_smb1_outbuf(req, 1, 0);
    3529             : 
    3530           0 :         memcpy(req->outbuf, old_outbuf, smb_size);
    3531           0 :         TALLOC_FREE(old_outbuf);
    3532           0 : }
    3533             : 
    3534             : /****************************************************************************
    3535             :  Read 4 bytes of a smb packet and return the smb length of the packet.
    3536             :  Store the result in the buffer. This version of the function will
    3537             :  never return a session keepalive (length of zero).
    3538             :  Timeout is in milliseconds.
    3539             : ****************************************************************************/
    3540             : 
    3541           0 : static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
    3542             :                                 size_t *len)
    3543             : {
    3544           0 :         uint8_t msgtype = NBSSkeepalive;
    3545             : 
    3546           0 :         while (msgtype == NBSSkeepalive) {
    3547             :                 NTSTATUS status;
    3548             : 
    3549           0 :                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
    3550             :                                                           len);
    3551           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3552             :                         char addr[INET6_ADDRSTRLEN];
    3553             :                         /* Try and give an error message
    3554             :                          * saying what client failed. */
    3555           0 :                         DEBUG(0, ("read_smb_length_return_keepalive failed for "
    3556             :                                   "client %s read error = %s.\n",
    3557             :                                   get_peer_addr(fd,addr,sizeof(addr)),
    3558             :                                   nt_errstr(status)));
    3559           0 :                         return status;
    3560             :                 }
    3561             : 
    3562           0 :                 msgtype = CVAL(inbuf, 0);
    3563             :         }
    3564             : 
    3565           0 :         DEBUG(10,("read_smb_length: got smb length of %lu\n",
    3566             :                   (unsigned long)len));
    3567             : 
    3568           0 :         return NT_STATUS_OK;
    3569             : }
    3570             : 
    3571             : /****************************************************************************
    3572             :  Reply to a writebraw (core+ or LANMAN1.0 protocol).
    3573             : ****************************************************************************/
    3574             : 
    3575           0 : void reply_writebraw(struct smb_request *req)
    3576             : {
    3577           0 :         connection_struct *conn = req->conn;
    3578           0 :         struct smbXsrv_connection *xconn = req->xconn;
    3579           0 :         char *buf = NULL;
    3580           0 :         ssize_t nwritten=0;
    3581           0 :         ssize_t total_written=0;
    3582           0 :         size_t numtowrite=0;
    3583             :         size_t tcount;
    3584             :         off_t startpos;
    3585           0 :         const char *data=NULL;
    3586             :         bool write_through;
    3587             :         files_struct *fsp;
    3588             :         struct lock_struct lock;
    3589             :         NTSTATUS status;
    3590             : 
    3591           0 :         START_PROFILE(SMBwritebraw);
    3592             : 
    3593             :         /*
    3594             :          * If we ever reply with an error, it must have the SMB command
    3595             :          * type of SMBwritec, not SMBwriteBraw, as this tells the client
    3596             :          * we're finished.
    3597             :          */
    3598           0 :         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
    3599             : 
    3600           0 :         if (smb1_srv_is_signing_active(xconn)) {
    3601           0 :                 END_PROFILE(SMBwritebraw);
    3602           0 :                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
    3603             :                                 "raw reads/writes are disallowed.");
    3604             :         }
    3605             : 
    3606           0 :         if (req->wct < 12) {
    3607           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3608           0 :                 error_to_writebrawerr(req);
    3609           0 :                 END_PROFILE(SMBwritebraw);
    3610           0 :                 return;
    3611             :         }
    3612             : 
    3613           0 :         if (xconn->smb1.echo_handler.trusted_fde) {
    3614           0 :                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
    3615             :                          "'async smb echo handler = yes'\n"));
    3616           0 :                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
    3617           0 :                 error_to_writebrawerr(req);
    3618           0 :                 END_PROFILE(SMBwritebraw);
    3619           0 :                 return;
    3620             :         }
    3621             : 
    3622           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    3623           0 :         if (!check_fsp(conn, req, fsp)) {
    3624           0 :                 error_to_writebrawerr(req);
    3625           0 :                 END_PROFILE(SMBwritebraw);
    3626           0 :                 return;
    3627             :         }
    3628             : 
    3629           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
    3630           0 :         if (!NT_STATUS_IS_OK(status)) {
    3631           0 :                 reply_nterror(req, status);
    3632           0 :                 error_to_writebrawerr(req);
    3633           0 :                 END_PROFILE(SMBwritebraw);
    3634           0 :                 return;
    3635             :         }
    3636             : 
    3637           0 :         tcount = IVAL(req->vwv+1, 0);
    3638           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
    3639           0 :         write_through = BITSETW(req->vwv+7,0);
    3640             : 
    3641             :         /* We have to deal with slightly different formats depending
    3642             :                 on whether we are using the core+ or lanman1.0 protocol */
    3643             : 
    3644           0 :         if(get_Protocol() <= PROTOCOL_COREPLUS) {
    3645           0 :                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
    3646           0 :                 data = smb_buf_const(req->inbuf);
    3647             :         } else {
    3648           0 :                 numtowrite = SVAL(req->vwv+10, 0);
    3649           0 :                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
    3650             :         }
    3651             : 
    3652             :         /* Ensure we don't write bytes past the end of this packet. */
    3653             :         /*
    3654             :          * This already protects us against CVE-2017-12163.
    3655             :          */
    3656           0 :         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
    3657           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3658           0 :                 error_to_writebrawerr(req);
    3659           0 :                 END_PROFILE(SMBwritebraw);
    3660           0 :                 return;
    3661             :         }
    3662             : 
    3663           0 :         if (!fsp->print_file) {
    3664           0 :                 init_strict_lock_struct(fsp,
    3665           0 :                                 (uint64_t)req->smbpid,
    3666             :                                 (uint64_t)startpos,
    3667             :                                 (uint64_t)tcount,
    3668             :                                 WRITE_LOCK,
    3669             :                                 lp_posix_cifsu_locktype(fsp),
    3670             :                                 &lock);
    3671             : 
    3672           0 :                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    3673           0 :                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    3674           0 :                         error_to_writebrawerr(req);
    3675           0 :                         END_PROFILE(SMBwritebraw);
    3676           0 :                         return;
    3677             :                 }
    3678             :         }
    3679             : 
    3680           0 :         if (numtowrite>0) {
    3681           0 :                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
    3682             :         }
    3683             : 
    3684           0 :         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
    3685             :                         "wrote=%d sync=%d\n",
    3686             :                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
    3687             :                 (int)nwritten, (int)write_through));
    3688             : 
    3689           0 :         if (nwritten < (ssize_t)numtowrite)  {
    3690           0 :                 reply_nterror(req, NT_STATUS_DISK_FULL);
    3691           0 :                 error_to_writebrawerr(req);
    3692           0 :                 goto out;
    3693             :         }
    3694             : 
    3695           0 :         total_written = nwritten;
    3696             : 
    3697             :         /* Allocate a buffer of 64k + length. */
    3698           0 :         buf = talloc_array(NULL, char, 65540);
    3699           0 :         if (!buf) {
    3700           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    3701           0 :                 error_to_writebrawerr(req);
    3702           0 :                 goto out;
    3703             :         }
    3704             : 
    3705             :         /* Return a SMBwritebraw message to the redirector to tell
    3706             :          * it to send more bytes */
    3707             : 
    3708           0 :         memcpy(buf, req->inbuf, smb_size);
    3709           0 :         srv_smb1_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
    3710           0 :         SCVAL(buf,smb_com,SMBwritebraw);
    3711           0 :         SSVALS(buf,smb_vwv0,0xFFFF);
    3712           0 :         show_msg(buf);
    3713           0 :         if (!smb1_srv_send(req->xconn,
    3714             :                           buf,
    3715             :                           false, 0, /* no signing */
    3716           0 :                           IS_CONN_ENCRYPTED(conn),
    3717             :                           &req->pcd)) {
    3718           0 :                 exit_server_cleanly("reply_writebraw: smb1_srv_send "
    3719             :                         "failed.");
    3720             :         }
    3721             : 
    3722             :         /* Now read the raw data into the buffer and write it */
    3723           0 :         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
    3724             :                                  &numtowrite);
    3725           0 :         if (!NT_STATUS_IS_OK(status)) {
    3726           0 :                 exit_server_cleanly("secondary writebraw failed");
    3727             :         }
    3728             : 
    3729             :         /* Set up outbuf to return the correct size */
    3730           0 :         reply_smb1_outbuf(req, 1, 0);
    3731             : 
    3732           0 :         if (numtowrite != 0) {
    3733             : 
    3734           0 :                 if (numtowrite > 0xFFFF) {
    3735           0 :                         DEBUG(0,("reply_writebraw: Oversize secondary write "
    3736             :                                 "raw requested (%u). Terminating\n",
    3737             :                                 (unsigned int)numtowrite ));
    3738           0 :                         exit_server_cleanly("secondary writebraw failed");
    3739             :                 }
    3740             : 
    3741           0 :                 if (tcount > nwritten+numtowrite) {
    3742           0 :                         DEBUG(3,("reply_writebraw: Client overestimated the "
    3743             :                                 "write %d %d %d\n",
    3744             :                                 (int)tcount,(int)nwritten,(int)numtowrite));
    3745             :                 }
    3746             : 
    3747           0 :                 status = read_data_ntstatus(xconn->transport.sock, buf+4,
    3748             :                                             numtowrite);
    3749             : 
    3750           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3751             :                         /* Try and give an error message
    3752             :                          * saying what client failed. */
    3753           0 :                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
    3754             :                                   "raw read failed (%s) for client %s. "
    3755             :                                   "Terminating\n", nt_errstr(status),
    3756             :                                   smbXsrv_connection_dbg(xconn)));
    3757           0 :                         exit_server_cleanly("secondary writebraw failed");
    3758             :                 }
    3759             : 
    3760             :                 /*
    3761             :                  * We are not vulnerable to CVE-2017-12163
    3762             :                  * here as we are guaranteed to have numtowrite
    3763             :                  * bytes available - we just read from the client.
    3764             :                  */
    3765           0 :                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
    3766           0 :                 if (nwritten == -1) {
    3767           0 :                         TALLOC_FREE(buf);
    3768           0 :                         reply_nterror(req, map_nt_error_from_unix(errno));
    3769           0 :                         error_to_writebrawerr(req);
    3770           0 :                         goto out;
    3771             :                 }
    3772             : 
    3773           0 :                 if (nwritten < (ssize_t)numtowrite) {
    3774           0 :                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
    3775           0 :                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
    3776             :                 }
    3777             : 
    3778           0 :                 if (nwritten > 0) {
    3779           0 :                         total_written += nwritten;
    3780             :                 }
    3781             :         }
    3782             : 
    3783           0 :         TALLOC_FREE(buf);
    3784           0 :         SSVAL(req->outbuf,smb_vwv0,total_written);
    3785             : 
    3786           0 :         status = sync_file(conn, fsp, write_through);
    3787           0 :         if (!NT_STATUS_IS_OK(status)) {
    3788           0 :                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
    3789             :                          fsp_str_dbg(fsp), nt_errstr(status)));
    3790           0 :                 reply_nterror(req, status);
    3791           0 :                 error_to_writebrawerr(req);
    3792           0 :                 goto out;
    3793             :         }
    3794             : 
    3795           0 :         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
    3796             :                 "wrote=%d\n",
    3797             :                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
    3798             :                 (int)total_written));
    3799             : 
    3800             :         /* We won't return a status if write through is not selected - this
    3801             :          * follows what WfWg does */
    3802           0 :         END_PROFILE(SMBwritebraw);
    3803             : 
    3804           0 :         if (!write_through && total_written==tcount) {
    3805             : 
    3806             : #if RABBIT_PELLET_FIX
    3807             :                 /*
    3808             :                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
    3809             :                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
    3810             :                  * JRA.
    3811             :                  */
    3812           0 :                 if (!send_keepalive(xconn->transport.sock)) {
    3813           0 :                         exit_server_cleanly("reply_writebraw: send of "
    3814             :                                 "keepalive failed");
    3815             :                 }
    3816             : #endif
    3817           0 :                 TALLOC_FREE(req->outbuf);
    3818             :         }
    3819           0 :         return;
    3820             : 
    3821           0 : out:
    3822           0 :         END_PROFILE(SMBwritebraw);
    3823           0 :         return;
    3824             : }
    3825             : 
    3826             : #undef DBGC_CLASS
    3827             : #define DBGC_CLASS DBGC_LOCKING
    3828             : 
    3829             : /****************************************************************************
    3830             :  Reply to a writeunlock (core+).
    3831             : ****************************************************************************/
    3832             : 
    3833           0 : void reply_writeunlock(struct smb_request *req)
    3834             : {
    3835           0 :         connection_struct *conn = req->conn;
    3836           0 :         ssize_t nwritten = -1;
    3837             :         size_t numtowrite;
    3838             :         size_t remaining;
    3839             :         off_t startpos;
    3840             :         const char *data;
    3841           0 :         NTSTATUS status = NT_STATUS_OK;
    3842             :         files_struct *fsp;
    3843             :         struct lock_struct lock;
    3844           0 :         int saved_errno = 0;
    3845             : 
    3846           0 :         START_PROFILE(SMBwriteunlock);
    3847             : 
    3848           0 :         if (req->wct < 5) {
    3849           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3850           0 :                 END_PROFILE(SMBwriteunlock);
    3851           0 :                 return;
    3852             :         }
    3853             : 
    3854           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    3855             : 
    3856           0 :         if (!check_fsp(conn, req, fsp)) {
    3857           0 :                 END_PROFILE(SMBwriteunlock);
    3858           0 :                 return;
    3859             :         }
    3860             : 
    3861           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
    3862           0 :         if (!NT_STATUS_IS_OK(status)) {
    3863           0 :                 reply_nterror(req, status);
    3864           0 :                 END_PROFILE(SMBwriteunlock);
    3865           0 :                 return;
    3866             :         }
    3867             : 
    3868           0 :         numtowrite = SVAL(req->vwv+1, 0);
    3869           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
    3870           0 :         data = (const char *)req->buf + 3;
    3871             : 
    3872             :         /*
    3873             :          * Ensure client isn't asking us to write more than
    3874             :          * they sent. CVE-2017-12163.
    3875             :          */
    3876           0 :         remaining = smbreq_bufrem(req, data);
    3877           0 :         if (numtowrite > remaining) {
    3878           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3879           0 :                 END_PROFILE(SMBwriteunlock);
    3880           0 :                 return;
    3881             :         }
    3882             : 
    3883           0 :         if (!fsp->print_file && numtowrite > 0) {
    3884           0 :                 init_strict_lock_struct(fsp,
    3885           0 :                                 (uint64_t)req->smbpid,
    3886             :                                 (uint64_t)startpos,
    3887             :                                 (uint64_t)numtowrite,
    3888             :                                 WRITE_LOCK,
    3889             :                                 lp_posix_cifsu_locktype(fsp),
    3890             :                                 &lock);
    3891             : 
    3892           0 :                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    3893           0 :                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    3894           0 :                         END_PROFILE(SMBwriteunlock);
    3895           0 :                         return;
    3896             :                 }
    3897             :         }
    3898             : 
    3899             :         /* The special X/Open SMB protocol handling of
    3900             :            zero length writes is *NOT* done for
    3901             :            this call */
    3902           0 :         if(numtowrite == 0) {
    3903           0 :                 nwritten = 0;
    3904             :         } else {
    3905           0 :                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
    3906           0 :                 saved_errno = errno;
    3907             :         }
    3908             : 
    3909           0 :         status = sync_file(conn, fsp, False /* write through */);
    3910           0 :         if (!NT_STATUS_IS_OK(status)) {
    3911           0 :                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
    3912             :                          fsp_str_dbg(fsp), nt_errstr(status)));
    3913           0 :                 reply_nterror(req, status);
    3914           0 :                 goto out;
    3915             :         }
    3916             : 
    3917           0 :         if(nwritten < 0) {
    3918           0 :                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
    3919           0 :                 goto out;
    3920             :         }
    3921             : 
    3922           0 :         if((nwritten < numtowrite) && (numtowrite != 0)) {
    3923           0 :                 reply_nterror(req, NT_STATUS_DISK_FULL);
    3924           0 :                 goto out;
    3925             :         }
    3926             : 
    3927           0 :         if (numtowrite && !fsp->print_file) {
    3928           0 :                 struct smbd_lock_element l = {
    3929           0 :                         .req_guid = smbd_request_guid(req, 0),
    3930           0 :                         .smblctx = req->smbpid,
    3931             :                         .brltype = UNLOCK_LOCK,
    3932             :                         .lock_flav = WINDOWS_LOCK,
    3933             :                         .offset = startpos,
    3934             :                         .count = numtowrite,
    3935             :                 };
    3936           0 :                 status = smbd_do_unlocking(req, fsp, 1, &l);
    3937           0 :                 if (NT_STATUS_V(status)) {
    3938           0 :                         reply_nterror(req, status);
    3939           0 :                         goto out;
    3940             :                 }
    3941             :         }
    3942             : 
    3943           0 :         reply_smb1_outbuf(req, 1, 0);
    3944             : 
    3945           0 :         SSVAL(req->outbuf,smb_vwv0,nwritten);
    3946             : 
    3947           0 :         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
    3948             :                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
    3949             : 
    3950           0 : out:
    3951           0 :         END_PROFILE(SMBwriteunlock);
    3952           0 :         return;
    3953             : }
    3954             : 
    3955             : #undef DBGC_CLASS
    3956             : #define DBGC_CLASS DBGC_ALL
    3957             : 
    3958             : /****************************************************************************
    3959             :  Reply to a write.
    3960             : ****************************************************************************/
    3961             : 
    3962           0 : void reply_write(struct smb_request *req)
    3963             : {
    3964           0 :         connection_struct *conn = req->conn;
    3965             :         size_t numtowrite;
    3966             :         size_t remaining;
    3967           0 :         ssize_t nwritten = -1;
    3968             :         off_t startpos;
    3969             :         const char *data;
    3970             :         files_struct *fsp;
    3971             :         struct lock_struct lock;
    3972             :         NTSTATUS status;
    3973           0 :         int saved_errno = 0;
    3974             : 
    3975           0 :         START_PROFILE(SMBwrite);
    3976             : 
    3977           0 :         if (req->wct < 5) {
    3978           0 :                 END_PROFILE(SMBwrite);
    3979           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3980           0 :                 return;
    3981             :         }
    3982             : 
    3983             :         /* If it's an IPC, pass off the pipe handler. */
    3984           0 :         if (IS_IPC(conn)) {
    3985           0 :                 reply_pipe_write(req);
    3986           0 :                 END_PROFILE(SMBwrite);
    3987           0 :                 return;
    3988             :         }
    3989             : 
    3990           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    3991             : 
    3992           0 :         if (!check_fsp(conn, req, fsp)) {
    3993           0 :                 END_PROFILE(SMBwrite);
    3994           0 :                 return;
    3995             :         }
    3996             : 
    3997           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
    3998           0 :         if (!NT_STATUS_IS_OK(status)) {
    3999           0 :                 reply_nterror(req, status);
    4000           0 :                 END_PROFILE(SMBwrite);
    4001           0 :                 return;
    4002             :         }
    4003             : 
    4004           0 :         numtowrite = SVAL(req->vwv+1, 0);
    4005           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
    4006           0 :         data = (const char *)req->buf + 3;
    4007             : 
    4008             :         /*
    4009             :          * Ensure client isn't asking us to write more than
    4010             :          * they sent. CVE-2017-12163.
    4011             :          */
    4012           0 :         remaining = smbreq_bufrem(req, data);
    4013           0 :         if (numtowrite > remaining) {
    4014           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4015           0 :                 END_PROFILE(SMBwrite);
    4016           0 :                 return;
    4017             :         }
    4018             : 
    4019           0 :         if (!fsp->print_file) {
    4020           0 :                 init_strict_lock_struct(fsp,
    4021           0 :                                 (uint64_t)req->smbpid,
    4022             :                                 (uint64_t)startpos,
    4023             :                                 (uint64_t)numtowrite,
    4024             :                                 WRITE_LOCK,
    4025             :                                 lp_posix_cifsu_locktype(fsp),
    4026             :                                 &lock);
    4027             : 
    4028           0 :                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    4029           0 :                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    4030           0 :                         END_PROFILE(SMBwrite);
    4031           0 :                         return;
    4032             :                 }
    4033             :         }
    4034             : 
    4035             :         /*
    4036             :          * X/Open SMB protocol says that if smb_vwv1 is
    4037             :          * zero then the file size should be extended or
    4038             :          * truncated to the size given in smb_vwv[2-3].
    4039             :          */
    4040             : 
    4041           0 :         if(numtowrite == 0) {
    4042             :                 /*
    4043             :                  * This is actually an allocate call, and set EOF. JRA.
    4044             :                  */
    4045           0 :                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
    4046           0 :                 if (nwritten < 0) {
    4047           0 :                         reply_nterror(req, NT_STATUS_DISK_FULL);
    4048           0 :                         goto out;
    4049             :                 }
    4050           0 :                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
    4051           0 :                 if (nwritten < 0) {
    4052           0 :                         reply_nterror(req, NT_STATUS_DISK_FULL);
    4053           0 :                         goto out;
    4054             :                 }
    4055           0 :                 trigger_write_time_update_immediate(fsp);
    4056             :         } else {
    4057           0 :                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
    4058             :         }
    4059             : 
    4060           0 :         status = sync_file(conn, fsp, False);
    4061           0 :         if (!NT_STATUS_IS_OK(status)) {
    4062           0 :                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
    4063             :                          fsp_str_dbg(fsp), nt_errstr(status)));
    4064           0 :                 reply_nterror(req, status);
    4065           0 :                 goto out;
    4066             :         }
    4067             : 
    4068           0 :         if(nwritten < 0) {
    4069           0 :                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
    4070           0 :                 goto out;
    4071             :         }
    4072             : 
    4073           0 :         if((nwritten == 0) && (numtowrite != 0)) {
    4074           0 :                 reply_nterror(req, NT_STATUS_DISK_FULL);
    4075           0 :                 goto out;
    4076             :         }
    4077             : 
    4078           0 :         reply_smb1_outbuf(req, 1, 0);
    4079             : 
    4080           0 :         SSVAL(req->outbuf,smb_vwv0,nwritten);
    4081             : 
    4082           0 :         if (nwritten < (ssize_t)numtowrite) {
    4083           0 :                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
    4084           0 :                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
    4085             :         }
    4086             : 
    4087           0 :         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
    4088             : 
    4089           0 : out:
    4090           0 :         END_PROFILE(SMBwrite);
    4091           0 :         return;
    4092             : }
    4093             : 
    4094             : /****************************************************************************
    4095             :  Ensure a buffer is a valid writeX for recvfile purposes.
    4096             : ****************************************************************************/
    4097             : 
    4098             : #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
    4099             :                                                 (2*14) + /* word count (including bcc) */ \
    4100             :                                                 1 /* pad byte */)
    4101             : 
    4102           0 : bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
    4103             :                             const uint8_t *inbuf)
    4104             : {
    4105             :         size_t numtowrite;
    4106           0 :         unsigned int doff = 0;
    4107           0 :         size_t len = smb_len_large(inbuf);
    4108             :         uint16_t fnum;
    4109           0 :         struct smbXsrv_open *op = NULL;
    4110           0 :         struct files_struct *fsp = NULL;
    4111             :         NTSTATUS status;
    4112             : 
    4113           0 :         if (is_encrypted_packet(inbuf)) {
    4114             :                 /* Can't do this on encrypted
    4115             :                  * connections. */
    4116           0 :                 return false;
    4117             :         }
    4118             : 
    4119           0 :         if (CVAL(inbuf,smb_com) != SMBwriteX) {
    4120           0 :                 return false;
    4121             :         }
    4122             : 
    4123           0 :         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
    4124           0 :                         CVAL(inbuf,smb_wct) != 14) {
    4125           0 :                 DEBUG(10,("is_valid_writeX_buffer: chained or "
    4126             :                         "invalid word length.\n"));
    4127           0 :                 return false;
    4128             :         }
    4129             : 
    4130           0 :         fnum = SVAL(inbuf, smb_vwv2);
    4131           0 :         status = smb1srv_open_lookup(xconn,
    4132             :                                      fnum,
    4133             :                                      0, /* now */
    4134             :                                      &op);
    4135           0 :         if (!NT_STATUS_IS_OK(status)) {
    4136           0 :                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
    4137           0 :                 return false;
    4138             :         }
    4139           0 :         fsp = op->compat;
    4140           0 :         if (fsp == NULL) {
    4141           0 :                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
    4142           0 :                 return false;
    4143             :         }
    4144           0 :         if (fsp->conn == NULL) {
    4145           0 :                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
    4146           0 :                 return false;
    4147             :         }
    4148             : 
    4149           0 :         if (IS_IPC(fsp->conn)) {
    4150           0 :                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
    4151           0 :                 return false;
    4152             :         }
    4153           0 :         if (IS_PRINT(fsp->conn)) {
    4154           0 :                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
    4155           0 :                 return false;
    4156             :         }
    4157           0 :         if (fsp_is_alternate_stream(fsp)) {
    4158           0 :                 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
    4159           0 :                 return false;
    4160             :         }
    4161           0 :         doff = SVAL(inbuf,smb_vwv11);
    4162             : 
    4163           0 :         numtowrite = SVAL(inbuf,smb_vwv10);
    4164             : 
    4165           0 :         if (len > doff && len - doff > 0xFFFF) {
    4166           0 :                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
    4167             :         }
    4168             : 
    4169           0 :         if (numtowrite == 0) {
    4170           0 :                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
    4171           0 :                 return false;
    4172             :         }
    4173             : 
    4174             :         /* Ensure the sizes match up. */
    4175           0 :         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
    4176             :                 /* no pad byte...old smbclient :-( */
    4177           0 :                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
    4178             :                         (unsigned int)doff,
    4179             :                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
    4180           0 :                 return false;
    4181             :         }
    4182             : 
    4183           0 :         if (len - doff != numtowrite) {
    4184           0 :                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
    4185             :                         "len = %u, doff = %u, numtowrite = %u\n",
    4186             :                         (unsigned int)len,
    4187             :                         (unsigned int)doff,
    4188             :                         (unsigned int)numtowrite ));
    4189           0 :                 return false;
    4190             :         }
    4191             : 
    4192           0 :         DEBUG(10,("is_valid_writeX_buffer: true "
    4193             :                 "len = %u, doff = %u, numtowrite = %u\n",
    4194             :                 (unsigned int)len,
    4195             :                 (unsigned int)doff,
    4196             :                 (unsigned int)numtowrite ));
    4197             : 
    4198           0 :         return true;
    4199             : }
    4200             : 
    4201             : /****************************************************************************
    4202             :  Reply to a write and X.
    4203             : ****************************************************************************/
    4204             : 
    4205           0 : void reply_write_and_X(struct smb_request *req)
    4206             : {
    4207           0 :         connection_struct *conn = req->conn;
    4208           0 :         struct smbXsrv_connection *xconn = req->xconn;
    4209             :         files_struct *fsp;
    4210             :         struct lock_struct lock;
    4211             :         off_t startpos;
    4212             :         size_t numtowrite;
    4213             :         bool write_through;
    4214             :         ssize_t nwritten;
    4215             :         unsigned int smb_doff;
    4216             :         unsigned int smblen;
    4217             :         const char *data;
    4218             :         NTSTATUS status;
    4219           0 :         int saved_errno = 0;
    4220             : 
    4221           0 :         START_PROFILE(SMBwriteX);
    4222             : 
    4223           0 :         if ((req->wct != 12) && (req->wct != 14)) {
    4224           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4225           0 :                 goto out;
    4226             :         }
    4227             : 
    4228           0 :         numtowrite = SVAL(req->vwv+10, 0);
    4229           0 :         smb_doff = SVAL(req->vwv+11, 0);
    4230           0 :         smblen = smb_len(req->inbuf);
    4231             : 
    4232           0 :         if (req->unread_bytes > 0xFFFF ||
    4233           0 :                         (smblen > smb_doff &&
    4234           0 :                                 smblen - smb_doff > 0xFFFF)) {
    4235           0 :                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
    4236             :         }
    4237             : 
    4238           0 :         if (req->unread_bytes) {
    4239             :                 /* Can't do a recvfile write on IPC$ */
    4240           0 :                 if (IS_IPC(conn)) {
    4241           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4242           0 :                         goto out;
    4243             :                 }
    4244           0 :                 if (numtowrite != req->unread_bytes) {
    4245           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4246           0 :                         goto out;
    4247             :                 }
    4248             :         } else {
    4249             :                 /*
    4250             :                  * This already protects us against CVE-2017-12163.
    4251             :                  */
    4252           0 :                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
    4253           0 :                                 smb_doff + numtowrite > smblen) {
    4254           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4255           0 :                         goto out;
    4256             :                 }
    4257             :         }
    4258             : 
    4259             :         /* If it's an IPC, pass off the pipe handler. */
    4260           0 :         if (IS_IPC(conn)) {
    4261           0 :                 if (req->unread_bytes) {
    4262           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4263           0 :                         goto out;
    4264             :                 }
    4265           0 :                 reply_pipe_write_and_X(req);
    4266           0 :                 goto out;
    4267             :         }
    4268             : 
    4269           0 :         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
    4270           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
    4271           0 :         write_through = BITSETW(req->vwv+7,0);
    4272             : 
    4273           0 :         if (!check_fsp(conn, req, fsp)) {
    4274           0 :                 goto out;
    4275             :         }
    4276             : 
    4277           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
    4278           0 :         if (!NT_STATUS_IS_OK(status)) {
    4279           0 :                 reply_nterror(req, status);
    4280           0 :                 goto out;
    4281             :         }
    4282             : 
    4283           0 :         data = smb_base(req->inbuf) + smb_doff;
    4284             : 
    4285           0 :         if(req->wct == 14) {
    4286             :                 /*
    4287             :                  * This is a large offset (64 bit) write.
    4288             :                  */
    4289           0 :                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
    4290             : 
    4291             :         }
    4292             : 
    4293             :         /* X/Open SMB protocol says that, unlike SMBwrite
    4294             :         if the length is zero then NO truncation is
    4295             :         done, just a write of zero. To truncate a file,
    4296             :         use SMBwrite. */
    4297             : 
    4298           0 :         if(numtowrite == 0) {
    4299           0 :                 nwritten = 0;
    4300             :         } else {
    4301           0 :                 if (req->unread_bytes == 0) {
    4302           0 :                         status = schedule_aio_write_and_X(conn,
    4303             :                                                 req,
    4304             :                                                 fsp,
    4305             :                                                 data,
    4306             :                                                 startpos,
    4307             :                                                 numtowrite);
    4308             : 
    4309           0 :                         if (NT_STATUS_IS_OK(status)) {
    4310             :                                 /* write scheduled - we're done. */
    4311           0 :                                 goto out;
    4312             :                         }
    4313           0 :                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
    4314             :                                 /* Real error - report to client. */
    4315           0 :                                 reply_nterror(req, status);
    4316           0 :                                 goto out;
    4317             :                         }
    4318             :                         /* NT_STATUS_RETRY - fall through to sync write. */
    4319             :                 }
    4320             : 
    4321           0 :                 init_strict_lock_struct(fsp,
    4322           0 :                                 (uint64_t)req->smbpid,
    4323             :                                 (uint64_t)startpos,
    4324             :                                 (uint64_t)numtowrite,
    4325             :                                 WRITE_LOCK,
    4326             :                                 lp_posix_cifsu_locktype(fsp),
    4327             :                                 &lock);
    4328             : 
    4329           0 :                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    4330           0 :                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    4331           0 :                         goto out;
    4332             :                 }
    4333             : 
    4334           0 :                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
    4335           0 :                 saved_errno = errno;
    4336             :         }
    4337             : 
    4338           0 :         if(nwritten < 0) {
    4339           0 :                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
    4340           0 :                 goto out;
    4341             :         }
    4342             : 
    4343           0 :         if((nwritten == 0) && (numtowrite != 0)) {
    4344           0 :                 reply_nterror(req, NT_STATUS_DISK_FULL);
    4345           0 :                 goto out;
    4346             :         }
    4347             : 
    4348           0 :         reply_smb1_outbuf(req, 6, 0);
    4349           0 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
    4350           0 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
    4351           0 :         SSVAL(req->outbuf,smb_vwv2,nwritten);
    4352           0 :         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
    4353             : 
    4354           0 :         DEBUG(3,("writeX %s num=%d wrote=%d\n",
    4355             :                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
    4356             : 
    4357           0 :         status = sync_file(conn, fsp, write_through);
    4358           0 :         if (!NT_STATUS_IS_OK(status)) {
    4359           0 :                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
    4360             :                          fsp_str_dbg(fsp), nt_errstr(status)));
    4361           0 :                 reply_nterror(req, status);
    4362           0 :                 goto out;
    4363             :         }
    4364             : 
    4365           0 :         END_PROFILE(SMBwriteX);
    4366           0 :         return;
    4367             : 
    4368           0 : out:
    4369           0 :         if (req->unread_bytes) {
    4370             :                 /* writeX failed. drain socket. */
    4371           0 :                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
    4372           0 :                                 req->unread_bytes) {
    4373           0 :                         smb_panic("failed to drain pending bytes");
    4374             :                 }
    4375           0 :                 req->unread_bytes = 0;
    4376             :         }
    4377             : 
    4378           0 :         END_PROFILE(SMBwriteX);
    4379           0 :         return;
    4380             : }
    4381             : 
    4382             : /****************************************************************************
    4383             :  Reply to a lseek.
    4384             : ****************************************************************************/
    4385             : 
    4386           0 : void reply_lseek(struct smb_request *req)
    4387             : {
    4388           0 :         connection_struct *conn = req->conn;
    4389             :         off_t startpos;
    4390           0 :         off_t res= -1;
    4391             :         int mode,umode;
    4392             :         files_struct *fsp;
    4393             :         NTSTATUS status;
    4394             : 
    4395           0 :         START_PROFILE(SMBlseek);
    4396             : 
    4397           0 :         if (req->wct < 4) {
    4398           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4399           0 :                 END_PROFILE(SMBlseek);
    4400           0 :                 return;
    4401             :         }
    4402             : 
    4403           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    4404             : 
    4405           0 :         if (!check_fsp(conn, req, fsp)) {
    4406           0 :                 return;
    4407             :         }
    4408             : 
    4409           0 :         mode = SVAL(req->vwv+1, 0) & 3;
    4410             :         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
    4411           0 :         startpos = (off_t)IVALS(req->vwv+2, 0);
    4412             : 
    4413           0 :         switch (mode) {
    4414           0 :                 case 0:
    4415           0 :                         umode = SEEK_SET;
    4416           0 :                         res = startpos;
    4417           0 :                         break;
    4418           0 :                 case 1:
    4419           0 :                         umode = SEEK_CUR;
    4420           0 :                         res = fh_get_pos(fsp->fh) + startpos;
    4421           0 :                         break;
    4422           0 :                 case 2:
    4423           0 :                         umode = SEEK_END;
    4424           0 :                         break;
    4425           0 :                 default:
    4426           0 :                         umode = SEEK_SET;
    4427           0 :                         res = startpos;
    4428           0 :                         break;
    4429             :         }
    4430             : 
    4431           0 :         if (umode == SEEK_END) {
    4432           0 :                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
    4433           0 :                         if(errno == EINVAL) {
    4434           0 :                                 off_t current_pos = startpos;
    4435             : 
    4436           0 :                                 status = vfs_stat_fsp(fsp);
    4437           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    4438           0 :                                         reply_nterror(req, status);
    4439           0 :                                         END_PROFILE(SMBlseek);
    4440           0 :                                         return;
    4441             :                                 }
    4442             : 
    4443           0 :                                 current_pos += fsp->fsp_name->st.st_ex_size;
    4444           0 :                                 if(current_pos < 0)
    4445           0 :                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
    4446             :                         }
    4447             :                 }
    4448             : 
    4449           0 :                 if(res == -1) {
    4450           0 :                         reply_nterror(req, map_nt_error_from_unix(errno));
    4451           0 :                         END_PROFILE(SMBlseek);
    4452           0 :                         return;
    4453             :                 }
    4454             :         }
    4455             : 
    4456           0 :         fh_set_pos(fsp->fh, res);
    4457             : 
    4458           0 :         reply_smb1_outbuf(req, 2, 0);
    4459           0 :         SIVAL(req->outbuf,smb_vwv0,res);
    4460             : 
    4461           0 :         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
    4462             :                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
    4463             : 
    4464           0 :         END_PROFILE(SMBlseek);
    4465           0 :         return;
    4466             : }
    4467             : 
    4468           0 : static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
    4469             :                                              void *private_data)
    4470             : {
    4471           0 :         connection_struct *conn = talloc_get_type_abort(
    4472             :                 private_data, connection_struct);
    4473             : 
    4474           0 :         if (conn != fsp->conn) {
    4475           0 :                 return NULL;
    4476             :         }
    4477           0 :         if (fsp_get_io_fd(fsp) == -1) {
    4478           0 :                 return NULL;
    4479             :         }
    4480           0 :         sync_file(conn, fsp, True /* write through */);
    4481             : 
    4482           0 :         if (fsp->fsp_flags.modified) {
    4483           0 :                 trigger_write_time_update_immediate(fsp);
    4484             :         }
    4485             : 
    4486           0 :         return NULL;
    4487             : }
    4488             : 
    4489             : /****************************************************************************
    4490             :  Reply to a flush.
    4491             : ****************************************************************************/
    4492             : 
    4493           0 : void reply_flush(struct smb_request *req)
    4494             : {
    4495           0 :         connection_struct *conn = req->conn;
    4496             :         uint16_t fnum;
    4497             :         files_struct *fsp;
    4498             : 
    4499           0 :         START_PROFILE(SMBflush);
    4500             : 
    4501           0 :         if (req->wct < 1) {
    4502           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4503           0 :                 return;
    4504             :         }
    4505             : 
    4506           0 :         fnum = SVAL(req->vwv+0, 0);
    4507           0 :         fsp = file_fsp(req, fnum);
    4508             : 
    4509           0 :         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
    4510           0 :                 return;
    4511             :         }
    4512             : 
    4513           0 :         if (!fsp) {
    4514           0 :                 files_forall(req->sconn, file_sync_one_fn, conn);
    4515             :         } else {
    4516           0 :                 NTSTATUS status = sync_file(conn, fsp, True);
    4517           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4518           0 :                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
    4519             :                                 fsp_str_dbg(fsp), nt_errstr(status)));
    4520           0 :                         reply_nterror(req, status);
    4521           0 :                         END_PROFILE(SMBflush);
    4522           0 :                         return;
    4523             :                 }
    4524           0 :                 if (fsp->fsp_flags.modified) {
    4525           0 :                         trigger_write_time_update_immediate(fsp);
    4526             :                 }
    4527             :         }
    4528             : 
    4529           0 :         reply_smb1_outbuf(req, 0, 0);
    4530             : 
    4531           0 :         DEBUG(3,("flush\n"));
    4532           0 :         END_PROFILE(SMBflush);
    4533           0 :         return;
    4534             : }
    4535             : 
    4536             : /****************************************************************************
    4537             :  Reply to a exit.
    4538             :  conn POINTER CAN BE NULL HERE !
    4539             : ****************************************************************************/
    4540             : 
    4541             : static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
    4542             : static void reply_exit_done(struct tevent_req *req);
    4543             : 
    4544           0 : void reply_exit(struct smb_request *smb1req)
    4545             : {
    4546             :         struct tevent_req *req;
    4547             : 
    4548             :         /*
    4549             :          * Don't setup the profile charge here, take
    4550             :          * it in reply_exit_done(). Not strictly correct
    4551             :          * but better than the other SMB1 async
    4552             :          * code that double-charges at the moment.
    4553             :          */
    4554           0 :         req = reply_exit_send(smb1req);
    4555           0 :         if (req == NULL) {
    4556             :                 /* Not going async, profile here. */
    4557           0 :                 START_PROFILE(SMBexit);
    4558           0 :                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
    4559           0 :                 END_PROFILE(SMBexit);
    4560           0 :                 return;
    4561             :         }
    4562             : 
    4563             :         /* We're async. This will complete later. */
    4564           0 :         tevent_req_set_callback(req, reply_exit_done, smb1req);
    4565           0 :         return;
    4566             : }
    4567             : 
    4568             : struct reply_exit_state {
    4569             :         struct tevent_queue *wait_queue;
    4570             : };
    4571             : 
    4572             : static void reply_exit_wait_done(struct tevent_req *subreq);
    4573             : 
    4574             : /****************************************************************************
    4575             :  Async SMB1 exit.
    4576             :  Note, on failure here we deallocate and return NULL to allow the caller to
    4577             :  SMB1 return an error of ERRnomem immediately.
    4578             : ****************************************************************************/
    4579             : 
    4580           0 : static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
    4581             : {
    4582             :         struct tevent_req *req;
    4583             :         struct reply_exit_state *state;
    4584             :         struct tevent_req *subreq;
    4585             :         files_struct *fsp;
    4586           0 :         struct smbd_server_connection *sconn = smb1req->sconn;
    4587             : 
    4588           0 :         req = tevent_req_create(smb1req, &state,
    4589             :                         struct reply_exit_state);
    4590           0 :         if (req == NULL) {
    4591           0 :                 return NULL;
    4592             :         }
    4593           0 :         state->wait_queue = tevent_queue_create(state,
    4594             :                                 "reply_exit_wait_queue");
    4595           0 :         if (tevent_req_nomem(state->wait_queue, req)) {
    4596           0 :                 TALLOC_FREE(req);
    4597           0 :                 return NULL;
    4598             :         }
    4599             : 
    4600           0 :         for (fsp = sconn->files; fsp; fsp = fsp->next) {
    4601           0 :                 if (fsp->file_pid != smb1req->smbpid) {
    4602           0 :                         continue;
    4603             :                 }
    4604           0 :                 if (fsp->vuid != smb1req->vuid) {
    4605           0 :                         continue;
    4606             :                 }
    4607             :                 /*
    4608             :                  * Flag the file as close in progress.
    4609             :                  * This will prevent any more IO being
    4610             :                  * done on it.
    4611             :                  */
    4612           0 :                 fsp->fsp_flags.closing = true;
    4613             : 
    4614           0 :                 if (fsp->num_aio_requests > 0) {
    4615             :                         /*
    4616             :                          * Now wait until all aio requests on this fsp are
    4617             :                          * finished.
    4618             :                          *
    4619             :                          * We don't set a callback, as we just want to block the
    4620             :                          * wait queue and the talloc_free() of fsp->aio_request
    4621             :                          * will remove the item from the wait queue.
    4622             :                          */
    4623           0 :                         subreq = tevent_queue_wait_send(fsp->aio_requests,
    4624             :                                                 sconn->ev_ctx,
    4625           0 :                                                 state->wait_queue);
    4626           0 :                         if (tevent_req_nomem(subreq, req)) {
    4627           0 :                                 TALLOC_FREE(req);
    4628           0 :                                 return NULL;
    4629             :                         }
    4630             :                 }
    4631             :         }
    4632             : 
    4633             :         /*
    4634             :          * Now we add our own waiter to the end of the queue,
    4635             :          * this way we get notified when all pending requests are finished
    4636             :          * and reply to the outstanding SMB1 request.
    4637             :          */
    4638           0 :         subreq = tevent_queue_wait_send(state,
    4639             :                                 sconn->ev_ctx,
    4640           0 :                                 state->wait_queue);
    4641           0 :         if (tevent_req_nomem(subreq, req)) {
    4642           0 :                 TALLOC_FREE(req);
    4643           0 :                 return NULL;
    4644             :         }
    4645             : 
    4646             :         /*
    4647             :          * We're really going async - move the SMB1 request from
    4648             :          * a talloc stackframe above us to the conn talloc-context.
    4649             :          * We need this to stick around until the wait_done
    4650             :          * callback is invoked.
    4651             :          */
    4652           0 :         smb1req = talloc_move(sconn, &smb1req);
    4653             : 
    4654           0 :         tevent_req_set_callback(subreq, reply_exit_wait_done, req);
    4655             : 
    4656           0 :         return req;
    4657             : }
    4658             : 
    4659           0 : static void reply_exit_wait_done(struct tevent_req *subreq)
    4660             : {
    4661           0 :         struct tevent_req *req = tevent_req_callback_data(
    4662             :                 subreq, struct tevent_req);
    4663             : 
    4664           0 :         tevent_queue_wait_recv(subreq);
    4665           0 :         TALLOC_FREE(subreq);
    4666           0 :         tevent_req_done(req);
    4667           0 : }
    4668             : 
    4669           0 : static NTSTATUS reply_exit_recv(struct tevent_req *req)
    4670             : {
    4671           0 :         return tevent_req_simple_recv_ntstatus(req);
    4672             : }
    4673             : 
    4674           0 : static void reply_exit_done(struct tevent_req *req)
    4675             : {
    4676           0 :         struct smb_request *smb1req = tevent_req_callback_data(
    4677             :                 req, struct smb_request);
    4678           0 :         struct smbd_server_connection *sconn = smb1req->sconn;
    4679           0 :         struct smbXsrv_connection *xconn = smb1req->xconn;
    4680           0 :         NTTIME now = timeval_to_nttime(&smb1req->request_time);
    4681           0 :         struct smbXsrv_session *session = NULL;
    4682             :         files_struct *fsp, *next;
    4683             :         NTSTATUS status;
    4684             : 
    4685             :         /*
    4686             :          * Take the profile charge here. Not strictly
    4687             :          * correct but better than the other SMB1 async
    4688             :          * code that double-charges at the moment.
    4689             :          */
    4690           0 :         START_PROFILE(SMBexit);
    4691             : 
    4692           0 :         status = reply_exit_recv(req);
    4693           0 :         TALLOC_FREE(req);
    4694           0 :         if (!NT_STATUS_IS_OK(status)) {
    4695           0 :                 TALLOC_FREE(smb1req);
    4696           0 :                 END_PROFILE(SMBexit);
    4697           0 :                 exit_server(__location__ ": reply_exit_recv failed");
    4698             :                 return;
    4699             :         }
    4700             : 
    4701             :         /*
    4702             :          * Ensure the session is still valid.
    4703             :          */
    4704           0 :         status = smb1srv_session_lookup(xconn,
    4705           0 :                                         smb1req->vuid,
    4706             :                                         now,
    4707             :                                         &session);
    4708           0 :         if (!NT_STATUS_IS_OK(status)) {
    4709           0 :                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
    4710           0 :                 smb_request_done(smb1req);
    4711           0 :                 END_PROFILE(SMBexit);
    4712           0 :                 return;
    4713             :         }
    4714             : 
    4715             :         /*
    4716             :          * Ensure the vuid is still valid - no one
    4717             :          * called reply_ulogoffX() in the meantime.
    4718             :          * reply_exit() doesn't have AS_USER set, so
    4719             :          * use set_current_user_info() directly.
    4720             :          * This is the same logic as in switch_message().
    4721             :          */
    4722           0 :         if (session->global->auth_session_info != NULL) {
    4723           0 :                 set_current_user_info(
    4724           0 :                         session->global->auth_session_info->unix_info->sanitized_username,
    4725           0 :                         session->global->auth_session_info->unix_info->unix_name,
    4726           0 :                         session->global->auth_session_info->info->domain_name);
    4727             :         }
    4728             : 
    4729             :         /* No more aio - do the actual closes. */
    4730           0 :         for (fsp = sconn->files; fsp; fsp = next) {
    4731             :                 bool ok;
    4732           0 :                 next = fsp->next;
    4733             : 
    4734           0 :                 if (fsp->file_pid != smb1req->smbpid) {
    4735           0 :                         continue;
    4736             :                 }
    4737           0 :                 if (fsp->vuid != smb1req->vuid) {
    4738           0 :                         continue;
    4739             :                 }
    4740           0 :                 if (!fsp->fsp_flags.closing) {
    4741           0 :                         continue;
    4742             :                 }
    4743             : 
    4744             :                 /*
    4745             :                  * reply_exit() has the DO_CHDIR flag set.
    4746             :                  */
    4747           0 :                 ok = chdir_current_service(fsp->conn);
    4748           0 :                 if (!ok) {
    4749           0 :                         reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
    4750           0 :                         smb_request_done(smb1req);
    4751           0 :                         END_PROFILE(SMBexit);
    4752           0 :                         return;
    4753             :                 }
    4754           0 :                 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
    4755             :         }
    4756             : 
    4757           0 :         reply_smb1_outbuf(smb1req, 0, 0);
    4758             :         /*
    4759             :          * The following call is needed to push the
    4760             :          * reply data back out the socket after async
    4761             :          * return. Plus it frees smb1req.
    4762             :          */
    4763           0 :         smb_request_done(smb1req);
    4764           0 :         DBG_INFO("reply_exit complete\n");
    4765           0 :         END_PROFILE(SMBexit);
    4766           0 :         return;
    4767             : }
    4768             : 
    4769             : static struct tevent_req *reply_close_send(struct smb_request *smb1req,
    4770             :                                 files_struct *fsp);
    4771             : static void reply_close_done(struct tevent_req *req);
    4772             : 
    4773           0 : void reply_close(struct smb_request *smb1req)
    4774             : {
    4775           0 :         connection_struct *conn = smb1req->conn;
    4776           0 :         NTSTATUS status = NT_STATUS_OK;
    4777           0 :         files_struct *fsp = NULL;
    4778           0 :         START_PROFILE(SMBclose);
    4779             : 
    4780           0 :         if (smb1req->wct < 3) {
    4781           0 :                 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
    4782           0 :                 END_PROFILE(SMBclose);
    4783           0 :                 return;
    4784             :         }
    4785             : 
    4786           0 :         fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
    4787             : 
    4788             :         /*
    4789             :          * We can only use check_fsp if we know it's not a directory.
    4790             :          */
    4791             : 
    4792           0 :         if (!check_fsp_open(conn, smb1req, fsp)) {
    4793           0 :                 END_PROFILE(SMBclose);
    4794           0 :                 return;
    4795             :         }
    4796             : 
    4797           0 :         DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
    4798             :                   fsp->fsp_flags.is_directory ?
    4799             :                   "directory" : "file",
    4800             :                   fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
    4801             :                   conn->num_files_open);
    4802             : 
    4803           0 :         if (!fsp->fsp_flags.is_directory) {
    4804             :                 time_t t;
    4805             : 
    4806             :                 /*
    4807             :                  * Take care of any time sent in the close.
    4808             :                  */
    4809             : 
    4810           0 :                 t = srv_make_unix_date3(smb1req->vwv+1);
    4811           0 :                 set_close_write_time(fsp, time_t_to_full_timespec(t));
    4812             :         }
    4813             : 
    4814           0 :         if (fsp->num_aio_requests != 0) {
    4815             :                 struct tevent_req *req;
    4816             : 
    4817           0 :                 req = reply_close_send(smb1req, fsp);
    4818           0 :                 if (req == NULL) {
    4819           0 :                         status = NT_STATUS_NO_MEMORY;
    4820           0 :                         goto done;
    4821             :                 }
    4822             :                 /* We're async. This will complete later. */
    4823           0 :                 tevent_req_set_callback(req, reply_close_done, smb1req);
    4824           0 :                 END_PROFILE(SMBclose);
    4825           0 :                 return;
    4826             :         }
    4827             : 
    4828             :         /*
    4829             :          * close_file_free() returns the unix errno if an error was detected on
    4830             :          * close - normally this is due to a disk full error. If not then it
    4831             :          * was probably an I/O error.
    4832             :          */
    4833             : 
    4834           0 :         status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
    4835           0 : done:
    4836           0 :         if (!NT_STATUS_IS_OK(status)) {
    4837           0 :                 reply_nterror(smb1req, status);
    4838           0 :                 END_PROFILE(SMBclose);
    4839           0 :                 return;
    4840             :         }
    4841             : 
    4842           0 :         reply_smb1_outbuf(smb1req, 0, 0);
    4843           0 :         END_PROFILE(SMBclose);
    4844           0 :         return;
    4845             : }
    4846             : 
    4847             : struct reply_close_state {
    4848             :         files_struct *fsp;
    4849             :         struct tevent_queue *wait_queue;
    4850             : };
    4851             : 
    4852             : static void reply_close_wait_done(struct tevent_req *subreq);
    4853             : 
    4854             : /****************************************************************************
    4855             :  Async SMB1 close.
    4856             :  Note, on failure here we deallocate and return NULL to allow the caller to
    4857             :  SMB1 return an error of ERRnomem immediately.
    4858             : ****************************************************************************/
    4859             : 
    4860           0 : static struct tevent_req *reply_close_send(struct smb_request *smb1req,
    4861             :                                 files_struct *fsp)
    4862             : {
    4863             :         struct tevent_req *req;
    4864             :         struct reply_close_state *state;
    4865             :         struct tevent_req *subreq;
    4866           0 :         struct smbd_server_connection *sconn = smb1req->sconn;
    4867             : 
    4868           0 :         req = tevent_req_create(smb1req, &state,
    4869             :                         struct reply_close_state);
    4870           0 :         if (req == NULL) {
    4871           0 :                 return NULL;
    4872             :         }
    4873           0 :         state->wait_queue = tevent_queue_create(state,
    4874             :                                 "reply_close_wait_queue");
    4875           0 :         if (tevent_req_nomem(state->wait_queue, req)) {
    4876           0 :                 TALLOC_FREE(req);
    4877           0 :                 return NULL;
    4878             :         }
    4879             : 
    4880             :         /*
    4881             :          * Flag the file as close in progress.
    4882             :          * This will prevent any more IO being
    4883             :          * done on it.
    4884             :          */
    4885           0 :         fsp->fsp_flags.closing = true;
    4886             : 
    4887             :         /*
    4888             :          * Now wait until all aio requests on this fsp are
    4889             :          * finished.
    4890             :          *
    4891             :          * We don't set a callback, as we just want to block the
    4892             :          * wait queue and the talloc_free() of fsp->aio_request
    4893             :          * will remove the item from the wait queue.
    4894             :          */
    4895           0 :         subreq = tevent_queue_wait_send(fsp->aio_requests,
    4896             :                                         sconn->ev_ctx,
    4897           0 :                                         state->wait_queue);
    4898           0 :         if (tevent_req_nomem(subreq, req)) {
    4899           0 :                 TALLOC_FREE(req);
    4900           0 :                 return NULL;
    4901             :         }
    4902             : 
    4903             :         /*
    4904             :          * Now we add our own waiter to the end of the queue,
    4905             :          * this way we get notified when all pending requests are finished
    4906             :          * and reply to the outstanding SMB1 request.
    4907             :          */
    4908           0 :         subreq = tevent_queue_wait_send(state,
    4909             :                                 sconn->ev_ctx,
    4910           0 :                                 state->wait_queue);
    4911           0 :         if (tevent_req_nomem(subreq, req)) {
    4912           0 :                 TALLOC_FREE(req);
    4913           0 :                 return NULL;
    4914             :         }
    4915             : 
    4916             :         /*
    4917             :          * We're really going async - move the SMB1 request from
    4918             :          * a talloc stackframe above us to the conn talloc-context.
    4919             :          * We need this to stick around until the wait_done
    4920             :          * callback is invoked.
    4921             :          */
    4922           0 :         smb1req = talloc_move(sconn, &smb1req);
    4923             : 
    4924           0 :         tevent_req_set_callback(subreq, reply_close_wait_done, req);
    4925             : 
    4926           0 :         return req;
    4927             : }
    4928             : 
    4929           0 : static void reply_close_wait_done(struct tevent_req *subreq)
    4930             : {
    4931           0 :         struct tevent_req *req = tevent_req_callback_data(
    4932             :                 subreq, struct tevent_req);
    4933             : 
    4934           0 :         tevent_queue_wait_recv(subreq);
    4935           0 :         TALLOC_FREE(subreq);
    4936           0 :         tevent_req_done(req);
    4937           0 : }
    4938             : 
    4939           0 : static NTSTATUS reply_close_recv(struct tevent_req *req)
    4940             : {
    4941           0 :         return tevent_req_simple_recv_ntstatus(req);
    4942             : }
    4943             : 
    4944           0 : static void reply_close_done(struct tevent_req *req)
    4945             : {
    4946           0 :         struct smb_request *smb1req = tevent_req_callback_data(
    4947             :                         req, struct smb_request);
    4948           0 :         struct reply_close_state *state = tevent_req_data(req,
    4949             :                                                 struct reply_close_state);
    4950             :         NTSTATUS status;
    4951             : 
    4952           0 :         status = reply_close_recv(req);
    4953           0 :         TALLOC_FREE(req);
    4954           0 :         if (!NT_STATUS_IS_OK(status)) {
    4955           0 :                 TALLOC_FREE(smb1req);
    4956           0 :                 exit_server(__location__ ": reply_close_recv failed");
    4957             :                 return;
    4958             :         }
    4959             : 
    4960           0 :         status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
    4961           0 :         if (NT_STATUS_IS_OK(status)) {
    4962           0 :                 reply_smb1_outbuf(smb1req, 0, 0);
    4963             :         } else {
    4964           0 :                 reply_nterror(smb1req, status);
    4965             :         }
    4966             :         /*
    4967             :          * The following call is needed to push the
    4968             :          * reply data back out the socket after async
    4969             :          * return. Plus it frees smb1req.
    4970             :          */
    4971           0 :         smb_request_done(smb1req);
    4972             : }
    4973             : 
    4974             : /****************************************************************************
    4975             :  Reply to a writeclose (Core+ protocol).
    4976             : ****************************************************************************/
    4977             : 
    4978           0 : void reply_writeclose(struct smb_request *req)
    4979             : {
    4980           0 :         connection_struct *conn = req->conn;
    4981             :         size_t numtowrite;
    4982             :         size_t remaining;
    4983           0 :         ssize_t nwritten = -1;
    4984           0 :         NTSTATUS close_status = NT_STATUS_OK;
    4985             :         off_t startpos;
    4986             :         const char *data;
    4987             :         struct timespec mtime;
    4988             :         files_struct *fsp;
    4989             :         struct lock_struct lock;
    4990             :         NTSTATUS status;
    4991             : 
    4992           0 :         START_PROFILE(SMBwriteclose);
    4993             : 
    4994           0 :         if (req->wct < 6) {
    4995           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4996           0 :                 END_PROFILE(SMBwriteclose);
    4997           0 :                 return;
    4998             :         }
    4999             : 
    5000           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    5001             : 
    5002           0 :         if (!check_fsp(conn, req, fsp)) {
    5003           0 :                 END_PROFILE(SMBwriteclose);
    5004           0 :                 return;
    5005             :         }
    5006           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
    5007           0 :         if (!NT_STATUS_IS_OK(status)) {
    5008           0 :                 reply_nterror(req, status);
    5009           0 :                 END_PROFILE(SMBwriteclose);
    5010           0 :                 return;
    5011             :         }
    5012             : 
    5013           0 :         numtowrite = SVAL(req->vwv+1, 0);
    5014           0 :         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
    5015           0 :         mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
    5016           0 :         data = (const char *)req->buf + 1;
    5017             : 
    5018             :         /*
    5019             :          * Ensure client isn't asking us to write more than
    5020             :          * they sent. CVE-2017-12163.
    5021             :          */
    5022           0 :         remaining = smbreq_bufrem(req, data);
    5023           0 :         if (numtowrite > remaining) {
    5024           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5025           0 :                 END_PROFILE(SMBwriteclose);
    5026           0 :                 return;
    5027             :         }
    5028             : 
    5029           0 :         if (fsp->print_file == NULL) {
    5030           0 :                 init_strict_lock_struct(fsp,
    5031           0 :                                 (uint64_t)req->smbpid,
    5032             :                                 (uint64_t)startpos,
    5033             :                                 (uint64_t)numtowrite,
    5034             :                                 WRITE_LOCK,
    5035             :                                 lp_posix_cifsu_locktype(fsp),
    5036             :                                 &lock);
    5037             : 
    5038           0 :                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
    5039           0 :                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    5040           0 :                         END_PROFILE(SMBwriteclose);
    5041           0 :                         return;
    5042             :                 }
    5043             :         }
    5044             : 
    5045           0 :         nwritten = write_file(req,fsp,data,startpos,numtowrite);
    5046             : 
    5047           0 :         set_close_write_time(fsp, mtime);
    5048             : 
    5049             :         /*
    5050             :          * More insanity. W2K only closes the file if writelen > 0.
    5051             :          * JRA.
    5052             :          */
    5053             : 
    5054           0 :         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
    5055             :                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
    5056             :                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
    5057             : 
    5058           0 :         if (numtowrite) {
    5059           0 :                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
    5060             :                          "file %s\n", fsp_str_dbg(fsp)));
    5061           0 :                 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
    5062             :         }
    5063             : 
    5064           0 :         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
    5065           0 :                 reply_nterror(req, NT_STATUS_DISK_FULL);
    5066           0 :                 goto out;
    5067             :         }
    5068             : 
    5069           0 :         if(!NT_STATUS_IS_OK(close_status)) {
    5070           0 :                 reply_nterror(req, close_status);
    5071           0 :                 goto out;
    5072             :         }
    5073             : 
    5074           0 :         reply_smb1_outbuf(req, 1, 0);
    5075             : 
    5076           0 :         SSVAL(req->outbuf,smb_vwv0,nwritten);
    5077             : 
    5078           0 : out:
    5079             : 
    5080           0 :         END_PROFILE(SMBwriteclose);
    5081           0 :         return;
    5082             : }
    5083             : 
    5084             : #undef DBGC_CLASS
    5085             : #define DBGC_CLASS DBGC_LOCKING
    5086             : 
    5087             : /****************************************************************************
    5088             :  Reply to a lock.
    5089             : ****************************************************************************/
    5090             : 
    5091             : static void reply_lock_done(struct tevent_req *subreq);
    5092             : 
    5093           0 : void reply_lock(struct smb_request *req)
    5094             : {
    5095           0 :         struct tevent_req *subreq = NULL;
    5096           0 :         connection_struct *conn = req->conn;
    5097             :         files_struct *fsp;
    5098           0 :         struct smbd_lock_element *lck = NULL;
    5099             : 
    5100           0 :         START_PROFILE(SMBlock);
    5101             : 
    5102           0 :         if (req->wct < 5) {
    5103           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5104           0 :                 END_PROFILE(SMBlock);
    5105           0 :                 return;
    5106             :         }
    5107             : 
    5108           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    5109             : 
    5110           0 :         if (!check_fsp(conn, req, fsp)) {
    5111           0 :                 END_PROFILE(SMBlock);
    5112           0 :                 return;
    5113             :         }
    5114             : 
    5115           0 :         lck = talloc(req, struct smbd_lock_element);
    5116           0 :         if (lck == NULL) {
    5117           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5118           0 :                 END_PROFILE(SMBlock);
    5119           0 :                 return;
    5120             :         }
    5121             : 
    5122           0 :         *lck = (struct smbd_lock_element) {
    5123           0 :                 .req_guid = smbd_request_guid(req, 0),
    5124           0 :                 .smblctx = req->smbpid,
    5125             :                 .brltype = WRITE_LOCK,
    5126             :                 .lock_flav = WINDOWS_LOCK,
    5127           0 :                 .count = IVAL(req->vwv+1, 0),
    5128           0 :                 .offset = IVAL(req->vwv+3, 0),
    5129             :         };
    5130             : 
    5131           0 :         DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
    5132             :                    fsp_get_io_fd(fsp),
    5133             :                    fsp_fnum_dbg(fsp),
    5134             :                    lck->offset,
    5135             :                    lck->count);
    5136             : 
    5137           0 :         subreq = smbd_smb1_do_locks_send(
    5138             :                 fsp,
    5139           0 :                 req->sconn->ev_ctx,
    5140             :                 &req,
    5141             :                 fsp,
    5142             :                 0,
    5143             :                 false,          /* large_offset */
    5144             :                 1,
    5145             :                 lck);
    5146           0 :         if (subreq == NULL) {
    5147           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5148           0 :                 END_PROFILE(SMBlock);
    5149           0 :                 return;
    5150             :         }
    5151           0 :         tevent_req_set_callback(subreq, reply_lock_done, NULL);
    5152           0 :         END_PROFILE(SMBlock);
    5153             : }
    5154             : 
    5155           0 : static void reply_lock_done(struct tevent_req *subreq)
    5156             : {
    5157           0 :         struct smb_request *req = NULL;
    5158             :         NTSTATUS status;
    5159             :         bool ok;
    5160             : 
    5161           0 :         START_PROFILE(SMBlock);
    5162             : 
    5163           0 :         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
    5164           0 :         SMB_ASSERT(ok);
    5165             : 
    5166           0 :         status = smbd_smb1_do_locks_recv(subreq);
    5167           0 :         TALLOC_FREE(subreq);
    5168             : 
    5169           0 :         if (NT_STATUS_IS_OK(status)) {
    5170           0 :                 reply_smb1_outbuf(req, 0, 0);
    5171             :         } else {
    5172           0 :                 reply_nterror(req, status);
    5173             :         }
    5174             : 
    5175           0 :         ok = smb1_srv_send(req->xconn,
    5176           0 :                           (char *)req->outbuf,
    5177             :                           true,
    5178           0 :                           req->seqnum+1,
    5179           0 :                           IS_CONN_ENCRYPTED(req->conn),
    5180             :                           NULL);
    5181           0 :         if (!ok) {
    5182           0 :                 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
    5183             :         }
    5184           0 :         TALLOC_FREE(req);
    5185           0 :         END_PROFILE(SMBlock);
    5186           0 : }
    5187             : 
    5188             : /****************************************************************************
    5189             :  Reply to a unlock.
    5190             : ****************************************************************************/
    5191             : 
    5192           0 : void reply_unlock(struct smb_request *req)
    5193             : {
    5194           0 :         connection_struct *conn = req->conn;
    5195             :         NTSTATUS status;
    5196             :         files_struct *fsp;
    5197             :         struct smbd_lock_element lck;
    5198             : 
    5199           0 :         START_PROFILE(SMBunlock);
    5200             : 
    5201           0 :         if (req->wct < 5) {
    5202           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5203           0 :                 END_PROFILE(SMBunlock);
    5204           0 :                 return;
    5205             :         }
    5206             : 
    5207           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    5208             : 
    5209           0 :         if (!check_fsp(conn, req, fsp)) {
    5210           0 :                 END_PROFILE(SMBunlock);
    5211           0 :                 return;
    5212             :         }
    5213             : 
    5214           0 :         lck = (struct smbd_lock_element) {
    5215           0 :                 .req_guid = smbd_request_guid(req, 0),
    5216           0 :                 .smblctx = req->smbpid,
    5217             :                 .brltype = UNLOCK_LOCK,
    5218             :                 .lock_flav = WINDOWS_LOCK,
    5219           0 :                 .offset = IVAL(req->vwv+3, 0),
    5220           0 :                 .count = IVAL(req->vwv+1, 0),
    5221             :         };
    5222             : 
    5223           0 :         status = smbd_do_unlocking(req, fsp, 1, &lck);
    5224             : 
    5225           0 :         if (!NT_STATUS_IS_OK(status)) {
    5226           0 :                 reply_nterror(req, status);
    5227           0 :                 END_PROFILE(SMBunlock);
    5228           0 :                 return;
    5229             :         }
    5230             : 
    5231           0 :         DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
    5232             :                    fsp_get_io_fd(fsp),
    5233             :                    fsp_fnum_dbg(fsp),
    5234             :                    lck.offset,
    5235             :                    lck.count);
    5236             : 
    5237           0 :         reply_smb1_outbuf(req, 0, 0);
    5238             : 
    5239           0 :         END_PROFILE(SMBunlock);
    5240           0 :         return;
    5241             : }
    5242             : 
    5243             : #undef DBGC_CLASS
    5244             : #define DBGC_CLASS DBGC_ALL
    5245             : 
    5246             : /****************************************************************************
    5247             :  Reply to a tdis.
    5248             :  conn POINTER CAN BE NULL HERE !
    5249             : ****************************************************************************/
    5250             : 
    5251             : static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
    5252             : static void reply_tdis_done(struct tevent_req *req);
    5253             : 
    5254          28 : void reply_tdis(struct smb_request *smb1req)
    5255             : {
    5256          28 :         connection_struct *conn = smb1req->conn;
    5257             :         struct tevent_req *req;
    5258             : 
    5259             :         /*
    5260             :          * Don't setup the profile charge here, take
    5261             :          * it in reply_tdis_done(). Not strictly correct
    5262             :          * but better than the other SMB1 async
    5263             :          * code that double-charges at the moment.
    5264             :          */
    5265             : 
    5266          28 :         if (conn == NULL) {
    5267             :                 /* Not going async, profile here. */
    5268           0 :                 START_PROFILE(SMBtdis);
    5269           0 :                 DBG_INFO("Invalid connection in tdis\n");
    5270           0 :                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
    5271           0 :                 END_PROFILE(SMBtdis);
    5272           0 :                 return;
    5273             :         }
    5274             : 
    5275          28 :         req = reply_tdis_send(smb1req);
    5276          28 :         if (req == NULL) {
    5277             :                 /* Not going async, profile here. */
    5278           0 :                 START_PROFILE(SMBtdis);
    5279           0 :                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
    5280           0 :                 END_PROFILE(SMBtdis);
    5281           0 :                 return;
    5282             :         }
    5283             :         /* We're async. This will complete later. */
    5284          28 :         tevent_req_set_callback(req, reply_tdis_done, smb1req);
    5285          28 :         return;
    5286             : }
    5287             : 
    5288             : struct reply_tdis_state {
    5289             :         struct tevent_queue *wait_queue;
    5290             : };
    5291             : 
    5292             : static void reply_tdis_wait_done(struct tevent_req *subreq);
    5293             : 
    5294             : /****************************************************************************
    5295             :  Async SMB1 tdis.
    5296             :  Note, on failure here we deallocate and return NULL to allow the caller to
    5297             :  SMB1 return an error of ERRnomem immediately.
    5298             : ****************************************************************************/
    5299             : 
    5300          28 : static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
    5301             : {
    5302             :         struct tevent_req *req;
    5303             :         struct reply_tdis_state *state;
    5304             :         struct tevent_req *subreq;
    5305          28 :         connection_struct *conn = smb1req->conn;
    5306             :         files_struct *fsp;
    5307             : 
    5308          28 :         req = tevent_req_create(smb1req, &state,
    5309             :                         struct reply_tdis_state);
    5310          28 :         if (req == NULL) {
    5311           0 :                 return NULL;
    5312             :         }
    5313          28 :         state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
    5314          28 :         if (tevent_req_nomem(state->wait_queue, req)) {
    5315           0 :                 TALLOC_FREE(req);
    5316           0 :                 return NULL;
    5317             :         }
    5318             : 
    5319             :         /*
    5320             :          * Make sure that no new request will be able to use this tcon.
    5321             :          * This ensures that once all outstanding fsp->aio_requests
    5322             :          * on this tcon are done, we are safe to close it.
    5323             :          */
    5324          28 :         conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
    5325             : 
    5326          28 :         for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
    5327           0 :                 if (fsp->conn != conn) {
    5328           0 :                         continue;
    5329             :                 }
    5330             :                 /*
    5331             :                  * Flag the file as close in progress.
    5332             :                  * This will prevent any more IO being
    5333             :                  * done on it. Not strictly needed, but
    5334             :                  * doesn't hurt to flag it as closing.
    5335             :                  */
    5336           0 :                 fsp->fsp_flags.closing = true;
    5337             : 
    5338           0 :                 if (fsp->num_aio_requests > 0) {
    5339             :                         /*
    5340             :                          * Now wait until all aio requests on this fsp are
    5341             :                          * finished.
    5342             :                          *
    5343             :                          * We don't set a callback, as we just want to block the
    5344             :                          * wait queue and the talloc_free() of fsp->aio_request
    5345             :                          * will remove the item from the wait queue.
    5346             :                          */
    5347           0 :                         subreq = tevent_queue_wait_send(fsp->aio_requests,
    5348           0 :                                                 conn->sconn->ev_ctx,
    5349           0 :                                                 state->wait_queue);
    5350           0 :                         if (tevent_req_nomem(subreq, req)) {
    5351           0 :                                 TALLOC_FREE(req);
    5352           0 :                                 return NULL;
    5353             :                         }
    5354             :                 }
    5355             :         }
    5356             : 
    5357             :         /*
    5358             :          * Now we add our own waiter to the end of the queue,
    5359             :          * this way we get notified when all pending requests are finished
    5360             :          * and reply to the outstanding SMB1 request.
    5361             :          */
    5362          28 :         subreq = tevent_queue_wait_send(state,
    5363          28 :                                 conn->sconn->ev_ctx,
    5364          28 :                                 state->wait_queue);
    5365          28 :         if (tevent_req_nomem(subreq, req)) {
    5366           0 :                 TALLOC_FREE(req);
    5367           0 :                 return NULL;
    5368             :         }
    5369             : 
    5370             :         /*
    5371             :          * We're really going async - move the SMB1 request from
    5372             :          * a talloc stackframe above us to the sconn talloc-context.
    5373             :          * We need this to stick around until the wait_done
    5374             :          * callback is invoked.
    5375             :          */
    5376          28 :         smb1req = talloc_move(smb1req->sconn, &smb1req);
    5377             : 
    5378          28 :         tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
    5379             : 
    5380          28 :         return req;
    5381             : }
    5382             : 
    5383          28 : static void reply_tdis_wait_done(struct tevent_req *subreq)
    5384             : {
    5385          28 :         struct tevent_req *req = tevent_req_callback_data(
    5386             :                 subreq, struct tevent_req);
    5387             : 
    5388          28 :         tevent_queue_wait_recv(subreq);
    5389          28 :         TALLOC_FREE(subreq);
    5390          28 :         tevent_req_done(req);
    5391          28 : }
    5392             : 
    5393          28 : static NTSTATUS reply_tdis_recv(struct tevent_req *req)
    5394             : {
    5395          28 :         return tevent_req_simple_recv_ntstatus(req);
    5396             : }
    5397             : 
    5398          28 : static void reply_tdis_done(struct tevent_req *req)
    5399             : {
    5400          28 :         struct smb_request *smb1req = tevent_req_callback_data(
    5401             :                 req, struct smb_request);
    5402             :         NTSTATUS status;
    5403          28 :         struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
    5404             :         bool ok;
    5405             : 
    5406             :         /*
    5407             :          * Take the profile charge here. Not strictly
    5408             :          * correct but better than the other SMB1 async
    5409             :          * code that double-charges at the moment.
    5410             :          */
    5411          28 :         START_PROFILE(SMBtdis);
    5412             : 
    5413          28 :         status = reply_tdis_recv(req);
    5414          28 :         TALLOC_FREE(req);
    5415          28 :         if (!NT_STATUS_IS_OK(status)) {
    5416           0 :                 TALLOC_FREE(smb1req);
    5417           0 :                 END_PROFILE(SMBtdis);
    5418           0 :                 exit_server(__location__ ": reply_tdis_recv failed");
    5419             :                 return;
    5420             :         }
    5421             : 
    5422             :         /*
    5423             :          * As we've been awoken, we may have changed
    5424             :          * directory in the meantime.
    5425             :          * reply_tdis() has the DO_CHDIR flag set.
    5426             :          */
    5427          28 :         ok = chdir_current_service(smb1req->conn);
    5428          28 :         if (!ok) {
    5429           0 :                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
    5430           0 :                 smb_request_done(smb1req);
    5431           0 :                 END_PROFILE(SMBtdis);
    5432             :         }
    5433             : 
    5434          28 :         status = smbXsrv_tcon_disconnect(tcon,
    5435             :                                          smb1req->vuid);
    5436          28 :         if (!NT_STATUS_IS_OK(status)) {
    5437           0 :                 TALLOC_FREE(smb1req);
    5438           0 :                 END_PROFILE(SMBtdis);
    5439           0 :                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
    5440             :                 return;
    5441             :         }
    5442             : 
    5443             :         /* smbXsrv_tcon_disconnect frees smb1req->conn. */
    5444          28 :         smb1req->conn = NULL;
    5445             : 
    5446          28 :         TALLOC_FREE(tcon);
    5447             : 
    5448          28 :         reply_smb1_outbuf(smb1req, 0, 0);
    5449             :         /*
    5450             :          * The following call is needed to push the
    5451             :          * reply data back out the socket after async
    5452             :          * return. Plus it frees smb1req.
    5453             :          */
    5454          28 :         smb_request_done(smb1req);
    5455          28 :         END_PROFILE(SMBtdis);
    5456             : }
    5457             : 
    5458             : /****************************************************************************
    5459             :  Reply to a echo.
    5460             :  conn POINTER CAN BE NULL HERE !
    5461             : ****************************************************************************/
    5462             : 
    5463           0 : void reply_echo(struct smb_request *req)
    5464             : {
    5465           0 :         connection_struct *conn = req->conn;
    5466             :         struct smb_perfcount_data local_pcd;
    5467             :         struct smb_perfcount_data *cur_pcd;
    5468             :         int smb_reverb;
    5469             :         int seq_num;
    5470             : 
    5471           0 :         START_PROFILE(SMBecho);
    5472             : 
    5473           0 :         smb_init_perfcount_data(&local_pcd);
    5474             : 
    5475           0 :         if (req->wct < 1) {
    5476           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5477           0 :                 END_PROFILE(SMBecho);
    5478           0 :                 return;
    5479             :         }
    5480             : 
    5481           0 :         smb_reverb = SVAL(req->vwv+0, 0);
    5482             : 
    5483           0 :         reply_smb1_outbuf(req, 1, req->buflen);
    5484             : 
    5485             :         /* copy any incoming data back out */
    5486           0 :         if (req->buflen > 0) {
    5487           0 :                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
    5488             :         }
    5489             : 
    5490           0 :         if (smb_reverb > 100) {
    5491           0 :                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
    5492           0 :                 smb_reverb = 100;
    5493             :         }
    5494             : 
    5495           0 :         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
    5496             : 
    5497             :                 /* this makes sure we catch the request pcd */
    5498           0 :                 if (seq_num == smb_reverb) {
    5499           0 :                         cur_pcd = &req->pcd;
    5500             :                 } else {
    5501           0 :                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
    5502           0 :                         cur_pcd = &local_pcd;
    5503             :                 }
    5504             : 
    5505           0 :                 SSVAL(req->outbuf,smb_vwv0,seq_num);
    5506             : 
    5507           0 :                 show_msg((char *)req->outbuf);
    5508           0 :                 if (!smb1_srv_send(req->xconn,
    5509           0 :                                 (char *)req->outbuf,
    5510           0 :                                 true, req->seqnum+1,
    5511           0 :                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
    5512             :                                 cur_pcd))
    5513           0 :                         exit_server_cleanly("reply_echo: smb1_srv_send failed.");
    5514             :         }
    5515             : 
    5516           0 :         DEBUG(3,("echo %d times\n", smb_reverb));
    5517             : 
    5518           0 :         TALLOC_FREE(req->outbuf);
    5519             : 
    5520           0 :         END_PROFILE(SMBecho);
    5521           0 :         return;
    5522             : }
    5523             : 
    5524             : /****************************************************************************
    5525             :  Reply to a printopen.
    5526             : ****************************************************************************/
    5527             : 
    5528           0 : void reply_printopen(struct smb_request *req)
    5529             : {
    5530           0 :         connection_struct *conn = req->conn;
    5531             :         files_struct *fsp;
    5532             :         NTSTATUS status;
    5533             : 
    5534           0 :         START_PROFILE(SMBsplopen);
    5535             : 
    5536           0 :         if (req->wct < 2) {
    5537           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5538           0 :                 END_PROFILE(SMBsplopen);
    5539           0 :                 return;
    5540             :         }
    5541             : 
    5542           0 :         if (!CAN_PRINT(conn)) {
    5543           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5544           0 :                 END_PROFILE(SMBsplopen);
    5545           0 :                 return;
    5546             :         }
    5547             : 
    5548           0 :         status = file_new(req, conn, &fsp);
    5549           0 :         if(!NT_STATUS_IS_OK(status)) {
    5550           0 :                 reply_nterror(req, status);
    5551           0 :                 END_PROFILE(SMBsplopen);
    5552           0 :                 return;
    5553             :         }
    5554             : 
    5555             :         /* Open for exclusive use, write only. */
    5556           0 :         status = print_spool_open(fsp, NULL, req->vuid);
    5557             : 
    5558           0 :         if (!NT_STATUS_IS_OK(status)) {
    5559           0 :                 file_free(req, fsp);
    5560           0 :                 reply_nterror(req, status);
    5561           0 :                 END_PROFILE(SMBsplopen);
    5562           0 :                 return;
    5563             :         }
    5564             : 
    5565           0 :         reply_smb1_outbuf(req, 1, 0);
    5566           0 :         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
    5567             : 
    5568           0 :         DEBUG(3,("openprint fd=%d %s\n",
    5569             :                  fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
    5570             : 
    5571           0 :         END_PROFILE(SMBsplopen);
    5572           0 :         return;
    5573             : }
    5574             : 
    5575             : /****************************************************************************
    5576             :  Reply to a printclose.
    5577             : ****************************************************************************/
    5578             : 
    5579           0 : void reply_printclose(struct smb_request *req)
    5580             : {
    5581           0 :         connection_struct *conn = req->conn;
    5582             :         files_struct *fsp;
    5583             :         NTSTATUS status;
    5584             : 
    5585           0 :         START_PROFILE(SMBsplclose);
    5586             : 
    5587           0 :         if (req->wct < 1) {
    5588           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5589           0 :                 END_PROFILE(SMBsplclose);
    5590           0 :                 return;
    5591             :         }
    5592             : 
    5593           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    5594             : 
    5595           0 :         if (!check_fsp(conn, req, fsp)) {
    5596           0 :                 END_PROFILE(SMBsplclose);
    5597           0 :                 return;
    5598             :         }
    5599             : 
    5600           0 :         if (!CAN_PRINT(conn)) {
    5601           0 :                 reply_force_doserror(req, ERRSRV, ERRerror);
    5602           0 :                 END_PROFILE(SMBsplclose);
    5603           0 :                 return;
    5604             :         }
    5605             : 
    5606           0 :         DEBUG(3,("printclose fd=%d %s\n",
    5607             :                  fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
    5608             : 
    5609           0 :         status = close_file_free(req, &fsp, NORMAL_CLOSE);
    5610             : 
    5611           0 :         if(!NT_STATUS_IS_OK(status)) {
    5612           0 :                 reply_nterror(req, status);
    5613           0 :                 END_PROFILE(SMBsplclose);
    5614           0 :                 return;
    5615             :         }
    5616             : 
    5617           0 :         reply_smb1_outbuf(req, 0, 0);
    5618             : 
    5619           0 :         END_PROFILE(SMBsplclose);
    5620           0 :         return;
    5621             : }
    5622             : 
    5623             : /****************************************************************************
    5624             :  Reply to a printqueue.
    5625             : ****************************************************************************/
    5626             : 
    5627           0 : void reply_printqueue(struct smb_request *req)
    5628             : {
    5629             :         const struct loadparm_substitution *lp_sub =
    5630           0 :                 loadparm_s3_global_substitution();
    5631           0 :         connection_struct *conn = req->conn;
    5632             :         int max_count;
    5633             :         int start_index;
    5634             : 
    5635           0 :         START_PROFILE(SMBsplretq);
    5636             : 
    5637           0 :         if (req->wct < 2) {
    5638           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5639           0 :                 END_PROFILE(SMBsplretq);
    5640           0 :                 return;
    5641             :         }
    5642             : 
    5643           0 :         max_count = SVAL(req->vwv+0, 0);
    5644           0 :         start_index = SVAL(req->vwv+1, 0);
    5645             : 
    5646             :         /* we used to allow the client to get the cnum wrong, but that
    5647             :            is really quite gross and only worked when there was only
    5648             :            one printer - I think we should now only accept it if they
    5649             :            get it right (tridge) */
    5650           0 :         if (!CAN_PRINT(conn)) {
    5651           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5652           0 :                 END_PROFILE(SMBsplretq);
    5653           0 :                 return;
    5654             :         }
    5655             : 
    5656           0 :         reply_smb1_outbuf(req, 2, 3);
    5657           0 :         SSVAL(req->outbuf,smb_vwv0,0);
    5658           0 :         SSVAL(req->outbuf,smb_vwv1,0);
    5659           0 :         SCVAL(smb_buf(req->outbuf),0,1);
    5660           0 :         SSVAL(smb_buf(req->outbuf),1,0);
    5661             : 
    5662           0 :         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
    5663             :                  start_index, max_count));
    5664             : 
    5665             :         {
    5666           0 :                 TALLOC_CTX *mem_ctx = talloc_tos();
    5667             :                 NTSTATUS status;
    5668             :                 WERROR werr;
    5669           0 :                 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
    5670           0 :                 struct rpc_pipe_client *cli = NULL;
    5671           0 :                 struct dcerpc_binding_handle *b = NULL;
    5672             :                 struct policy_handle handle;
    5673             :                 struct spoolss_DevmodeContainer devmode_ctr;
    5674             :                 union spoolss_JobInfo *info;
    5675             :                 uint32_t count;
    5676             :                 uint32_t num_to_get;
    5677             :                 uint32_t first;
    5678             :                 uint32_t i;
    5679             : 
    5680           0 :                 ZERO_STRUCT(handle);
    5681             : 
    5682           0 :                 status = rpc_pipe_open_interface(mem_ctx,
    5683             :                                                  &ndr_table_spoolss,
    5684           0 :                                                  conn->session_info,
    5685           0 :                                                  conn->sconn->remote_address,
    5686           0 :                                                  conn->sconn->local_address,
    5687           0 :                                                  conn->sconn->msg_ctx,
    5688             :                                                  &cli);
    5689           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5690           0 :                         DEBUG(0, ("reply_printqueue: "
    5691             :                                   "could not connect to spoolss: %s\n",
    5692             :                                   nt_errstr(status)));
    5693           0 :                         reply_nterror(req, status);
    5694           0 :                         goto out;
    5695             :                 }
    5696           0 :                 b = cli->binding_handle;
    5697             : 
    5698           0 :                 ZERO_STRUCT(devmode_ctr);
    5699             : 
    5700           0 :                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    5701             :                                                 sharename,
    5702             :                                                 NULL, devmode_ctr,
    5703             :                                                 SEC_FLAG_MAXIMUM_ALLOWED,
    5704             :                                                 &handle,
    5705             :                                                 &werr);
    5706           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5707           0 :                         reply_nterror(req, status);
    5708           0 :                         goto out;
    5709             :                 }
    5710           0 :                 if (!W_ERROR_IS_OK(werr)) {
    5711           0 :                         reply_nterror(req, werror_to_ntstatus(werr));
    5712           0 :                         goto out;
    5713             :                 }
    5714             : 
    5715           0 :                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
    5716             :                                                &handle,
    5717             :                                                0, /* firstjob */
    5718             :                                                0xff, /* numjobs */
    5719             :                                                2, /* level */
    5720             :                                                0, /* offered */
    5721             :                                                &count,
    5722             :                                                &info);
    5723           0 :                 if (!W_ERROR_IS_OK(werr)) {
    5724           0 :                         reply_nterror(req, werror_to_ntstatus(werr));
    5725           0 :                         goto out;
    5726             :                 }
    5727             : 
    5728           0 :                 if (max_count > 0) {
    5729           0 :                         first = start_index;
    5730             :                 } else {
    5731           0 :                         first = start_index + max_count + 1;
    5732             :                 }
    5733             : 
    5734           0 :                 if (first >= count) {
    5735           0 :                         num_to_get = first;
    5736             :                 } else {
    5737           0 :                         num_to_get = first + MIN(ABS(max_count), count - first);
    5738             :                 }
    5739             : 
    5740           0 :                 for (i = first; i < num_to_get; i++) {
    5741             :                         char blob[28];
    5742           0 :                         char *p = blob;
    5743           0 :                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
    5744             :                         int qstatus;
    5745           0 :                         size_t len = 0;
    5746           0 :                         uint16_t qrapjobid = pjobid_to_rap(sharename,
    5747           0 :                                                         info[i].info2.job_id);
    5748             : 
    5749           0 :                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
    5750           0 :                                 qstatus = 2;
    5751             :                         } else {
    5752           0 :                                 qstatus = 3;
    5753             :                         }
    5754             : 
    5755           0 :                         srv_put_dos_date2(p, 0, qtime);
    5756           0 :                         SCVAL(p, 4, qstatus);
    5757           0 :                         SSVAL(p, 5, qrapjobid);
    5758           0 :                         SIVAL(p, 7, info[i].info2.size);
    5759           0 :                         SCVAL(p, 11, 0);
    5760           0 :                         status = srvstr_push(blob, req->flags2, p+12,
    5761             :                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
    5762           0 :                         if (!NT_STATUS_IS_OK(status)) {
    5763           0 :                                 reply_nterror(req, status);
    5764           0 :                                 goto out;
    5765             :                         }
    5766           0 :                         if (message_push_blob(
    5767             :                                     &req->outbuf,
    5768             :                                     data_blob_const(
    5769             :                                             blob, sizeof(blob))) == -1) {
    5770           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5771           0 :                                 goto out;
    5772             :                         }
    5773             :                 }
    5774             : 
    5775           0 :                 if (count > 0) {
    5776           0 :                         SSVAL(req->outbuf,smb_vwv0,count);
    5777           0 :                         SSVAL(req->outbuf,smb_vwv1,
    5778             :                               (max_count>0?first+count:first-1));
    5779           0 :                         SCVAL(smb_buf(req->outbuf),0,1);
    5780           0 :                         SSVAL(smb_buf(req->outbuf),1,28*count);
    5781             :                 }
    5782             : 
    5783             : 
    5784           0 :                 DEBUG(3, ("%u entries returned in queue\n",
    5785             :                           (unsigned)count));
    5786             : 
    5787           0 : out:
    5788           0 :                 if (b && is_valid_policy_hnd(&handle)) {
    5789           0 :                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    5790             :                 }
    5791             : 
    5792             :         }
    5793             : 
    5794           0 :         END_PROFILE(SMBsplretq);
    5795           0 :         return;
    5796             : }
    5797             : 
    5798             : /****************************************************************************
    5799             :  Reply to a printwrite.
    5800             : ****************************************************************************/
    5801             : 
    5802           0 : void reply_printwrite(struct smb_request *req)
    5803             : {
    5804           0 :         connection_struct *conn = req->conn;
    5805             :         int numtowrite;
    5806             :         const char *data;
    5807             :         files_struct *fsp;
    5808             :         NTSTATUS status;
    5809             : 
    5810           0 :         START_PROFILE(SMBsplwr);
    5811             : 
    5812           0 :         if (req->wct < 1) {
    5813           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5814           0 :                 END_PROFILE(SMBsplwr);
    5815           0 :                 return;
    5816             :         }
    5817             : 
    5818           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    5819             : 
    5820           0 :         if (!check_fsp(conn, req, fsp)) {
    5821           0 :                 END_PROFILE(SMBsplwr);
    5822           0 :                 return;
    5823             :         }
    5824             : 
    5825           0 :         if (!fsp->print_file) {
    5826           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5827           0 :                 END_PROFILE(SMBsplwr);
    5828           0 :                 return;
    5829             :         }
    5830             : 
    5831           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
    5832           0 :         if (!NT_STATUS_IS_OK(status)) {
    5833           0 :                 reply_nterror(req, status);
    5834           0 :                 END_PROFILE(SMBsplwr);
    5835           0 :                 return;
    5836             :         }
    5837             : 
    5838           0 :         numtowrite = SVAL(req->buf, 1);
    5839             : 
    5840             :         /*
    5841             :          * This already protects us against CVE-2017-12163.
    5842             :          */
    5843           0 :         if (req->buflen < numtowrite + 3) {
    5844           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5845           0 :                 END_PROFILE(SMBsplwr);
    5846           0 :                 return;
    5847             :         }
    5848             : 
    5849           0 :         data = (const char *)req->buf + 3;
    5850             : 
    5851           0 :         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
    5852           0 :                 reply_nterror(req, map_nt_error_from_unix(errno));
    5853           0 :                 END_PROFILE(SMBsplwr);
    5854           0 :                 return;
    5855             :         }
    5856             : 
    5857           0 :         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
    5858             : 
    5859           0 :         reply_smb1_outbuf(req, 0, 0);
    5860             : 
    5861           0 :         END_PROFILE(SMBsplwr);
    5862           0 :         return;
    5863             : }
    5864             : 
    5865             : /****************************************************************************
    5866             :  Reply to a mkdir.
    5867             : ****************************************************************************/
    5868             : 
    5869           0 : void reply_mkdir(struct smb_request *req)
    5870             : {
    5871           0 :         connection_struct *conn = req->conn;
    5872           0 :         struct files_struct *dirfsp = NULL;
    5873           0 :         struct smb_filename *smb_dname = NULL;
    5874           0 :         char *directory = NULL;
    5875             :         NTSTATUS status;
    5876             :         uint32_t ucf_flags;
    5877           0 :         NTTIME twrp = 0;
    5878           0 :         TALLOC_CTX *ctx = talloc_tos();
    5879             : 
    5880           0 :         START_PROFILE(SMBmkdir);
    5881             : 
    5882           0 :         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
    5883             :                             STR_TERMINATE, &status);
    5884           0 :         if (!NT_STATUS_IS_OK(status)) {
    5885           0 :                 reply_nterror(req, status);
    5886           0 :                 goto out;
    5887             :         }
    5888             : 
    5889           0 :         ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
    5890           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    5891           0 :                 extract_snapshot_token(directory, &twrp);
    5892             :         }
    5893           0 :         status = filename_convert_dirfsp(ctx,
    5894             :                                          conn,
    5895             :                                          directory,
    5896             :                                          ucf_flags,
    5897             :                                          twrp,
    5898             :                                          &dirfsp,
    5899             :                                          &smb_dname);
    5900           0 :         if (!NT_STATUS_IS_OK(status)) {
    5901           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    5902           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    5903             :                                         ERRSRV, ERRbadpath);
    5904           0 :                         goto out;
    5905             :                 }
    5906           0 :                 reply_nterror(req, status);
    5907           0 :                 goto out;
    5908             :         }
    5909             : 
    5910           0 :         status = create_directory(conn, req, dirfsp, smb_dname);
    5911             : 
    5912           0 :         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
    5913             : 
    5914           0 :         if (!NT_STATUS_IS_OK(status)) {
    5915             : 
    5916           0 :                 if (!use_nt_status()
    5917           0 :                     && NT_STATUS_EQUAL(status,
    5918             :                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
    5919             :                         /*
    5920             :                          * Yes, in the DOS error code case we get a
    5921             :                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
    5922             :                          * samba4 torture test.
    5923             :                          */
    5924           0 :                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
    5925             :                 }
    5926             : 
    5927           0 :                 reply_nterror(req, status);
    5928           0 :                 goto out;
    5929             :         }
    5930             : 
    5931           0 :         reply_smb1_outbuf(req, 0, 0);
    5932             : 
    5933           0 :         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
    5934           0 :  out:
    5935           0 :         TALLOC_FREE(smb_dname);
    5936           0 :         END_PROFILE(SMBmkdir);
    5937           0 :         return;
    5938             : }
    5939             : 
    5940             : /****************************************************************************
    5941             :  Reply to a rmdir.
    5942             : ****************************************************************************/
    5943             : 
    5944           0 : void reply_rmdir(struct smb_request *req)
    5945             : {
    5946           0 :         connection_struct *conn = req->conn;
    5947           0 :         struct smb_filename *smb_dname = NULL;
    5948           0 :         char *directory = NULL;
    5949             :         NTSTATUS status;
    5950           0 :         TALLOC_CTX *ctx = talloc_tos();
    5951           0 :         struct files_struct *dirfsp = NULL;
    5952           0 :         files_struct *fsp = NULL;
    5953           0 :         int info = 0;
    5954           0 :         NTTIME twrp = 0;
    5955           0 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    5956             : 
    5957           0 :         START_PROFILE(SMBrmdir);
    5958             : 
    5959           0 :         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
    5960             :                             STR_TERMINATE, &status);
    5961           0 :         if (!NT_STATUS_IS_OK(status)) {
    5962           0 :                 reply_nterror(req, status);
    5963           0 :                 goto out;
    5964             :         }
    5965             : 
    5966           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    5967           0 :                 extract_snapshot_token(directory, &twrp);
    5968             :         }
    5969           0 :         status = filename_convert_dirfsp(ctx,
    5970             :                                          conn,
    5971             :                                          directory,
    5972             :                                          ucf_flags,
    5973             :                                          twrp,
    5974             :                                          &dirfsp,
    5975             :                                          &smb_dname);
    5976           0 :         if (!NT_STATUS_IS_OK(status)) {
    5977           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    5978           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    5979             :                                         ERRSRV, ERRbadpath);
    5980           0 :                         goto out;
    5981             :                 }
    5982           0 :                 reply_nterror(req, status);
    5983           0 :                 goto out;
    5984             :         }
    5985             : 
    5986           0 :         status = SMB_VFS_CREATE_FILE(
    5987             :                 conn,                                   /* conn */
    5988             :                 req,                                    /* req */
    5989             :                 dirfsp,                                 /* dirfsp */
    5990             :                 smb_dname,                              /* fname */
    5991             :                 DELETE_ACCESS,                          /* access_mask */
    5992             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    5993             :                         FILE_SHARE_DELETE),
    5994             :                 FILE_OPEN,                              /* create_disposition*/
    5995             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    5996             :                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
    5997             :                 0,                                      /* oplock_request */
    5998             :                 NULL,                                   /* lease */
    5999             :                 0,                                      /* allocation_size */
    6000             :                 0,                                      /* private_flags */
    6001             :                 NULL,                                   /* sd */
    6002             :                 NULL,                                   /* ea_list */
    6003             :                 &fsp,                                   /* result */
    6004             :                 &info,                                  /* pinfo */
    6005             :                 NULL, NULL);                            /* create context */
    6006             : 
    6007           0 :         if (!NT_STATUS_IS_OK(status)) {
    6008           0 :                 if (open_was_deferred(req->xconn, req->mid)) {
    6009             :                         /* We have re-scheduled this call. */
    6010           0 :                         goto out;
    6011             :                 }
    6012           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    6013           0 :                         bool ok = defer_smb1_sharing_violation(req);
    6014           0 :                         if (ok) {
    6015           0 :                                 goto out;
    6016             :                         }
    6017             :                 }
    6018           0 :                 reply_nterror(req, status);
    6019           0 :                 goto out;
    6020             :         }
    6021             : 
    6022           0 :         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
    6023           0 :         if (!NT_STATUS_IS_OK(status)) {
    6024           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
    6025           0 :                 reply_nterror(req, status);
    6026           0 :                 goto out;
    6027             :         }
    6028             : 
    6029           0 :         if (!set_delete_on_close(fsp, true,
    6030           0 :                         conn->session_info->security_token,
    6031           0 :                         conn->session_info->unix_token)) {
    6032           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
    6033           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    6034           0 :                 goto out;
    6035             :         }
    6036             : 
    6037           0 :         status = close_file_free(req, &fsp, NORMAL_CLOSE);
    6038           0 :         if (!NT_STATUS_IS_OK(status)) {
    6039           0 :                 reply_nterror(req, status);
    6040             :         } else {
    6041           0 :                 reply_smb1_outbuf(req, 0, 0);
    6042             :         }
    6043             : 
    6044           0 :         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
    6045           0 :  out:
    6046           0 :         TALLOC_FREE(smb_dname);
    6047           0 :         END_PROFILE(SMBrmdir);
    6048           0 :         return;
    6049             : }
    6050             : 
    6051             : /****************************************************************************
    6052             :  Reply to a mv.
    6053             : ****************************************************************************/
    6054             : 
    6055           0 : void reply_mv(struct smb_request *req)
    6056             : {
    6057           0 :         connection_struct *conn = req->conn;
    6058           0 :         char *name = NULL;
    6059           0 :         char *newname = NULL;
    6060             :         const char *p;
    6061             :         uint32_t attrs;
    6062             :         NTSTATUS status;
    6063           0 :         TALLOC_CTX *ctx = talloc_tos();
    6064           0 :         struct files_struct *src_dirfsp = NULL;
    6065           0 :         struct smb_filename *smb_fname_src = NULL;
    6066           0 :         struct files_struct *dst_dirfsp = NULL;
    6067           0 :         struct smb_filename *smb_fname_dst = NULL;
    6068           0 :         const char *dst_original_lcomp = NULL;
    6069           0 :         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
    6070           0 :         NTTIME src_twrp = 0;
    6071           0 :         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
    6072           0 :         NTTIME dst_twrp = 0;
    6073           0 :         bool stream_rename = false;
    6074             : 
    6075           0 :         START_PROFILE(SMBmv);
    6076             : 
    6077           0 :         if (req->wct < 1) {
    6078           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6079           0 :                 goto out;
    6080             :         }
    6081             : 
    6082           0 :         attrs = SVAL(req->vwv+0, 0);
    6083             : 
    6084           0 :         p = (const char *)req->buf + 1;
    6085           0 :         p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
    6086             :                                        &status);
    6087           0 :         if (!NT_STATUS_IS_OK(status)) {
    6088           0 :                 reply_nterror(req, status);
    6089           0 :                 goto out;
    6090             :         }
    6091           0 :         p++;
    6092           0 :         p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
    6093             :                                        &status);
    6094           0 :         if (!NT_STATUS_IS_OK(status)) {
    6095           0 :                 reply_nterror(req, status);
    6096           0 :                 goto out;
    6097             :         }
    6098             : 
    6099           0 :         if (!req->posix_pathnames) {
    6100             :                 /* The newname must begin with a ':' if the
    6101             :                    name contains a ':'. */
    6102           0 :                 if (strchr_m(name, ':')) {
    6103           0 :                         if (newname[0] != ':') {
    6104           0 :                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6105           0 :                                 goto out;
    6106             :                         }
    6107           0 :                         stream_rename = true;
    6108             :                 }
    6109             :         }
    6110             : 
    6111           0 :         if (src_ucf_flags & UCF_GMT_PATHNAME) {
    6112           0 :                 extract_snapshot_token(name, &src_twrp);
    6113             :         }
    6114           0 :         status = filename_convert_dirfsp(ctx,
    6115             :                                          conn,
    6116             :                                          name,
    6117             :                                          src_ucf_flags,
    6118             :                                          src_twrp,
    6119             :                                          &src_dirfsp,
    6120             :                                          &smb_fname_src);
    6121             : 
    6122           0 :         if (!NT_STATUS_IS_OK(status)) {
    6123           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    6124           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    6125             :                                         ERRSRV, ERRbadpath);
    6126           0 :                         goto out;
    6127             :                 }
    6128           0 :                 reply_nterror(req, status);
    6129           0 :                 goto out;
    6130             :         }
    6131             : 
    6132           0 :         if (dst_ucf_flags & UCF_GMT_PATHNAME) {
    6133           0 :                 extract_snapshot_token(newname, &dst_twrp);
    6134             :         }
    6135           0 :         status = filename_convert_dirfsp(ctx,
    6136             :                                          conn,
    6137             :                                          newname,
    6138             :                                          dst_ucf_flags,
    6139             :                                          dst_twrp,
    6140             :                                          &dst_dirfsp,
    6141             :                                          &smb_fname_dst);
    6142             : 
    6143           0 :         if (!NT_STATUS_IS_OK(status)) {
    6144           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    6145           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    6146             :                                         ERRSRV, ERRbadpath);
    6147           0 :                         goto out;
    6148             :                 }
    6149           0 :                 reply_nterror(req, status);
    6150           0 :                 goto out;
    6151             :         }
    6152             : 
    6153             :         /* Get the last component of the destination for rename_internals(). */
    6154           0 :         dst_original_lcomp = get_original_lcomp(ctx,
    6155             :                                         conn,
    6156             :                                         newname,
    6157             :                                         dst_ucf_flags);
    6158           0 :         if (dst_original_lcomp == NULL) {
    6159           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    6160           0 :                 goto out;
    6161             :         }
    6162             : 
    6163           0 :         if (stream_rename) {
    6164             :                 /* smb_fname_dst->base_name must be the same as
    6165             :                    smb_fname_src->base_name. */
    6166           0 :                 TALLOC_FREE(smb_fname_dst->base_name);
    6167           0 :                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
    6168           0 :                                                 smb_fname_src->base_name);
    6169           0 :                 if (!smb_fname_dst->base_name) {
    6170           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    6171           0 :                         goto out;
    6172             :                 }
    6173             :         }
    6174             : 
    6175           0 :         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
    6176             :                  smb_fname_str_dbg(smb_fname_dst)));
    6177             : 
    6178           0 :         status = rename_internals(ctx,
    6179             :                                 conn,
    6180             :                                 req,
    6181             :                                 src_dirfsp, /* src_dirfsp */
    6182             :                                 smb_fname_src,
    6183             :                                 dst_dirfsp, /* dst_dirfsp */
    6184             :                                 smb_fname_dst,
    6185             :                                 dst_original_lcomp,
    6186             :                                 attrs,
    6187             :                                 false,
    6188             :                                 DELETE_ACCESS);
    6189           0 :         if (!NT_STATUS_IS_OK(status)) {
    6190           0 :                 if (open_was_deferred(req->xconn, req->mid)) {
    6191             :                         /* We have re-scheduled this call. */
    6192           0 :                         goto out;
    6193             :                 }
    6194           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    6195           0 :                         bool ok = defer_smb1_sharing_violation(req);
    6196           0 :                         if (ok) {
    6197           0 :                                 goto out;
    6198             :                         }
    6199             :                 }
    6200           0 :                 reply_nterror(req, status);
    6201           0 :                 goto out;
    6202             :         }
    6203             : 
    6204           0 :         reply_smb1_outbuf(req, 0, 0);
    6205           0 :  out:
    6206           0 :         TALLOC_FREE(smb_fname_src);
    6207           0 :         TALLOC_FREE(smb_fname_dst);
    6208           0 :         END_PROFILE(SMBmv);
    6209           0 :         return;
    6210             : }
    6211             : 
    6212             : /****************************************************************************
    6213             :  Reply to a file copy.
    6214             : 
    6215             :  From MS-CIFS.
    6216             : 
    6217             :  This command was introduced in the LAN Manager 1.0 dialect
    6218             :  It was rendered obsolete in the NT LAN Manager dialect.
    6219             :  This command was used to perform server-side file copies, but
    6220             :  is no longer used. Clients SHOULD
    6221             :  NOT send requests using this command code.
    6222             :  Servers receiving requests with this command code
    6223             :  SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
    6224             : ****************************************************************************/
    6225             : 
    6226           0 : void reply_copy(struct smb_request *req)
    6227             : {
    6228           0 :         START_PROFILE(SMBcopy);
    6229           0 :         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    6230           0 :         END_PROFILE(SMBcopy);
    6231           0 :         return;
    6232             : }
    6233             : 
    6234             : #undef DBGC_CLASS
    6235             : #define DBGC_CLASS DBGC_LOCKING
    6236             : 
    6237             : /****************************************************************************
    6238             :  Get a lock pid, dealing with large count requests.
    6239             : ****************************************************************************/
    6240             : 
    6241           0 : uint64_t get_lock_pid(const uint8_t *data, int data_offset,
    6242             :                     bool large_file_format)
    6243             : {
    6244           0 :         if(!large_file_format)
    6245           0 :                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
    6246             :         else
    6247           0 :                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
    6248             : }
    6249             : 
    6250             : /****************************************************************************
    6251             :  Get a lock count, dealing with large count requests.
    6252             : ****************************************************************************/
    6253             : 
    6254           0 : uint64_t get_lock_count(const uint8_t *data, int data_offset,
    6255             :                         bool large_file_format)
    6256             : {
    6257           0 :         uint64_t count = 0;
    6258             : 
    6259           0 :         if(!large_file_format) {
    6260           0 :                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
    6261             :         } else {
    6262             :                 /*
    6263             :                  * No BVAL, this is reversed!
    6264             :                  */
    6265           0 :                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
    6266           0 :                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
    6267             :         }
    6268             : 
    6269           0 :         return count;
    6270             : }
    6271             : 
    6272             : /****************************************************************************
    6273             :  Reply to a lockingX request.
    6274             : ****************************************************************************/
    6275             : 
    6276             : static void reply_lockingx_done(struct tevent_req *subreq);
    6277             : 
    6278           0 : void reply_lockingX(struct smb_request *req)
    6279             : {
    6280           0 :         connection_struct *conn = req->conn;
    6281             :         files_struct *fsp;
    6282             :         unsigned char locktype;
    6283             :         enum brl_type brltype;
    6284             :         unsigned char oplocklevel;
    6285             :         uint16_t num_ulocks;
    6286             :         uint16_t num_locks;
    6287             :         int32_t lock_timeout;
    6288             :         uint16_t i;
    6289             :         const uint8_t *data;
    6290             :         bool large_file_format;
    6291           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    6292           0 :         struct smbd_lock_element *locks = NULL;
    6293           0 :         struct tevent_req *subreq = NULL;
    6294             : 
    6295           0 :         START_PROFILE(SMBlockingX);
    6296             : 
    6297           0 :         if (req->wct < 8) {
    6298           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6299           0 :                 END_PROFILE(SMBlockingX);
    6300           0 :                 return;
    6301             :         }
    6302             : 
    6303           0 :         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
    6304           0 :         locktype = CVAL(req->vwv+3, 0);
    6305           0 :         oplocklevel = CVAL(req->vwv+3, 1);
    6306           0 :         num_ulocks = SVAL(req->vwv+6, 0);
    6307           0 :         num_locks = SVAL(req->vwv+7, 0);
    6308           0 :         lock_timeout = IVAL(req->vwv+4, 0);
    6309           0 :         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
    6310             : 
    6311           0 :         if (!check_fsp(conn, req, fsp)) {
    6312           0 :                 END_PROFILE(SMBlockingX);
    6313           0 :                 return;
    6314             :         }
    6315             : 
    6316           0 :         data = req->buf;
    6317             : 
    6318           0 :         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
    6319             :                 /* we don't support these - and CANCEL_LOCK makes w2k
    6320             :                    and XP reboot so I don't really want to be
    6321             :                    compatible! (tridge) */
    6322           0 :                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
    6323           0 :                 END_PROFILE(SMBlockingX);
    6324           0 :                 return;
    6325             :         }
    6326             : 
    6327             :         /* Check if this is an oplock break on a file
    6328             :            we have granted an oplock on.
    6329             :         */
    6330           0 :         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
    6331             :                 /* Client can insist on breaking to none. */
    6332           0 :                 bool break_to_none = (oplocklevel == 0);
    6333             :                 bool result;
    6334             : 
    6335           0 :                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
    6336             :                          "for %s\n", (unsigned int)oplocklevel,
    6337             :                          fsp_fnum_dbg(fsp)));
    6338             : 
    6339             :                 /*
    6340             :                  * Make sure we have granted an exclusive or batch oplock on
    6341             :                  * this file.
    6342             :                  */
    6343             : 
    6344           0 :                 if (fsp->oplock_type == 0) {
    6345             : 
    6346             :                         /* The Samba4 nbench simulator doesn't understand
    6347             :                            the difference between break to level2 and break
    6348             :                            to none from level2 - it sends oplock break
    6349             :                            replies in both cases. Don't keep logging an error
    6350             :                            message here - just ignore it. JRA. */
    6351             : 
    6352           0 :                         DEBUG(5,("reply_lockingX: Error : oplock break from "
    6353             :                                  "client for %s (oplock=%d) and no "
    6354             :                                  "oplock granted on this file (%s).\n",
    6355             :                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
    6356             :                                  fsp_str_dbg(fsp)));
    6357             : 
    6358             :                         /* if this is a pure oplock break request then don't
    6359             :                          * send a reply */
    6360           0 :                         if (num_locks == 0 && num_ulocks == 0) {
    6361           0 :                                 END_PROFILE(SMBlockingX);
    6362           0 :                                 return;
    6363             :                         }
    6364             : 
    6365           0 :                         END_PROFILE(SMBlockingX);
    6366           0 :                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    6367           0 :                         return;
    6368             :                 }
    6369             : 
    6370           0 :                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
    6371             :                     (break_to_none)) {
    6372           0 :                         result = remove_oplock(fsp);
    6373             :                 } else {
    6374           0 :                         result = downgrade_oplock(fsp);
    6375             :                 }
    6376             : 
    6377           0 :                 if (!result) {
    6378           0 :                         DEBUG(0, ("reply_lockingX: error in removing "
    6379             :                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
    6380             :                         /* Hmmm. Is this panic justified? */
    6381           0 :                         smb_panic("internal tdb error");
    6382             :                 }
    6383             : 
    6384             :                 /* if this is a pure oplock break request then don't send a
    6385             :                  * reply */
    6386           0 :                 if (num_locks == 0 && num_ulocks == 0) {
    6387             :                         /* Sanity check - ensure a pure oplock break is not a
    6388             :                            chained request. */
    6389           0 :                         if (CVAL(req->vwv+0, 0) != 0xff) {
    6390           0 :                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
    6391             :                                          "break is a chained %d request !\n",
    6392             :                                          (unsigned int)CVAL(req->vwv+0, 0)));
    6393             :                         }
    6394           0 :                         END_PROFILE(SMBlockingX);
    6395           0 :                         return;
    6396             :                 }
    6397             :         }
    6398             : 
    6399           0 :         if (req->buflen <
    6400           0 :             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
    6401           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6402           0 :                 END_PROFILE(SMBlockingX);
    6403           0 :                 return;
    6404             :         }
    6405             : 
    6406           0 :         if (num_ulocks != 0) {
    6407           0 :                 struct smbd_lock_element *ulocks = NULL;
    6408             :                 bool ok;
    6409             : 
    6410           0 :                 ulocks = talloc_array(
    6411             :                         req, struct smbd_lock_element, num_ulocks);
    6412           0 :                 if (ulocks == NULL) {
    6413           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    6414           0 :                         END_PROFILE(SMBlockingX);
    6415           0 :                         return;
    6416             :                 }
    6417             : 
    6418             :                 /*
    6419             :                  * Data now points at the beginning of the list of
    6420             :                  * smb_unlkrng structs
    6421             :                  */
    6422           0 :                 for (i = 0; i < num_ulocks; i++) {
    6423           0 :                         ulocks[i].req_guid = smbd_request_guid(req,
    6424           0 :                                 UINT16_MAX - i),
    6425           0 :                         ulocks[i].smblctx = get_lock_pid(
    6426             :                                 data, i, large_file_format);
    6427           0 :                         ulocks[i].count = get_lock_count(
    6428             :                                 data, i, large_file_format);
    6429           0 :                         ulocks[i].offset = get_lock_offset(
    6430             :                                 data, i, large_file_format);
    6431           0 :                         ulocks[i].brltype = UNLOCK_LOCK;
    6432           0 :                         ulocks[i].lock_flav = WINDOWS_LOCK;
    6433             :                 }
    6434             : 
    6435             :                 /*
    6436             :                  * Unlock cancels pending locks
    6437             :                  */
    6438             : 
    6439           0 :                 ok = smbd_smb1_brl_finish_by_lock(
    6440             :                         fsp,
    6441             :                         large_file_format,
    6442             :                         ulocks[0],
    6443           0 :                         NT_STATUS_OK);
    6444           0 :                 if (ok) {
    6445           0 :                         reply_smb1_outbuf(req, 2, 0);
    6446           0 :                         SSVAL(req->outbuf, smb_vwv0, 0xff);
    6447           0 :                         SSVAL(req->outbuf, smb_vwv1, 0);
    6448           0 :                         END_PROFILE(SMBlockingX);
    6449           0 :                         return;
    6450             :                 }
    6451             : 
    6452           0 :                 status = smbd_do_unlocking(
    6453             :                         req, fsp, num_ulocks, ulocks);
    6454           0 :                 TALLOC_FREE(ulocks);
    6455           0 :                 if (!NT_STATUS_IS_OK(status)) {
    6456           0 :                         END_PROFILE(SMBlockingX);
    6457           0 :                         reply_nterror(req, status);
    6458           0 :                         return;
    6459             :                 }
    6460             :         }
    6461             : 
    6462             :         /* Now do any requested locks */
    6463           0 :         data += ((large_file_format ? 20 : 10)*num_ulocks);
    6464             : 
    6465             :         /* Data now points at the beginning of the list
    6466             :            of smb_lkrng structs */
    6467             : 
    6468           0 :         if (locktype & LOCKING_ANDX_SHARED_LOCK) {
    6469           0 :                 brltype = READ_LOCK;
    6470             :         } else {
    6471           0 :                 brltype = WRITE_LOCK;
    6472             :         }
    6473             : 
    6474           0 :         locks = talloc_array(req, struct smbd_lock_element, num_locks);
    6475           0 :         if (locks == NULL) {
    6476           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    6477           0 :                 END_PROFILE(SMBlockingX);
    6478           0 :                 return;
    6479             :         }
    6480             : 
    6481           0 :         for (i = 0; i < num_locks; i++) {
    6482           0 :                 locks[i].req_guid = smbd_request_guid(req, i),
    6483           0 :                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
    6484           0 :                 locks[i].count = get_lock_count(data, i, large_file_format);
    6485           0 :                 locks[i].offset = get_lock_offset(data, i, large_file_format);
    6486           0 :                 locks[i].brltype = brltype;
    6487           0 :                 locks[i].lock_flav = WINDOWS_LOCK;
    6488             :         }
    6489             : 
    6490           0 :         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
    6491             : 
    6492             :                 bool ok;
    6493             : 
    6494           0 :                 if (num_locks == 0) {
    6495             :                         /* See smbtorture3 lock11 test */
    6496           0 :                         reply_smb1_outbuf(req, 2, 0);
    6497             :                         /* andx chain ends */
    6498           0 :                         SSVAL(req->outbuf, smb_vwv0, 0xff);
    6499           0 :                         SSVAL(req->outbuf, smb_vwv1, 0);
    6500           0 :                         END_PROFILE(SMBlockingX);
    6501           0 :                         return;
    6502             :                 }
    6503             : 
    6504           0 :                 ok = smbd_smb1_brl_finish_by_lock(
    6505             :                         fsp,
    6506             :                         large_file_format,
    6507             :                         locks[0], /* Windows only cancels the first lock */
    6508           0 :                         NT_STATUS_FILE_LOCK_CONFLICT);
    6509             : 
    6510           0 :                 if (!ok) {
    6511           0 :                         reply_force_doserror(req, ERRDOS, ERRcancelviolation);
    6512           0 :                         END_PROFILE(SMBlockingX);
    6513           0 :                         return;
    6514             :                 }
    6515             : 
    6516           0 :                 reply_smb1_outbuf(req, 2, 0);
    6517           0 :                 SSVAL(req->outbuf, smb_vwv0, 0xff);
    6518           0 :                 SSVAL(req->outbuf, smb_vwv1, 0);
    6519           0 :                 END_PROFILE(SMBlockingX);
    6520           0 :                 return;
    6521             :         }
    6522             : 
    6523           0 :         subreq = smbd_smb1_do_locks_send(
    6524             :                 fsp,
    6525           0 :                 req->sconn->ev_ctx,
    6526             :                 &req,
    6527             :                 fsp,
    6528             :                 lock_timeout,
    6529             :                 large_file_format,
    6530             :                 num_locks,
    6531             :                 locks);
    6532           0 :         if (subreq == NULL) {
    6533           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    6534           0 :                 END_PROFILE(SMBlockingX);
    6535           0 :                 return;
    6536             :         }
    6537           0 :         tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
    6538           0 :         END_PROFILE(SMBlockingX);
    6539             : }
    6540             : 
    6541           0 : static void reply_lockingx_done(struct tevent_req *subreq)
    6542             : {
    6543           0 :         struct smb_request *req = NULL;
    6544             :         NTSTATUS status;
    6545             :         bool ok;
    6546             : 
    6547           0 :         START_PROFILE(SMBlockingX);
    6548             : 
    6549           0 :         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
    6550           0 :         SMB_ASSERT(ok);
    6551             : 
    6552           0 :         status = smbd_smb1_do_locks_recv(subreq);
    6553           0 :         TALLOC_FREE(subreq);
    6554             : 
    6555           0 :         DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
    6556             : 
    6557           0 :         if (NT_STATUS_IS_OK(status)) {
    6558           0 :                 reply_smb1_outbuf(req, 2, 0);
    6559           0 :                 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
    6560           0 :                 SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
    6561             :         } else {
    6562           0 :                 reply_nterror(req, status);
    6563             :         }
    6564             : 
    6565           0 :         ok = smb1_srv_send(req->xconn,
    6566           0 :                           (char *)req->outbuf,
    6567             :                           true,
    6568           0 :                           req->seqnum+1,
    6569           0 :                           IS_CONN_ENCRYPTED(req->conn),
    6570             :                           NULL);
    6571           0 :         if (!ok) {
    6572           0 :                 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
    6573             :         }
    6574           0 :         TALLOC_FREE(req);
    6575           0 :         END_PROFILE(SMBlockingX);
    6576           0 : }
    6577             : 
    6578             : #undef DBGC_CLASS
    6579             : #define DBGC_CLASS DBGC_ALL
    6580             : 
    6581             : /****************************************************************************
    6582             :  Reply to a SMBreadbmpx (read block multiplex) request.
    6583             :  Always reply with an error, if someone has a platform really needs this,
    6584             :  please contact vl@samba.org
    6585             : ****************************************************************************/
    6586             : 
    6587           0 : void reply_readbmpx(struct smb_request *req)
    6588             : {
    6589           0 :         START_PROFILE(SMBreadBmpx);
    6590           0 :         reply_force_doserror(req, ERRSRV, ERRuseSTD);
    6591           0 :         END_PROFILE(SMBreadBmpx);
    6592           0 :         return;
    6593             : }
    6594             : 
    6595             : /****************************************************************************
    6596             :  Reply to a SMBreadbs (read block multiplex secondary) request.
    6597             :  Always reply with an error, if someone has a platform really needs this,
    6598             :  please contact vl@samba.org
    6599             : ****************************************************************************/
    6600             : 
    6601           0 : void reply_readbs(struct smb_request *req)
    6602             : {
    6603           0 :         START_PROFILE(SMBreadBs);
    6604           0 :         reply_force_doserror(req, ERRSRV, ERRuseSTD);
    6605           0 :         END_PROFILE(SMBreadBs);
    6606           0 :         return;
    6607             : }
    6608             : 
    6609             : /****************************************************************************
    6610             :  Reply to a SMBsetattrE.
    6611             : ****************************************************************************/
    6612             : 
    6613           0 : void reply_setattrE(struct smb_request *req)
    6614             : {
    6615           0 :         connection_struct *conn = req->conn;
    6616             :         struct smb_file_time ft;
    6617             :         files_struct *fsp;
    6618             :         NTSTATUS status;
    6619             : 
    6620           0 :         START_PROFILE(SMBsetattrE);
    6621           0 :         init_smb_file_time(&ft);
    6622             : 
    6623           0 :         if (req->wct < 7) {
    6624           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6625           0 :                 goto out;
    6626             :         }
    6627             : 
    6628           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    6629             : 
    6630           0 :         if(!fsp || (fsp->conn != conn)) {
    6631           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    6632           0 :                 goto out;
    6633             :         }
    6634             : 
    6635             :         /*
    6636             :          * Convert the DOS times into unix times.
    6637             :          */
    6638             : 
    6639           0 :         ft.atime = time_t_to_full_timespec(
    6640           0 :             srv_make_unix_date2(req->vwv+3));
    6641           0 :         ft.mtime = time_t_to_full_timespec(
    6642           0 :             srv_make_unix_date2(req->vwv+5));
    6643           0 :         ft.create_time = time_t_to_full_timespec(
    6644           0 :             srv_make_unix_date2(req->vwv+1));
    6645             : 
    6646           0 :         reply_smb1_outbuf(req, 0, 0);
    6647             : 
    6648             :         /* 
    6649             :          * Patch from Ray Frush <frush@engr.colostate.edu>
    6650             :          * Sometimes times are sent as zero - ignore them.
    6651             :          */
    6652             : 
    6653             :         /* Ensure we have a valid stat struct for the source. */
    6654           0 :         status = vfs_stat_fsp(fsp);
    6655           0 :         if (!NT_STATUS_IS_OK(status)) {
    6656           0 :                 reply_nterror(req, status);
    6657           0 :                 goto out;
    6658             :         }
    6659             : 
    6660           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    6661           0 :         if (!NT_STATUS_IS_OK(status)) {
    6662           0 :                 reply_nterror(req, status);
    6663           0 :                 goto out;
    6664             :         }
    6665             : 
    6666           0 :         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
    6667           0 :         if (!NT_STATUS_IS_OK(status)) {
    6668           0 :                 reply_nterror(req, status);
    6669           0 :                 goto out;
    6670             :         }
    6671             : 
    6672           0 :         if (fsp->fsp_flags.modified) {
    6673           0 :                 trigger_write_time_update_immediate(fsp);
    6674             :         }
    6675             : 
    6676           0 :         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
    6677             :                " createtime=%u\n",
    6678             :                 fsp_fnum_dbg(fsp),
    6679             :                 (unsigned int)ft.atime.tv_sec,
    6680             :                 (unsigned int)ft.mtime.tv_sec,
    6681             :                 (unsigned int)ft.create_time.tv_sec
    6682             :                 ));
    6683           0 :  out:
    6684           0 :         END_PROFILE(SMBsetattrE);
    6685           0 :         return;
    6686             : }
    6687             : 
    6688             : 
    6689             : /* Back from the dead for OS/2..... JRA. */
    6690             : 
    6691             : /****************************************************************************
    6692             :  Reply to a SMBwritebmpx (write block multiplex primary) request.
    6693             :  Always reply with an error, if someone has a platform really needs this,
    6694             :  please contact vl@samba.org
    6695             : ****************************************************************************/
    6696             : 
    6697           0 : void reply_writebmpx(struct smb_request *req)
    6698             : {
    6699           0 :         START_PROFILE(SMBwriteBmpx);
    6700           0 :         reply_force_doserror(req, ERRSRV, ERRuseSTD);
    6701           0 :         END_PROFILE(SMBwriteBmpx);
    6702           0 :         return;
    6703             : }
    6704             : 
    6705             : /****************************************************************************
    6706             :  Reply to a SMBwritebs (write block multiplex secondary) request.
    6707             :  Always reply with an error, if someone has a platform really needs this,
    6708             :  please contact vl@samba.org
    6709             : ****************************************************************************/
    6710             : 
    6711           0 : void reply_writebs(struct smb_request *req)
    6712             : {
    6713           0 :         START_PROFILE(SMBwriteBs);
    6714           0 :         reply_force_doserror(req, ERRSRV, ERRuseSTD);
    6715           0 :         END_PROFILE(SMBwriteBs);
    6716           0 :         return;
    6717             : }
    6718             : 
    6719             : /****************************************************************************
    6720             :  Reply to a SMBgetattrE.
    6721             : ****************************************************************************/
    6722             : 
    6723           0 : void reply_getattrE(struct smb_request *req)
    6724             : {
    6725           0 :         connection_struct *conn = req->conn;
    6726             :         int mode;
    6727             :         files_struct *fsp;
    6728             :         struct timespec create_ts;
    6729             :         NTSTATUS status;
    6730             : 
    6731           0 :         START_PROFILE(SMBgetattrE);
    6732             : 
    6733           0 :         if (req->wct < 1) {
    6734           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6735           0 :                 END_PROFILE(SMBgetattrE);
    6736           0 :                 return;
    6737             :         }
    6738             : 
    6739           0 :         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
    6740             : 
    6741           0 :         if(!fsp || (fsp->conn != conn)) {
    6742           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    6743           0 :                 END_PROFILE(SMBgetattrE);
    6744           0 :                 return;
    6745             :         }
    6746             : 
    6747             :         /* Do an fstat on this file */
    6748           0 :         status = vfs_stat_fsp(fsp);
    6749           0 :         if (!NT_STATUS_IS_OK(status)) {
    6750           0 :                 reply_nterror(req, status);
    6751           0 :                 END_PROFILE(SMBgetattrE);
    6752           0 :                 return;
    6753             :         }
    6754             : 
    6755           0 :         mode = fdos_mode(fsp);
    6756             : 
    6757             :         /*
    6758             :          * Convert the times into dos times. Set create
    6759             :          * date to be last modify date as UNIX doesn't save
    6760             :          * this.
    6761             :          */
    6762             : 
    6763           0 :         reply_smb1_outbuf(req, 11, 0);
    6764             : 
    6765           0 :         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
    6766           0 :         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
    6767           0 :         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
    6768           0 :                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
    6769             :         /* Should we check pending modtime here ? JRA */
    6770           0 :         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
    6771           0 :                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
    6772             : 
    6773           0 :         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
    6774           0 :                 SIVAL(req->outbuf, smb_vwv6, 0);
    6775           0 :                 SIVAL(req->outbuf, smb_vwv8, 0);
    6776             :         } else {
    6777           0 :                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
    6778           0 :                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
    6779           0 :                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
    6780             :         }
    6781           0 :         SSVAL(req->outbuf,smb_vwv10, mode);
    6782             : 
    6783           0 :         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
    6784             : 
    6785           0 :         END_PROFILE(SMBgetattrE);
    6786           0 :         return;
    6787             : }
    6788             : 
    6789             : /****************************************************************************
    6790             :  Reply to a SMBfindclose (stop trans2 directory search).
    6791             : ****************************************************************************/
    6792             : 
    6793           0 : void reply_findclose(struct smb_request *req)
    6794             : {
    6795             :         int dptr_num;
    6796           0 :         struct smbd_server_connection *sconn = req->sconn;
    6797           0 :         files_struct *fsp = NULL;
    6798             : 
    6799           0 :         START_PROFILE(SMBfindclose);
    6800             : 
    6801           0 :         if (req->wct < 1) {
    6802           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6803           0 :                 END_PROFILE(SMBfindclose);
    6804           0 :                 return;
    6805             :         }
    6806             : 
    6807           0 :         dptr_num = SVALS(req->vwv+0, 0);
    6808             : 
    6809           0 :         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
    6810             : 
    6811             :         /*
    6812             :          * OS/2 seems to use -1 to indicate "close all directories"
    6813             :          * This has to mean on this specific connection struct.
    6814             :          */
    6815           0 :         if (dptr_num == -1) {
    6816           0 :                 dptr_closecnum(req->conn);
    6817             :         } else {
    6818           0 :                 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
    6819           0 :                 dptr_num = -1;
    6820           0 :                 if (fsp != NULL) {
    6821           0 :                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
    6822             :                 }
    6823             :         }
    6824             : 
    6825           0 :         reply_smb1_outbuf(req, 0, 0);
    6826             : 
    6827           0 :         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
    6828             : 
    6829           0 :         END_PROFILE(SMBfindclose);
    6830           0 :         return;
    6831             : }
    6832             : 
    6833             : /****************************************************************************
    6834             :  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
    6835             : ****************************************************************************/
    6836             : 
    6837           0 : void reply_findnclose(struct smb_request *req)
    6838             : {
    6839             :         int dptr_num;
    6840             : 
    6841           0 :         START_PROFILE(SMBfindnclose);
    6842             : 
    6843           0 :         if (req->wct < 1) {
    6844           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6845           0 :                 END_PROFILE(SMBfindnclose);
    6846           0 :                 return;
    6847             :         }
    6848             : 
    6849           0 :         dptr_num = SVAL(req->vwv+0, 0);
    6850             : 
    6851           0 :         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
    6852             : 
    6853             :         /* We never give out valid handles for a
    6854             :            findnotifyfirst - so any dptr_num is ok here.
    6855             :            Just ignore it. */
    6856             : 
    6857           0 :         reply_smb1_outbuf(req, 0, 0);
    6858             : 
    6859           0 :         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
    6860             : 
    6861           0 :         END_PROFILE(SMBfindnclose);
    6862           0 :         return;
    6863             : }

Generated by: LCOV version 1.14