EINVAL is also a valid error return, meaning "this filesystem
[kai/samba.git] / source3 / smbd / reply.c
index 84c189256010b6ad85bd1d1e3a4ef97f48317bc0..06aa835cb0e975356619dab725177c055af76a67 100644 (file)
@@ -32,7 +32,6 @@ extern int max_recv;
 unsigned int smb_echo_count = 0;
 extern uint32 global_client_caps;
 
-extern struct current_user current_user;
 extern bool global_encrypted_passwords_negotiated;
 
 /****************************************************************************
@@ -167,6 +166,7 @@ static NTSTATUS check_path_syntax_internal(char *path,
        }
 
        *d = '\0';
+
        return ret;
 }
 
@@ -326,13 +326,13 @@ size_t srvstr_get_path(TALLOC_CTX *ctx,
 ****************************************************************************/
 
 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
-              files_struct *fsp, struct current_user *user)
+                   files_struct *fsp)
 {
        if (!(fsp) || !(conn)) {
                reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                return False;
        }
-       if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
+       if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
                reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                return False;
        }
@@ -345,9 +345,9 @@ bool check_fsp_open(connection_struct *conn, struct smb_request *req,
 ****************************************************************************/
 
 bool check_fsp(connection_struct *conn, struct smb_request *req,
-              files_struct *fsp, struct current_user *user)
+              files_struct *fsp)
 {
-       if (!check_fsp_open(conn, req, fsp, user)) {
+       if (!check_fsp_open(conn, req, fsp)) {
                return False;
        }
        if ((fsp)->is_directory) {
@@ -362,15 +362,46 @@ bool check_fsp(connection_struct *conn, struct smb_request *req,
        return True;
 }
 
+/****************************************************************************
+ Check if we have a correct fsp pointing to a quota fake file. Replacement for
+ the CHECK_NTQUOTA_HANDLE_OK macro.
+****************************************************************************/
+
+bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
+                             files_struct *fsp)
+{
+       if (!check_fsp_open(conn, req, fsp)) {
+               return false;
+       }
+
+       if (fsp->is_directory) {
+               return false;
+       }
+
+       if (fsp->fake_file_handle == NULL) {
+               return false;
+       }
+
+       if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
+               return false;
+       }
+
+       if (fsp->fake_file_handle->private_data == NULL) {
+               return false;
+       }
+
+       return true;
+}
+
 /****************************************************************************
  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
 ****************************************************************************/
 
 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
-                     files_struct *fsp, struct current_user *user)
+                     files_struct *fsp)
 {
        if ((fsp) && (conn) && ((conn)==(fsp)->conn)
-           && (current_user.vuid==(fsp)->vuid)) {
+           && (req->vuid == (fsp)->vuid)) {
                return True;
        }
 
@@ -391,7 +422,7 @@ void reply_special(char *inbuf)
 
        /*
         * We only really use 4 bytes of the outbuf, but for the smb_setlen
-        * calculation & friends (send_smb uses that) we need the full smb
+        * calculation & friends (srv_send_smb uses that) we need the full smb
         * header.
         */
        char outbuf[smb_size];
@@ -470,7 +501,7 @@ void reply_special(char *inbuf)
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
 
-       send_smb(smbd_server_fd(), outbuf);
+       srv_send_smb(smbd_server_fd(), outbuf, false);
        return;
 }
 
@@ -479,8 +510,9 @@ void reply_special(char *inbuf)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_tcon(connection_struct *conn, struct smb_request *req)
+void reply_tcon(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        const char *service;
        char *service_buf = NULL;
        char *password = NULL;
@@ -523,6 +555,7 @@ void reply_tcon(connection_struct *conn, struct smb_request *req)
        password_blob = data_blob(password, pwlen+1);
 
        conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
+       req->conn = conn;
 
        data_blob_clear_free(&password_blob);
 
@@ -549,8 +582,9 @@ void reply_tcon(connection_struct *conn, struct smb_request *req)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
+void reply_tcon_and_X(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *service = NULL;
        DATA_BLOB password;
        TALLOC_CTX *ctx = talloc_tos();
@@ -578,6 +612,8 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
        /* we might have to close an old one */
        if ((tcon_flags & 0x1) && conn) {
                close_cnum(conn,req->vuid);
+               req->conn = NULL;
+               conn = NULL;
        }
 
        if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
@@ -587,7 +623,8 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
        }
 
        if (global_encrypted_passwords_negotiated) {
-               password = data_blob(smb_buf(req->inbuf),passlen);
+               password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
+                                           passlen);
                if (lp_security() == SEC_SHARE) {
                        /*
                         * Security = share always has a pad byte
@@ -598,7 +635,8 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
                        p = smb_buf(req->inbuf) + passlen;
                }
        } else {
-               password = data_blob(smb_buf(req->inbuf),passlen+1);
+               password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
+                                           passlen+1);
                /* Ensure correct termination */
                password.data[passlen]=0;
                p = smb_buf(req->inbuf) + passlen + 1;
@@ -646,6 +684,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
 
        conn = make_connection(service, password, client_devicetype,
                               req->vuid, &nt_status);
+       req->conn =conn;
 
        data_blob_clear_free(&password);
 
@@ -731,17 +770,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
  Reply to an unknown type.
 ****************************************************************************/
 
-int reply_unknown(char *inbuf,char *outbuf)
-{
-       int type;
-       type = CVAL(inbuf,smb_com);
-  
-       DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
-                smb_fn_name(type), type, type));
-  
-       return(ERROR_DOS(ERRSRV,ERRunknownsmb));
-}
-
 void reply_unknown_new(struct smb_request *req, uint8 type)
 {
        DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
@@ -755,8 +783,9 @@ void reply_unknown_new(struct smb_request *req, uint8 type)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_ioctl(connection_struct *conn, struct smb_request *req)
+void reply_ioctl(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        uint16 device;
        uint16 function;
        uint32 ioctl_code;
@@ -844,8 +873,9 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
  Reply to a checkpath.
 ****************************************************************************/
 
-void reply_checkpath(connection_struct *conn, struct smb_request *req)
+void reply_checkpath(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *name = NULL;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
@@ -938,8 +968,9 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
  Reply to a getatr.
 ****************************************************************************/
 
-void reply_getatr(connection_struct *conn, struct smb_request *req)
+void reply_getatr(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *fname = NULL;
        SMB_STRUCT_STAT sbuf;
        int mode=0;
@@ -1039,8 +1070,10 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
  Reply to a setatr.
 ****************************************************************************/
 
-void reply_setatr(connection_struct *conn, struct smb_request *req)
+void reply_setatr(struct smb_request *req)
 {
+       struct timespec ts[2];
+       connection_struct *conn = req->conn;
        char *fname = NULL;
        int mode;
        time_t mtime;
@@ -1051,6 +1084,8 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
 
        START_PROFILE(SMBsetatr);
 
+       ZERO_STRUCT(ts);
+
        if (req->wct < 2) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                return;
@@ -1108,6 +1143,15 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
        mode = SVAL(req->inbuf,smb_vwv0);
        mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
 
+       ts[1] = convert_time_t_to_timespec(mtime);
+       status = smb_set_file_time(conn, NULL, fname,
+                                  &sbuf, ts, true);
+       if (!NT_STATUS_IS_OK(status)) {
+               reply_unixerror(req, ERRDOS, ERRnoaccess);
+               END_PROFILE(SMBsetatr);
+               return;
+       }
+
        if (mode != FILE_ATTRIBUTE_NORMAL) {
                if (VALID_STAT_OF_DIR(sbuf))
                        mode |= aDIR;
@@ -1121,12 +1165,6 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
                }
        }
 
-       if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
-               reply_unixerror(req, ERRDOS, ERRnoaccess);
-               END_PROFILE(SMBsetatr);
-               return;
-       }
-
        reply_outbuf(req, 0, 0);
  
        DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
@@ -1139,8 +1177,9 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
  Reply to a dskattr.
 ****************************************************************************/
 
-void reply_dskattr(connection_struct *conn, struct smb_request *req)
+void reply_dskattr(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_BIG_UINT dfree,dsize,bsize;
        START_PROFILE(SMBdskattr);
 
@@ -1163,8 +1202,8 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
                total_space = dsize * (double)bsize;
                free_space = dfree * (double)bsize;
 
-               dsize = (total_space+63*512) / (64*512);
-               dfree = (free_space+63*512) / (64*512);
+               dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512));
+               dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512));
                
                if (dsize > 0xFFFF) dsize = 0xFFFF;
                if (dfree > 0xFFFF) dfree = 0xFFFF;
@@ -1191,8 +1230,9 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
  Can be called from SMBsearch, SMBffirst or SMBfunique.
 ****************************************************************************/
 
-void reply_search(connection_struct *conn, struct smb_request *req)
+void reply_search(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *mask = NULL;
        char *directory = NULL;
        char *fname = NULL;
@@ -1214,6 +1254,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
        bool mask_contains_wcard = False;
        bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
        TALLOC_CTX *ctx = talloc_tos();
+       bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
 
        START_PROFILE(SMBsearch);
 
@@ -1399,8 +1440,16 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                }
 
                for (i=numentries;(i<maxentries) && !finished;i++) {
-                       finished = !get_dir_entry(ctx,conn,mask,dirtype,&fname,
-                                       &size,&mode,&date,check_descend);
+                       finished = !get_dir_entry(ctx,
+                                                 conn,
+                                                 mask,
+                                                 dirtype,
+                                                 &fname,
+                                                 &size,
+                                                 &mode,
+                                                 &date,
+                                                 check_descend,
+                                                 ask_sharemode);
                        if (!finished) {
                                char buf[DIR_STRUCT_SIZE];
                                memcpy(buf,status,21);
@@ -1493,7 +1542,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
  Reply to a fclose (stop directory search).
 ****************************************************************************/
 
-void reply_fclose(connection_struct *conn, struct smb_request *req)
+void reply_fclose(struct smb_request *req)
 {
        int status_len;
        char status[21];
@@ -1557,8 +1606,9 @@ void reply_fclose(connection_struct *conn, struct smb_request *req)
  Reply to an open.
 ****************************************************************************/
 
-void reply_open(connection_struct *conn, struct smb_request *req)
+void reply_open(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *fname = NULL;
        uint32 fattr=0;
        SMB_OFF_T size = 0;
@@ -1597,51 +1647,30 @@ void reply_open(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath(ctx, conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
-                               fname,
-                               &fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
-                                       ERRSRV, ERRbadpath);
-                       END_PROFILE(SMBopen);
-                       return;
-               }
-               reply_nterror(req, status);
-               END_PROFILE(SMBopen);
-               return;
-       }
-
-       status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               END_PROFILE(SMBopen);
-               return;
-       }
-
-       status = check_name(conn, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               END_PROFILE(SMBopen);
-               return;
-       }
-
-       if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
-                       &access_mask, &share_mode, &create_disposition, &create_options)) {
+       if (!map_open_params_to_ntcreate(
+                   fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
+                   &share_mode, &create_disposition, &create_options)) {
                reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
                END_PROFILE(SMBopen);
                return;
        }
 
-       status = open_file_ntcreate(conn, req, fname, &sbuf,
-                       access_mask,
-                       share_mode,
-                       create_disposition,
-                       create_options,
-                       dos_attr,
-                       oplock_request,
-                       &info, &fsp);
+       status = create_file(conn,                      /* conn */
+                            req,                       /* req */
+                            0,                         /* root_dir_fid */
+                            fname,                     /* fname */
+                            access_mask,               /* access_mask */
+                            share_mode,                /* share_access */
+                            create_disposition,        /* create_disposition*/
+                            create_options,            /* create_options */
+                            dos_attr,                  /* file_attributes */
+                            oplock_request,            /* oplock_request */
+                            0,                         /* allocation_size */
+                            NULL,                      /* sd */
+                            NULL,                      /* ea_list */
+                            &fsp,                      /* result */
+                            &info,                     /* pinfo */
+                            &sbuf);                    /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(req->mid)) {
@@ -1655,11 +1684,11 @@ void reply_open(connection_struct *conn, struct smb_request *req)
        }
 
        size = sbuf.st_size;
-       fattr = dos_mode(conn,fname,&sbuf);
+       fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
        mtime = sbuf.st_mtime;
 
        if (fattr & aDIR) {
-               DEBUG(3,("attempt to open a directory %s\n",fname));
+               DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
                close_file(fsp,ERROR_CLOSE);
                reply_doserror(req, ERRDOS,ERRnoaccess);
                END_PROFILE(SMBopen);
@@ -1694,8 +1723,9 @@ void reply_open(connection_struct *conn, struct smb_request *req)
  Reply to an open and X.
 ****************************************************************************/
 
-void reply_open_and_X(connection_struct *conn, struct smb_request *req)
+void reply_open_and_X(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *fname = NULL;
        uint16 open_flags;
        int deny_mode;
@@ -1762,53 +1792,30 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath(ctx, conn,
-                               req->flags2 & FLAGS2_DFS_PATHNAMES,
-                               fname,
-                               &fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBopenX);
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
-                                       ERRSRV, ERRbadpath);
-                       return;
-               }
-               reply_nterror(req, status);
-               return;
-       }
-
-       status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               END_PROFILE(SMBopenX);
-               return;
-       }
-
-       status = check_name(conn, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               END_PROFILE(SMBopenX);
-               return;
-       }
-
-       if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
-                               &access_mask,
-                               &share_mode,
-                               &create_disposition,
-                               &create_options)) {
+       if (!map_open_params_to_ntcreate(
+                   fname, deny_mode, smb_ofun, &access_mask,
+                   &share_mode, &create_disposition, &create_options)) {
                reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
                END_PROFILE(SMBopenX);
                return;
        }
 
-       status = open_file_ntcreate(conn, req, fname, &sbuf,
-                       access_mask,
-                       share_mode,
-                       create_disposition,
-                       create_options,
-                       smb_attr,
-                       oplock_request,
-                       &smb_action, &fsp);
+       status = create_file(conn,                      /* conn */
+                            req,                       /* req */
+                            0,                         /* root_dir_fid */
+                            fname,                     /* fname */
+                            access_mask,               /* access_mask */
+                            share_mode,                /* share_access */
+                            create_disposition,        /* create_disposition*/
+                            create_options,            /* create_options */
+                            smb_attr,                  /* file_attributes */
+                            oplock_request,            /* oplock_request */
+                            0,                         /* allocation_size */
+                            NULL,                      /* sd */
+                            NULL,                      /* ea_list */
+                            &fsp,                      /* result */
+                            &smb_action,               /* pinfo */
+                            &sbuf);                    /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopenX);
@@ -1840,7 +1847,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
                sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
        }
 
-       fattr = dos_mode(conn,fname,&sbuf);
+       fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
        mtime = sbuf.st_mtime;
        if (fattr & aDIR) {
                close_file(fsp,ERROR_CLOSE);
@@ -1905,10 +1912,9 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
 
 /****************************************************************************
  Reply to a SMBulogoffX.
- conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
+void reply_ulogoffX(struct smb_request *req)
 {
        user_struct *vuser;
 
@@ -1941,8 +1947,9 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
  Reply to a mknew or a create.
 ****************************************************************************/
 
-void reply_mknew(connection_struct *conn, struct smb_request *req)
+void reply_mknew(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *fname = NULL;
        int com;
        uint32 fattr = 0;
@@ -1982,35 +1989,6 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath(ctx, conn,
-                       req->flags2 & FLAGS2_DFS_PATHNAMES,
-                       fname,
-                       &fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBcreate);
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
-                                       ERRSRV, ERRbadpath);
-                       return;
-               }
-               reply_nterror(req, status);
-               return;
-       }
-
-       status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               END_PROFILE(SMBcreate);
-               return;
-       }
-
-       status = check_name(conn, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               END_PROFILE(SMBcreate);
-               return;
-       }
-
        if (fattr & aVOLID) {
                DEBUG(0,("Attempt to create file (%s) with volid set - "
                        "please report this\n", fname));
@@ -2024,15 +2002,22 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
                create_disposition = FILE_OVERWRITE_IF;
        }
 
-       /* Open file using ntcreate. */
-       status = open_file_ntcreate(conn, req, fname, &sbuf,
-                               access_mask,
-                               share_mode,
-                               create_disposition,
-                               create_options,
-                               fattr,
-                               oplock_request,
-                               NULL, &fsp);
+       status = create_file(conn,                      /* conn */
+                            req,                       /* req */
+                            0,                         /* root_dir_fid */
+                            fname,                     /* fname */
+                            access_mask,               /* access_mask */
+                            share_mode,                /* share_access */
+                            create_disposition,        /* create_disposition*/
+                            create_options,            /* create_options */
+                            fattr,                     /* file_attributes */
+                            oplock_request,            /* oplock_request */
+                            0,                         /* allocation_size */
+                            NULL,                      /* sd */
+                            NULL,                      /* ea_list */
+                            &fsp,                      /* result */
+                            NULL,                      /* pinfo */
+                            &sbuf);                    /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcreate);
@@ -2045,7 +2030,12 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
        }
 
        ts[0] = get_atimespec(&sbuf); /* atime. */
-       file_ntimes(conn, fname, ts);
+       status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBcreate);
+               reply_openerror(req, status);
+               return;
+       }
 
        reply_outbuf(req, 1, 0);
        SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
@@ -2060,9 +2050,9 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
                                CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
 
-       DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
+       DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
        DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
-                               fname, fsp->fh->fd, (unsigned int)fattr ) );
+                   fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
 
        END_PROFILE(SMBcreate);
        return;
@@ -2072,8 +2062,9 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
  Reply to a create temporary file.
 ****************************************************************************/
 
-void reply_ctemp(connection_struct *conn, struct smb_request *req)
+void reply_ctemp(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *fname = NULL;
        uint32 fattr;
        files_struct *fsp;
@@ -2140,7 +2131,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = check_name(conn, CONST_DISCARD(char *,fname));
+       status = check_name(conn, fname);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                END_PROFILE(SMBctemp);
@@ -2184,9 +2175,9 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)
        SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
 
        /* the returned filename is relative to the directory */
-       s = strrchr_m(fname, '/');
+       s = strrchr_m(fsp->fsp_name, '/');
        if (!s) {
-               s = fname;
+               s = fsp->fsp_name;
        } else {
                s++;
        }
@@ -2213,9 +2204,9 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)
                      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
 
-       DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
-       DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
-                       (unsigned int)sbuf.st_mode ) );
+       DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
+       DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
+                   fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
 
        END_PROFILE(SMBctemp);
        return;
@@ -2243,7 +2234,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
                return NT_STATUS_OK;
        }
 
-       if (fsp->access_mask & DELETE_ACCESS) {
+       if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
                return NT_STATUS_OK;
        }
 
@@ -2349,23 +2340,31 @@ static NTSTATUS do_unlink(connection_struct *conn,
        /* On open checks the open itself will check the share mode, so
           don't do it here as we'll get it wrong. */
 
-       status = open_file_ntcreate(conn, req, fname, &sbuf,
-                                   DELETE_ACCESS,
-                                   FILE_SHARE_NONE,
-                                   FILE_OPEN,
-                                   0,
-                                   FILE_ATTRIBUTE_NORMAL,
-                                   req != NULL ? 0 : INTERNAL_OPEN_ONLY,
-                                   NULL, &fsp);
+       status = create_file_unixpath
+               (conn,                  /* conn */
+                req,                   /* req */
+                fname,                 /* fname */
+                DELETE_ACCESS,         /* access_mask */
+                FILE_SHARE_NONE,       /* share_access */
+                FILE_OPEN,             /* create_disposition*/
+                FILE_NON_DIRECTORY_FILE, /* create_options */
+                FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+                0,                     /* oplock_request */
+                0,                     /* allocation_size */
+                NULL,                  /* sd */
+                NULL,                  /* ea_list */
+                &fsp,                  /* result */
+                NULL,                  /* pinfo */
+                &sbuf);                /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("open_file_ntcreate failed: %s\n",
+               DEBUG(10, ("create_file_unixpath failed: %s\n",
                           nt_errstr(status)));
                return status;
        }
 
        /* The set is across all open files on this dev/inode pair. */
-       if (!set_delete_on_close(fsp, True, &current_user.ut)) {
+       if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
                close_file(fsp, NORMAL_CLOSE);
                return NT_STATUS_ACCESS_DENIED;
        }
@@ -2470,7 +2469,8 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        return status;
                }
 
-               dir_hnd = OpenDir(conn, directory, mask, dirtype);
+               dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
+                                 dirtype);
                if (dir_hnd == NULL) {
                        return map_nt_error_from_unix(errno);
                }
@@ -2508,7 +2508,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
 
                        status = check_name(conn, fname);
                        if (!NT_STATUS_IS_OK(status)) {
-                               CloseDir(dir_hnd);
+                               TALLOC_FREE(dir_hnd);
                                return status;
                        }
 
@@ -2519,15 +2519,15 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        }
 
                        count++;
-                       DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
+                       DEBUG(3,("unlink_internals: successful unlink [%s]\n",
                                 fname));
 
                        TALLOC_FREE(fname);
                }
-               CloseDir(dir_hnd);
+               TALLOC_FREE(dir_hnd);
        }
 
-       if (count == 0 && NT_STATUS_IS_OK(status)) {
+       if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
                status = map_nt_error_from_unix(errno);
        }
 
@@ -2538,8 +2538,9 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
  Reply to a unlink
 ****************************************************************************/
 
-void reply_unlink(connection_struct *conn, struct smb_request *req)
+void reply_unlink(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *name = NULL;
        uint32 dirtype;
        NTSTATUS status;
@@ -2705,7 +2706,7 @@ void send_file_readbraw(connection_struct *conn,
         * reply_readbraw has already checked the length.
         */
 
-       if ( (chain_size == 0) && (nread > 0) &&
+       if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
            (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
                char header[4];
                DATA_BLOB header_blob;
@@ -2713,7 +2714,7 @@ void send_file_readbraw(connection_struct *conn,
                _smb_setlen(header,nread);
                header_blob = data_blob_const(header, 4);
 
-               if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
+               if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
                                &header_blob, startpos, nread) == -1) {
                        /* Returning ENOSYS means no data at all was sent.
                         * Do this as a normal read. */
@@ -2780,8 +2781,9 @@ normal_readbraw:
  Reply to a readbraw (core+ protocol).
 ****************************************************************************/
 
-void reply_readbraw(connection_struct *conn, struct smb_request *req)
+void reply_readbraw(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        ssize_t maxcount,mincount;
        size_t nread = 0;
        SMB_OFF_T startpos;
@@ -2791,8 +2793,8 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req)
 
        START_PROFILE(SMBreadbraw);
 
-       if (srv_is_signing_active()) {
-               exit_server_cleanly("reply_readbraw: SMB signing is active - "
+       if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
+               exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
                        "raw reads/writes are disallowed.");
        }
 
@@ -2817,7 +2819,7 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req)
         */
 
        if (!fsp || !conn || conn != fsp->conn ||
-                       current_user.vuid != fsp->vuid ||
+                       req->vuid != fsp->vuid ||
                        fsp->is_directory || fsp->fh->fd == -1) {
                /*
                 * fsp could be NULL here so use the value from the packet. JRA.
@@ -2895,7 +2897,7 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
+       if (SMB_VFS_FSTAT(fsp, &st) == 0) {
                size = st.st_size;
        }
 
@@ -2930,8 +2932,9 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req)
  Reply to a lockread (core+ protocol).
 ****************************************************************************/
 
-void reply_lockread(connection_struct *conn, struct smb_request *req)
+void reply_lockread(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        ssize_t nread = -1;
        char *data;
        SMB_OFF_T startpos;
@@ -2951,7 +2954,7 @@ void reply_lockread(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBlockread);
                return;
        }
@@ -3017,7 +3020,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                return;
        }
        
-       set_message((char *)req->outbuf, 5, nread+3, False);
+       srv_set_message((char *)req->outbuf, 5, nread+3, False);
 
        SSVAL(req->outbuf,smb_vwv0,nread);
        SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -3039,8 +3042,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
  Reply to a read.
 ****************************************************************************/
 
-void reply_read(connection_struct *conn, struct smb_request *req)
+void reply_read(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        size_t numtoread;
        ssize_t nread = 0;
        char *data;
@@ -3058,7 +3062,7 @@ void reply_read(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBread);
                return;
        }
@@ -3104,7 +3108,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                return;
        }
 
-       set_message((char *)req->outbuf, 5, nread+3, False);
+       srv_set_message((char *)req->outbuf, 5, nread+3, False);
 
        SSVAL(req->outbuf,smb_vwv0,nread);
        SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -3127,7 +3131,7 @@ static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
        int outsize;
        char *data;
 
-       outsize = set_message(outbuf,12,smb_maxcnt,False);
+       outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
        data = smb_buf(outbuf);
 
        memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
@@ -3154,7 +3158,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
        SMB_STRUCT_STAT sbuf;
        ssize_t nread = -1;
 
-       if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
+       if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
                reply_unixerror(req, ERRDOS, ERRnoaccess);
                return;
        }
@@ -3177,6 +3181,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
         */
 
        if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
+           !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
            lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
                uint8 headerbuf[smb_size + 12 * 2];
                DATA_BLOB header;
@@ -3192,9 +3197,10 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                construct_reply_common((char *)req->inbuf, (char *)headerbuf);
                setup_readX_header((char *)headerbuf, smb_maxcnt);
 
-               if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
-                       /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
-                       if (errno == ENOSYS) {
+               if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
+                       /* Returning ENOSYS or EINVAL means no data at all was sent. 
+                          Do this as a normal read. */
+                       if (errno == ENOSYS || errno == EINVAL) {
                                goto normal_read;
                        }
 
@@ -3283,8 +3289,9 @@ normal_read:
  Reply to a read and X.
 ****************************************************************************/
 
-void reply_read_and_X(connection_struct *conn, struct smb_request *req)
+void reply_read_and_X(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        files_struct *fsp;
        SMB_OFF_T startpos;
        size_t smb_maxcnt;
@@ -3311,7 +3318,7 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBreadX);
                return;
        }
@@ -3332,8 +3339,8 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req)
                                END_PROFILE(SMBreadX);
                                return;
                        }
-                       /* We currently don't do this on signed data. */
-                       if (srv_is_signing_active()) {
+                       /* We currently don't do this on signed or sealed data. */
+                       if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
                                reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
                                END_PROFILE(SMBreadX);
                                return;
@@ -3382,8 +3389,8 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       if (!big_readX
-           && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
+       if (!big_readX &&
+           schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
                END_PROFILE(SMBreadX);
                return;
        }
@@ -3412,9 +3419,9 @@ void error_to_writebrawerr(struct smb_request *req)
  Reply to a writebraw (core+ or LANMAN1.0 protocol).
 ****************************************************************************/
 
-void reply_writebraw(connection_struct *conn, struct smb_request *req)
+void reply_writebraw(struct smb_request *req)
 {
-       int outsize = 0;
+       connection_struct *conn = req->conn;
        char *buf = NULL;
        ssize_t nwritten=0;
        ssize_t total_written=0;
@@ -3449,7 +3456,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
        }
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                error_to_writebrawerr(req);
                END_PROFILE(SMBwritebraw);
                return;
@@ -3524,28 +3531,24 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
         * it to send more bytes */
 
        memcpy(buf, req->inbuf, smb_size);
-       outsize = set_message(buf,
-                       Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+       srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
        SCVAL(buf,smb_com,SMBwritebraw);
        SSVALS(buf,smb_vwv0,0xFFFF);
        show_msg(buf);
-       if (!send_smb(smbd_server_fd(),buf)) {
-               exit_server_cleanly("reply_writebraw: send_smb "
+       if (!srv_send_smb(smbd_server_fd(),
+                       buf,
+                       IS_CONN_ENCRYPTED(conn))) {
+               exit_server_cleanly("reply_writebraw: srv_send_smb "
                        "failed.");
        }
 
        /* Now read the raw data into the buffer and write it */
-       if (read_smb_length(smbd_server_fd(),buf,SMB_SECONDARY_WAIT) == -1) {
+       status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
+                                &numtowrite);
+       if (!NT_STATUS_IS_OK(status)) {
                exit_server_cleanly("secondary writebraw failed");
        }
 
-       /*
-        * Even though this is not an smb message,
-        * smb_len returns the generic length of a packet.
-        */
-
-       numtowrite = smb_len(buf);
-
        /* Set up outbuf to return the correct size */
        reply_outbuf(req, 1, 0);
 
@@ -3564,11 +3567,12 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
                                (int)tcount,(int)nwritten,(int)numtowrite));
                }
 
-               if (read_data(smbd_server_fd(), buf+4, numtowrite)
-                                       != numtowrite ) {
+               status = read_data(smbd_server_fd(), buf+4, numtowrite);
+
+               if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0,("reply_writebraw: Oversize secondary write "
-                               "raw read failed (%s). Terminating\n",
-                               strerror(errno) ));
+                                "raw read failed (%s). Terminating\n",
+                                nt_errstr(status)));
                        exit_server_cleanly("secondary writebraw failed");
                }
 
@@ -3638,8 +3642,9 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
  Reply to a writeunlock (core+).
 ****************************************************************************/
 
-void reply_writeunlock(connection_struct *conn, struct smb_request *req)
+void reply_writeunlock(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        ssize_t nwritten = -1;
        size_t numtowrite;
        SMB_OFF_T startpos;
@@ -3657,7 +3662,7 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req)
        
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBwriteunlock);
                return;
        }
@@ -3737,8 +3742,9 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req)
  Reply to a write.
 ****************************************************************************/
 
-void reply_write(connection_struct *conn, struct smb_request *req)
+void reply_write(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        size_t numtowrite;
        ssize_t nwritten = -1;
        SMB_OFF_T startpos;
@@ -3763,7 +3769,7 @@ void reply_write(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBwrite);
                return;
        }
@@ -3848,35 +3854,58 @@ void reply_write(connection_struct *conn, struct smb_request *req)
                                                (2*14) + /* word count (including bcc) */ \
                                                1 /* pad byte */)
 
-bool is_valid_writeX_buffer(char *inbuf)
+bool is_valid_writeX_buffer(const uint8_t *inbuf)
 {
        size_t numtowrite;
        connection_struct *conn = NULL;
        unsigned int doff = 0;
-       size_t len = smb_len(inbuf);
+       size_t len = smb_len_large(inbuf);
+
+       if (is_encrypted_packet(inbuf)) {
+               /* Can't do this on encrypted
+                * connections. */
+               return false;
+       }
+
+       if (CVAL(inbuf,smb_com) != SMBwriteX) {
+               return false;
+       }
 
-       if (CVAL(inbuf,smb_com) != SMBwriteX ||
-                       CVAL(inbuf,smb_vwv0) != 0xFF ||
+       if (CVAL(inbuf,smb_vwv0) != 0xFF ||
                        CVAL(inbuf,smb_wct) != 14) {
+               DEBUG(10,("is_valid_writeX_buffer: chained or "
+                       "invalid word length.\n"));
                return false;
        }
+
        conn = conn_find(SVAL(inbuf, smb_tid));
        if (conn == NULL) {
+               DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
                return false;
        }
        if (IS_IPC(conn)) {
+               DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
                return false;
        }
+       doff = SVAL(inbuf,smb_vwv11);
+
        numtowrite = SVAL(inbuf,smb_vwv10);
-       numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
+
+       if (len > doff && len - doff > 0xFFFF) {
+               numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
+       }
+
        if (numtowrite == 0) {
+               DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
                return false;
        }
-       /* Ensure the sizes match up. */
-       doff = SVAL(inbuf,smb_vwv11);
 
+       /* Ensure the sizes match up. */
        if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
                /* no pad byte...old smbclient :-( */
+               DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
+                       (unsigned int)doff,
+                       (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
                return false;
        }
 
@@ -3902,8 +3931,9 @@ bool is_valid_writeX_buffer(char *inbuf)
  Reply to a write and X.
 ****************************************************************************/
 
-void reply_write_and_X(connection_struct *conn, struct smb_request *req)
+void reply_write_and_X(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        files_struct *fsp;
        SMB_OFF_T startpos;
        size_t numtowrite;
@@ -3933,6 +3963,12 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
        }
 
        if (req->unread_bytes) {
+               /* Can't do a recvfile write on IPC$ */
+               if (IS_IPC(conn)) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       END_PROFILE(SMBwriteX);
+                       return;
+               }
                if (numtowrite != req->unread_bytes) {
                        reply_doserror(req, ERRDOS, ERRbadmem);
                        END_PROFILE(SMBwriteX);
@@ -3963,7 +3999,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
        startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
        write_through = BITSETW(req->inbuf+smb_vwv7,0);
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBwriteX);
                return;
        }
@@ -4018,13 +4054,13 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
                nwritten = 0;
        } else {
 
-               if (req->unread_bytes == 0 &&
-                               schedule_aio_write_and_X(conn, req, fsp, data,
-                                                       startpos, numtowrite)) {
+               if ((req->unread_bytes == 0) &&
+                   schedule_aio_write_and_X(conn, req, fsp, data, startpos,
+                                            numtowrite)) {
                        END_PROFILE(SMBwriteX);
                        return;
                }
-
+               
                nwritten = write_file(req,fsp,data,startpos,numtowrite);
        }
 
@@ -4064,8 +4100,9 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
  Reply to a lseek.
 ****************************************************************************/
 
-void reply_lseek(connection_struct *conn, struct smb_request *req)
+void reply_lseek(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_OFF_T startpos;
        SMB_OFF_T res= -1;
        int mode,umode;
@@ -4081,7 +4118,7 @@ void reply_lseek(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                return;
        }
 
@@ -4110,12 +4147,12 @@ void reply_lseek(connection_struct *conn, struct smb_request *req)
        }
 
        if (umode == SEEK_END) {
-               if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
+               if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
                        if(errno == EINVAL) {
                                SMB_OFF_T current_pos = startpos;
                                SMB_STRUCT_STAT sbuf;
 
-                               if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
+                               if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
                                        reply_unixerror(req, ERRDOS,
                                                        ERRnoaccess);
                                        END_PROFILE(SMBlseek);
@@ -4124,7 +4161,7 @@ void reply_lseek(connection_struct *conn, struct smb_request *req)
 
                                current_pos += sbuf.st_size;
                                if(current_pos < 0)
-                                       res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
+                                       res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
                        }
                }
 
@@ -4151,8 +4188,9 @@ void reply_lseek(connection_struct *conn, struct smb_request *req)
  Reply to a flush.
 ****************************************************************************/
 
-void reply_flush(connection_struct *conn, struct smb_request *req)
+void reply_flush(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        uint16 fnum;
        files_struct *fsp;
 
@@ -4166,7 +4204,7 @@ void reply_flush(connection_struct *conn, struct smb_request *req)
        fnum = SVAL(req->inbuf,smb_vwv0);
        fsp = file_fsp(fnum);
 
-       if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
+       if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
                return;
        }
        
@@ -4195,7 +4233,7 @@ void reply_flush(connection_struct *conn, struct smb_request *req)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_exit(connection_struct *conn, struct smb_request *req)
+void reply_exit(struct smb_request *req)
 {
        START_PROFILE(SMBexit);
 
@@ -4213,8 +4251,9 @@ void reply_exit(connection_struct *conn, struct smb_request *req)
  Reply to a close - has to deal with closing a directory opened by NT SMB's.
 ****************************************************************************/
 
-void reply_close(connection_struct *conn, struct smb_request *req)
+void reply_close(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        NTSTATUS status = NT_STATUS_OK;
        files_struct *fsp = NULL;
        START_PROFILE(SMBclose);
@@ -4238,7 +4277,7 @@ void reply_close(connection_struct *conn, struct smb_request *req)
         * We can only use CHECK_FSP if we know it's not a directory.
         */
 
-       if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
+       if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
                reply_doserror(req, ERRDOS, ERRbadfid);
                END_PROFILE(SMBclose);
                return;
@@ -4251,6 +4290,7 @@ void reply_close(connection_struct *conn, struct smb_request *req)
                DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
                status = close_file(fsp,NORMAL_CLOSE);
        } else {
+               time_t t;
                /*
                 * Close ordinary file.
                 */
@@ -4263,9 +4303,8 @@ void reply_close(connection_struct *conn, struct smb_request *req)
                 * Take care of any time sent in the close.
                 */
 
-               fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
-                                               srv_make_unix_date3(
-                                                       req->inbuf+smb_vwv1)));
+               t = srv_make_unix_date3(req->inbuf+smb_vwv1);
+               set_close_write_time(fsp, convert_time_t_to_timespec(t));
 
                /*
                 * close_file() returns the unix errno if an error
@@ -4291,8 +4330,9 @@ void reply_close(connection_struct *conn, struct smb_request *req)
  Reply to a writeclose (Core+ protocol).
 ****************************************************************************/
 
-void reply_writeclose(connection_struct *conn, struct smb_request *req)
+void reply_writeclose(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        size_t numtowrite;
        ssize_t nwritten = -1;
        NTSTATUS close_status = NT_STATUS_OK;
@@ -4311,7 +4351,7 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBwriteclose);
                return;
        }
@@ -4337,8 +4377,8 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req)
   
        nwritten = write_file(req,fsp,data,startpos,numtowrite);
 
-       set_filetime(conn, fsp->fsp_name, mtime);
-  
+       set_close_write_time(fsp, mtime);
+
        /*
         * More insanity. W2K only closes the file if writelen > 0.
         * JRA.
@@ -4380,8 +4420,9 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req)
  Reply to a lock.
 ****************************************************************************/
 
-void reply_lock(connection_struct *conn, struct smb_request *req)
+void reply_lock(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
        files_struct *fsp;
@@ -4397,7 +4438,7 @@ void reply_lock(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBlock);
                return;
        }
@@ -4439,8 +4480,9 @@ void reply_lock(connection_struct *conn, struct smb_request *req)
  Reply to a unlock.
 ****************************************************************************/
 
-void reply_unlock(connection_struct *conn, struct smb_request *req)
+void reply_unlock(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
        files_struct *fsp;
@@ -4455,7 +4497,7 @@ void reply_unlock(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBunlock);
                return;
        }
@@ -4493,8 +4535,9 @@ void reply_unlock(connection_struct *conn, struct smb_request *req)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_tdis(connection_struct *conn, struct smb_request *req)
+void reply_tdis(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        START_PROFILE(SMBtdis);
 
        if (!conn) {
@@ -4507,6 +4550,7 @@ void reply_tdis(connection_struct *conn, struct smb_request *req)
        conn->used = False;
 
        close_cnum(conn,req->vuid);
+       req->conn = NULL;
 
        reply_outbuf(req, 0, 0);
        END_PROFILE(SMBtdis);
@@ -4518,8 +4562,9 @@ void reply_tdis(connection_struct *conn, struct smb_request *req)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_echo(connection_struct *conn, struct smb_request *req)
+void reply_echo(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        int smb_reverb;
        int seq_num;
        unsigned int data_len = smb_buflen(req->inbuf);
@@ -4557,8 +4602,10 @@ void reply_echo(connection_struct *conn, struct smb_request *req)
                SSVAL(req->outbuf,smb_vwv0,seq_num);
 
                show_msg((char *)req->outbuf);
-               if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
-                       exit_server_cleanly("reply_echo: send_smb failed.");
+               if (!srv_send_smb(smbd_server_fd(),
+                               (char *)req->outbuf,
+                               IS_CONN_ENCRYPTED(conn)||req->encrypted))
+                       exit_server_cleanly("reply_echo: srv_send_smb failed.");
        }
 
        DEBUG(3,("echo %d times\n", smb_reverb));
@@ -4575,8 +4622,9 @@ void reply_echo(connection_struct *conn, struct smb_request *req)
  Reply to a printopen.
 ****************************************************************************/
 
-void reply_printopen(connection_struct *conn, struct smb_request *req)
+void reply_printopen(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        files_struct *fsp;
        NTSTATUS status;
        
@@ -4595,7 +4643,7 @@ void reply_printopen(connection_struct *conn, struct smb_request *req)
        }
 
        /* Open for exclusive use, write only. */
-       status = print_fsp_open(conn, NULL, &fsp);
+       status = print_fsp_open(conn, NULL, req->vuid, &fsp);
 
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -4617,14 +4665,15 @@ void reply_printopen(connection_struct *conn, struct smb_request *req)
  Reply to a printclose.
 ****************************************************************************/
 
-void reply_printclose(connection_struct *conn, struct smb_request *req)
+void reply_printclose(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        files_struct *fsp;
        NTSTATUS status;
 
        START_PROFILE(SMBsplclose);
 
-       if (req->wct < 3) {
+       if (req->wct < 1) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBsplclose);
                return;
@@ -4632,7 +4681,7 @@ void reply_printclose(connection_struct *conn, struct smb_request *req)
 
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBsplclose);
                 return;
         }
@@ -4654,6 +4703,8 @@ void reply_printclose(connection_struct *conn, struct smb_request *req)
                return;
        }
 
+       reply_outbuf(req, 0, 0);
+
        END_PROFILE(SMBsplclose);
        return;
 }
@@ -4662,8 +4713,9 @@ void reply_printclose(connection_struct *conn, struct smb_request *req)
  Reply to a printqueue.
 ****************************************************************************/
 
-void reply_printqueue(connection_struct *conn, struct smb_request *req)
+void reply_printqueue(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        int max_count;
        int start_index;
 
@@ -4754,8 +4806,9 @@ void reply_printqueue(connection_struct *conn, struct smb_request *req)
  Reply to a printwrite.
 ****************************************************************************/
 
-void reply_printwrite(connection_struct *conn, struct smb_request *req)
+void reply_printwrite(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        int numtowrite;
        char *data;
        files_struct *fsp;
@@ -4770,7 +4823,7 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req)
   
        fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBsplwr);
                 return;
         }
@@ -4813,8 +4866,9 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req)
  Reply to a mkdir.
 ****************************************************************************/
 
-void reply_mkdir(connection_struct *conn, struct smb_request *req)
+void reply_mkdir(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *directory = NULL;
        NTSTATUS status;
        SMB_STRUCT_STAT sbuf;
@@ -4861,7 +4915,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = create_directory(conn, directory);
+       status = create_directory(conn, req, directory);
 
        DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
 
@@ -4903,7 +4957,8 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
        const char *dname = NULL;
        bool ret = True;
        long offset = 0;
-       struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
+       struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
+                                         NULL, 0);
 
        if(dir_hnd == NULL)
                return False;
@@ -4951,7 +5006,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
                }
                TALLOC_FREE(fullname);
        }
-       CloseDir(dir_hnd);
+       TALLOC_FREE(dir_hnd);
        return ret;
 }
 
@@ -4999,7 +5054,8 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                 */
                const char *dname;
                long dirpos = 0;
-               struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
+               struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
+                                                 directory, NULL, 0);
 
                if(dir_hnd == NULL) {
                        errno = ENOTEMPTY;
@@ -5012,7 +5068,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                        if (!is_visible_file(conn, directory, dname, &st, False))
                                continue;
                        if(!IS_VETO_PATH(conn, dname)) {
-                               CloseDir(dir_hnd);
+                               TALLOC_FREE(dir_hnd);
                                errno = ENOTEMPTY;
                                goto err;
                        }
@@ -5057,7 +5113,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                        }
                        TALLOC_FREE(fullname);
                }
-               CloseDir(dir_hnd);
+               TALLOC_FREE(dir_hnd);
                /* Retry the rmdir */
                ret = SMB_VFS_RMDIR(conn,directory);
        }
@@ -5081,8 +5137,9 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
  Reply to a rmdir.
 ****************************************************************************/
 
-void reply_rmdir(connection_struct *conn, struct smb_request *req)
+void reply_rmdir(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *directory = NULL;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
@@ -5291,7 +5348,7 @@ static void rename_open_files(connection_struct *conn,
                   sharepaths we need to manipulate relative paths. */
                /* TODO - create the absolute path and manipulate the newname
                   relative to the sharepath. */
-               if (fsp->conn != conn) {
+               if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
                        continue;
                }
                DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
@@ -5488,7 +5545,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 
        /* Ensure we have a valid stat struct for the source. */
        if (fsp->fh->fd != -1) {
-               if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
+               if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
                        return map_nt_error_from_unix(errno);
                }
        } else {
@@ -5511,7 +5568,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+       lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+                                 NULL);
 
        /*
         * We have the file open ourselves, so not being able to get the
@@ -5581,7 +5639,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        uint32 attrs,
                        bool replace_if_exists,
                        bool src_has_wild,
-                       bool dest_has_wild)
+                       bool dest_has_wild,
+                       uint32_t access_mask)
 {
        char *directory = NULL;
        char *mask = NULL;
@@ -5711,12 +5770,12 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
 
                status = S_ISDIR(sbuf1.st_mode) ?
                        open_directory(conn, req, directory, &sbuf1,
-                                      DELETE_ACCESS,
+                                      access_mask,
                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
                                       FILE_OPEN, 0, 0, NULL,
                                       &fsp)
                        : open_file_ntcreate(conn, req, directory, &sbuf1,
-                                            DELETE_ACCESS,
+                                            access_mask,
                                             FILE_SHARE_READ|FILE_SHARE_WRITE,
                                             FILE_OPEN, 0, 0, 0, NULL,
                                             &fsp);
@@ -5752,7 +5811,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                return status;
        }
 
-       dir_hnd = OpenDir(conn, directory, mask, attrs);
+       dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
        if (dir_hnd == NULL) {
                return map_nt_error_from_unix(errno);
        }
@@ -5815,12 +5874,12 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
 
                status = S_ISDIR(sbuf1.st_mode) ?
                        open_directory(conn, req, fname, &sbuf1,
-                                      DELETE_ACCESS,
+                                      access_mask,
                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
                                       FILE_OPEN, 0, 0, NULL,
                                       &fsp)
                        : open_file_ntcreate(conn, req, fname, &sbuf1,
-                                            DELETE_ACCESS,
+                                            access_mask,
                                             FILE_SHARE_READ|FILE_SHARE_WRITE,
                                             FILE_OPEN, 0, 0, 0, NULL,
                                             &fsp);
@@ -5852,9 +5911,9 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                TALLOC_FREE(fname);
                TALLOC_FREE(destname);
        }
-       CloseDir(dir_hnd);
+       TALLOC_FREE(dir_hnd);
 
-       if (count == 0 && NT_STATUS_IS_OK(status)) {
+       if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
                status = map_nt_error_from_unix(errno);
        }
 
@@ -5865,8 +5924,9 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
  Reply to a mv.
 ****************************************************************************/
 
-void reply_mv(connection_struct *conn, struct smb_request *req)
+void reply_mv(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *name = NULL;
        char *newname = NULL;
        char *p;
@@ -5942,7 +6002,7 @@ void reply_mv(connection_struct *conn, struct smb_request *req)
        DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
 
        status = rename_internals(ctx, conn, req, name, newname, attrs, False,
-                                 src_has_wcard, dest_has_wcard);
+                                 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
@@ -6054,7 +6114,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
        }
 
        if ((ofun&3) == 1) {
-               if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
+               if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
                        DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
                        /*
                         * Stop the copy from occurring.
@@ -6071,7 +6131,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
        close_file(fsp1,NORMAL_CLOSE);
 
        /* Ensure the modtime is set correctly on the destination file. */
-       fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
+       set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
 
        /*
         * As we are opening fsp1 read-only we only expect
@@ -6096,8 +6156,9 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
  Reply to a file copy.
 ****************************************************************************/
 
-void reply_copy(connection_struct *conn, struct smb_request *req)
+void reply_copy(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *name = NULL;
        char *newname = NULL;
        char *directory = NULL;
@@ -6324,7 +6385,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                        return;
                }
 
-               dir_hnd = OpenDir(conn, directory, mask, 0);
+               dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
                if (dir_hnd == NULL) {
                        status = map_nt_error_from_unix(errno);
                        reply_nterror(req, status);
@@ -6356,6 +6417,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                                        directory,
                                        dname);
                        if (!fname) {
+                               TALLOC_FREE(dir_hnd);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                END_PROFILE(SMBcopy);
                                return;
@@ -6366,6 +6428,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                                continue;
                        }
                        if (!destname) {
+                               TALLOC_FREE(dir_hnd);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                END_PROFILE(SMBcopy);
                                return;
@@ -6373,6 +6436,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
 
                        status = check_name(conn, fname);
                        if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(dir_hnd);
                                reply_nterror(req, status);
                                END_PROFILE(SMBcopy);
                                return;
@@ -6380,6 +6444,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
 
                        status = check_name(conn, destname);
                        if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(dir_hnd);
                                reply_nterror(req, status);
                                END_PROFILE(SMBcopy);
                                return;
@@ -6395,7 +6460,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                        TALLOC_FREE(fname);
                        TALLOC_FREE(destname);
                }
-               CloseDir(dir_hnd);
+               TALLOC_FREE(dir_hnd);
        }
 
        if (count == 0) {
@@ -6559,8 +6624,9 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_forma
  Reply to a lockingX request.
 ****************************************************************************/
 
-void reply_lockingX(connection_struct *conn, struct smb_request *req)
+void reply_lockingX(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        files_struct *fsp;
        unsigned char locktype;
        unsigned char oplocklevel;
@@ -6591,7 +6657,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req)
        lock_timeout = IVAL(req->inbuf,smb_vwv4);
        large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
 
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                END_PROFILE(SMBlockingX);
                return;
        }
@@ -6834,8 +6900,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req)
                                 * onto the blocking lock queue.
                                 */
                                if(push_blocking_lock_request(br_lck,
-                                                       (char *)req->inbuf,
-                                                       smb_len(req->inbuf)+4,
+                                                       req,
                                                        fsp,
                                                        lock_timeout,
                                                        i,
@@ -6918,7 +6983,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req)
  please contact vl@samba.org
 ****************************************************************************/
 
-void reply_readbmpx(connection_struct *conn, struct smb_request *req)
+void reply_readbmpx(struct smb_request *req)
 {
        START_PROFILE(SMBreadBmpx);
        reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -6932,7 +6997,7 @@ void reply_readbmpx(connection_struct *conn, struct smb_request *req)
  please contact vl@samba.org
 ****************************************************************************/
 
-void reply_readbs(connection_struct *conn, struct smb_request *req)
+void reply_readbs(struct smb_request *req)
 {
        START_PROFILE(SMBreadBs);
        reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -6944,10 +7009,13 @@ void reply_readbs(connection_struct *conn, struct smb_request *req)
  Reply to a SMBsetattrE.
 ****************************************************************************/
 
-void reply_setattrE(connection_struct *conn, struct smb_request *req)
+void reply_setattrE(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        struct timespec ts[2];
        files_struct *fsp;
+       SMB_STRUCT_STAT sbuf;
+       NTSTATUS status;
 
        START_PROFILE(SMBsetattrE);
 
@@ -6983,22 +7051,26 @@ void reply_setattrE(connection_struct *conn, struct smb_request *req)
         * Sometimes times are sent as zero - ignore them.
         */
 
-       if (null_timespec(ts[0]) && null_timespec(ts[1])) {
-               /* Ignore request */
-               if( DEBUGLVL( 3 ) ) {
-                       dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
-                       dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
+       /* Ensure we have a valid stat struct for the source. */
+       if (fsp->fh->fd != -1) {
+               if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+                       status = map_nt_error_from_unix(errno);
+                       reply_nterror(req, status);
+                       END_PROFILE(SMBsetattrE);
+                       return;
+               }
+       } else {
+               if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
+                       status = map_nt_error_from_unix(errno);
+                       reply_nterror(req, status);
+                       END_PROFILE(SMBsetattrE);
+                       return;
                }
-               END_PROFILE(SMBsetattrE);
-               return;
-       } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
-               /* set modify time = to access time if modify time was unset */
-               ts[1] = ts[0];
        }
 
-       /* Set the date on this file */
-       /* Should we set pending modtime here ? JRA */
-       if(file_ntimes(conn, fsp->fsp_name, ts)) {
+       status = smb_set_file_time(conn, fsp, fsp->fsp_name,
+                                  &sbuf, ts, true);
+       if (!NT_STATUS_IS_OK(status)) {
                reply_doserror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBsetattrE);
                return;
@@ -7022,7 +7094,7 @@ void reply_setattrE(connection_struct *conn, struct smb_request *req)
  please contact vl@samba.org
 ****************************************************************************/
 
-void reply_writebmpx(connection_struct *conn, struct smb_request *req)
+void reply_writebmpx(struct smb_request *req)
 {
        START_PROFILE(SMBwriteBmpx);
        reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -7036,7 +7108,7 @@ void reply_writebmpx(connection_struct *conn, struct smb_request *req)
  please contact vl@samba.org
 ****************************************************************************/
 
-void reply_writebs(connection_struct *conn, struct smb_request *req)
+void reply_writebs(struct smb_request *req)
 {
        START_PROFILE(SMBwriteBs);
        reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -7048,8 +7120,9 @@ void reply_writebs(connection_struct *conn, struct smb_request *req)
  Reply to a SMBgetattrE.
 ****************************************************************************/
 
-void reply_getattrE(connection_struct *conn, struct smb_request *req)
+void reply_getattrE(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_STRUCT_STAT sbuf;
        int mode;
        files_struct *fsp;