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

Generated by: LCOV version 1.14