r6146: Added OS/2 EA support in trans2_open and trans2_mkdir. Fixed in nttrans_create.
[samba.git] / source / smbd / nttrans.c
index e7d7c20f6beb3ebee8dc2ad5662546db734945b5..70b3f0d0e00ce4479fda61a3f3379043710234e0 100644 (file)
 
 #include "includes.h"
 
-extern int Protocol;
+extern enum protocol_types Protocol;
 extern int smb_read_error;
 extern int global_oplock_break;
-extern BOOL case_sensitive;
-extern BOOL case_preserve;
-extern BOOL short_case_preserve;
 extern struct current_user current_user;
 
 static const char *known_nt_pipes[] = {
@@ -43,7 +40,8 @@ static const char *known_nt_pipes[] = {
        "\\spoolss",
        "\\netdfs",
        "\\rpcecho",
-       "\\epmapper",
+        "\\svcctl",
+       "\\eventlog",
        NULL
 };
 
@@ -56,17 +54,18 @@ struct generic_mapping file_generic_mapping = {
        FILE_GENERIC_ALL
 };
 
-char *nttrans_realloc(char **ptr, size_t size)
+static char *nttrans_realloc(char **ptr, size_t size)
 {
        char *tptr = NULL;
        if (ptr==NULL)
                smb_panic("nttrans_realloc() called with NULL ptr\n");
                
-       tptr = Realloc_zero(*ptr, size);
+       tptr = SMB_REALLOC(*ptr, size);
        if(tptr == NULL) {
                *ptr = NULL;
                return NULL;
        }
+       memset(tptr,'\0',size);
 
        *ptr = tptr;
 
@@ -275,33 +274,33 @@ static BOOL saved_short_case_preserve;
  Save case semantics.
 ****************************************************************************/
 
-static void set_posix_case_semantics(uint32 file_attributes)
+static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
 {
        if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
                return;
 
-       saved_case_sensitive = case_sensitive;
-       saved_case_preserve = case_preserve;
-       saved_short_case_preserve = short_case_preserve;
+       saved_case_sensitive = conn->case_sensitive;
+       saved_case_preserve = conn->case_preserve;
+       saved_short_case_preserve = conn->short_case_preserve;
 
        /* Set to POSIX. */
-       case_sensitive = True;
-       case_preserve = True;
-       short_case_preserve = True;
+       conn->case_sensitive = True;
+       conn->case_preserve = True;
+       conn->short_case_preserve = True;
 }
 
 /****************************************************************************
  Restore case semantics.
 ****************************************************************************/
 
-static void restore_case_semantics(uint32 file_attributes)
+static void restore_case_semantics(connection_struct *conn, uint32 file_attributes)
 {
        if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
                return;
 
-       case_sensitive = saved_case_sensitive;
-       case_preserve = saved_case_preserve;
-       short_case_preserve = saved_short_case_preserve;
+       conn->case_sensitive = saved_case_sensitive;
+       conn->case_preserve = saved_case_preserve;
+       conn->short_case_preserve = saved_short_case_preserve;
 }
 
 /****************************************************************************
@@ -354,6 +353,12 @@ static int map_share_mode( char *fname, uint32 create_options,
                        uint32 *desired_access, uint32 share_access, uint32 file_attributes)
 {
        int smb_open_mode = -1;
+       uint32 original_desired_access = *desired_access;
+
+       /* This is a nasty hack - must fix... JRA. */
+       if (*desired_access == MAXIMUM_ALLOWED_ACCESS) {
+               *desired_access = FILE_GENERIC_ALL;
+       }
 
        /*
         * Convert GENERIC bits to specific bits.
@@ -425,6 +430,10 @@ static int map_share_mode( char *fname, uint32 create_options,
                DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode));
        }
 
+       if(*desired_access & DELETE_ACCESS) {
+               DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode));
+       }
+
        /*
         * We need to store the intent to open for Delete. This
         * is what determines if a delete on close flag can be set.
@@ -432,11 +441,19 @@ static int map_share_mode( char *fname, uint32 create_options,
         * is the only practical way. JRA.
         */
 
-       if(*desired_access & DELETE_ACCESS) {
-               DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode));
-       }
-
        if (create_options & FILE_DELETE_ON_CLOSE) {
+               /*
+                * W2K3 bug compatibility mode... To set delete on close
+                * the redirector must have *specifically* set DELETE_ACCESS
+                * in the desired_access field. Just asking for GENERIC_ALL won't do. JRA.
+                */
+
+               if (!(original_desired_access & DELETE_ACCESS)) {
+                       DEBUG(5,("map_share_mode: FILE_DELETE_ON_CLOSE requested without \
+DELETE_ACCESS for file %s. (desired_access = 0x%lx)\n",
+                               fname, (unsigned long)*desired_access));
+                       return -1;
+               }
                /* Implicit delete access is *NOT* requested... */
                smb_open_mode |= DELETE_ON_CLOSE_FLAG;
                DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode));
@@ -523,11 +540,8 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
        int ret;
        int pnum = -1;
        char *p = NULL;
-       NTSTATUS status;
 
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
-       if (!NT_STATUS_IS_OK(status))
-               return ERROR_NT(status);
+       srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
 
        if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
                return ret;
@@ -577,11 +591,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
        SMB_BIG_UINT allocation_size = 0;
        int smb_ofun;
        int smb_open_mode;
-       int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
        /* Breakout the oplock request bits so we can set the
           reply bits separately. */
        int oplock_request = 0;
-       mode_t unixmode;
        int fmode=0,rmode=0;
        SMB_OFF_T file_len = 0;
        SMB_STRUCT_STAT sbuf;
@@ -625,7 +637,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        
        if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
                END_PROFILE(SMBntcreateX);
-               return(ERROR_DOS(ERRDOS,ERRnoaccess));
+               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
        /*
@@ -636,6 +648,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                /*
                 * This filename is relative to a directory fid.
                 */
+               pstring rel_fname;
                files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid);
                size_t dir_name_len;
 
@@ -646,7 +659,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
 
                if(!dir_fsp->is_directory) {
 
-                       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
+                       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
                        if (!NT_STATUS_IS_OK(status)) {
                                END_PROFILE(SMBntcreateX);
                                return ERROR_NT(status);
@@ -661,14 +674,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                                return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
                        }
 
-
                        /*
                          we need to handle the case when we get a
                          relative open relative to a file and the
                          pathname is blank - this is a reopen!
                          (hint from demyn plantenberg)
                        */
-                       
 
                        END_PROFILE(SMBntcreateX);
                        return(ERROR_DOS(ERRDOS,ERRbadfid));
@@ -686,17 +697,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                 */
 
                if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') {
-                       pstrcat(fname, "\\");
+                       pstrcat(fname, "/");
                        dir_name_len++;
                }
 
-               srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE,&status);
+               srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status,False);
                if (!NT_STATUS_IS_OK(status)) {
                        END_PROFILE(SMBntcreateX);
                        return ERROR_NT(status);
                }
+               pstrcat(fname, rel_fname);
        } else {
-               srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
+               srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
                if (!NT_STATUS_IS_OK(status)) {
                        END_PROFILE(SMBntcreateX);
                        return ERROR_NT(status);
@@ -739,7 +751,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                                           share_access, 
                                           file_attributes)) == -1) {
                END_PROFILE(SMBntcreateX);
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
@@ -755,12 +767,47 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
         * Check if POSIX semantics are wanted.
         */
                
-       set_posix_case_semantics(file_attributes);
+       set_posix_case_semantics(conn, file_attributes);
                
        unix_convert(fname,conn,0,&bad_path,&sbuf);
-               
-       unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-    
+
+       /* FAKE_FILE is a special case */
+       if (fake_file_type == FAKE_FILE_TYPE_NONE) {
+               /* Normal file. */
+               if (bad_path) {
+                       restore_case_semantics(conn, file_attributes);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+               }
+               /* All file access must go through check_name() */
+               if (!check_name(fname,conn)) {
+                       restore_case_semantics(conn, file_attributes);
+                       END_PROFILE(SMBntcreateX);
+                       return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+               }
+       }
+
+#if 0
+       /* This is the correct thing to do (check every time) but can_delete is
+          expensive (it may have to read the parent directory permissions). So
+          for now we're not doing it unless we have a strong hint the client
+          is really going to delete this file. */
+       if (desired_access & DELETE_ACCESS) {
+#else
+       /* Setting FILE_SHARE_DELETE is the hint. */
+       if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+#endif
+               status = can_delete(conn, fname, file_attributes, bad_path, True);
+               /* We're only going to fail here if it's access denied, as that's the
+                  only error we care about for "can we delete this ?" questions. */
+               if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
+                                                NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+                       restore_case_semantics(conn, file_attributes);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(status);
+               }
+       }
+
        /* 
         * If it's a request for a directory open, deal with it separately.
         */
@@ -774,9 +821,9 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                }
 
-               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
                        
-               restore_case_semantics(file_attributes);
+               restore_case_semantics(conn, file_attributes);
 
                if(!fsp) {
                        END_PROFILE(SMBntcreateX);
@@ -804,14 +851,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                        fsp = open_file_shared1(conn,fname,&sbuf,
                                        desired_access,
                                        smb_open_mode,
-                                       smb_ofun,unixmode, oplock_request,
+                                       smb_ofun,file_attributes,oplock_request,
                                        &rmode,&smb_action);
                } else {
                        /* to open a fake_file --metze */
                        fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf,
                                        desired_access,
                                        smb_open_mode,
-                                       smb_ofun,unixmode, oplock_request,
+                                       smb_ofun,file_attributes, oplock_request,
                                        &rmode,&smb_action);
                }
                
@@ -842,7 +889,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                                 */
 
                                if (create_options & FILE_NON_DIRECTORY_FILE) {
-                                       restore_case_semantics(file_attributes);
+                                       restore_case_semantics(conn, file_attributes);
                                        SSVAL(outbuf, smb_flg2, 
                                              SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
                                        END_PROFILE(SMBntcreateX);
@@ -850,23 +897,28 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                                }
        
                                oplock_request = 0;
-                               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+                               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
                                
                                if(!fsp) {
-                                       restore_case_semantics(file_attributes);
+                                       restore_case_semantics(conn, file_attributes);
                                        END_PROFILE(SMBntcreateX);
                                        return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
                                }
                        } else {
 
-                               restore_case_semantics(file_attributes);
+                               restore_case_semantics(conn, file_attributes);
                                END_PROFILE(SMBntcreateX);
+                               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                                       /* We have re-scheduled this call. */
+                                       clear_cached_errors();
+                                       return -1;
+                               }
                                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
                        }
                } 
        }
                
-       restore_case_semantics(file_attributes);
+       restore_case_semantics(conn, file_attributes);
                
        file_len = sbuf.st_size;
        fmode = dos_mode(conn,fname,&sbuf);
@@ -884,14 +936,20 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
 #endif
        if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
-               fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+               fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
+               if (fsp->is_directory) {
+                       close_file(fsp,False);
+                       END_PROFILE(SMBntcreateX);
+                       /* Can't set allocation size on a directory. */
+                       return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+               }
                if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
                        close_file(fsp,False);
                        END_PROFILE(SMBntcreateX);
                        return ERROR_NT(NT_STATUS_DISK_FULL);
                }
        } else {
-               fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE);
+               fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len);
        }
 
        /* 
@@ -961,12 +1019,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        p += 8;
        SIVAL(p,0,fmode); /* File Attributes. */
        p += 4;
-       SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
+       SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
-       p += 12;
+       p += 8;
+       if (flags & EXTENDED_RESPONSE_REQUIRED)
+               SSVAL(p,2,0x7);
+       p += 4;
        SCVAL(p,0,fsp->is_directory ? 1 : 0);
-       
+
        DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
 
        result = chain_reply(inbuf,outbuf,length,bufsize);
@@ -999,8 +1060,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
-       srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
-       status = check_path_syntax(fname);
+       srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
@@ -1049,7 +1109,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
        TALLOC_CTX *mem_ctx;
        BOOL ret;
        
-       if (sd_len == 0) {
+       if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
                return NT_STATUS_OK;
        }
 
@@ -1105,6 +1165,34 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
        return NT_STATUS_OK;
 }
 
+/****************************************************************************
+ Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
+****************************************************************************/
+                                                                                                                             
+static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
+{
+       struct ea_list *ea_list_head = NULL;
+       size_t offset = 0;
+
+       if (data_size < 4) {
+               return NULL;
+       }
+
+       while (offset + 4 <= data_size) {
+               size_t next_offset = IVAL(pdata,offset);
+               struct ea_list *tmp;
+               struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL);
+
+               DLIST_ADD_END(ea_list_head, eal, tmp);
+               if (next_offset == 0) {
+                       break;
+               }
+               offset += next_offset;
+       }
+                                                                                                                             
+       return ea_list_head;
+}
+
 /****************************************************************************
  Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
 ****************************************************************************/
@@ -1112,14 +1200,13 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
 static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
        pstring fname;
        char *params = *ppparams;
        char *data = *ppdata;
        /* Breakout the oplock request bits so we can set the reply bits separately. */
        int oplock_request = 0;
-       mode_t unixmode;
        int fmode=0,rmode=0;
        SMB_OFF_T file_len = 0;
        SMB_STRUCT_STAT sbuf;
@@ -1135,13 +1222,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        uint32 create_disposition;
        uint32 create_options;
        uint32 sd_len;
+       uint32 ea_len;
        uint16 root_dir_fid;
        SMB_BIG_UINT allocation_size = 0;
        int smb_ofun;
        int smb_open_mode;
-       int smb_attr;
        time_t c_time;
-       NTSTATUS nt_status;
+       struct ea_list *ea_list = NULL;
+       TALLOC_CTX *ctx = NULL;
+       char *pdata = NULL;
+       NTSTATUS status;
 
        DEBUG(5,("call_nt_transact_create\n"));
 
@@ -1166,7 +1256,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
 
        if(parameter_count < 54) {
                DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
        flags = IVAL(params,0);
@@ -1176,8 +1266,31 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        create_disposition = IVAL(params,28);
        create_options = IVAL(params,32);
        sd_len = IVAL(params,36);
+       ea_len = IVAL(params,40);
        root_dir_fid = (uint16)IVAL(params,4);
-       smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
+
+       /* Ensure the data_len is correct for the sd and ea values given. */
+       if ((ea_len + sd_len > data_count) ||
+                       (ea_len > data_count) || (sd_len > data_count) ||
+                       (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
+               DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n",
+                       (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count ));
+               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+       }
+
+       if (ea_len) {
+               if (!lp_ea_support(SNUM(conn))) {
+                       DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n",
+                               (unsigned int)ea_len ));
+                       return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
+               }
+
+               if (ea_len < 10) {
+                       DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n",
+                               (unsigned int)ea_len ));
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+       }
 
        if (create_options & FILE_OPEN_BY_FILE_ID) {
                return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
@@ -1188,8 +1301,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
         * NT values, as that's what our code is structured to accept.
         */    
 
-       if((smb_ofun = map_create_disposition( create_disposition )) == -1)
-               return ERROR_DOS(ERRDOS,ERRbadmem);
+       if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
+               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+       }
 
        /*
         * Get the file name.
@@ -1199,7 +1313,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                /*
                 * This filename is relative to a directory fid.
                 */
-
                files_struct *dir_fsp = file_fsp(params,4);
                size_t dir_name_len;
 
@@ -1207,11 +1320,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                        return ERROR_DOS(ERRDOS,ERRbadfid);
 
                if(!dir_fsp->is_directory) {
-
-                       srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
-                       nt_status = check_path_syntax(fname);
-                       if (!NT_STATUS_IS_OK(nt_status)) {
-                               return ERROR_NT(nt_status);
+                       srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return ERROR_NT(status);
                        }
 
                        /*
@@ -1236,21 +1347,22 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 */
 
                if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
-                       pstrcat(fname, "\\");
+                       pstrcat(fname, "/");
                        dir_name_len++;
                }
 
-               srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, 
-                               parameter_count-53, STR_TERMINATE);
-               nt_status = check_path_syntax(fname);
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       return ERROR_NT(nt_status);
+               {
+                       pstring tmpname;
+                       srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status, False);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return ERROR_NT(status);
+                       }
+                       pstrcat(fname, tmpname);
                }
        } else {
-               srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
-               nt_status = check_path_syntax(fname);
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       return ERROR_NT(nt_status);
+               srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
                }
 
                /*
@@ -1268,7 +1380,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
 
        if((smb_open_mode = map_share_mode( fname, create_options, &desired_access,
                                                share_access, file_attributes)) == -1)
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
        oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
@@ -1277,14 +1389,61 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
         * Check if POSIX semantics are wanted.
         */
 
-       set_posix_case_semantics(file_attributes);
+       set_posix_case_semantics(conn, file_attributes);
     
        RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               restore_case_semantics(conn, file_attributes);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
+       /* All file access must go through check_name() */
+       if (!check_name(fname,conn)) {
+               restore_case_semantics(conn, file_attributes);
+               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+       }
     
-       unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-   
+#if 0
+       /* This is the correct thing to do (check every time) but can_delete is
+          expensive (it may have to read the parent directory permissions). So
+          for now we're not doing it unless we have a strong hint the client
+          is really going to delete this file. */
+       if (desired_access & DELETE_ACCESS) {
+#else
+       /* Setting FILE_SHARE_DELETE is the hint. */
+       if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+#endif
+               status = can_delete(conn, fname, file_attributes, bad_path, True);
+               /* We're only going to fail here if it's access denied, as that's the
+                  only error we care about for "can we delete this ?" questions. */
+               if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
+                                                NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+                       restore_case_semantics(conn, file_attributes);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(status);
+               }
+       }
+
+       if (ea_len) {
+               ctx = talloc_init("NTTRANS_CREATE_EA");
+               if (!ctx) {
+                       talloc_destroy(ctx);
+                       restore_case_semantics(conn, file_attributes);
+                       return ERROR_NT(NT_STATUS_NO_MEMORY);
+               }
+
+               pdata = data + sd_len;
+
+               /* We have already checked that ea_len <= data_count here. */
+               ea_list = read_nttrans_ea_list(ctx, pdata, ea_len);
+               if (!ea_list ) {
+                       talloc_destroy(ctx);
+                       restore_case_semantics(conn, file_attributes);
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+       }
+
        /*
         * If it's a request for a directory open, deal with it separately.
         */
@@ -1293,6 +1452,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
 
                /* Can't open a temp directory. IFS kit test. */
                if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
+                       talloc_destroy(ctx);
+                       restore_case_semantics(conn, file_attributes);
                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                }
 
@@ -1304,10 +1465,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 * CreateDirectory() call.
                 */
 
-               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
 
                if(!fsp) {
-                       restore_case_semantics(file_attributes);
+                       talloc_destroy(ctx);
+                       restore_case_semantics(conn, file_attributes);
                        return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
                }
 
@@ -1318,7 +1480,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 */
 
                fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
-                                               smb_open_mode,smb_ofun,unixmode,
+                                               smb_open_mode,smb_ofun,file_attributes,
                                                oplock_request,&rmode,&smb_action);
 
                if (!fsp) { 
@@ -1330,20 +1492,27 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                 */
 
                                if (create_options & FILE_NON_DIRECTORY_FILE) {
-                                       restore_case_semantics(file_attributes);
+                                       restore_case_semantics(conn, file_attributes);
                                        SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
                                        return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
                                }
        
                                oplock_request = 0;
-                               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+                               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
                                
                                if(!fsp) {
-                                       restore_case_semantics(file_attributes);
+                                       talloc_destroy(ctx);
+                                       restore_case_semantics(conn, file_attributes);
                                        return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
                                }
                        } else {
-                               restore_case_semantics(file_attributes);
+                               talloc_destroy(ctx);
+                               restore_case_semantics(conn, file_attributes);
+                               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                                       /* We have re-scheduled this call. */
+                                       clear_cached_errors();
+                                       return -1;
+                               }
                                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
                        }
                } 
@@ -1354,9 +1523,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                        fmode = FILE_ATTRIBUTE_NORMAL;
 
                if (fmode & aDIR) {
+                       talloc_destroy(ctx);
                        close_file(fsp,False);
-                       restore_case_semantics(file_attributes);
-                       return ERROR_DOS(ERRDOS,ERRnoaccess);
+                       restore_case_semantics(conn, file_attributes);
+                       return ERROR_NT(NT_STATUS_ACCESS_DENIED);
                } 
 
                /* 
@@ -1365,24 +1535,54 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 * correct bit for extended oplock reply.
                 */
     
-               if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+               if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
                        extended_oplock_granted = True;
+               }
   
-               if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+               if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                        extended_oplock_granted = True;
+               }
        }
 
        /*
-        * Now try and apply the desired SD.
+        * According to the MS documentation, the only time the security
+        * descriptor is applied to the opened file is iff we *created* the
+        * file; an existing file stays the same.
+        * 
+        * Also, it seems (from observation) that you can open the file with
+        * any access mask but you can still write the sd. We need to override
+        * the granted access before we call set_sd
+        * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>.
         */
 
-       if (sd_len && !NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
-               close_file(fsp,False);
-               restore_case_semantics(file_attributes);
-               return ERROR_NT(nt_status);
-       }
+       if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) {
+               uint32 saved_access = fsp->desired_access;
+
+               /* We have already checked that sd_len <= data_count here. */
+
+               fsp->desired_access = FILE_GENERIC_ALL;
+
+               status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION);
+               if (!NT_STATUS_IS_OK(status)) {
+                       talloc_destroy(ctx);
+                       close_file(fsp,False);
+                       restore_case_semantics(conn, file_attributes);
+                       return ERROR_NT(status);
+               }
+               fsp->desired_access = saved_access;
+       }
        
-       restore_case_semantics(file_attributes);
+       if (ea_len && (smb_action == FILE_WAS_CREATED)) {
+               status = set_ea(conn, fsp, fname, ea_list);
+               talloc_destroy(ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       close_file(fsp,False);
+                       restore_case_semantics(conn, file_attributes);
+                       return ERROR_NT(status);
+               }
+       }
+
+       restore_case_semantics(conn, file_attributes);
 
        /* Save the requested allocation size. */
        allocation_size = (SMB_BIG_UINT)IVAL(params,12);
@@ -1390,13 +1590,19 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
 #endif
        if (allocation_size && (allocation_size > file_len)) {
-               fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+               fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
+               if (fsp->is_directory) {
+                       close_file(fsp,False);
+                       END_PROFILE(SMBntcreateX);
+                       /* Can't set allocation size on a directory. */
+                       return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+               }
                if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
                        close_file(fsp,False);
                        return ERROR_NT(NT_STATUS_DISK_FULL);
                }
        } else {
-               fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE);
+               fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len);
        }
 
        /* Realloc the size of parameters and data we will return */
@@ -1441,9 +1647,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        p += 8;
        SIVAL(p,0,fmode); /* File Attributes. */
        p += 4;
-       SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
+       SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
+       p += 8;
+       if (flags & EXTENDED_RESPONSE_REQUIRED)
+               SSVAL(p,2,0x7);
+       p += 4;
+       SCVAL(p,0,fsp->is_directory ? 1 : 0);
 
        DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
 
@@ -1476,6 +1687,241 @@ int reply_ntcancel(connection_struct *conn,
        return(-1);
 }
 
+/****************************************************************************
+ Copy a file.
+****************************************************************************/
+
+static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint16 attrs)
+{
+       BOOL bad_path_oldname = False;
+       BOOL bad_path_newname = False;
+       SMB_STRUCT_STAT sbuf1, sbuf2;
+       pstring last_component_oldname;
+       pstring last_component_newname;
+       files_struct *fsp1,*fsp2;
+       uint16 fmode;
+       int access_mode;
+       int smb_action;
+       SMB_OFF_T ret=-1;
+       int close_ret;
+       NTSTATUS status = NT_STATUS_OK;
+
+       ZERO_STRUCT(sbuf1);
+       ZERO_STRUCT(sbuf2);
+
+       /* No wildcards. */
+       if (ms_has_wild(newname) || ms_has_wild(oldname)) {
+               return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+       }
+
+       if (!CAN_WRITE(conn))
+               return NT_STATUS_MEDIA_WRITE_PROTECTED;
+
+       unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
+       if (bad_path_oldname) {
+               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
+       /* Quick check for "." and ".." */
+       if (last_component_oldname[0] == '.') {
+               if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
+                       return NT_STATUS_OBJECT_NAME_INVALID;
+               }
+       }
+
+        /* Source must already exist. */
+       if (!VALID_STAT(sbuf1)) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+       if (!check_name(oldname,conn)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* Ensure attributes match. */
+       fmode = dos_mode(conn,oldname,&sbuf1);
+       if ((fmode & ~attrs) & (aHIDDEN | aSYSTEM))
+               return NT_STATUS_NO_SUCH_FILE;
+
+       unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
+       if (bad_path_newname) {
+               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
+       /* Quick check for "." and ".." */
+       if (last_component_newname[0] == '.') {
+               if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
+                       return NT_STATUS_OBJECT_NAME_INVALID;
+               }
+       }
+
+       /* Disallow if newname already exists. */
+       if (VALID_STAT(sbuf2)) {
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+
+       if (!check_name(newname,conn)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* No links from a directory. */
+       if (S_ISDIR(sbuf1.st_mode)) {
+               return NT_STATUS_FILE_IS_A_DIRECTORY;
+       }
+
+       /* Ensure this is within the share. */
+       if (!reduce_name(conn, oldname) != 0) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
+
+        fsp1 = open_file_shared1(conn,oldname,&sbuf1,FILE_READ_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,
+                       &access_mode,&smb_action);
+
+       if (!fsp1) {
+               status = NT_STATUS_ACCESS_DENIED;
+               if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+                       status = NT_STATUS_SHARING_VIOLATION;
+               unix_ERR_class = 0;
+               unix_ERR_code = 0;
+               unix_ERR_ntstatus = NT_STATUS_OK;
+               return status;
+       }
+
+       fsp2 = open_file_shared1(conn,newname,&sbuf2,FILE_WRITE_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
+                       (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL),fmode,INTERNAL_OPEN_ONLY,
+                       &access_mode,&smb_action);
+
+       if (!fsp2) {
+               status = NT_STATUS_ACCESS_DENIED;
+               if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+                       status = NT_STATUS_SHARING_VIOLATION;
+               unix_ERR_class = 0;
+               unix_ERR_code = 0;
+               unix_ERR_ntstatus = NT_STATUS_OK;
+               close_file(fsp1,False);
+               return status;
+       }
+
+       if (sbuf1.st_size)
+               ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size);
+
+       /*
+        * As we are opening fsp1 read-only we only expect
+        * an error on close on fsp2 if we are out of space.
+        * Thus we don't look at the error return from the
+        * close of fsp1.
+        */
+       close_file(fsp1,False);
+
+       /* Ensure the modtime is set correctly on the destination file. */
+       fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
+
+       close_ret = close_file(fsp2,False);
+
+       /* Grrr. We have to do this as open_file_shared1 adds aARCH when it
+          creates the file. This isn't the correct thing to do in the copy case. JRA */
+       file_set_dosmode(conn, newname, fmode, &sbuf2, True);
+
+       if (ret < (SMB_OFF_T)sbuf1.st_size) {
+               return NT_STATUS_DISK_FULL;
+       }
+
+       if (close_ret != 0) {
+               status = map_nt_error_from_unix(close_ret);
+               DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
+                       nt_errstr(status), oldname, newname));
+       }
+       return status;
+}
+
+/****************************************************************************
+ Reply to a NT rename request.
+****************************************************************************/
+
+int reply_ntrename(connection_struct *conn,
+                  char *inbuf,char *outbuf,int length,int bufsize)
+{
+       int outsize = 0;
+       pstring oldname;
+       pstring newname;
+       char *p;
+       NTSTATUS status;
+       uint16 attrs = SVAL(inbuf,smb_vwv0);
+       uint16 rename_type = SVAL(inbuf,smb_vwv1);
+
+       START_PROFILE(SMBntrename);
+
+       p = smb_buf(inbuf) + 1;
+       p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, True);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBntrename);
+               return ERROR_NT(status);
+       }
+
+       if( strchr_m(oldname, ':')) {
+               /* Can't rename a stream. */
+               END_PROFILE(SMBntrename);
+               return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+       }
+
+       if (ms_has_wild(oldname)) {
+               END_PROFILE(SMBntrename);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
+       }
+
+       p++;
+       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, False);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBntrename);
+               return ERROR_NT(status);
+       }
+       
+       RESOLVE_DFSPATH(oldname, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+       
+       DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
+       
+       switch(rename_type) {
+               case RENAME_FLAG_RENAME:
+                       status = rename_internals(conn, oldname, newname, attrs, False);
+                       break;
+               case RENAME_FLAG_HARD_LINK:
+                       status = hardlink_internals(conn, oldname, newname);
+                       break;
+               case RENAME_FLAG_COPY:
+                       status = copy_internals(conn, oldname, newname, attrs);
+                       break;
+               case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       break;
+               default:
+                       status = NT_STATUS_ACCESS_DENIED; /* Default error. */
+                       break;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBntrename);
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
+               return ERROR_NT(status);
+       }
+
+       /*
+        * Win2k needs a changenotify request response before it will
+        * update after a rename..
+        */     
+       process_pending_change_notify_queue((time_t)0);
+       outsize = set_message(outbuf,0,0,True);
+  
+       END_PROFILE(SMBntrename);
+       return(outsize);
+}
+
 /****************************************************************************
  Reply to an unsolicited SMBNTtranss - just ignore it!
 ****************************************************************************/
@@ -1497,7 +1943,7 @@ int reply_nttranss(connection_struct *conn,
 static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
        char *setup = *ppsetup;
        files_struct *fsp;
@@ -1533,7 +1979,7 @@ name = %s\n", fsp->fsp_name ));
 static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
        char *params = *ppparams;
        pstring new_name;
@@ -1547,14 +1993,13 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
        fsp = file_fsp(params, 0);
        replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
        CHECK_FSP(fsp, conn);
-       srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE);
-       status = check_path_syntax(new_name);
+       srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
 
        status = rename_internals(conn, fsp->fsp_name,
-                                 new_name, replace_if_exists);
+                                 new_name, 0, replace_if_exists);
        if (!NT_STATUS_IS_OK(status))
                return ERROR_NT(status);
 
@@ -1601,9 +2046,8 @@ static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd)
 static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
-       uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
        char *params = *ppparams;
        char *data = *ppdata;
        prs_struct pd;
@@ -1713,7 +2157,7 @@ security descriptor.\n"));
 static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
        char *params= *ppparams;
        char *data = *ppdata;
@@ -1754,7 +2198,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb
 static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
        uint32 function;
        uint16 fidnum;
@@ -1831,7 +2275,6 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                 * Allocate the correct amount and return the pointer to let
                 * it be deallocated when we return.
                 */
-               uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
                SHADOW_COPY_DATA *shadow_data = NULL;
                TALLOC_CTX *shadow_mem_ctx = NULL;
                BOOL labels = False;
@@ -1857,9 +2300,10 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                        return ERROR_NT(NT_STATUS_NO_MEMORY);
                }
 
-               shadow_data = (SHADOW_COPY_DATA *)talloc_zero(shadow_mem_ctx,sizeof(SHADOW_COPY_DATA));
+               shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA);
                if (shadow_data == NULL) {
                        DEBUG(0,("talloc_zero() failed!\n"));
+                       talloc_destroy(shadow_mem_ctx);
                        return ERROR_NT(NT_STATUS_NO_MEMORY);
                }
                
@@ -1957,8 +2401,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid)));
 
                if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) {
-                       DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%u]\n",
-                               sid_string_static(&sid),sid_len));
+                       DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
+                               sid_string_static(&sid),(unsigned long)sid_len));
                        uid = (-1);
                }
                
@@ -2004,10 +2448,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
 static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
        NTSTATUS nt_status = NT_STATUS_OK;
-       uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
        char *params = *ppparams;
        char *pdata = *ppdata;
        char *entry;
@@ -2022,12 +2465,13 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
        SMB_NTQUOTA_STRUCT qt;
        SMB_NTQUOTA_LIST *tmp_list;
        SMB_NTQUOTA_HANDLE *qt_handle = NULL;
+       extern struct current_user current_user;
 
        ZERO_STRUCT(qt);
 
        /* access check */
-       if (conn->admin_user != True) {
-               DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
+       if (current_user.uid != 0) {
+               DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n",
                        lp_servicename(SNUM(conn)),conn->user));
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
@@ -2167,9 +2611,13 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
                        }
 
                        sid_len = IVAL(pdata,4);
+                       /* Ensure this is less than 1mb. */
+                       if (sid_len > (1024*1024)) {
+                               return ERROR_DOS(ERRDOS,ERRnomem);
+                       }
 
                        if (data_count < 8+sid_len) {
-                               DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8+sid_len));
+                               DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len)));
                                return ERROR_DOS(ERRDOS,ERRunknownlevel);                               
                        }
 
@@ -2253,7 +2701,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
 static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
                                   char **ppsetup, uint32 setup_count,
                                  char **ppparams, uint32 parameter_count,
-                                 char **ppdata, uint32 data_count)
+                                 char **ppdata, uint32 data_count, uint32 max_data_count)
 {
        char *params = *ppparams;
        char *pdata = *ppdata;
@@ -2266,7 +2714,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
        ZERO_STRUCT(qt);
 
        /* access check */
-       if (conn->admin_user != True) {
+       if (current_user.uid != 0) {
                DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
                        lp_servicename(SNUM(conn)),conn->user));
                return ERROR_DOS(ERRDOS,ERRnoaccess);
@@ -2302,7 +2750,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
        sid_len = IVAL(pdata,4);
 
        if (data_count < 40+sid_len) {
-               DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40+sid_len));
+               DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data\n",data_count,(unsigned long)40+sid_len));
                return ERROR_DOS(ERRDOS,ERRunknownlevel);               
        }
 
@@ -2372,10 +2820,10 @@ int reply_nttrans(connection_struct *conn,
                        char *inbuf,char *outbuf,int length,int bufsize)
 {
        int  outsize = 0;
+       uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
 #if 0 /* Not used. */
        uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
        uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
-       uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
 #endif /* Not used. */
        uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
        uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
@@ -2421,15 +2869,21 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                        CVAL(inbuf, smb_wct), 19 + (setup_count/2)));
                goto bad_param;
        }
-    
+
+       /* Don't allow more than 128mb for each value. */
+       if ((total_parameter_count > (1024*1024*128)) || (total_data_count > (1024*1024*128))) {
+               END_PROFILE(SMBnttrans);
+               return ERROR_DOS(ERRDOS,ERRnomem);
+       }
+
        /* Allocate the space for the setup, the maximum needed parameters and data */
 
        if(setup_count > 0)
-               setup = (char *)malloc(setup_count);
+               setup = (char *)SMB_MALLOC(setup_count);
        if (total_parameter_count > 0)
-               params = (char *)malloc(total_parameter_count);
+               params = (char *)SMB_MALLOC(total_parameter_count);
        if (total_data_count > 0)
-               data = (char *)malloc(total_data_count);
+               data = (char *)SMB_MALLOC(total_data_count);
  
        if ((total_parameter_count && !params)  || (total_data_count && !data) ||
                                (setup_count && !setup)) {
@@ -2489,6 +2943,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                /* We need to send an interim response then receive the rest
                        of the parameter/data bytes */
                outsize = set_message(outbuf,0,0,True);
+               srv_signing_trans_stop();
                if (!send_smb(smbd_server_fd(),outbuf))
                        exit_server("reply_nttrans: send_smb failed.");
 
@@ -2499,6 +2954,13 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
 
                        ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
 
+                       /*
+                        * The sequence number for the trans reply is always
+                        * based on the last secondary received.
+                        */
+
+                       srv_signing_trans_start(SVAL(inbuf,smb_mid));
+
                        if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
                                outsize = set_message(outbuf,0,0,True);
                                if(ret) {
@@ -2532,7 +2994,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                        }
 
                        if (parameter_count) {
-                               if (parameter_displacement + parameter_count >= total_parameter_count)
+                               if (parameter_displacement + parameter_count > total_parameter_count)
                                        goto bad_param;
                                if ((parameter_displacement + parameter_count < parameter_displacement) ||
                                                (parameter_displacement + parameter_count < parameter_count))
@@ -2549,7 +3011,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                        }
 
                        if (data_count) {
-                               if (data_displacement + data_count >= total_data_count)
+                               if (data_displacement + data_count > total_data_count)
                                        goto bad_param;
                                if ((data_displacement + data_count < data_displacement) ||
                                                (data_displacement + data_count < data_count))
@@ -2578,7 +3040,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                        length, bufsize, 
                                                        &setup, setup_count,
                                                        &params, total_parameter_count, 
-                                                       &data, total_data_count);
+                                                       &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_create);
                        break;
                case NT_TRANSACT_IOCTL:
@@ -2587,7 +3049,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                         length, bufsize, 
                                                         &setup, setup_count,
                                                         &params, total_parameter_count, 
-                                                        &data, total_data_count);
+                                                        &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_ioctl);
                        break;
                case NT_TRANSACT_SET_SECURITY_DESC:
@@ -2596,7 +3058,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                         length, bufsize, 
                                                         &setup, setup_count,
                                                         &params, total_parameter_count, 
-                                                        &data, total_data_count);
+                                                        &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_set_security_desc);
                        break;
                case NT_TRANSACT_NOTIFY_CHANGE:
@@ -2605,7 +3067,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                         length, bufsize, 
                                                         &setup, setup_count,
                                                         &params, total_parameter_count, 
-                                                        &data, total_data_count);
+                                                        &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_notify_change);
                        break;
                case NT_TRANSACT_RENAME:
@@ -2614,7 +3076,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                         length, bufsize, 
                                                         &setup, setup_count,
                                                         &params, total_parameter_count, 
-                                                        &data, total_data_count);
+                                                        &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_rename);
                        break;
 
@@ -2624,7 +3086,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                         length, bufsize, 
                                                         &setup, setup_count,
                                                         &params, total_parameter_count, 
-                                                        &data, total_data_count);
+                                                        &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_query_security_desc);
                        break;
 #ifdef HAVE_SYS_QUOTAS
@@ -2634,7 +3096,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                         length, bufsize, 
                                                         &setup, setup_count,
                                                         &params, total_parameter_count, 
-                                                        &data, total_data_count);
+                                                        &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_get_user_quota);
                        break;
                case NT_TRANSACT_SET_USER_QUOTA:
@@ -2643,7 +3105,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                                                         length, bufsize, 
                                                         &setup, setup_count,
                                                         &params, total_parameter_count, 
-                                                        &data, total_data_count);
+                                                        &data, total_data_count, max_data_count);
                        END_PROFILE_NESTED(NT_transact_set_user_quota);
                        break;                                  
 #endif /* HAVE_SYS_QUOTAS */