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

Generated by: LCOV version 1.14