LCOV - code coverage report
Current view: top level - source3/smbd - smb1_reply.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 2142 3535 60.6 %
Date: 2024-04-21 15:09:00 Functions: 69 92 75.0 %

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

Generated by: LCOV version 1.14