mirror of
https://github.com/samba-team/samba.git
synced 2025-01-13 13:18:06 +03:00
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 b8327b21dd
)
This commit is contained in:
parent
9b0f22d065
commit
10ab7a3a78
@ -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",
|
||||
|
@ -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))) {
|
||||
|
@ -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);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sysdir_entry) {
|
||||
status = NT_STATUS_OBJECT_NAME_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
dir_hnd = OpenDir(conn, directory, mask, attrs);
|
||||
if (dir_hnd == NULL) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
|
||||
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 = 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_visible_file(conn, directory, dname, &sbuf1,
|
||||
False)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
status = can_rename(conn,fname,attrs,&sbuf1);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(6, ("rename %s refused\n", fname));
|
||||
continue;
|
||||
}
|
||||
CloseDir(dir_hnd);
|
||||
pstrcpy(destname,newname);
|
||||
|
||||
if (!resolve_wildcards(fname,destname)) {
|
||||
DEBUG(6, ("resolve_wildcards %s %s failed\n",
|
||||
fname, destname));
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
@ -3743,31 +3743,31 @@ 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);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user