s3:smbd: Fix converity warning with _smb_setlen_large()
[metze/samba/wip.git] / source3 / smbd / reply.c
index d54326a66bbba780edad232ad4036005d7834ded..fc56e3234be6b3916c50f6cb3451197edf03139d 100644 (file)
@@ -25,6 +25,7 @@
 */
 
 #include "includes.h"
+#include "libsmb/namequery.h"
 #include "system/filesys.h"
 #include "printing.h"
 #include "smbd/smbd.h"
@@ -43,6 +44,7 @@
 #include "../lib/tsocket/tsocket.h"
 #include "lib/tevent_wait.h"
 #include "libcli/smb/smb_signing.h"
+#include "lib/util/sys_rw_data.h"
 
 /****************************************************************************
  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
@@ -189,16 +191,16 @@ static NTSTATUS check_path_syntax_internal(char *path,
                        switch(siz) {
                                case 5:
                                        *d++ = *s++;
-                                       /*fall through*/
+                                       FALL_THROUGH;
                                case 4:
                                        *d++ = *s++;
-                                       /*fall through*/
+                                       FALL_THROUGH;
                                case 3:
                                        *d++ = *s++;
-                                       /*fall through*/
+                                       FALL_THROUGH;
                                case 2:
                                        *d++ = *s++;
-                                       /*fall through*/
+                                       FALL_THROUGH;
                                case 1:
                                        *d++ = *s++;
                                        break;
@@ -252,15 +254,17 @@ NTSTATUS check_path_syntax_posix(char *path)
 
 /****************************************************************************
  Pull a string and check the path allowing a wilcard - provide for error return.
+ Passes in posix flag.
 ****************************************************************************/
 
-size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
+static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
                        const char *base_ptr,
-                       uint16 smb_flags2,
+                       uint16_t smb_flags2,
                        char **pp_dest,
                        const char *src,
                        size_t src_len,
                        int flags,
+                       bool posix_pathnames,
                        NTSTATUS *err,
                        bool *contains_wcard)
 {
@@ -287,7 +291,7 @@ size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
                return ret;
        }
 
-       if (lp_posix_pathnames()) {
+       if (posix_pathnames) {
                *err = check_path_syntax_posix(*pp_dest);
        } else {
                *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
@@ -296,13 +300,66 @@ size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
        return ret;
 }
 
+/****************************************************************************
+ Pull a string and check the path allowing a wilcard - provide for error return.
+****************************************************************************/
+
+size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
+                       const char *base_ptr,
+                       uint16_t smb_flags2,
+                       char **pp_dest,
+                       const char *src,
+                       size_t src_len,
+                       int flags,
+                       NTSTATUS *err,
+                       bool *contains_wcard)
+{
+       return srvstr_get_path_wcard_internal(ctx,
+                       base_ptr,
+                       smb_flags2,
+                       pp_dest,
+                       src,
+                       src_len,
+                       flags,
+                       false,
+                       err,
+                       contains_wcard);
+}
+
+/****************************************************************************
+ Pull a string and check the path allowing a wilcard - provide for error return.
+ posix_pathnames version.
+****************************************************************************/
+
+size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
+                       const char *base_ptr,
+                       uint16_t smb_flags2,
+                       char **pp_dest,
+                       const char *src,
+                       size_t src_len,
+                       int flags,
+                       NTSTATUS *err,
+                       bool *contains_wcard)
+{
+       return srvstr_get_path_wcard_internal(ctx,
+                       base_ptr,
+                       smb_flags2,
+                       pp_dest,
+                       src,
+                       src_len,
+                       flags,
+                       true,
+                       err,
+                       contains_wcard);
+}
+
 /****************************************************************************
  Pull a string and check the path - provide for error return.
 ****************************************************************************/
 
 size_t srvstr_get_path(TALLOC_CTX *ctx,
                        const char *base_ptr,
-                       uint16 smb_flags2,
+                       uint16_t smb_flags2,
                        char **pp_dest,
                        const char *src,
                        size_t src_len,
@@ -310,10 +367,46 @@ size_t srvstr_get_path(TALLOC_CTX *ctx,
                        NTSTATUS *err)
 {
        bool ignore;
-       return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
-                                    src_len, flags, err, &ignore);
+       return srvstr_get_path_wcard_internal(ctx,
+                       base_ptr,
+                       smb_flags2,
+                       pp_dest,
+                       src,
+                       src_len,
+                       flags,
+                       false,
+                       err,
+                       &ignore);
 }
 
+/****************************************************************************
+ Pull a string and check the path - provide for error return.
+ posix_pathnames version.
+****************************************************************************/
+
+size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
+                       const char *base_ptr,
+                       uint16_t smb_flags2,
+                       char **pp_dest,
+                       const char *src,
+                       size_t src_len,
+                       int flags,
+                       NTSTATUS *err)
+{
+       bool ignore;
+       return srvstr_get_path_wcard_internal(ctx,
+                       base_ptr,
+                       smb_flags2,
+                       pp_dest,
+                       src,
+                       src_len,
+                       flags,
+                       true,
+                       err,
+                       &ignore);
+}
+
+
 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
                                 char **pp_dest, const char *src, int flags,
                                 NTSTATUS *err, bool *contains_wcard)
@@ -325,9 +418,29 @@ size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
                return 0;
        }
 
-       return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf,
-                                    req->flags2, pp_dest, src, bufrem, flags,
-                                    err, contains_wcard);
+       if (req->posix_pathnames) {
+               return srvstr_get_path_wcard_internal(mem_ctx,
+                               (const char *)req->inbuf,
+                               req->flags2,
+                               pp_dest,
+                               src,
+                               bufrem,
+                               flags,
+                               true,
+                               err,
+                               contains_wcard);
+       } else {
+               return srvstr_get_path_wcard_internal(mem_ctx,
+                               (const char *)req->inbuf,
+                               req->flags2,
+                               pp_dest,
+                               src,
+                               bufrem,
+                               flags,
+                               false,
+                               err,
+                               contains_wcard);
+       }
 }
 
 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
@@ -428,7 +541,7 @@ bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
        return true;
 }
 
-static bool netbios_session_retarget(struct smbd_server_connection *sconn,
+static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
                                     const char *name, int name_type)
 {
        char *trim_name;
@@ -443,7 +556,7 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn,
        bool ret = false;
        uint8_t outbuf[10];
 
-       if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
+       if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
                return false;
        }
 
@@ -508,7 +621,7 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn,
        *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
        *(uint16_t *)(outbuf+8) = htons(retarget_port);
 
-       if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
+       if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
                          NULL)) {
                exit_server_cleanly("netbios_session_retarget: srv_send_smb "
                                    "failed.");
@@ -531,8 +644,9 @@ static void reply_called_name_not_present(char *outbuf)
  Reply to a (netbios-level) special message. 
 ****************************************************************************/
 
-void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
+void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
 {
+       struct smbd_server_connection *sconn = xconn->client->sconn;
        int msg_type = CVAL(inbuf,0);
        int msg_flags = CVAL(inbuf,1);
        /*
@@ -556,7 +670,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
 
                *name1 = *name2 = 0;
 
-               if (sconn->nbt.got_session) {
+               if (xconn->transport.nbt.got_session) {
                        exit_server_cleanly("multiple session request not permitted");
                }
 
@@ -591,7 +705,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
                DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
                         name1, name_type1, name2, name_type2));
 
-               if (netbios_session_retarget(sconn, name1, name_type1)) {
+               if (netbios_session_retarget(xconn, name1, name_type1)) {
                        exit_server_cleanly("retargeted client");
                }
 
@@ -625,7 +739,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
                        if (sconn->remote_hostname == NULL) {
                                exit_server_cleanly("could not copy remote name");
                        }
-                       sconn->conn->remote_hostname = sconn->remote_hostname;
+                       xconn->remote_hostname = sconn->remote_hostname;
                }
 
                DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
@@ -642,7 +756,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
                reload_services(sconn, conn_snum_used, true);
                reopen_logs();
 
-               sconn->nbt.got_session = true;
+               xconn->transport.nbt.got_session = true;
                break;
        }
 
@@ -666,7 +780,9 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
 
-       srv_send_smb(sconn, outbuf, false, 0, false, NULL);
+       if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
+               exit_server_cleanly("reply_special: srv_send_smb failed.");
+       }
 
        if (CVAL(outbuf, 0) != 0x82) {
                exit_server_cleanly("invalid netbios session");
@@ -691,7 +807,7 @@ void reply_tcon(struct smb_request *req)
        const uint8_t *p;
        const char *p2;
        TALLOC_CTX *ctx = talloc_tos();
-       struct smbd_server_connection *sconn = req->sconn;
+       struct smbXsrv_connection *xconn = req->xconn;
        NTTIME now = timeval_to_nttime(&req->request_time);
 
        START_PROFILE(SMBtcon);
@@ -722,7 +838,7 @@ void reply_tcon(struct smb_request *req)
                service = service_buf;
        }
 
-       conn = make_connection(sconn, now, service, dev,
+       conn = make_connection(req, now, service, dev,
                               req->vuid,&nt_status);
        req->conn = conn;
 
@@ -733,7 +849,7 @@ void reply_tcon(struct smb_request *req)
        }
 
        reply_outbuf(req, 2, 0);
-       SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
+       SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
        SSVAL(req->outbuf,smb_vwv1,conn->cnum);
        SSVAL(req->outbuf,smb_tid,conn->cnum);
 
@@ -754,7 +870,7 @@ void reply_tcon_and_X(struct smb_request *req)
        connection_struct *conn = req->conn;
        const char *service = NULL;
        TALLOC_CTX *ctx = talloc_tos();
-       /* what the cleint thinks the device is */
+       /* what the client thinks the device is */
        char *client_devicetype = NULL;
        /* what the server tells the client the share represents */
        const char *server_devicetype;
@@ -768,7 +884,7 @@ void reply_tcon_and_X(struct smb_request *req)
        NTTIME now = timeval_to_nttime(&req->request_time);
        bool session_key_updated = false;
        uint16_t optional_support = 0;
-       struct smbd_server_connection *sconn = req->sconn;
+       struct smbXsrv_connection *xconn = req->xconn;
 
        START_PROFILE(SMBtconX);
 
@@ -808,6 +924,11 @@ void reply_tcon_and_X(struct smb_request *req)
                }
 
                TALLOC_FREE(tcon);
+               /*
+                * This tree id is gone. Make sure we can't re-use it
+                * by accident.
+                */
+               req->tid = 0;
        }
 
        if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
@@ -816,7 +937,7 @@ void reply_tcon_and_X(struct smb_request *req)
                return;
        }
 
-       if (sconn->smb1.negprot.encrypted_passwords) {
+       if (xconn->smb1.negprot.encrypted_passwords) {
                p = req->buf + passlen;
        } else {
                p = req->buf + passlen + 1;
@@ -858,7 +979,7 @@ void reply_tcon_and_X(struct smb_request *req)
 
        DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
 
-       nt_status = smb1srv_session_lookup(req->sconn->conn,
+       nt_status = smb1srv_session_lookup(xconn,
                                           req->vuid, now, &session);
        if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
                reply_force_doserror(req, ERRSRV, ERRbaduid);
@@ -939,7 +1060,7 @@ void reply_tcon_and_X(struct smb_request *req)
                session_key_updated = true;
        }
 
-       conn = make_connection(sconn, now, service, client_devicetype,
+       conn = make_connection(req, now, service, client_devicetype,
                               req->vuid, &nt_status);
        req->conn =conn;
 
@@ -977,8 +1098,8 @@ void reply_tcon_and_X(struct smb_request *req)
 
                if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
                        /* Return permissions. */
-                       uint32 perm1 = 0;
-                       uint32 perm2 = 0;
+                       uint32_t perm1 = 0;
+                       uint32_t perm2 = 0;
 
                        reply_outbuf(req, 7, 0);
 
@@ -1038,7 +1159,7 @@ void reply_tcon_and_X(struct smb_request *req)
  Reply to an unknown type.
 ****************************************************************************/
 
-void reply_unknown_new(struct smb_request *req, uint8 type)
+void reply_unknown_new(struct smb_request *req, uint8_t type)
 {
        DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
                  smb_fn_name(type), type, type));
@@ -1054,9 +1175,9 @@ void reply_unknown_new(struct smb_request *req, uint8 type)
 void reply_ioctl(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
-       uint16 device;
-       uint16 function;
-       uint32 ioctl_code;
+       uint16_t device;
+       uint16_t function;
+       uint32_t ioctl_code;
        int replysize;
        char *p;
 
@@ -1095,6 +1216,8 @@ void reply_ioctl(struct smb_request *req)
        switch (ioctl_code) {
                case IOCTL_QUERY_JOB_INFO:                  
                {
+                       NTSTATUS status;
+                       size_t len = 0;
                        files_struct *fsp = file_fsp(
                                req, SVAL(req->vwv+0, 0));
                        if (!fsp) {
@@ -1105,15 +1228,25 @@ void reply_ioctl(struct smb_request *req)
                        /* Job number */
                        SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
 
-                       srvstr_push((char *)req->outbuf, req->flags2, p+2,
+                       status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
                                    lp_netbios_name(), 15,
-                                   STR_TERMINATE|STR_ASCII);
+                                   STR_TERMINATE|STR_ASCII, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               reply_nterror(req, status);
+                               END_PROFILE(SMBioctl);
+                               return;
+                       }
                        if (conn) {
-                               srvstr_push((char *)req->outbuf, req->flags2,
+                               status = srvstr_push((char *)req->outbuf, req->flags2,
                                            p+18,
                                            lp_servicename(talloc_tos(),
                                                           SNUM(conn)),
-                                           13, STR_TERMINATE|STR_ASCII);
+                                           13, STR_TERMINATE|STR_ASCII, &len);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       reply_nterror(req, status);
+                                       END_PROFILE(SMBioctl);
+                                       return;
+                               }
                        } else {
                                memset(p+18, 0, 13);
                        }
@@ -1151,6 +1284,7 @@ void reply_checkpath(struct smb_request *req)
        struct smb_filename *smb_fname = NULL;
        char *name = NULL;
        NTSTATUS status;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBcheckpath);
@@ -1169,9 +1303,8 @@ void reply_checkpath(struct smb_request *req)
 
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                name,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
 
@@ -1265,11 +1398,11 @@ void reply_getatr(struct smb_request *req)
                size = 0;
                mtime = 0;
        } else {
+               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
                status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
@@ -1319,7 +1452,7 @@ void reply_getatr(struct smb_request *req)
        } else {
                srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
        }
-       SIVAL(req->outbuf,smb_vwv3,(uint32)size);
+       SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
 
        if (get_Protocol() >= PROTOCOL_NT1) {
                SSVAL(req->outbuf, smb_flg2,
@@ -1350,6 +1483,7 @@ void reply_setatr(struct smb_request *req)
        time_t mtime;
        const char *p;
        NTSTATUS status;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBsetatr);
@@ -1370,9 +1504,8 @@ void reply_setatr(struct smb_request *req)
 
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               0,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1442,15 +1575,45 @@ void reply_setatr(struct smb_request *req)
 void reply_dskattr(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
+       uint64_t ret;
        uint64_t dfree,dsize,bsize;
+       struct smb_filename smb_fname;
        START_PROFILE(SMBdskattr);
 
-       if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+       ZERO_STRUCT(smb_fname);
+       smb_fname.base_name = discard_const_p(char, ".");
+
+       if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
+               reply_nterror(req, map_nt_error_from_unix(errno));
+               DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
+               END_PROFILE(SMBdskattr);
+               return;
+       }
+
+       ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
+       if (ret == (uint64_t)-1) {
                reply_nterror(req, map_nt_error_from_unix(errno));
                END_PROFILE(SMBdskattr);
                return;
        }
 
+       /*
+        * Force max to fit in 16 bit fields.
+        */
+       while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
+               dfree /= 2;
+               dsize /= 2;
+               bsize *= 2;
+               if (bsize > (WORDMAX*512)) {
+                       bsize = (WORDMAX*512);
+                       if (dsize > WORDMAX)
+                               dsize = WORDMAX;
+                       if (dfree >  WORDMAX)
+                               dfree = WORDMAX;
+                       break;
+               }
+       }
+
        reply_outbuf(req, 5, 0);
 
        if (get_Protocol() <= PROTOCOL_LANMAN2) {
@@ -1519,6 +1682,52 @@ static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
        return NT_STATUS_OK;
 }
 
+/****************************************************************************
+ Make a dir struct.
+****************************************************************************/
+
+static bool make_dir_struct(TALLOC_CTX *ctx,
+                           char *buf,
+                           const char *mask,
+                           const char *fname,
+                           off_t size,
+                           uint32_t mode,
+                           time_t date,
+                           bool uc)
+{
+       char *p;
+       char *mask2 = talloc_strdup(ctx, mask);
+
+       if (!mask2) {
+               return False;
+       }
+
+       if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+               size = 0;
+       }
+
+       memset(buf+1,' ',11);
+       if ((p = strchr_m(mask2,'.')) != NULL) {
+               *p = 0;
+               push_ascii(buf+1,mask2,8, 0);
+               push_ascii(buf+9,p+1,3, 0);
+               *p = '.';
+       } else {
+               push_ascii(buf+1,mask2,11, 0);
+       }
+
+       memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
+       SCVAL(buf,21,mode);
+       srv_put_dos_date(buf,22,date);
+       SSVAL(buf,26,size & 0xFFFF);
+       SSVAL(buf,28,(size >> 16)&0xFFFF);
+       /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
+          Strange, but verified on W2K3. Needed for OS/2. JRA. */
+       push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
+       DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
+       return True;
+}
+
 /****************************************************************************
  Reply to a search.
  Can be called from SMBsearch, SMBffirst or SMBfunique.
@@ -1528,14 +1737,14 @@ void reply_search(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
        char *path = NULL;
-       const char *mask = NULL;
+       char *mask = NULL;
        char *directory = NULL;
        struct smb_filename *smb_fname = NULL;
        char *fname = NULL;
        off_t size;
-       uint32 mode;
+       uint32_t mode;
        struct timespec date;
-       uint32 dirtype;
+       uint32_t dirtype;
        unsigned int numentries = 0;
        unsigned int maxentries = 0;
        bool finished = False;
@@ -1551,6 +1760,7 @@ void reply_search(struct smb_request *req)
        TALLOC_CTX *ctx = talloc_tos();
        bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
        struct dptr_struct *dirptr = NULL;
+       struct smbXsrv_connection *xconn = req->xconn;
        struct smbd_server_connection *sconn = req->sconn;
 
        START_PROFILE(SMBsearch);
@@ -1560,7 +1770,7 @@ void reply_search(struct smb_request *req)
                goto out;
        }
 
-       if (lp_posix_pathnames()) {
+       if (req->posix_pathnames) {
                reply_unknown_new(req, req->cmd);
                goto out;
        }
@@ -1588,10 +1798,12 @@ void reply_search(struct smb_request *req)
        /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
 
        if (status_len == 0) {
+               struct smb_filename *smb_dname = NULL;
+               uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
+                       ucf_flags_from_smb_request(req);
                nt_status = filename_convert(ctx, conn,
-                                            req->flags2 & FLAGS2_DFS_PATHNAMES,
                                             path,
-                                            UCF_ALWAYS_ALLOW_WCARD_LCOMP,
+                                            ucf_flags,
                                             &mask_contains_wcard,
                                             &smb_fname);
                if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1608,11 +1820,11 @@ void reply_search(struct smb_request *req)
 
                p = strrchr_m(directory,'/');
                if ((p != NULL) && (*directory != '/')) {
-                       mask = p + 1;
+                       mask = talloc_strdup(ctx, p + 1);
                        directory = talloc_strndup(ctx, directory,
                                                   PTR_DIFF(p, directory));
                } else {
-                       mask = directory;
+                       mask = talloc_strdup(ctx, directory);
                        directory = talloc_strdup(ctx,".");
                }
 
@@ -1624,10 +1836,20 @@ void reply_search(struct smb_request *req)
                memset((char *)status,'\0',21);
                SCVAL(status,0,(dirtype & 0x1F));
 
+               smb_dname = synthetic_smb_fname(talloc_tos(),
+                                       directory,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->flags);
+               if (smb_dname == NULL) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       goto out;
+               }
+
                nt_status = dptr_create(conn,
                                        NULL, /* req */
                                        NULL, /* fsp */
-                                       directory,
+                                       smb_dname,
                                        True,
                                        expect_close,
                                        req->smbpid,
@@ -1635,6 +1857,9 @@ void reply_search(struct smb_request *req)
                                        mask_contains_wcard,
                                        dirtype,
                                        &dirptr);
+
+               TALLOC_FREE(smb_dname);
+
                if (!NT_STATUS_IS_OK(nt_status)) {
                        reply_nterror(req, nt_status);
                        goto out;
@@ -1661,7 +1886,7 @@ void reply_search(struct smb_request *req)
                        goto out;
                }
 
-               mask = dptr_wcard(sconn, dptr_num);
+               mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
                if (!mask) {
                        goto SearchEmpty;
                }
@@ -1669,15 +1894,14 @@ void reply_search(struct smb_request *req)
                 * For a 'continue' search we have no string. So
                 * check from the initial saved string.
                 */
-               mask_contains_wcard = ms_has_wild(mask);
+               if (!req->posix_pathnames) {
+                       mask_contains_wcard = ms_has_wild(mask);
+               }
                dirtype = dptr_attr(sconn, dptr_num);
        }
 
        DEBUG(4,("dptr_num is %d\n",dptr_num));
 
-       /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
-       dptr_init_search_op(dirptr);
-
        if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
                char buf[DIR_STRUCT_SIZE];
                memcpy(buf,status,21);
@@ -1701,7 +1925,7 @@ void reply_search(struct smb_request *req)
        } else {
                unsigned int i;
                size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
-               size_t available_space = sconn->smb1.sessions.max_send - hdr_size;
+               size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
 
                maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
 
@@ -1800,6 +2024,7 @@ void reply_search(struct smb_request *req)
                maxentries ));
  out:
        TALLOC_FREE(directory);
+       TALLOC_FREE(mask);
        TALLOC_FREE(smb_fname);
        END_PROFILE(SMBsearch);
        return;
@@ -1823,7 +2048,7 @@ void reply_fclose(struct smb_request *req)
 
        START_PROFILE(SMBfclose);
 
-       if (lp_posix_pathnames()) {
+       if (req->posix_pathnames) {
                reply_unknown_new(req, req->cmd);
                END_PROFILE(SMBfclose);
                return;
@@ -1872,20 +2097,21 @@ void reply_open(struct smb_request *req)
        connection_struct *conn = req->conn;
        struct smb_filename *smb_fname = NULL;
        char *fname = NULL;
-       uint32 fattr=0;
+       uint32_t fattr=0;
        off_t size = 0;
        time_t mtime=0;
        int info;
        files_struct *fsp;
        int oplock_request;
        int deny_mode;
-       uint32 dos_attr;
-       uint32 access_mask;
-       uint32 share_mode;
-       uint32 create_disposition;
-       uint32 create_options = 0;
+       uint32_t dos_attr;
+       uint32_t access_mask;
+       uint32_t share_mode;
+       uint32_t create_disposition;
+       uint32_t create_options = 0;
        uint32_t private_flags = 0;
        NTSTATUS status;
+       uint32_t ucf_flags;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBopen);
@@ -1914,11 +2140,12 @@ void reply_open(struct smb_request *req)
                goto out;
        }
 
+       ucf_flags = filename_create_ucf_flags(req, create_disposition);
+
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               UCF_PREP_CREATEFILE,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1943,15 +2170,17 @@ void reply_open(struct smb_request *req)
                create_options,                         /* create_options */
                dos_attr,                               /* file_attributes */
                oplock_request,                         /* oplock_request */
+               NULL,                                   /* lease */
                0,                                      /* allocation_size */
                private_flags,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               &info);                                 /* pinfo */
+               &info,                                  /* pinfo */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -1985,7 +2214,7 @@ void reply_open(struct smb_request *req)
        } else {
                srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
        }
-       SIVAL(req->outbuf,smb_vwv4,(uint32)size);
+       SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
        SSVAL(req->outbuf,smb_vwv6,deny_mode);
 
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
@@ -2011,9 +2240,9 @@ void reply_open_and_X(struct smb_request *req)
        connection_struct *conn = req->conn;
        struct smb_filename *smb_fname = NULL;
        char *fname = NULL;
-       uint16 open_flags;
+       uint16_t open_flags;
        int deny_mode;
-       uint32 smb_attr;
+       uint32_t smb_attr;
        /* Breakout the oplock request bits so we can set the
                reply bits separately. */
        int ex_oplock_request;
@@ -2021,21 +2250,22 @@ void reply_open_and_X(struct smb_request *req)
        int oplock_request;
 #if 0
        int smb_sattr = SVAL(req->vwv+4, 0);
-       uint32 smb_time = make_unix_date3(req->vwv+6);
+       uint32_t smb_time = make_unix_date3(req->vwv+6);
 #endif
        int smb_ofun;
-       uint32 fattr=0;
+       uint32_t fattr=0;
        int mtime=0;
        int smb_action = 0;
        files_struct *fsp;
        NTSTATUS status;
        uint64_t allocation_size;
        ssize_t retval = -1;
-       uint32 access_mask;
-       uint32 share_mode;
-       uint32 create_disposition;
-       uint32 create_options = 0;
+       uint32_t access_mask;
+       uint32_t share_mode;
+       uint32_t create_disposition;
+       uint32_t create_options = 0;
        uint32_t private_flags = 0;
+       uint32_t ucf_flags;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBopenX);
@@ -2082,11 +2312,12 @@ void reply_open_and_X(struct smb_request *req)
                goto out;
        }
 
+       ucf_flags = filename_create_ucf_flags(req, create_disposition);
+
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               UCF_PREP_CREATEFILE,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2111,15 +2342,17 @@ void reply_open_and_X(struct smb_request *req)
                create_options,                         /* create_options */
                smb_attr,                               /* file_attributes */
                oplock_request,                         /* oplock_request */
+               NULL,                                   /* lease */
                0,                                      /* allocation_size */
                private_flags,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               &smb_action);                           /* pinfo */
+               &smb_action,                            /* pinfo */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -2202,7 +2435,7 @@ void reply_open_and_X(struct smb_request *req)
        } else {
                srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
        }
-       SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
+       SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
        SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
        SSVAL(req->outbuf,smb_vwv11,smb_action);
 
@@ -2283,15 +2516,16 @@ void reply_mknew(struct smb_request *req)
        connection_struct *conn = req->conn;
        struct smb_filename *smb_fname = NULL;
        char *fname = NULL;
-       uint32 fattr = 0;
+       uint32_t fattr = 0;
        struct smb_file_time ft;
        files_struct *fsp;
        int oplock_request = 0;
        NTSTATUS status;
-       uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
-       uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
-       uint32 create_disposition;
-       uint32 create_options = 0;
+       uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+       uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+       uint32_t create_disposition;
+       uint32_t create_options = 0;
+       uint32_t ucf_flags;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBcreate);
@@ -2305,6 +2539,14 @@ void reply_mknew(struct smb_request *req)
        fattr = SVAL(req->vwv+0, 0);
        oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
 
+       if (req->cmd == SMBmknew) {
+               /* We should fail if file exists. */
+               create_disposition = FILE_CREATE;
+       } else {
+               /* Create if file doesn't exist, truncate if it does. */
+               create_disposition = FILE_OVERWRITE_IF;
+       }
+
        /* mtime. */
        ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
 
@@ -2315,11 +2557,11 @@ void reply_mknew(struct smb_request *req)
                goto out;
        }
 
+       ucf_flags = filename_create_ucf_flags(req, create_disposition);
        status = filename_convert(ctx,
                                conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               UCF_PREP_CREATEFILE,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2339,14 +2581,6 @@ void reply_mknew(struct smb_request *req)
                         smb_fname_str_dbg(smb_fname)));
        }
 
-       if(req->cmd == SMBmknew) {
-               /* We should fail if file exists. */
-               create_disposition = FILE_CREATE;
-       } else {
-               /* Create if file doesn't exist, truncate if it does. */
-               create_disposition = FILE_OVERWRITE_IF;
-       }
-
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
@@ -2358,15 +2592,17 @@ void reply_mknew(struct smb_request *req)
                create_options,                         /* create_options */
                fattr,                                  /* file_attributes */
                oplock_request,                         /* oplock_request */
+               NULL,                                   /* lease */
                0,                                      /* allocation_size */
                0,                                      /* private_flags */
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               NULL);                                  /* pinfo */
+               NULL,                                   /* pinfo */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -2415,12 +2651,13 @@ void reply_ctemp(struct smb_request *req)
        struct smb_filename *smb_fname = NULL;
        char *wire_name = NULL;
        char *fname = NULL;
-       uint32 fattr;
+       uint32_t fattr;
        files_struct *fsp;
        int oplock_request;
        char *s;
        NTSTATUS status;
        int i;
+       uint32_t ucf_flags;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBctemp);
@@ -2457,10 +2694,10 @@ void reply_ctemp(struct smb_request *req)
                        goto out;
                }
 
+               ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
                status = filename_convert(ctx, conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
                                fname,
-                               UCF_PREP_CREATEFILE,
+                               ucf_flags,
                                NULL,
                                &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
@@ -2485,12 +2722,14 @@ void reply_ctemp(struct smb_request *req)
                        0,                                      /* create_options */
                        fattr,                                  /* file_attributes */
                        oplock_request,                         /* oplock_request */
+                       NULL,                                   /* lease */
                        0,                                      /* allocation_size */
                        0,                                      /* private_flags */
                        NULL,                                   /* sd */
                        NULL,                                   /* ea_list */
                        &fsp,                                   /* result */
-                       NULL);                                  /* pinfo */
+                       NULL,                                   /* pinfo */
+                       NULL, NULL);                            /* create context */
 
                if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
                        TALLOC_FREE(fname);
@@ -2499,7 +2738,7 @@ void reply_ctemp(struct smb_request *req)
                }
 
                if (!NT_STATUS_IS_OK(status)) {
-                       if (open_was_deferred(req->sconn, req->mid)) {
+                       if (open_was_deferred(req->xconn, req->mid)) {
                                /* We have re-scheduled this call. */
                                goto out;
                        }
@@ -2563,7 +2802,7 @@ void reply_ctemp(struct smb_request *req)
 ********************************************************************/
 
 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
-                       uint16 dirtype)
+                       uint16_t dirtype)
 {
        if (!CAN_WRITE(conn)) {
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
@@ -2572,7 +2811,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
        if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
                        (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
                /* Only bother to read the DOS attribute if we might deny the
-                  rename on the grounds of attribute missmatch. */
+                  rename on the grounds of attribute mismatch. */
                uint32_t fmode = dos_mode(conn, fsp->fsp_name);
                if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
                        return NT_STATUS_NO_SUCH_FILE;
@@ -2580,14 +2819,24 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
        }
 
        if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
-               if (fsp->posix_open) {
+               if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
                        return NT_STATUS_OK;
                }
 
                /* If no pathnames are open below this
                   directory, allow the rename. */
 
-               if (file_find_subpath(fsp)) {
+               if (lp_strict_rename(SNUM(conn))) {
+                       /*
+                        * Strict rename, check open file db.
+                        */
+                       if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
+                               return NT_STATUS_ACCESS_DENIED;
+                       }
+               } else if (file_find_subpath(fsp)) {
+                       /*
+                        * No strict rename, just look in local process.
+                        */
                        return NT_STATUS_ACCESS_DENIED;
                }
                return NT_STATUS_OK;
@@ -2607,14 +2856,14 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
 static NTSTATUS do_unlink(connection_struct *conn,
                        struct smb_request *req,
                        struct smb_filename *smb_fname,
-                       uint32 dirtype)
+                       uint32_t dirtype)
 {
-       uint32 fattr;
+       uint32_t fattr;
        files_struct *fsp;
-       uint32 dirtype_orig = dirtype;
+       uint32_t dirtype_orig = dirtype;
        NTSTATUS status;
        int ret;
-       bool posix_paths = lp_posix_pathnames();
+       bool posix_paths = (req != NULL && req->posix_pathnames);
 
        DEBUG(10,("do_unlink: %s, dirtype = %d\n",
                  smb_fname_str_dbg(smb_fname),
@@ -2702,12 +2951,14 @@ static NTSTATUS do_unlink(connection_struct *conn,
                 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
                                FILE_ATTRIBUTE_NORMAL,
                 0,                     /* oplock_request */
+                NULL,                  /* lease */
                 0,                     /* allocation_size */
                 0,                     /* private_flags */
                 NULL,                  /* sd */
                 NULL,                  /* ea_list */
                 &fsp,                  /* result */
-                NULL);                 /* pinfo */
+                NULL,                  /* pinfo */
+                NULL, NULL);           /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
@@ -2742,13 +2993,14 @@ static NTSTATUS do_unlink(connection_struct *conn,
 ****************************************************************************/
 
 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
-                         uint32 dirtype, struct smb_filename *smb_fname,
+                         uint32_t dirtype, struct smb_filename *smb_fname,
                          bool has_wild)
 {
        char *fname_dir = NULL;
        char *fname_mask = NULL;
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
+       struct smb_filename *smb_fname_dir = NULL;
        TALLOC_CTX *ctx = talloc_tos();
 
        /* Split up the directory from the filename/mask. */
@@ -2804,7 +3056,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        dirtype = FILE_ATTRIBUTE_NORMAL;
                }
 
-               status = check_name(conn, smb_fname->base_name);
+               status = check_name(conn, smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        goto out;
                }
@@ -2825,6 +3077,9 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        status = NT_STATUS_OBJECT_NAME_INVALID;
                        goto out;
                }
+               if (dirtype == 0) {
+                       dirtype = FILE_ATTRIBUTE_NORMAL;
+               }
 
                if (strequal(fname_mask,"????????.???")) {
                        TALLOC_FREE(fname_mask);
@@ -2835,12 +3090,22 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        }
                }
 
-               status = check_name(conn, fname_dir);
+               smb_fname_dir = synthetic_smb_fname(talloc_tos(),
+                                       fname_dir,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->flags);
+               if (smb_fname_dir == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto out;
+               }
+
+               status = check_name(conn, smb_fname_dir);
                if (!NT_STATUS_IS_OK(status)) {
                        goto out;
                }
 
-               dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
+               dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
                                  dirtype);
                if (dir_hnd == NULL) {
                        status = map_nt_error_from_unix(errno);
@@ -2899,7 +3164,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                                goto out;
                        }
 
-                       status = check_name(conn, smb_fname->base_name);
+                       status = check_name(conn, smb_fname);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(frame);
@@ -2930,6 +3195,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
        }
 
  out:
+       TALLOC_FREE(smb_fname_dir);
        TALLOC_FREE(fname_dir);
        TALLOC_FREE(fname_mask);
        return status;
@@ -2944,9 +3210,11 @@ void reply_unlink(struct smb_request *req)
        connection_struct *conn = req->conn;
        char *name = NULL;
        struct smb_filename *smb_fname = NULL;
-       uint32 dirtype;
+       uint32_t dirtype;
        NTSTATUS status;
        bool path_contains_wcard = False;
+       uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
+                       ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBunlink);
@@ -2967,9 +3235,8 @@ void reply_unlink(struct smb_request *req)
        }
 
        status = filename_convert(ctx, conn,
-                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
                                  name,
-                                 UCF_COND_ALLOW_WCARD_LCOMP,
+                                 ucf_flags,
                                  &path_contains_wcard,
                                  &smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2987,7 +3254,7 @@ void reply_unlink(struct smb_request *req)
        status = unlink_internals(conn, req, dirtype, smb_fname,
                                  path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -3021,7 +3288,8 @@ static void fail_readraw(void)
  Fake (read/write) sendfile. Returns -1 on read or write fail.
 ****************************************************************************/
 
-ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
+ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
+                     off_t startpos, size_t nread)
 {
        size_t bufsize;
        size_t tosend = nread;
@@ -3041,11 +3309,7 @@ ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
                ssize_t ret;
                size_t cur_read;
 
-               if (tosend > bufsize) {
-                       cur_read = bufsize;
-               } else {
-                       cur_read = tosend;
-               }
+               cur_read = MIN(tosend, bufsize);
                ret = read_file(fsp,buf,startpos,cur_read);
                if (ret == -1) {
                        SAFE_FREE(buf);
@@ -3057,19 +3321,19 @@ ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
                        memset(buf + ret, '\0', cur_read - ret);
                }
 
-               if (write_data(fsp->conn->sconn->sock, buf, cur_read)
-                   != cur_read) {
-                       char addr[INET6_ADDRSTRLEN];
+               ret = write_data(xconn->transport.sock, buf, cur_read);
+               if (ret != cur_read) {
+                       int saved_errno = errno;
                        /*
                         * Try and give an error message saying what
                         * client failed.
                         */
                        DEBUG(0, ("write_data failed for client %s. "
                                  "Error %s\n",
-                                 get_peer_addr(fsp->conn->sconn->sock, addr,
-                                               sizeof(addr)),
-                                 strerror(errno)));
+                                 smbXsrv_connection_dbg(xconn),
+                                 strerror(saved_errno)));
                        SAFE_FREE(buf);
+                       errno = saved_errno;
                        return -1;
                }
                tosend -= cur_read;
@@ -3082,20 +3346,21 @@ ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
 
 /****************************************************************************
  Deal with the case of sendfile reading less bytes from the file than
- requested. Fill with zeros (all we can do).
+ requested. Fill with zeros (all we can do). Returns 0 on success
 ****************************************************************************/
 
-void sendfile_short_send(files_struct *fsp,
-                               ssize_t nread,
-                               size_t headersize,
-                               size_t smb_maxcnt)
+ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
+                           files_struct *fsp,
+                           ssize_t nread,
+                           size_t headersize,
+                           size_t smb_maxcnt)
 {
 #define SHORT_SEND_BUFSIZE 1024
        if (nread < headersize) {
                DEBUG(0,("sendfile_short_send: sendfile failed to send "
                        "header for file %s (%s). Terminating\n",
                        fsp_str_dbg(fsp), strerror(errno)));
-               exit_server_cleanly("sendfile_short_send failed");
+               return -1;
        }
 
        nread -= headersize;
@@ -3103,8 +3368,10 @@ void sendfile_short_send(files_struct *fsp,
        if (nread < smb_maxcnt) {
                char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
                if (!buf) {
-                       exit_server_cleanly("sendfile_short_send: "
-                               "malloc failed");
+                       DEBUG(0,("sendfile_short_send: malloc failed "
+                               "for file %s (%s). Terminating\n",
+                               fsp_str_dbg(fsp), strerror(errno)));
+                       return -1;
                }
 
                DEBUG(0,("sendfile_short_send: filling truncated file %s "
@@ -3126,55 +3393,57 @@ void sendfile_short_send(files_struct *fsp,
                         * about efficiency here :-)
                         */
                        size_t to_write;
+                       ssize_t ret;
 
                        to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
-                       if (write_data(fsp->conn->sconn->sock, buf, to_write)
-                           != to_write) {
-                               char addr[INET6_ADDRSTRLEN];
+                       ret = write_data(xconn->transport.sock, buf, to_write);
+                       if (ret != to_write) {
+                               int saved_errno = errno;
                                /*
                                 * Try and give an error message saying what
                                 * client failed.
                                 */
                                DEBUG(0, ("write_data failed for client %s. "
                                          "Error %s\n",
-                                         get_peer_addr(
-                                                 fsp->conn->sconn->sock, addr,
-                                                 sizeof(addr)),
-                                         strerror(errno)));
-                               exit_server_cleanly("sendfile_short_send: "
-                                                   "write_data failed");
+                                         smbXsrv_connection_dbg(xconn),
+                                         strerror(saved_errno)));
+                               errno = saved_errno;
+                               return -1;
                        }
                        nread += to_write;
                }
                SAFE_FREE(buf);
        }
+
+       return 0;
 }
 
 /****************************************************************************
  Return a readbraw error (4 bytes of zero).
 ****************************************************************************/
 
-static void reply_readbraw_error(struct smbd_server_connection *sconn)
+static void reply_readbraw_error(struct smbXsrv_connection *xconn)
 {
        char header[4];
 
        SIVAL(header,0,0);
 
-       smbd_lock_socket(sconn);
-       if (write_data(sconn->sock,header,4) != 4) {
-               char addr[INET6_ADDRSTRLEN];
+       smbd_lock_socket(xconn);
+       if (write_data(xconn->transport.sock,header,4) != 4) {
+               int saved_errno = errno;
                /*
                 * Try and give an error message saying what
                 * client failed.
                 */
                DEBUG(0, ("write_data failed for client %s. "
                          "Error %s\n",
-                         get_peer_addr(sconn->sock, addr, sizeof(addr)),
-                         strerror(errno)));
+                         smbXsrv_connection_dbg(xconn),
+                         strerror(saved_errno)));
+               errno = saved_errno;
 
                fail_readraw();
        }
-       smbd_unlock_socket(sconn);
+       smbd_unlock_socket(xconn);
 }
 
 /****************************************************************************
@@ -3188,7 +3457,7 @@ static void send_file_readbraw(connection_struct *conn,
                               size_t nread,
                               ssize_t mincount)
 {
-       struct smbd_server_connection *sconn = req->sconn;
+       struct smbXsrv_connection *xconn = req->xconn;
        char *outbuf = NULL;
        ssize_t ret=0;
 
@@ -3201,7 +3470,7 @@ static void send_file_readbraw(connection_struct *conn,
 
        if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
            (fsp->wcp == NULL) &&
-           lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
+           lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
                ssize_t sendfile_read = -1;
                char header[4];
                DATA_BLOB header_blob;
@@ -3209,7 +3478,7 @@ static void send_file_readbraw(connection_struct *conn,
                _smb_setlen(header,nread);
                header_blob = data_blob_const(header, 4);
 
-               sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
+               sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
                                                 &header_blob, startpos,
                                                 nread);
                if (sendfile_read == -1) {
@@ -3229,7 +3498,7 @@ static void send_file_readbraw(connection_struct *conn,
                                set_use_sendfile(SNUM(conn), False);
                                DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
 
-                               if (fake_sendfile(fsp, startpos, nread) == -1) {
+                               if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
                                        DEBUG(0,("send_file_readbraw: "
                                                 "fake_sendfile failed for "
                                                 "file %s (%s).\n",
@@ -3260,7 +3529,11 @@ static void send_file_readbraw(connection_struct *conn,
 
                /* Deal with possible short send. */
                if (sendfile_read != 4+nread) {
-                       sendfile_short_send(fsp, sendfile_read, 4, nread);
+                       ret = sendfile_short_send(xconn, fsp,
+                                                 sendfile_read, 4, nread);
+                       if (ret == -1) {
+                               fail_readraw();
+                       }
                }
                return;
        }
@@ -3271,7 +3544,7 @@ normal_readbraw:
        if (!outbuf) {
                DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
                        (unsigned)(nread+4)));
-               reply_readbraw_error(sconn);
+               reply_readbraw_error(xconn);
                return;
        }
 
@@ -3287,17 +3560,16 @@ normal_readbraw:
        }
 
        _smb_setlen(outbuf,ret);
-       if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
-               char addr[INET6_ADDRSTRLEN];
+       if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
+               int saved_errno = errno;
                /*
                 * Try and give an error message saying what
                 * client failed.
                 */
-               DEBUG(0, ("write_data failed for client %s. "
-                         "Error %s\n",
-                         get_peer_addr(fsp->conn->sconn->sock, addr,
-                                       sizeof(addr)),
-                         strerror(errno)));
+               DEBUG(0, ("write_data failed for client %s. Error %s\n",
+                         smbXsrv_connection_dbg(xconn),
+                         strerror(saved_errno)));
+               errno = saved_errno;
 
                fail_readraw();
        }
@@ -3312,7 +3584,7 @@ normal_readbraw:
 void reply_readbraw(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
-       struct smbd_server_connection *sconn = req->sconn;
+       struct smbXsrv_connection *xconn = req->xconn;
        ssize_t maxcount,mincount;
        size_t nread = 0;
        off_t startpos;
@@ -3322,21 +3594,21 @@ void reply_readbraw(struct smb_request *req)
 
        START_PROFILE(SMBreadbraw);
 
-       if (srv_is_signing_active(sconn) || req->encrypted) {
+       if (srv_is_signing_active(xconn) || req->encrypted) {
                exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
                        "raw reads/writes are disallowed.");
        }
 
        if (req->wct < 8) {
-               reply_readbraw_error(sconn);
+               reply_readbraw_error(xconn);
                END_PROFILE(SMBreadbraw);
                return;
        }
 
-       if (sconn->smb1.echo_handler.trusted_fde) {
+       if (xconn->smb1.echo_handler.trusted_fde) {
                DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
                         "'async smb echo handler = yes'\n"));
-               reply_readbraw_error(sconn);
+               reply_readbraw_error(xconn);
                END_PROFILE(SMBreadbraw);
                return;
        }
@@ -3364,7 +3636,7 @@ void reply_readbraw(struct smb_request *req)
                DEBUG(3,("reply_readbraw: fnum %d not valid "
                        "- cache prime?\n",
                        (int)SVAL(req->vwv+0, 0)));
-               reply_readbraw_error(sconn);
+               reply_readbraw_error(xconn);
                END_PROFILE(SMBreadbraw);
                return;
        }
@@ -3375,7 +3647,7 @@ void reply_readbraw(struct smb_request *req)
                                (fsp->access_mask & FILE_EXECUTE)))) {
                DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
                                (int)SVAL(req->vwv+0, 0)));
-               reply_readbraw_error(sconn);
+               reply_readbraw_error(xconn);
                END_PROFILE(SMBreadbraw);
                return;
        }
@@ -3394,7 +3666,7 @@ void reply_readbraw(struct smb_request *req)
                        DEBUG(0,("reply_readbraw: negative 64 bit "
                                "readraw offset (%.0f) !\n",
                                (double)startpos ));
-                       reply_readbraw_error(sconn);
+                       reply_readbraw_error(xconn);
                        END_PROFILE(SMBreadbraw);
                        return;
                }
@@ -3410,8 +3682,8 @@ void reply_readbraw(struct smb_request *req)
            (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
            &lock);
 
-       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
-               reply_readbraw_error(sconn);
+       if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
+               reply_readbraw_error(xconn);
                END_PROFILE(SMBreadbraw);
                return;
        }
@@ -3442,8 +3714,6 @@ void reply_readbraw(struct smb_request *req)
 
        DEBUG(5,("reply_readbraw finished\n"));
 
-       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-
        END_PROFILE(SMBreadbraw);
        return;
 }
@@ -3467,7 +3737,7 @@ void reply_lockread(struct smb_request *req)
        files_struct *fsp;
        struct byte_range_lock *br_lck = NULL;
        char *p = NULL;
-       struct smbd_server_connection *sconn = req->sconn;
+       struct smbXsrv_connection *xconn = req->xconn;
 
        START_PROFILE(SMBlockread);
 
@@ -3522,13 +3792,13 @@ void reply_lockread(struct smb_request *req)
        /*
         * However the requested READ size IS affected by max_send. Insanity.... JRA.
         */
-       maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
+       maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
 
        if (numtoread > maxtoread) {
                DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                        (unsigned int)numtoread, (unsigned int)maxtoread,
-                       (unsigned int)sconn->smb1.sessions.max_send));
+                       (unsigned int)xconn->smb1.sessions.max_send));
                numtoread = maxtoread;
        }
 
@@ -3576,7 +3846,7 @@ void reply_read(struct smb_request *req)
        off_t startpos;
        files_struct *fsp;
        struct lock_struct lock;
-       struct smbd_server_connection *sconn = req->sconn;
+       struct smbXsrv_connection *xconn = req->xconn;
 
        START_PROFILE(SMBread);
 
@@ -3605,13 +3875,13 @@ void reply_read(struct smb_request *req)
        /*
         * The requested read size cannot be greater than max_send. JRA.
         */
-       maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
+       maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
 
        if (numtoread > maxtoread) {
                DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                        (unsigned int)numtoread, (unsigned int)maxtoread,
-                       (unsigned int)sconn->smb1.sessions.max_send));
+                       (unsigned int)xconn->smb1.sessions.max_send));
                numtoread = maxtoread;
        }
 
@@ -3623,7 +3893,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
            (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
            &lock);
 
-       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+       if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
                reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                END_PROFILE(SMBread);
                return;
@@ -3634,7 +3904,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
 
        if (nread < 0) {
                reply_nterror(req, map_nt_error_from_unix(errno));
-               goto strict_unlock;
+               goto out;
        }
 
        srv_set_message((char *)req->outbuf, 5, nread+3, False);
@@ -3647,9 +3917,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
        DEBUG(3, ("read %s num=%d nread=%d\n",
                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
 
-strict_unlock:
-       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-
+out:
        END_PROFILE(SMBread);
        return;
 }
@@ -3658,12 +3926,12 @@ strict_unlock:
  Setup readX header.
 ****************************************************************************/
 
-static int setup_readX_header(struct smb_request *req, char *outbuf,
-                             size_t smb_maxcnt)
+size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
 {
-       int outsize;
+       size_t outsize;
 
-       outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
+       outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
+                                 False);
 
        memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
 
@@ -3674,11 +3942,13 @@ static int setup_readX_header(struct smb_request *req, char *outbuf,
              (smb_wct - 4)     /* offset from smb header to wct */
              + 1               /* the wct field */
              + 12 * sizeof(uint16_t) /* vwv */
-             + 2);             /* the buflen field */
+             + 2               /* the buflen field */
+             + 1);             /* padding byte */
        SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
-       SSVAL(outbuf,smb_vwv11,smb_maxcnt);
+       SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
        /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
-       _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
+       _smb_setlen_large(outbuf,
+                         smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
        return outsize;
 }
 
@@ -3690,6 +3960,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                            files_struct *fsp, off_t startpos,
                            size_t smb_maxcnt)
 {
+       struct smbXsrv_connection *xconn = req->xconn;
        ssize_t nread = -1;
        struct lock_struct lock;
        int saved_errno = 0;
@@ -3698,7 +3969,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
            (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
            &lock);
 
-       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+       if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
                reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                return;
        }
@@ -3713,13 +3984,13 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
            !req->encrypted &&
            (fsp->base_fsp == NULL) &&
            (fsp->wcp == NULL) &&
-           lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
-               uint8 headerbuf[smb_size + 12 * 2];
+           lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
+               uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
                DATA_BLOB header;
 
                if(fsp_stat(fsp) == -1) {
                        reply_nterror(req, map_nt_error_from_unix(errno));
-                       goto strict_unlock;
+                       goto out;
                }
 
                if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
@@ -3741,11 +4012,13 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                header = data_blob_const(headerbuf, sizeof(headerbuf));
 
                construct_reply_common_req(req, (char *)headerbuf);
-               setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
+               setup_readX_header((char *)headerbuf, smb_maxcnt);
 
-               nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
+               nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
                                         startpos, smb_maxcnt);
                if (nread == -1) {
+                       saved_errno = errno;
+
                        /* Returning ENOSYS means no data at all was sent.
                           Do this as a normal read. */
                        if (errno == ENOSYS) {
@@ -3762,20 +4035,24 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                                /* Ensure we don't do this again. */
                                set_use_sendfile(SNUM(conn), False);
                                DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
-                               nread = fake_sendfile(fsp, startpos,
+                               nread = fake_sendfile(xconn, fsp, startpos,
                                                      smb_maxcnt);
                                if (nread == -1) {
+                                       saved_errno = errno;
                                        DEBUG(0,("send_file_readX: "
                                                 "fake_sendfile failed for "
-                                                "file %s (%s).\n",
+                                                "file %s (%s) for client %s. "
+                                                "Terminating\n",
                                                 fsp_str_dbg(fsp),
-                                                strerror(errno)));
+                                                smbXsrv_connection_dbg(xconn),
+                                                strerror(saved_errno)));
+                                       errno = saved_errno;
                                        exit_server_cleanly("send_file_readX: fake_sendfile failed");
                                }
                                DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
                                          fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
                                /* No outbuf here means successful sendfile. */
-                               goto strict_unlock;
+                               goto out;
                        }
 
                        DEBUG(0,("send_file_readX: sendfile failed for file "
@@ -3801,76 +4078,96 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
 
                /* Deal with possible short send. */
                if (nread != smb_maxcnt + sizeof(headerbuf)) {
-                       sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
+                       ssize_t ret;
+
+                       ret = sendfile_short_send(xconn, fsp, nread,
+                                                 sizeof(headerbuf), smb_maxcnt);
+                       if (ret == -1) {
+                               const char *r;
+                               r = "send_file_readX: sendfile_short_send failed";
+                               DEBUG(0,("%s for file %s (%s).\n",
+                                        r, fsp_str_dbg(fsp), strerror(errno)));
+                               exit_server_cleanly(r);
+                       }
                }
                /* No outbuf here means successful sendfile. */
                SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
                SMB_PERFCOUNT_END(&req->pcd);
-               goto strict_unlock;
+               goto out;
        }
 
 normal_read:
 
        if ((smb_maxcnt & 0xFF0000) > 0x10000) {
-               uint8 headerbuf[smb_size + 2*12];
+               uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
+               ssize_t ret;
+
+               if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
+                   (startpos > fsp->fsp_name->st.st_ex_size) ||
+                   (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
+                       /*
+                        * We already know that we would do a short
+                        * read, so don't try the sendfile() path.
+                        */
+                       goto nosendfile_read;
+               }
 
                construct_reply_common_req(req, (char *)headerbuf);
-               setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
+               setup_readX_header((char *)headerbuf, smb_maxcnt);
 
                /* Send out the header. */
-               if (write_data(req->sconn->sock, (char *)headerbuf,
-                              sizeof(headerbuf)) != sizeof(headerbuf)) {
-
-                       char addr[INET6_ADDRSTRLEN];
+               ret = write_data(xconn->transport.sock, (char *)headerbuf,
+                                sizeof(headerbuf));
+               if (ret != sizeof(headerbuf)) {
+                       saved_errno = errno;
                        /*
                         * Try and give an error message saying what
                         * client failed.
                         */
-                       DEBUG(0, ("write_data failed for client %s. "
-                                 "Error %s\n",
-                                 get_peer_addr(req->sconn->sock, addr,
-                                               sizeof(addr)),
-                                 strerror(errno)));
-
                        DEBUG(0,("send_file_readX: write_data failed for file "
-                                "%s (%s). Terminating\n", fsp_str_dbg(fsp),
-                                strerror(errno)));
+                                "%s (%s) for client %s. Terminating\n",
+                                fsp_str_dbg(fsp),
+                                smbXsrv_connection_dbg(xconn),
+                                strerror(saved_errno)));
+                       errno = saved_errno;
                        exit_server_cleanly("send_file_readX sendfile failed");
                }
-               nread = fake_sendfile(fsp, startpos, smb_maxcnt);
+               nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
                if (nread == -1) {
-                       DEBUG(0,("send_file_readX: fake_sendfile failed for "
-                                "file %s (%s).\n", fsp_str_dbg(fsp),
-                                strerror(errno)));
+                       saved_errno = errno;
+                       DEBUG(0,("send_file_readX: fake_sendfile failed for file "
+                                "%s (%s) for client %s. Terminating\n",
+                                fsp_str_dbg(fsp),
+                                smbXsrv_connection_dbg(xconn),
+                                strerror(saved_errno)));
+                       errno = saved_errno;
                        exit_server_cleanly("send_file_readX: fake_sendfile failed");
                }
-               goto strict_unlock;
+               goto out;
        }
 
 nosendfile_read:
 
-       reply_outbuf(req, 12, smb_maxcnt);
+       reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
        SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
        SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
 
-       nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
+       nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
+                         startpos, smb_maxcnt);
        saved_errno = errno;
 
-       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-
        if (nread < 0) {
                reply_nterror(req, map_nt_error_from_unix(saved_errno));
                return;
        }
 
-       setup_readX_header(req, (char *)req->outbuf, nread);
+       setup_readX_header((char *)req->outbuf, nread);
 
        DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
                  fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
        return;
 
- strict_unlock:
-       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+out:
        TALLOC_FREE(req->outbuf);
        return;
 }
@@ -3881,16 +4178,18 @@ nosendfile_read:
 
 static size_t calc_max_read_pdu(const struct smb_request *req)
 {
-       if (req->sconn->conn->protocol < PROTOCOL_NT1) {
-               return req->sconn->smb1.sessions.max_send;
+       struct smbXsrv_connection *xconn = req->xconn;
+
+       if (xconn->protocol < PROTOCOL_NT1) {
+               return xconn->smb1.sessions.max_send;
        }
 
        if (!lp_large_readwrite()) {
-               return req->sconn->smb1.sessions.max_send;
+               return xconn->smb1.sessions.max_send;
        }
 
        if (req_is_in_chain(req)) {
-               return req->sconn->smb1.sessions.max_send;
+               return xconn->smb1.sessions.max_send;
        }
 
        if (req->encrypted) {
@@ -3899,10 +4198,10 @@ static size_t calc_max_read_pdu(const struct smb_request *req)
                 * limit. There are padding considerations
                 * that make that tricky.
                 */
-               return req->sconn->smb1.sessions.max_send;
+               return xconn->smb1.sessions.max_send;
        }
 
-       if (srv_is_signing_active(req->sconn)) {
+       if (srv_is_signing_active(xconn)) {
                return 0x1FFFF;
        }
 
@@ -3925,10 +4224,11 @@ static size_t calc_read_size(const struct smb_request *req,
                             size_t upper_size,
                             size_t lower_size)
 {
+       struct smbXsrv_connection *xconn = req->xconn;
        size_t max_pdu = calc_max_read_pdu(req);
        size_t total_size = 0;
        size_t hdr_len = MIN_SMB_SIZE + VWV(12);
-       size_t max_len = max_pdu - hdr_len;
+       size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
 
        /*
         * Windows explicitly ignores upper size of 0xFFFF.
@@ -3940,7 +4240,7 @@ static size_t calc_read_size(const struct smb_request *req,
                upper_size = 0;
        }
 
-       if (req->sconn->conn->protocol < PROTOCOL_NT1) {
+       if (xconn->protocol < PROTOCOL_NT1) {
                upper_size = 0;
        }
 
@@ -4036,9 +4336,9 @@ void reply_read_and_X(struct smb_request *req)
                /* NT_STATUS_RETRY - fall back to sync read. */
        }
 
-       smbd_lock_socket(req->sconn);
+       smbd_lock_socket(req->xconn);
        send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
-       smbd_unlock_socket(req->sconn);
+       smbd_unlock_socket(req->xconn);
 
  out:
        END_PROFILE(SMBreadX);
@@ -4051,7 +4351,7 @@ void reply_read_and_X(struct smb_request *req)
 
 void error_to_writebrawerr(struct smb_request *req)
 {
-       uint8 *old_outbuf = req->outbuf;
+       uint8_t *old_outbuf = req->outbuf;
 
        reply_outbuf(req, 1, 0);
 
@@ -4103,6 +4403,7 @@ static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
 void reply_writebraw(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
+       struct smbXsrv_connection *xconn = req->xconn;
        char *buf = NULL;
        ssize_t nwritten=0;
        ssize_t total_written=0;
@@ -4124,7 +4425,7 @@ void reply_writebraw(struct smb_request *req)
         */
        SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
 
-       if (srv_is_signing_active(req->sconn)) {
+       if (srv_is_signing_active(xconn)) {
                END_PROFILE(SMBwritebraw);
                exit_server_cleanly("reply_writebraw: SMB signing is active - "
                                "raw reads/writes are disallowed.");
@@ -4137,7 +4438,7 @@ void reply_writebraw(struct smb_request *req)
                return;
        }
 
-       if (req->sconn->smb1.echo_handler.trusted_fde) {
+       if (xconn->smb1.echo_handler.trusted_fde) {
                DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
                         "'async smb echo handler = yes'\n"));
                reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
@@ -4176,6 +4477,9 @@ void reply_writebraw(struct smb_request *req)
        }
 
        /* Ensure we don't write bytes past the end of this packet. */
+       /*
+        * This already protects us against CVE-2017-12163.
+        */
        if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                error_to_writebrawerr(req);
@@ -4188,7 +4492,7 @@ void reply_writebraw(struct smb_request *req)
                    (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
                    &lock);
 
-               if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+               if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
                        reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                        error_to_writebrawerr(req);
                        END_PROFILE(SMBwritebraw);
@@ -4208,7 +4512,7 @@ void reply_writebraw(struct smb_request *req)
        if (nwritten < (ssize_t)numtowrite)  {
                reply_nterror(req, NT_STATUS_DISK_FULL);
                error_to_writebrawerr(req);
-               goto strict_unlock;
+               goto out;
        }
 
        total_written = nwritten;
@@ -4218,7 +4522,7 @@ void reply_writebraw(struct smb_request *req)
        if (!buf) {
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                error_to_writebrawerr(req);
-               goto strict_unlock;
+               goto out;
        }
 
        /* Return a SMBwritebraw message to the redirector to tell
@@ -4229,7 +4533,7 @@ void reply_writebraw(struct smb_request *req)
        SCVAL(buf,smb_com,SMBwritebraw);
        SSVALS(buf,smb_vwv0,0xFFFF);
        show_msg(buf);
-       if (!srv_send_smb(req->sconn,
+       if (!srv_send_smb(req->xconn,
                          buf,
                          false, 0, /* no signing */
                          IS_CONN_ENCRYPTED(conn),
@@ -4239,7 +4543,7 @@ void reply_writebraw(struct smb_request *req)
        }
 
        /* Now read the raw data into the buffer and write it */
-       status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
+       status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
                                 &numtowrite);
        if (!NT_STATUS_IS_OK(status)) {
                exit_server_cleanly("secondary writebraw failed");
@@ -4263,26 +4567,30 @@ void reply_writebraw(struct smb_request *req)
                                (int)tcount,(int)nwritten,(int)numtowrite));
                }
 
-               status = read_data(req->sconn->sock, buf+4, numtowrite);
+               status = read_data_ntstatus(xconn->transport.sock, buf+4,
+                                           numtowrite);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       char addr[INET6_ADDRSTRLEN];
                        /* Try and give an error message
                         * saying what client failed. */
                        DEBUG(0, ("reply_writebraw: Oversize secondary write "
                                  "raw read failed (%s) for client %s. "
                                  "Terminating\n", nt_errstr(status),
-                                 get_peer_addr(req->sconn->sock, addr,
-                                               sizeof(addr))));
+                                 smbXsrv_connection_dbg(xconn)));
                        exit_server_cleanly("secondary writebraw failed");
                }
 
+               /*
+                * We are not vulnerable to CVE-2017-12163
+                * here as we are guarenteed to have numtowrite
+                * bytes available - we just read from the client.
+                */
                nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
                if (nwritten == -1) {
                        TALLOC_FREE(buf);
                        reply_nterror(req, map_nt_error_from_unix(errno));
                        error_to_writebrawerr(req);
-                       goto strict_unlock;
+                       goto out;
                }
 
                if (nwritten < (ssize_t)numtowrite) {
@@ -4304,7 +4612,7 @@ void reply_writebraw(struct smb_request *req)
                         fsp_str_dbg(fsp), nt_errstr(status)));
                reply_nterror(req, status);
                error_to_writebrawerr(req);
-               goto strict_unlock;
+               goto out;
        }
 
        DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
@@ -4312,10 +4620,6 @@ void reply_writebraw(struct smb_request *req)
                fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
                (int)total_written));
 
-       if (!fsp->print_file) {
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-       }
-
        /* We won't return a status if write through is not selected - this
         * follows what WfWg does */
        END_PROFILE(SMBwritebraw);
@@ -4328,7 +4632,7 @@ void reply_writebraw(struct smb_request *req)
                 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
                 * JRA.
                 */
-               if (!send_keepalive(req->sconn->sock)) {
+               if (!send_keepalive(xconn->transport.sock)) {
                        exit_server_cleanly("reply_writebraw: send of "
                                "keepalive failed");
                }
@@ -4337,11 +4641,7 @@ void reply_writebraw(struct smb_request *req)
        }
        return;
 
-strict_unlock:
-       if (!fsp->print_file) {
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-       }
-
+out:
        END_PROFILE(SMBwritebraw);
        return;
 }
@@ -4358,6 +4658,7 @@ void reply_writeunlock(struct smb_request *req)
        connection_struct *conn = req->conn;
        ssize_t nwritten = -1;
        size_t numtowrite;
+       size_t remaining;
        off_t startpos;
        const char *data;
        NTSTATUS status = NT_STATUS_OK;
@@ -4390,12 +4691,23 @@ void reply_writeunlock(struct smb_request *req)
        startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
        data = (const char *)req->buf + 3;
 
+       /*
+        * Ensure client isn't asking us to write more than
+        * they sent. CVE-2017-12163.
+        */
+       remaining = smbreq_bufrem(req, data);
+       if (numtowrite > remaining) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBwriteunlock);
+               return;
+       }
+
        if (!fsp->print_file && numtowrite > 0) {
                init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
                    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
                    &lock);
 
-               if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+               if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
                        reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                        END_PROFILE(SMBwriteunlock);
                        return;
@@ -4417,17 +4729,17 @@ void reply_writeunlock(struct smb_request *req)
                DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
                         fsp_str_dbg(fsp), nt_errstr(status)));
                reply_nterror(req, status);
-               goto strict_unlock;
+               goto out;
        }
 
        if(nwritten < 0) {
                reply_nterror(req, map_nt_error_from_unix(saved_errno));
-               goto strict_unlock;
+               goto out;
        }
 
        if((nwritten < numtowrite) && (numtowrite != 0)) {
                reply_nterror(req, NT_STATUS_DISK_FULL);
-               goto strict_unlock;
+               goto out;
        }
 
        if (numtowrite && !fsp->print_file) {
@@ -4440,7 +4752,7 @@ void reply_writeunlock(struct smb_request *req)
 
                if (NT_STATUS_V(status)) {
                        reply_nterror(req, status);
-                       goto strict_unlock;
+                       goto out;
                }
        }
 
@@ -4451,11 +4763,7 @@ void reply_writeunlock(struct smb_request *req)
        DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
                  fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
 
-strict_unlock:
-       if (numtowrite && !fsp->print_file) {
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-       }
-
+out:
        END_PROFILE(SMBwriteunlock);
        return;
 }
@@ -4471,6 +4779,7 @@ void reply_write(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
        size_t numtowrite;
+       size_t remaining;
        ssize_t nwritten = -1;
        off_t startpos;
        const char *data;
@@ -4511,12 +4820,23 @@ void reply_write(struct smb_request *req)
        startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
        data = (const char *)req->buf + 3;
 
+       /*
+        * Ensure client isn't asking us to write more than
+        * they sent. CVE-2017-12163.
+        */
+       remaining = smbreq_bufrem(req, data);
+       if (numtowrite > remaining) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBwrite);
+               return;
+       }
+
        if (!fsp->print_file) {
                init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
                        (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
                        &lock);
 
-               if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+               if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
                        reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                        END_PROFILE(SMBwrite);
                        return;
@@ -4536,12 +4856,12 @@ void reply_write(struct smb_request *req)
                nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
                if (nwritten < 0) {
                        reply_nterror(req, NT_STATUS_DISK_FULL);
-                       goto strict_unlock;
+                       goto out;
                }
                nwritten = vfs_set_filelen(fsp, (off_t)startpos);
                if (nwritten < 0) {
                        reply_nterror(req, NT_STATUS_DISK_FULL);
-                       goto strict_unlock;
+                       goto out;
                }
                trigger_write_time_update_immediate(fsp);
        } else {
@@ -4553,17 +4873,17 @@ void reply_write(struct smb_request *req)
                DEBUG(5,("reply_write: sync_file for %s returned %s\n",
                         fsp_str_dbg(fsp), nt_errstr(status)));
                reply_nterror(req, status);
-               goto strict_unlock;
+               goto out;
        }
 
        if(nwritten < 0) {
                reply_nterror(req, map_nt_error_from_unix(saved_errno));
-               goto strict_unlock;
+               goto out;
        }
 
        if((nwritten == 0) && (numtowrite != 0)) {
                reply_nterror(req, NT_STATUS_DISK_FULL);
-               goto strict_unlock;
+               goto out;
        }
 
        reply_outbuf(req, 1, 0);
@@ -4577,11 +4897,7 @@ void reply_write(struct smb_request *req)
 
        DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
 
-strict_unlock:
-       if (!fsp->print_file) {
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-       }
-
+out:
        END_PROFILE(SMBwrite);
        return;
 }
@@ -4594,7 +4910,7 @@ strict_unlock:
                                                (2*14) + /* word count (including bcc) */ \
                                                1 /* pad byte */)
 
-bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
+bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
                            const uint8_t *inbuf)
 {
        size_t numtowrite;
@@ -4605,7 +4921,7 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
        struct files_struct *fsp = NULL;
        NTSTATUS status;
 
-       if (is_encrypted_packet(sconn, inbuf)) {
+       if (is_encrypted_packet(inbuf)) {
                /* Can't do this on encrypted
                 * connections. */
                return false;
@@ -4623,7 +4939,7 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
        }
 
        fnum = SVAL(inbuf, smb_vwv2);
-       status = smb1srv_open_lookup(sconn->conn,
+       status = smb1srv_open_lookup(xconn,
                                     fnum,
                                     0, /* now */
                                     &op);
@@ -4696,6 +5012,7 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
 void reply_write_and_X(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
+       struct smbXsrv_connection *xconn = req->xconn;
        files_struct *fsp;
        struct lock_struct lock;
        off_t startpos;
@@ -4736,6 +5053,9 @@ void reply_write_and_X(struct smb_request *req)
                        goto out;
                }
        } else {
+               /*
+                * This already protects us against CVE-2017-12163.
+                */
                if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
                                smb_doff + numtowrite > smblen) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -4808,15 +5128,13 @@ void reply_write_and_X(struct smb_request *req)
                    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
                    &lock);
 
-               if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+               if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
                        reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                        goto out;
                }
 
                nwritten = write_file(req,fsp,data,startpos,numtowrite);
                saved_errno = errno;
-
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
        }
 
        if(nwritten < 0) {
@@ -4852,7 +5170,7 @@ void reply_write_and_X(struct smb_request *req)
 out:
        if (req->unread_bytes) {
                /* writeX failed. drain socket. */
-               if (drain_socket(req->sconn->sock, req->unread_bytes) !=
+               if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
                                req->unread_bytes) {
                        smb_panic("failed to drain pending bytes");
                }
@@ -4957,7 +5275,7 @@ void reply_lseek(struct smb_request *req)
 void reply_flush(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
-       uint16 fnum;
+       uint16_t fnum;
        files_struct *fsp;
 
        START_PROFILE(SMBflush);
@@ -5144,7 +5462,7 @@ static void do_smb1_close(struct tevent_req *req)
        } else {
                reply_nterror(smbreq, status);
        }
-       if (!srv_send_smb(smbreq->sconn,
+       if (!srv_send_smb(smbreq->xconn,
                        (char *)smbreq->outbuf,
                        true,
                        smbreq->seqnum+1,
@@ -5164,6 +5482,7 @@ void reply_writeclose(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
        size_t numtowrite;
+       size_t remaining;
        ssize_t nwritten = -1;
        NTSTATUS close_status = NT_STATUS_OK;
        off_t startpos;
@@ -5197,12 +5516,23 @@ void reply_writeclose(struct smb_request *req)
        mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
        data = (const char *)req->buf + 1;
 
+       /*
+        * Ensure client isn't asking us to write more than
+        * they sent. CVE-2017-12163.
+        */
+       remaining = smbreq_bufrem(req, data);
+       if (numtowrite > remaining) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBwriteclose);
+               return;
+       }
+
        if (fsp->print_file == NULL) {
                init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
                    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
                    &lock);
 
-               if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+               if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
                        reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
                        END_PROFILE(SMBwriteclose);
                        return;
@@ -5211,10 +5541,6 @@ void reply_writeclose(struct smb_request *req)
 
        nwritten = write_file(req,fsp,data,startpos,numtowrite);
 
-       if (fsp->print_file == NULL) {
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-       }
-
        set_close_write_time(fsp, mtime);
 
        /*
@@ -5465,7 +5791,7 @@ void reply_echo(struct smb_request *req)
                SSVAL(req->outbuf,smb_vwv0,seq_num);
 
                show_msg((char *)req->outbuf);
-               if (!srv_send_smb(req->sconn,
+               if (!srv_send_smb(req->xconn,
                                (char *)req->outbuf,
                                true, req->seqnum+1,
                                IS_CONN_ENCRYPTED(conn)||req->encrypted,
@@ -5637,10 +5963,11 @@ void reply_printqueue(struct smb_request *req)
 
                ZERO_STRUCT(handle);
 
-               status = rpc_pipe_open_interface(conn,
+               status = rpc_pipe_open_interface(mem_ctx,
                                                 &ndr_table_spoolss,
                                                 conn->session_info,
                                                 conn->sconn->remote_address,
+                                                conn->sconn->local_address,
                                                 conn->sconn->msg_ctx,
                                                 &cli);
                if (!NT_STATUS_IS_OK(status)) {
@@ -5699,6 +6026,7 @@ void reply_printqueue(struct smb_request *req)
                        char *p = blob;
                        time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
                        int qstatus;
+                       size_t len = 0;
                        uint16_t qrapjobid = pjobid_to_rap(sharename,
                                                        info[i].info2.job_id);
 
@@ -5713,9 +6041,12 @@ void reply_printqueue(struct smb_request *req)
                        SSVAL(p, 5, qrapjobid);
                        SIVAL(p, 7, info[i].info2.size);
                        SCVAL(p, 11, 0);
-                       srvstr_push(blob, req->flags2, p+12,
-                                   info[i].info2.notify_name, 16, STR_ASCII);
-
+                       status = srvstr_push(blob, req->flags2, p+12,
+                                   info[i].info2.notify_name, 16, STR_ASCII, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               reply_nterror(req, status);
+                               goto out;
+                       }
                        if (message_push_blob(
                                    &req->outbuf,
                                    data_blob_const(
@@ -5788,6 +6119,9 @@ void reply_printwrite(struct smb_request *req)
 
        numtowrite = SVAL(req->buf, 1);
 
+       /*
+        * This already protects us against CVE-2017-12163.
+        */
        if (req->buflen < numtowrite + 3) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBsplwr);
@@ -5818,6 +6152,7 @@ void reply_mkdir(struct smb_request *req)
        struct smb_filename *smb_dname = NULL;
        char *directory = NULL;
        NTSTATUS status;
+       uint32_t ucf_flags;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBmkdir);
@@ -5829,10 +6164,10 @@ void reply_mkdir(struct smb_request *req)
                goto out;
        }
 
+       ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
        status = filename_convert(ctx, conn,
-                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                 directory,
-                                UCF_PREP_CREATEFILE,
+                                ucf_flags,
                                 NULL,
                                 &smb_dname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -5888,6 +6223,7 @@ void reply_rmdir(struct smb_request *req)
        TALLOC_CTX *ctx = talloc_tos();
        files_struct *fsp = NULL;
        int info = 0;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        struct smbd_server_connection *sconn = req->sconn;
 
        START_PROFILE(SMBrmdir);
@@ -5900,9 +6236,8 @@ void reply_rmdir(struct smb_request *req)
        }
 
        status = filename_convert(ctx, conn,
-                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                 directory,
-                                0,
+                                ucf_flags,
                                 NULL,
                                 &smb_dname);
        if (!NT_STATUS_IS_OK(status)) {
@@ -5932,15 +6267,17 @@ void reply_rmdir(struct smb_request *req)
                FILE_DIRECTORY_FILE,                    /* create_options */
                FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
                0,                                      /* oplock_request */
+               NULL,                                   /* lease */
                0,                                      /* allocation_size */
                0,                                      /* private_flags */
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               &info);                                 /* pinfo */
+               &info,                                  /* pinfo */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -6199,7 +6536,7 @@ static void notify_rename(connection_struct *conn, bool is_dir,
 {
        char *parent_dir_src = NULL;
        char *parent_dir_dst = NULL;
-       uint32 mask;
+       uint32_t mask;
 
        mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
                : FILE_NOTIFY_CHANGE_FILE_NAME;
@@ -6286,16 +6623,17 @@ static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
 NTSTATUS rename_internals_fsp(connection_struct *conn,
                        files_struct *fsp,
                        const struct smb_filename *smb_fname_dst_in,
-                       uint32 attrs,
+                       uint32_t attrs,
                        bool replace_if_exists)
 {
        TALLOC_CTX *ctx = talloc_tos();
        struct smb_filename *smb_fname_dst = NULL;
        NTSTATUS status = NT_STATUS_OK;
        struct share_mode_lock *lck = NULL;
+       uint32_t access_mask = SEC_DIR_ADD_FILE;
        bool dst_exists, old_is_stream, new_is_stream;
 
-       status = check_name(conn, smb_fname_dst_in->base_name);
+       status = check_name(conn, smb_fname_dst_in);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -6315,67 +6653,83 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 
        /*
         * Check for special case with case preserving and not
-        * case sensitive. If the old last component differs from the original
+        * case sensitive. If the new last component differs from the original
         * last component only by case, then we should allow
         * the rename (user is trying to change the case of the
         * filename).
         */
-       if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
+       if (!conn->case_sensitive && conn->case_preserve &&
            strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
            strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
-               char *last_slash;
-               char *fname_dst_lcomp_base_mod = NULL;
-               struct smb_filename *smb_fname_orig_lcomp = NULL;
+               char *fname_dst_parent = NULL;
+               const char *fname_dst_lcomp = NULL;
+               char *orig_lcomp_path = NULL;
+               char *orig_lcomp_stream = NULL;
+               bool ok = true;
 
                /*
-                * Get the last component of the destination name.
+                * Split off the last component of the processed
+                * destination name. We will compare this to
+                * the split components of smb_fname_dst->original_lcomp.
                 */
-               last_slash = strrchr_m(smb_fname_dst->base_name, '/');
-               if (last_slash) {
-                       fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
-               } else {
-                       fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
-               }
-               if (!fname_dst_lcomp_base_mod) {
+               if (!parent_dirname(ctx,
+                               smb_fname_dst->base_name,
+                               &fname_dst_parent,
+                               &fname_dst_lcomp)) {
                        status = NT_STATUS_NO_MEMORY;
                        goto out;
                }
 
                /*
-                * Create an smb_filename struct using the original last
-                * component of the destination.
+                * The original_lcomp component contains
+                * the last_component of the path + stream
+                * name (if a stream exists).
+                *
+                * Split off the stream name so we
+                * can check them separately.
                 */
-               smb_fname_orig_lcomp = synthetic_smb_fname_split(
-                       ctx, smb_fname_dst->original_lcomp, NULL);
-               if (smb_fname_orig_lcomp == NULL) {
+
+               if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
+                       /* POSIX - no stream component. */
+                       orig_lcomp_path = talloc_strdup(ctx,
+                                               smb_fname_dst->original_lcomp);
+                       if (orig_lcomp_path == NULL) {
+                               ok = false;
+                       }
+               } else {
+                       ok = split_stream_filename(ctx,
+                                       smb_fname_dst->original_lcomp,
+                                       &orig_lcomp_path,
+                                       &orig_lcomp_stream);
+               }
+
+               if (!ok) {
+                       TALLOC_FREE(fname_dst_parent);
                        status = NT_STATUS_NO_MEMORY;
-                       TALLOC_FREE(fname_dst_lcomp_base_mod);
                        goto out;
                }
 
                /* If the base names only differ by case, use original. */
-               if(!strcsequal(fname_dst_lcomp_base_mod,
-                              smb_fname_orig_lcomp->base_name)) {
+               if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
                        char *tmp;
                        /*
                         * Replace the modified last component with the
                         * original.
                         */
-                       if (last_slash) {
-                               *last_slash = '\0'; /* Truncate at the '/' */
+                       if (!ISDOT(fname_dst_parent)) {
                                tmp = talloc_asprintf(smb_fname_dst,
                                        "%s/%s",
-                                       smb_fname_dst->base_name,
-                                       smb_fname_orig_lcomp->base_name);
+                                       fname_dst_parent,
+                                       orig_lcomp_path);
                        } else {
-                               tmp = talloc_asprintf(smb_fname_dst,
-                                       "%s",
-                                       smb_fname_orig_lcomp->base_name);
+                               tmp = talloc_strdup(smb_fname_dst,
+                                       orig_lcomp_path);
                        }
                        if (tmp == NULL) {
                                status = NT_STATUS_NO_MEMORY;
-                               TALLOC_FREE(fname_dst_lcomp_base_mod);
-                               TALLOC_FREE(smb_fname_orig_lcomp);
+                               TALLOC_FREE(fname_dst_parent);
+                               TALLOC_FREE(orig_lcomp_path);
+                               TALLOC_FREE(orig_lcomp_stream);
                                goto out;
                        }
                        TALLOC_FREE(smb_fname_dst->base_name);
@@ -6384,22 +6738,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 
                /* If the stream_names only differ by case, use original. */
                if(!strcsequal(smb_fname_dst->stream_name,
-                              smb_fname_orig_lcomp->stream_name)) {
-                       char *tmp = NULL;
+                              orig_lcomp_stream)) {
                        /* Use the original stream. */
-                       tmp = talloc_strdup(smb_fname_dst,
-                                           smb_fname_orig_lcomp->stream_name);
+                       char *tmp = talloc_strdup(smb_fname_dst,
+                                           orig_lcomp_stream);
                        if (tmp == NULL) {
                                status = NT_STATUS_NO_MEMORY;
-                               TALLOC_FREE(fname_dst_lcomp_base_mod);
-                               TALLOC_FREE(smb_fname_orig_lcomp);
+                               TALLOC_FREE(fname_dst_parent);
+                               TALLOC_FREE(orig_lcomp_path);
+                               TALLOC_FREE(orig_lcomp_stream);
                                goto out;
                        }
                        TALLOC_FREE(smb_fname_dst->stream_name);
                        smb_fname_dst->stream_name = tmp;
                }
-               TALLOC_FREE(fname_dst_lcomp_base_mod);
-               TALLOC_FREE(smb_fname_orig_lcomp);
+               TALLOC_FREE(fname_dst_parent);
+               TALLOC_FREE(orig_lcomp_path);
+               TALLOC_FREE(orig_lcomp_stream);
        }
 
        /*
@@ -6473,6 +6828,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 
        if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
                status = NT_STATUS_ACCESS_DENIED;
+               goto out;
+       }
+
+       /* Do we have rights to move into the destination ? */
+       if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
+               /* We're moving a directory. */
+               access_mask = SEC_DIR_ADD_SUBDIR;
+       }
+       status = check_parent_access(conn,
+                               smb_fname_dst,
+                               access_mask);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_INFO("check_parent_access on "
+                       "dst %s returned %s\n",
+                       smb_fname_str_dbg(smb_fname_dst),
+                       nt_errstr(status));
+               goto out;
        }
 
        lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
@@ -6485,14 +6857,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
        SMB_ASSERT(lck != NULL);
 
        if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
-               uint32 create_options = fsp->fh->private_options;
+               uint32_t create_options = fsp->fh->private_options;
 
                DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
                          "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
                          smb_fname_str_dbg(smb_fname_dst)));
 
                if (!fsp->is_directory &&
-                   !lp_posix_pathnames() &&
+                   !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
                    (lp_map_archive(SNUM(conn)) ||
                    lp_store_dos_attributes(SNUM(conn)))) {
                        /* We must set the archive bit on the newly
@@ -6565,13 +6937,14 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        struct smb_request *req,
                        struct smb_filename *smb_fname_src,
                        struct smb_filename *smb_fname_dst,
-                       uint32 attrs,
+                       uint32_t attrs,
                        bool replace_if_exists,
                        bool src_has_wild,
                        bool dest_has_wild,
                        uint32_t access_mask)
 {
        char *fname_src_dir = NULL;
+       struct smb_filename *smb_fname_src_dir = NULL;
        char *fname_src_mask = NULL;
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
@@ -6580,7 +6953,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
        char *talloced = NULL;
        long offset = 0;
        int create_options = 0;
-       bool posix_pathnames = lp_posix_pathnames();
+       bool posix_pathnames = (req != NULL && req->posix_pathnames);
        int rc;
 
        /*
@@ -6699,12 +7072,14 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        create_options,                 /* create_options */
                        posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
                        0,                              /* oplock_request */
+                       NULL,                           /* lease */
                        0,                              /* allocation_size */
                        0,                              /* private_flags */
                        NULL,                           /* sd */
                        NULL,                           /* ea_list */
                        &fsp,                           /* result */
-                       NULL);                          /* pinfo */
+                       NULL,                           /* pinfo */
+                       NULL, NULL);                    /* create context */
 
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3, ("Could not open rename source %s: %s\n",
@@ -6737,12 +7112,22 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                }
        }
 
-       status = check_name(conn, fname_src_dir);
+       smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
+                               fname_src_dir,
+                               NULL,
+                               NULL,
+                               smb_fname_src->flags);
+       if (smb_fname_src_dir == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       status = check_name(conn, smb_fname_src_dir);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
        }
 
-       dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
+       dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
                          attrs);
        if (dir_hnd == NULL) {
                status = map_nt_error_from_unix(errno);
@@ -6845,12 +7230,14 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        create_options,                 /* create_options */
                        posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
                        0,                              /* oplock_request */
+                       NULL,                           /* lease */
                        0,                              /* allocation_size */
                        0,                              /* private_flags */
                        NULL,                           /* sd */
                        NULL,                           /* ea_list */
                        &fsp,                           /* result */
-                       NULL);                          /* pinfo */
+                       NULL,                           /* pinfo */
+                       NULL, NULL);                    /* create context */
 
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
@@ -6896,6 +7283,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
 
  out:
        TALLOC_FREE(talloced);
+       TALLOC_FREE(smb_fname_src_dir);
        TALLOC_FREE(fname_src_dir);
        TALLOC_FREE(fname_src_mask);
        return status;
@@ -6911,15 +7299,22 @@ void reply_mv(struct smb_request *req)
        char *name = NULL;
        char *newname = NULL;
        const char *p;
-       uint32 attrs;
+       uint32_t attrs;
        NTSTATUS status;
        bool src_has_wcard = False;
        bool dest_has_wcard = False;
        TALLOC_CTX *ctx = talloc_tos();
        struct smb_filename *smb_fname_src = NULL;
        struct smb_filename *smb_fname_dst = NULL;
-       uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
-       uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
+       uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
+               (req->posix_pathnames ?
+                       UCF_UNIX_NAME_LOOKUP :
+                       UCF_COND_ALLOW_WCARD_LCOMP);
+       uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
+               UCF_SAVE_LCOMP |
+               (req->posix_pathnames ?
+                       0 :
+                       UCF_COND_ALLOW_WCARD_LCOMP);
        bool stream_rename = false;
 
        START_PROFILE(SMBmv);
@@ -6946,7 +7341,7 @@ void reply_mv(struct smb_request *req)
                goto out;
        }
 
-       if (!lp_posix_pathnames()) {
+       if (!req->posix_pathnames) {
                /* The newname must begin with a ':' if the
                   name contains a ':'. */
                if (strchr_m(name, ':')) {
@@ -6960,7 +7355,6 @@ void reply_mv(struct smb_request *req)
 
        status = filename_convert(ctx,
                                  conn,
-                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
                                  name,
                                  src_ucf_flags,
                                  &src_has_wcard,
@@ -6978,7 +7372,6 @@ void reply_mv(struct smb_request *req)
 
        status = filename_convert(ctx,
                                  conn,
-                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
                                  newname,
                                  dst_ucf_flags,
                                  &dest_has_wcard,
@@ -7013,7 +7406,7 @@ void reply_mv(struct smb_request *req)
                                  attrs, False, src_has_wcard, dest_has_wcard,
                                  DELETE_ACCESS);
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->sconn, req->mid)) {
+               if (open_was_deferred(req->xconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -7048,8 +7441,8 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
        struct smb_filename *smb_fname_dst_tmp = NULL;
        off_t ret=-1;
        files_struct *fsp1,*fsp2;
-       uint32 dosattrs;
-       uint32 new_create_disposition;
+       uint32_t dosattrs;
+       uint32_t new_create_disposition;
        NTSTATUS status;
 
 
@@ -7114,12 +7507,14 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
                0,                                      /* create_options */
                FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
                INTERNAL_OPEN_ONLY,                     /* oplock_request */
+               NULL,                                   /* lease */
                0,                                      /* allocation_size */
                0,                                      /* private_flags */
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp1,                                  /* result */
-               NULL);                                  /* psbuf */
+               NULL,                                   /* psbuf */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
@@ -7143,12 +7538,14 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
                0,                                      /* create_options */
                dosattrs,                               /* file_attributes */
                INTERNAL_OPEN_ONLY,                     /* oplock_request */
+               NULL,                                   /* lease */
                0,                                      /* allocation_size */
                0,                                      /* private_flags */
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp2,                                  /* result */
-               NULL);                                  /* psbuf */
+               NULL,                                   /* psbuf */
+               NULL, NULL);                            /* create context */
 
        if (!NT_STATUS_IS_OK(status)) {
                close_file(NULL, fsp1, ERROR_CLOSE);
@@ -7211,6 +7608,7 @@ void reply_copy(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
        struct smb_filename *smb_fname_src = NULL;
+       struct smb_filename *smb_fname_src_dir = NULL;
        struct smb_filename *smb_fname_dst = NULL;
        char *fname_src = NULL;
        char *fname_dst = NULL;
@@ -7226,6 +7624,10 @@ void reply_copy(struct smb_request *req)
        bool source_has_wild = False;
        bool dest_has_wild = False;
        NTSTATUS status;
+       uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
+               ucf_flags_from_smb_request(req);
+       uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
+               ucf_flags_from_smb_request(req);
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBcopy);
@@ -7263,9 +7665,8 @@ void reply_copy(struct smb_request *req)
        }
 
        status = filename_convert(ctx, conn,
-                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
                                  fname_src,
-                                 UCF_COND_ALLOW_WCARD_LCOMP,
+                                 ucf_flags_src,
                                  &source_has_wild,
                                  &smb_fname_src);
        if (!NT_STATUS_IS_OK(status)) {
@@ -7279,9 +7680,8 @@ void reply_copy(struct smb_request *req)
        }
 
        status = filename_convert(ctx, conn,
-                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
                                  fname_dst,
-                                 UCF_COND_ALLOW_WCARD_LCOMP,
+                                 ucf_flags_dst,
                                  &dest_has_wild,
                                  &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -7378,13 +7778,13 @@ void reply_copy(struct smb_request *req)
                        smb_fname_dst->base_name = fname_dst_mod;
                }
 
-               status = check_name(conn, smb_fname_src->base_name);
+               status = check_name(conn, smb_fname_src);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
                }
 
-               status = check_name(conn, smb_fname_dst->base_name);
+               status = check_name(conn, smb_fname_dst);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
@@ -7426,13 +7826,27 @@ void reply_copy(struct smb_request *req)
                        }
                }
 
-               status = check_name(conn, fname_src_dir);
+               smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
+                                       fname_src_dir,
+                                       NULL,
+                                       NULL,
+                                       smb_fname_src->flags);
+               if (smb_fname_src_dir == NULL) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       goto out;
+               }
+
+               status = check_name(conn, smb_fname_src_dir);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
                }
 
-               dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
+               dir_hnd = OpenDir(ctx,
+                               conn,
+                               smb_fname_src_dir,
+                               fname_src_mask,
+                               0);
                if (dir_hnd == NULL) {
                        status = map_nt_error_from_unix(errno);
                        reply_nterror(req, status);
@@ -7501,7 +7915,7 @@ void reply_copy(struct smb_request *req)
                        TALLOC_FREE(smb_fname_dst->base_name);
                        smb_fname_dst->base_name = destname;
 
-                       status = check_name(conn, smb_fname_src->base_name);
+                       status = check_name(conn, smb_fname_src);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(talloced);
@@ -7509,7 +7923,7 @@ void reply_copy(struct smb_request *req)
                                goto out;
                        }
 
-                       status = check_name(conn, smb_fname_dst->base_name);
+                       status = check_name(conn, smb_fname_dst);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(talloced);
@@ -7542,6 +7956,7 @@ void reply_copy(struct smb_request *req)
        SSVAL(req->outbuf,smb_vwv0,count);
  out:
        TALLOC_FREE(smb_fname_src);
+       TALLOC_FREE(smb_fname_src_dir);
        TALLOC_FREE(smb_fname_dst);
        TALLOC_FREE(fname_src);
        TALLOC_FREE(fname_dst);
@@ -7860,9 +8275,9 @@ void reply_lockingX(struct smb_request *req)
        files_struct *fsp;
        unsigned char locktype;
        unsigned char oplocklevel;
-       uint16 num_ulocks;
-       uint16 num_locks;
-       int32 lock_timeout;
+       uint16_t num_ulocks;
+       uint16_t num_locks;
+       int32_t lock_timeout;
        int i;
        const uint8_t *data;
        bool large_file_format;
@@ -8254,8 +8669,8 @@ void reply_getattrE(struct smb_request *req)
                SIVAL(req->outbuf, smb_vwv6, 0);
                SIVAL(req->outbuf, smb_vwv8, 0);
        } else {
-               uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
-               SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
+               uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
+               SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
                SIVAL(req->outbuf, smb_vwv8, allocation_size);
        }
        SSVAL(req->outbuf,smb_vwv10, mode);