r6146: Added OS/2 EA support in trans2_open and trans2_mkdir. Fixed in nttrans_create.
authorJeremy Allison <jra@samba.org>
Thu, 31 Mar 2005 02:12:09 +0000 (02:12 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:56:24 +0000 (10:56 -0500)
Jeremy.

source/smbd/nttrans.c
source/smbd/trans2.c

index 1d4acf28449a05c351e6e1a297bd78a58f30909c..70b3f0d0e00ce4479fda61a3f3379043710234e0 100644 (file)
@@ -637,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);
        
        if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
                END_PROFILE(SMBntcreateX);
-               return(ERROR_DOS(ERRDOS,ERRnoaccess));
+               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
        /*
        }
 
        /*
@@ -1273,15 +1273,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        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)) {
        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);
        }
 
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
-       if (ea_len && !lp_ea_support(SNUM(conn))) {
-               return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
-       }
+       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) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               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) {
        }
 
        if (create_options & FILE_OPEN_BY_FILE_ID) {
@@ -1293,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.
         */    
 
         * 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.
 
        /*
         * Get the file name.
@@ -1416,21 +1425,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                }
        }
 
                }
        }
 
-       ctx = talloc_init("NTTRANS_CREATE_EA");
-       if (!ctx) {
-               talloc_destroy(ctx);
-               restore_case_semantics(conn, file_attributes);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
-       }
+       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;
+               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);
+               /* 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);
+               }
        }
 
        /*
        }
 
        /*
@@ -1551,7 +1562,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
 
                fsp->desired_access = FILE_GENERIC_ALL;
 
 
                fsp->desired_access = FILE_GENERIC_ALL;
 
-               if (!NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
+               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);
                        talloc_destroy(ctx);
                        close_file(fsp,False);
                        restore_case_semantics(conn, file_attributes);
@@ -1560,10 +1572,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                fsp->desired_access = saved_access;
        }
        
                fsp->desired_access = saved_access;
        }
        
-       if (ea_len && smb_action == FILE_WAS_CREATED) {
+       if (ea_len && (smb_action == FILE_WAS_CREATED)) {
                status = set_ea(conn, fsp, fname, ea_list);
                talloc_destroy(ctx);
                status = set_ea(conn, fsp, fname, ea_list);
                talloc_destroy(ctx);
-               if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK)) {
+               if (!NT_STATUS_IS_OK(status)) {
                        close_file(fsp,False);
                        restore_case_semantics(conn, file_attributes);
                        return ERROR_NT(status);
                        close_file(fsp,False);
                        restore_case_semantics(conn, file_attributes);
                        return ERROR_NT(status);
index 1ae013d23a624a6fd81f6496899e11b3cf69c819..a68b165cb0088fd81cd74a7eaf3d97d93806ecc9 100644 (file)
@@ -710,6 +710,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                                unsigned int max_data_bytes)
 {
        char *params = *pparams;
                                unsigned int max_data_bytes)
 {
        char *params = *pparams;
+       char *pdata = *ppdata;
        int16 open_mode;
        int16 open_attr;
        BOOL oplock_request;
        int16 open_mode;
        int16 open_attr;
        BOOL oplock_request;
@@ -729,6 +730,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        int smb_action = 0;
        BOOL bad_path = False;
        files_struct *fsp;
        int smb_action = 0;
        BOOL bad_path = False;
        files_struct *fsp;
+       TALLOC_CTX *ctx = NULL;
+       struct ea_list *ea_list = NULL;
        NTSTATUS status;
 
        /*
        NTSTATUS status;
 
        /*
@@ -759,7 +762,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                return ERROR_NT(status);
        }
 
                return ERROR_NT(status);
        }
 
-       DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
+       DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
                fname,open_mode, open_attr, open_ofun, open_size));
 
        /* XXXX we need to handle passed times, sattr and flags */
                fname,open_mode, open_attr, open_ofun, open_size));
 
        /* XXXX we need to handle passed times, sattr and flags */
@@ -773,10 +776,38 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
        }
 
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
        }
 
+       /* Any data in this call is an EA list. */
+       if (total_data && !lp_ea_support(SNUM(conn))) {
+               return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
+       }
+
+       if (total_data) {
+               if (total_data < 10) {
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+
+               if (IVAL(pdata,0) > total_data) {
+                       DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
+                               IVAL(pdata,0), (unsigned int)total_data));
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+
+               ctx = talloc_init("TRANS2_OPEN_SET_EA");
+               if (!ctx) {
+                       return ERROR_NT(NT_STATUS_NO_MEMORY);
+               }
+               ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
+               if (!ea_list) {
+                       talloc_destroy(ctx);
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+       }
+
        fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
                oplock_request, &rmode,&smb_action);
       
        if (!fsp) {
        fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
                oplock_request, &rmode,&smb_action);
       
        if (!fsp) {
+               talloc_destroy(ctx);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
                        clear_cached_errors();
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
                        clear_cached_errors();
@@ -790,10 +821,20 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        mtime = sbuf.st_mtime;
        inode = sbuf.st_ino;
        if (fmode & aDIR) {
        mtime = sbuf.st_mtime;
        inode = sbuf.st_ino;
        if (fmode & aDIR) {
+               talloc_destroy(ctx);
                close_file(fsp,False);
                return(ERROR_DOS(ERRDOS,ERRnoaccess));
        }
 
                close_file(fsp,False);
                return(ERROR_DOS(ERRDOS,ERRnoaccess));
        }
 
+       if (total_data && 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);
+                       return ERROR_NT(status);
+               }
+       }
+
        /* Realloc the size of parameters and data we will return */
        params = SMB_REALLOC(*pparams, 28);
        if( params == NULL ) {
        /* Realloc the size of parameters and data we will return */
        params = SMB_REALLOC(*pparams, 28);
        if( params == NULL ) {
@@ -3670,7 +3711,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        status = set_ea(conn, fsp, fname, ea_list);
                        talloc_destroy(ctx);
 
                        status = set_ea(conn, fsp, fname, ea_list);
                        talloc_destroy(ctx);
 
-                       if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK)) {
+                       if (!NT_STATUS_IS_OK(status)) {
                                return ERROR_NT(status);
                        }
                        break;
                                return ERROR_NT(status);
                        }
                        break;
@@ -3853,13 +3894,15 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
 
                        status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
  
 
                        status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
  
-                       if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
+                       if (!NT_STATUS_IS_OK(status)) {
                                return ERROR_NT(status);
                                return ERROR_NT(status);
+                       }
 
                        /* The set is across all open files on this dev/inode pair. */
                        status =set_delete_on_close_over_all(fsp, delete_on_close);
 
                        /* The set is across all open files on this dev/inode pair. */
                        status =set_delete_on_close_over_all(fsp, delete_on_close);
-                       if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
+                       if (!NT_STATUS_IS_OK(status)) {
                                return ERROR_NT(status);
                                return ERROR_NT(status);
+                       }
 
                        break;
                }
 
                        break;
                }
@@ -4371,11 +4414,14 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
                                        unsigned int max_data_bytes)
 {
        char *params = *pparams;
                                        unsigned int max_data_bytes)
 {
        char *params = *pparams;
+       char *pdata = *ppdata;
        pstring directory;
        int ret = -1;
        SMB_STRUCT_STAT sbuf;
        BOOL bad_path = False;
        NTSTATUS status = NT_STATUS_OK;
        pstring directory;
        int ret = -1;
        SMB_STRUCT_STAT sbuf;
        BOOL bad_path = False;
        NTSTATUS status = NT_STATUS_OK;
+       TALLOC_CTX *ctx = NULL;
+       struct ea_list *ea_list = NULL;
 
        if (!CAN_WRITE(conn))
                return ERROR_DOS(ERRSRV,ERRaccess);
 
        if (!CAN_WRITE(conn))
                return ERROR_DOS(ERRSRV,ERRaccess);
@@ -4395,14 +4441,53 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
        if (bad_path) {
                return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
        }
        if (bad_path) {
                return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
        }
-       if (check_name(directory,conn))
+
+       /* Any data in this call is an EA list. */
+       if (total_data && !lp_ea_support(SNUM(conn))) {
+               return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
+       }
+
+       if (total_data) {
+               if (total_data < 10) {
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+
+               if (IVAL(pdata,0) > total_data) {
+                       DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
+                               IVAL(pdata,0), (unsigned int)total_data));
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+
+               ctx = talloc_init("TRANS2_MKDIR_SET_EA");
+               if (!ctx) {
+                       return ERROR_NT(NT_STATUS_NO_MEMORY);
+               }
+               ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
+               if (!ea_list) {
+                       talloc_destroy(ctx);
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+       }
+
+       if (check_name(directory,conn)) {
                ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
                ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
+       }
   
        if(ret < 0) {
   
        if(ret < 0) {
+               talloc_destroy(ctx);
                DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
        }
 
                DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
        }
 
+       /* Try and set any given EA. */
+       if (total_data) {
+               status = set_ea(conn, NULL, directory, ea_list);
+               talloc_destroy(ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
+               }
+       }
+
        /* Realloc the parameter and data sizes */
        params = SMB_REALLOC(*pparams,2);
        if(params == NULL) {
        /* Realloc the parameter and data sizes */
        params = SMB_REALLOC(*pparams,2);
        if(params == NULL) {