diff options
author | Jeremy Allison <jra@samba.org> | 2007-03-03 01:35:58 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:18:23 -0500 |
commit | 10ab7a3a78b5b4d38f93f13f5b91b5eea5308e86 (patch) | |
tree | 27a0f601d022b7fef497914dd0333ef174795f08 /source3 | |
parent | 9b0f22d065b80d8cc0d4d2c9c1f52476ae68df95 (diff) | |
download | samba-10ab7a3a78b5b4d38f93f13f5b91b5eea5308e86.tar.gz samba-10ab7a3a78b5b4d38f93f13f5b91b5eea5308e86.tar.bz2 samba-10ab7a3a78b5b4d38f93f13f5b91b5eea5308e86.zip |
r21672: The cannonical file access pattern should look like this :
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.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/printing/nt_printing.c | 10 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 39 | ||||
-rw-r--r-- | source3/smbd/reply.c | 417 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 44 |
4 files changed, 303 insertions, 207 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 77b31bc517..b3c04913f1 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -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", diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 19710d1dcd..968c536caf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -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))) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8bccd45f4b..25c2aaa4dc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 86e5f56fe2..33618360f1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -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)) { |