]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
r21672: The cannonical file access pattern should look like this :
authorJeremy Allison <jra@samba.org>
Sat, 3 Mar 2007 01:35:58 +0000 (01:35 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:18:23 +0000 (12:18 -0500)
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}

RESOLVE_DFSPATH(name, conn, inbuf, outbuf);

status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}

status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}

Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....

Jeremy.

source/printing/nt_printing.c
source/smbd/nttrans.c
source/smbd/reply.c
source/smbd/trans2.c

index 77b31bc51795f91b83fec058c1a6a578d1ac51ef..b3c04913f132258f6b09852ed34739ea37c0fcd0 100644 (file)
@@ -1823,7 +1823,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                        driver_unix_convert(new_name, conn, NULL, &st);
-                       if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                       if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                new_name, old_name));
@@ -1839,7 +1839,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &st);
-                               if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1857,7 +1857,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &st);
-                               if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1876,7 +1876,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &st);
-                               if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1904,7 +1904,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
                                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                        driver_unix_convert(new_name, conn, NULL, &st);
-                                       if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn,
+                                       if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
                                                        OPENX_FILE_EXISTS_TRUNCATE|
                                                        OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
index 19710d1dcdd0e0d60591f87c7ea9bb38e0eeb7b9..968c536cafd7152923b1e694a8b17800b8e8d8ed 100644 (file)
@@ -1592,15 +1592,15 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                return status;
        }
 
-        /* Source must already exist. */
-       if (!VALID_STAT(sbuf1)) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
        status = check_name(conn, oldname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
+        /* Source must already exist. */
+       if (!VALID_STAT(sbuf1)) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
        /* Ensure attributes match. */
        fattr = dos_mode(conn,oldname,&sbuf1);
        if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
@@ -1612,16 +1612,16 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                return status;
        }
 
-       /* Disallow if newname already exists. */
-       if (VALID_STAT(sbuf2)) {
-               return NT_STATUS_OBJECT_NAME_COLLISION;
-       }
-
        status = check_name(conn, newname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
+       /* Disallow if newname already exists. */
+       if (VALID_STAT(sbuf2)) {
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+
        /* No links from a directory. */
        if (S_ISDIR(sbuf1.st_mode)) {
                return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -1708,15 +1708,15 @@ int reply_ntrename(connection_struct *conn,
        pstring newname;
        char *p;
        NTSTATUS status;
-       BOOL path1_contains_wcard = False;
-       BOOL path2_contains_wcard = False;
+       BOOL src_has_wcard = False;
+       BOOL dest_has_wcard = False;
        uint32 attrs = SVAL(inbuf,smb_vwv0);
        uint16 rename_type = SVAL(inbuf,smb_vwv1);
 
        START_PROFILE(SMBntrename);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path1_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBntrename);
                return ERROR_NT(status);
@@ -1734,7 +1734,7 @@ int reply_ntrename(connection_struct *conn,
        }
 
        p++;
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBntrename);
                return ERROR_NT(status);
@@ -1747,10 +1747,10 @@ int reply_ntrename(connection_struct *conn,
        
        switch(rename_type) {
                case RENAME_FLAG_RENAME:
-                       status = rename_internals(conn, oldname, newname, attrs, False, path1_contains_wcard);
+                       status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard);
                        break;
                case RENAME_FLAG_HARD_LINK:
-                       if (path1_contains_wcard || path2_contains_wcard) {
+                       if (src_has_wcard || dest_has_wcard) {
                                /* No wildcards. */
                                status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        } else {
@@ -1758,7 +1758,7 @@ int reply_ntrename(connection_struct *conn,
                        }
                        break;
                case RENAME_FLAG_COPY:
-                       if (path1_contains_wcard || path2_contains_wcard) {
+                       if (src_has_wcard || dest_has_wcard) {
                                /* No wildcards. */
                                status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        } else {
@@ -1899,7 +1899,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
        pstring new_name;
        files_struct *fsp = NULL;
        BOOL replace_if_exists = False;
-       BOOL path_contains_wcard = False;
+       BOOL dest_has_wcard = False;
        NTSTATUS status;
 
         if(parameter_count < 5) {
@@ -1909,13 +1909,14 @@ 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_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, STR_TERMINATE, &status, &path_contains_wcard);
+       srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4,
+                       STR_TERMINATE, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
 
        status = rename_internals(conn, fsp->fsp_name,
-                                 new_name, 0, replace_if_exists, path_contains_wcard);
+                                 new_name, 0, replace_if_exists, False, dest_has_wcard);
 
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
index 8bccd45f4bd44f7a132695be016388ec808c5dc2..25c2aaa4dcb730054382ec9d0283d64f1e910983 100644 (file)
@@ -798,6 +798,12 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBsetatr);
+               return ERROR_NT(status);
+       }
+
        if (fname[0] == '.' && fname[1] == '\0') {
                /*
                 * Not sure here is the right place to catch this
@@ -807,12 +813,6 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(NT_STATUS_ACCESS_DENIED);
        }
 
-       status = check_name(conn, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBsetatr);
-               return ERROR_NT(status);
-       }
-
        mode = SVAL(inbuf,smb_vwv0);
        mtime = srv_make_unix_date3(inbuf+smb_vwv1);
   
@@ -1211,6 +1211,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
     
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBopen);
+               return ERROR_NT(status);
+       }
+
        if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
                        &access_mask, &share_mode, &create_disposition, &create_options)) {
                END_PROFILE(SMBopen);
@@ -1329,6 +1335,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBopenX);
+               return ERROR_NT(status);
+       }
+
        if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
                                &access_mask,
                                &share_mode,
@@ -1501,6 +1513,12 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBcreate);
+               return ERROR_NT(status);
+       }
+
        if (fattr & aVOLID) {
                DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
        }
@@ -1590,6 +1608,12 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                END_PROFILE(SMBctemp);
                return ERROR_NT(status);
        }
+
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBctemp);
+               return ERROR_NT(status);
+       }
   
        tmpfd = smb_mkstemp(fname);
        if (tmpfd == -1) {
@@ -1859,6 +1883,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                if (dirtype == 0) {
                        dirtype = FILE_ATTRIBUTE_NORMAL;
                }
+
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
                status = can_delete(conn,directory,dirtype,can_defer);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
@@ -1921,6 +1951,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                        }
                                
                        slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+
+                       status = check_name(conn, fname);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+
                        status = can_delete(conn, fname, dirtype, can_defer);
                        if (!NT_STATUS_IS_OK(status)) {
                                continue;
@@ -3607,6 +3643,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBmkdir);
+               return ERROR_NT(status);
+       }
+  
        status = create_directory(conn, directory);
 
        DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
@@ -3855,7 +3897,6 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
        char *p,*p2, *pname1, *pname2;
        int available_space, actual_space;
        
-
        pname1 = strrchr_m(name1,'/');
        pname2 = strrchr_m(name2,'/');
 
@@ -4009,6 +4050,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                return status;
        }
 
+       status = check_name(conn, newname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+  
        /* Ensure newname contains a '/' */
        if(strrchr_m(newname,'/') == 0) {
                pstring tmpstr;
@@ -4153,9 +4199,13 @@ static void notify_rename(connection_struct *conn, BOOL is_dir,
  code. 
 ****************************************************************************/
 
-NTSTATUS rename_internals(connection_struct *conn, pstring name,
-                         pstring newname, uint32 attrs,
-                         BOOL replace_if_exists, BOOL has_wild)
+NTSTATUS rename_internals(connection_struct *conn,
+                               pstring name,
+                               pstring newname,
+                               uint32 attrs,
+                               BOOL replace_if_exists,
+                               BOOL src_has_wild,
+                               BOOL dest_has_wild)
 {
        pstring directory;
        pstring mask;
@@ -4166,20 +4216,22 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
        NTSTATUS status = NT_STATUS_OK;
        SMB_STRUCT_STAT sbuf1, sbuf2;
        struct share_mode_lock *lck = NULL;
+       struct smb_Dir *dir_hnd = NULL;
+       const char *dname;
+       long offset = 0;
+       pstring destname;
 
        *directory = *mask = 0;
 
        ZERO_STRUCT(sbuf1);
        ZERO_STRUCT(sbuf2);
 
-       status = unix_convert(conn, name, has_wild, last_component_src,
-                             &sbuf1);
+       status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       status = unix_convert(conn, newname, True, last_component_dest,
-                             &sbuf2);
+       status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4213,10 +4265,11 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
                mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+       }
 
-       if (!has_wild) {
+       if (!src_has_wild) {
                /*
                 * No wildcards - just process the one file.
                 */
@@ -4243,6 +4296,21 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
                          conn->short_case_preserve, directory, 
                          newname, last_component_dest, is_short_name));
 
+               /* Ensure the source name is valid for us to access. */
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               /* The dest name still may have wildcards. */
+               if (dest_has_wild) {
+                       if (!resolve_wildcards(directory,newname)) {
+                               DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
+                                         directory,newname));
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+                               
                /*
                 * Check for special case with case preserving and not
                 * case sensitive, if directory and newname are identical,
@@ -4277,8 +4345,12 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
                        }
                }
        
-               resolve_wildcards(directory,newname);
-       
+               /* Ensure the dest name is valid for us to access. */
+               status = check_name(conn, newname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
                /*
                 * The source object must exist.
                 */
@@ -4370,136 +4442,130 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
                        nt_errstr(status), directory,newname));
 
                return status;
-       } else {
-               /*
-                * Wildcards - process each file that matches.
-                */
-               struct smb_Dir *dir_hnd = NULL;
-               const char *dname;
-               long offset = 0;
-               pstring destname;
-               
-               if (strequal(mask,"????????.???"))
-                       pstrcpy(mask,"*");
+       }
+
+       /*
+        * Wildcards - process each file that matches.
+        */
+       if (strequal(mask,"????????.???")) {
+               pstrcpy(mask,"*");
+       }
                        
-               status = check_name(conn, directory);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
        
-               dir_hnd = OpenDir(conn, directory, mask, attrs);
-               if (dir_hnd == NULL) {
-                       return map_nt_error_from_unix(errno);
-               }
+       dir_hnd = OpenDir(conn, directory, mask, attrs);
+       if (dir_hnd == NULL) {
+               return map_nt_error_from_unix(errno);
+       }
                
-               status = NT_STATUS_NO_SUCH_FILE;
-               /*
-                * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                * - gentest fix. JRA
-                */
+       status = NT_STATUS_NO_SUCH_FILE;
+       /*
+        * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+        * - gentest fix. JRA
+        */
                        
-               while ((dname = ReadDirName(dir_hnd, &offset))) {
-                       pstring fname;
-                       BOOL sysdir_entry = False;
+       while ((dname = ReadDirName(dir_hnd, &offset))) {
+               pstring fname;
+               BOOL sysdir_entry = False;
 
-                       pstrcpy(fname,dname);
+               pstrcpy(fname,dname);
                                
-                       /* Quick check for "." and ".." */
-                       if (fname[0] == '.') {
-                               if (!fname[1]
-                                   || (fname[1] == '.' && !fname[2])) {
-                                       if (attrs & aDIR) {
-                                               sysdir_entry = True;
-                                       } else {
-                                               continue;
-                                       }
+               /* Quick check for "." and ".." */
+               if (fname[0] == '.') {
+                       if (!fname[1] || (fname[1] == '.' && !fname[2])) {
+                               if (attrs & aDIR) {
+                                       sysdir_entry = True;
+                               } else {
+                                       continue;
                                }
                        }
+               }
 
-                       if (!is_visible_file(conn, directory, dname, &sbuf1,
-                                            False)) {
-                               continue;
-                       }
+               if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+                       continue;
+               }
 
-                       if(!mask_match(fname, mask, conn->case_sensitive)) {
-                               continue;
-                       }
+               if(!mask_match(fname, mask, conn->case_sensitive)) {
+                       continue;
+               }
                                
-                       if (sysdir_entry) {
-                               status = NT_STATUS_OBJECT_NAME_INVALID;
-                               break;
-                       }
+               if (sysdir_entry) {
+                       status = NT_STATUS_OBJECT_NAME_INVALID;
+                       break;
+               }
 
-                       status = NT_STATUS_ACCESS_DENIED;
-                       slprintf(fname, sizeof(fname)-1, "%s/%s", directory,
-                                dname);
-                       if (!vfs_object_exist(conn, fname, &sbuf1)) {
-                               status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                               DEBUG(6, ("rename %s failed. Error %s\n",
-                                         fname, nt_errstr(status)));
-                               continue;
-                       }
-                       status = can_rename(conn,fname,attrs,&sbuf1);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(6, ("rename %s refused\n", fname));
-                               continue;
-                       }
-                       pstrcpy(destname,newname);
+               status = NT_STATUS_ACCESS_DENIED;
+               slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
+
+               /* Ensure the source name is valid for us to access. */
+               status = check_name(conn, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               if (!vfs_object_exist(conn, fname, &sbuf1)) {
+                       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                       DEBUG(6, ("rename %s failed. Error %s\n",
+                                 fname, nt_errstr(status)));
+                       continue;
+               }
+               status = can_rename(conn,fname,attrs,&sbuf1);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(6, ("rename %s refused\n", fname));
+                       continue;
+               }
+               pstrcpy(destname,newname);
                        
-                       if (!resolve_wildcards(fname,destname)) {
-                               DEBUG(6, ("resolve_wildcards %s %s failed\n", 
-                                         fname, destname));
-                               continue;
-                       }
+               if (!resolve_wildcards(fname,destname)) {
+                       DEBUG(6, ("resolve_wildcards %s %s failed\n", 
+                                 fname, destname));
+                       continue;
+               }
                                
-                       if (strcsequal(fname,destname)) {
-                               rename_open_files(conn, NULL, sbuf1.st_dev,
-                                                 sbuf1.st_ino, newname);
-                               DEBUG(3,("rename_internals: identical names "
-                                        "in wildcard rename %s - success\n",
-                                        fname));
-                               count++;
-                               status = NT_STATUS_OK;
-                               continue;
-                       }
+               /* Ensure the dest name is valid for us to access. */
+               status = check_name(conn, destname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
 
-                       if (!replace_if_exists
-                           && vfs_file_exist(conn,destname, NULL)) {
-                               DEBUG(6,("file_exist %s\n", destname));
-                               status = NT_STATUS_OBJECT_NAME_COLLISION;
-                               continue;
-                       }
+               if (strcsequal(fname,destname)) {
+                       rename_open_files(conn, NULL, sbuf1.st_dev,
+                                         sbuf1.st_ino, newname);
+                       DEBUG(3,("rename_internals: identical names "
+                                "in wildcard rename %s - success\n",
+                                fname));
+                       count++;
+                       status = NT_STATUS_OK;
+                       continue;
+               }
+
+               if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
+                       DEBUG(6,("file_exist %s\n", destname));
+                       status = NT_STATUS_OBJECT_NAME_COLLISION;
+                       continue;
+               }
                                
-                       if (rename_path_prefix_equal(fname, destname)) {
-                               return NT_STATUS_SHARING_VIOLATION;
-                       }
+               if (rename_path_prefix_equal(fname, destname)) {
+                       return NT_STATUS_SHARING_VIOLATION;
+               }
 
-                       lck = get_share_mode_lock(NULL, sbuf1.st_dev,
-                                                 sbuf1.st_ino, NULL, NULL);
+               lck = get_share_mode_lock(NULL, sbuf1.st_dev,
+                                         sbuf1.st_ino, NULL, NULL);
 
-                       if (!SMB_VFS_RENAME(conn,fname,destname)) {
-                               rename_open_files(conn, lck, sbuf1.st_dev,
-                                                 sbuf1.st_ino, newname);
-                               count++;
-                               status = NT_STATUS_OK;
-                       }
-                       TALLOC_FREE(lck);
-                       DEBUG(3,("rename_internals: doing rename on %s -> "
-                                "%s\n",fname,destname));
+               if (!SMB_VFS_RENAME(conn,fname,destname)) {
+                       rename_open_files(conn, lck, sbuf1.st_dev,
+                                         sbuf1.st_ino, newname);
+                       count++;
+                       status = NT_STATUS_OK;
                }
-               CloseDir(dir_hnd);
+               TALLOC_FREE(lck);
+               DEBUG(3,("rename_internals: doing rename on %s -> "
+                        "%s\n",fname,destname));
        }
-
-#if 0
-       /* Don't think needed any more - JRA. */
-               if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
-                       if (!rcdest && bad_path_dest) {
-                               if (ms_has_wild(last_component_dest))
-                                       return NT_STATUS_OBJECT_NAME_INVALID;
-                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                       }
-               }
-#endif
+       CloseDir(dir_hnd);
 
        if (count == 0 && NT_STATUS_IS_OK(status)) {
                status = map_nt_error_from_unix(errno);
@@ -4521,19 +4587,19 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        char *p;
        uint32 attrs = SVAL(inbuf,smb_vwv0);
        NTSTATUS status;
-       BOOL path1_contains_wcard = False;
-       BOOL path2_contains_wcard = False;
+       BOOL src_has_wcard = False;
+       BOOL dest_has_wcard = False;
 
        START_PROFILE(SMBmv);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
        }
        p++;
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
@@ -4544,7 +4610,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        
        DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
        
-       status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
+       status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -4568,8 +4634,12 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  * TODO: check error codes on all callers
  */
 
-NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
-                  int count, BOOL target_is_directory)
+NTSTATUS copy_file(connection_struct *conn,
+                       char *src,
+                       char *dest1,
+                       int ofun,
+                       int count,
+                       BOOL target_is_directory)
 {
        SMB_STRUCT_STAT src_sbuf, sbuf2;
        SMB_OFF_T ret=-1;
@@ -4689,14 +4759,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        int count=0;
        int error = ERRnoaccess;
        int err = 0;
-       BOOL has_wild;
-       BOOL exists=False;
        int tid2 = SVAL(inbuf,smb_vwv0);
        int ofun = SVAL(inbuf,smb_vwv1);
        int flags = SVAL(inbuf,smb_vwv2);
        BOOL target_is_directory=False;
-       BOOL path_contains_wcard1 = False;
-       BOOL path_contains_wcard2 = False;
+       BOOL source_has_wild = False;
+       BOOL dest_has_wild = False;
        SMB_STRUCT_STAT sbuf1, sbuf2;
        NTSTATUS status;
        START_PROFILE(SMBcopy);
@@ -4704,12 +4772,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        *directory = *mask = 0;
 
        p = smb_buf(inbuf);
-       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
+       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
        }
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
+       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
@@ -4727,13 +4795,13 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
        RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
 
-       status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
+       status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
        }
 
-       status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
+       status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
@@ -4777,25 +4845,38 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
                mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+       }
 
-       has_wild = path_contains_wcard1;
-
-       if (!has_wild) {
+       if (!source_has_wild) {
                pstrcat(directory,"/");
                pstrcat(directory,mask);
-               if (resolve_wildcards(directory,newname)
-                   && NT_STATUS_IS_OK(status = copy_file(
-                                              directory,newname,conn,ofun,
-                                              count,target_is_directory))) 
-                       count++;
-               if(!count && !NT_STATUS_IS_OK(status)) {
-                       END_PROFILE(SMBcopy);
+               if (dest_has_wild) {
+                       if (!resolve_wildcards(directory,newname)) {
+                               END_PROFILE(SMBcopy);
+                               return ERROR_NT(NT_STATUS_NO_MEMORY);
+                       }
+               }
+
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
-               if (!count) {
-                       exists = vfs_file_exist(conn,directory,NULL);
+               
+               status = check_name(conn, newname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
+               }
+               
+               status = copy_file(conn,directory,newname,ofun,
+                                       count,target_is_directory);
+
+               if(!NT_STATUS_IS_OK(status)) {
+                       END_PROFILE(SMBcopy);
+                       return ERROR_NT(status);
+               } else {
+                       count++;
                }
        } else {
                struct smb_Dir *dir_hnd = NULL;
@@ -4834,13 +4915,27 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                        error = ERRnoaccess;
                        slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
                        pstrcpy(destname,newname);
-                       if (resolve_wildcards(fname,destname) &&
-                                       NT_STATUS_IS_OK(status = copy_file(
-                                               fname,destname,conn,ofun,
-                                               count,target_is_directory))) {
+                       if (!resolve_wildcards(fname,destname)) {
+                               continue;
+                       }
+
+                       status = check_name(conn, fname);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return ERROR_NT(status);
+                       }
+               
+                       status = check_name(conn, destname);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return ERROR_NT(status);
+                       }
+               
+                       DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
+
+                       status = copy_file(conn,fname,destname,ofun,
+                                       count,target_is_directory);
+                       if (NT_STATUS_IS_OK(status)) {
                                count++;
                        }
-                       DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
                }
                CloseDir(dir_hnd);
        }
index 86e5f56fe2e7f9f8829814ab8c5a548044a942dc..33618360f1944cdd61c5e9c773b7be690b5304cf 100644 (file)
@@ -3743,17 +3743,22 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                return status;
        }
 
+       status = check_name(conn, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        /* source must already exist. */
        if (!VALID_STAT(sbuf1)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       status = check_name(conn, oldname);
+       status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_ACCESS_DENIED;
+               return status;
        }
 
-       status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+       status = check_name(conn, newname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -3763,11 +3768,6 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       status = check_name(conn, newname);
-       if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        /* No links from a directory. */
        if (S_ISDIR(sbuf1.st_mode)) {
                return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -4217,6 +4217,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        uint32 len;
        pstring newname;
        pstring base_name;
+       BOOL dest_has_wcard = False;
        NTSTATUS status = NT_STATUS_OK;
        char *p;
 
@@ -4232,7 +4233,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+       srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4261,7 +4262,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        } else {
                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
                        fname, newname ));
-               status = rename_internals(conn, fname, base_name, 0, overwrite, False);
+               status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
        }
 
        return status;
@@ -5324,6 +5325,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        return ERROR_NT(status);
                }
 
+               status = check_name(conn, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
+               }
+
                /*
                 * For CIFS UNIX extensions the target name may not exist.
                 */
@@ -5332,12 +5338,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
                        return UNIXERROR(ERRDOS,ERRbadpath);
                }    
-
-               status = check_name(conn, fname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
-               }
-
        }
 
        if (!CAN_WRITE(conn)) {
@@ -5642,6 +5642,12 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
+               return ERROR_NT(status);
+       }
+
        /* Any data in this call is an EA list. */
        if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
                return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
@@ -5673,12 +5679,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
-       status = check_name(conn, directory);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
-               return ERROR_NT(status);
-       }
-
        status = create_directory(conn, directory);
 
        if (!NT_STATUS_IS_OK(status)) {