summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-01-12 23:47:16 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:17:04 -0500
commitdb0ad252a0622dfac17d44ca646168df4c1c22e5 (patch)
tree36128572dc6d4319ec9f7ab4622aa620d165b3b9
parent700c3ab1c94fcd0ff422afa0e0e3faf419b3c5af (diff)
downloadsamba-db0ad252a0622dfac17d44ca646168df4c1c22e5.tar.gz
samba-db0ad252a0622dfac17d44ca646168df4c1c22e5.tar.bz2
samba-db0ad252a0622dfac17d44ca646168df4c1c22e5.zip
r20718: Sync up the filename path parsing changes from SAMBA_3_0_24.
The only difference between the two trees now w.r.t file serving are the changes to smbd/open.c in this branch I need to review. Jeremy. (This used to be commit f4474edf6a0c71001dbd01429ef70bafad6abd74)
-rw-r--r--source3/printing/nt_printing.c38
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c10
-rw-r--r--source3/smbd/dosmode.c8
-rw-r--r--source3/smbd/filename.c160
-rw-r--r--source3/smbd/msdfs.c6
-rw-r--r--source3/smbd/nttrans.c52
-rw-r--r--source3/smbd/reply.c685
-rw-r--r--source3/smbd/trans2.c88
8 files changed, 408 insertions, 639 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 5fa5db54e4..8f264bfd1e 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -656,13 +656,13 @@ BOOL nt_printing_init(void)
Function to allow filename parsing "the old way".
********************************************************************/
-static BOOL driver_unix_convert(char *name,connection_struct *conn,
- char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
+static void driver_unix_convert(char *name,connection_struct *conn,
+ char *saved_last_component, SMB_STRUCT_STAT *pst)
{
unix_format(name);
unix_clean_name(name);
trim_string(name,"/","/");
- return unix_convert(name, conn, saved_last_component, bad_path, pst);
+ unix_convert(conn, name, False, saved_last_component, pst);
}
/*******************************************************************
@@ -1279,7 +1279,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
SMB_STRUCT_STAT stat_buf;
- BOOL bad_path;
NTSTATUS status;
@@ -1291,7 +1290,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
/* Get file version info (if available) for previous file (if it exists) */
pstrcpy(filepath, old_file);
- driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
+ driver_unix_convert(filepath,conn,NULL,&stat_buf);
status = open_file_ntcreate(conn, filepath, &stat_buf,
FILE_GENERIC_READ,
@@ -1327,7 +1326,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
/* Get file version info (if available) for new file */
pstrcpy(filepath, new_file);
- driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
+ driver_unix_convert(filepath,conn,NULL,&stat_buf);
status = open_file_ntcreate(conn, filepath, &stat_buf,
FILE_GENERIC_READ,
@@ -1404,7 +1403,6 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
DATA_BLOB null_pw;
fstring res_type;
files_struct *fsp = NULL;
- BOOL bad_path;
SMB_STRUCT_STAT st;
connection_struct *conn;
NTSTATUS status;
@@ -1456,7 +1454,7 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
* deriver the cversion. */
slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
- driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
+ driver_unix_convert(driverpath,conn,NULL,&st);
if ( !vfs_file_exist( conn, driverpath, &st ) ) {
*perr = WERR_BADFILE;
@@ -1742,7 +1740,6 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
pstring inbuf;
pstring outbuf;
fstring res_type;
- BOOL bad_path;
SMB_STRUCT_STAT st;
int ver = 0;
int i;
@@ -1798,7 +1795,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
*/
DEBUG(5,("Creating first directory\n"));
slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
- driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
+ driver_unix_convert(new_dir, conn, NULL, &st);
create_directory(conn, new_dir);
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
@@ -1824,7 +1821,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
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, &bad_path, &st);
+ driver_unix_convert(new_name, conn, NULL, &st);
if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, 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",
@@ -1840,7 +1837,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
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, &bad_path, &st);
+ driver_unix_convert(new_name, conn, NULL, &st);
if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, 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",
@@ -1858,7 +1855,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
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, &bad_path, &st);
+ driver_unix_convert(new_name, conn, NULL, &st);
if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, 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",
@@ -1877,7 +1874,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
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, &bad_path, &st);
+ driver_unix_convert(new_name, conn, NULL, &st);
if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, 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",
@@ -1905,7 +1902,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
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, &bad_path, &st);
+ driver_unix_convert(new_name, conn, NULL, &st);
if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn,
OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
@@ -4812,7 +4809,6 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
DATA_BLOB null_pw;
NTSTATUS nt_status;
fstring res_type;
- BOOL bad_path;
SMB_STRUCT_STAT st;
if ( !info_3 )
@@ -4855,7 +4851,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->driverpath ) {
if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting driverfile [%s]\n", s));
unlink_internals(conn, 0, file, False);
}
@@ -4864,7 +4860,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->configfile ) {
if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting configfile [%s]\n", s));
unlink_internals(conn, 0, file, False);
}
@@ -4873,7 +4869,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->datafile ) {
if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting datafile [%s]\n", s));
unlink_internals(conn, 0, file, False);
}
@@ -4882,7 +4878,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->helpfile ) {
if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting helpfile [%s]\n", s));
unlink_internals(conn, 0, file, False);
}
@@ -4898,7 +4894,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
pstrcpy( file, p );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting dependent file [%s]\n", file));
unlink_internals(conn, 0, file, False);
}
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index abfa794518..646a414cda 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -2036,7 +2036,6 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, const char *server_unc, const
DATA_BLOB null_pw;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
- BOOL bad_path;
NTSTATUS nt_status;
connection_struct *conn = NULL;
BOOL became_user = False;
@@ -2067,8 +2066,8 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, const char *server_unc, const
became_user = True;
pstrcpy(tmp_file, file);
- unix_convert(tmp_file, conn, NULL, &bad_path, &st);
- if (bad_path) {
+ nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", file));
status = WERR_ACCESS_DENIED;
goto error_exit;
@@ -2141,7 +2140,6 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, const char *server_unc, const
DATA_BLOB null_pw;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
- BOOL bad_path;
NTSTATUS nt_status;
connection_struct *conn = NULL;
BOOL became_user = False;
@@ -2171,8 +2169,8 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, const char *server_unc, const
became_user = True;
pstrcpy(tmp_file, file);
- unix_convert(tmp_file, conn, NULL, &bad_path, &st);
- if (bad_path) {
+ nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", file));
status = WERR_ACCESS_DENIED;
goto error_exit;
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 1172fe3e6b..ff4291c08c 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -35,14 +35,6 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
Work out whether this file is offline
****************************************************************************/
-#ifndef ISDOT
-#define ISDOT(p) (*(p) == '.' && *((p) + 1) == '\0')
-#endif /* ISDOT */
-
-#ifndef ISDOTDOT
-#define ISDOTDOT(p) (*(p) == '.' && *((p) + 1) == '.' && *((p) + 2) == '\0')
-#endif /* ISDOTDOT */
-
static uint32 set_offline_flag(connection_struct *conn, const char *const path)
{
if (ISDOT(path) || ISDOTDOT(path)) {
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 1ea5228e91..3f02f6090f 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -64,18 +64,20 @@ changes etc.
We assume that we have already done a chdir() to the right "root" directory
for this service.
-The function will return False if some part of the name except for the last
-part cannot be resolved
+The function will return an NTSTATUS error if some part of the name except for the last
+part cannot be resolved, else NT_STATUS_OK.
+
+Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
+get any fatal errors that should immediately terminate the calling
+SMB processing whilst resolving.
If the saved_last_component != 0, then the unmodified last component
of the pathname is returned there. This is used in an exceptional
case in reply_mv (so far). If saved_last_component == 0 then nothing
is returned there.
-The bad_path arg is set to True if the filename walk failed. This is
-used to pick the correct error code to return between ENOENT and ENOTDIR
-as Windows applications depend on ERRbadpath being returned if a component
-of a pathname does not exist.
+If last_component_wcard is true then a MS wildcard was detected and
+should be allowed in the last component of the path only.
On exit from unix_convert, if *pst was not null, then the file stat
struct will be returned if the file exists and was found, if not this
@@ -83,8 +85,11 @@ stat struct will be filled with zeros (and this can be detected by checking
for nlinks = 0, which can never be true for any file).
****************************************************************************/
-BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component,
- BOOL *bad_path, SMB_STRUCT_STAT *pst)
+NTSTATUS unix_convert(connection_struct *conn,
+ pstring name,
+ BOOL allow_wcard_last_component,
+ char *saved_last_component,
+ SMB_STRUCT_STAT *pst)
{
SMB_STRUCT_STAT st;
char *start, *end;
@@ -96,14 +101,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
SET_STAT_INVALID(*pst);
*dirpath = 0;
- *bad_path = False;
- if(saved_last_component)
+
+ if(saved_last_component) {
*saved_last_component = 0;
+ }
if (conn->printer) {
/* we don't ever use the filenames on a printer share as a
filename - so don't convert them */
- return True;
+ return NT_STATUS_OK;
}
DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
@@ -136,7 +142,12 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
*pst = st;
}
DEBUG(5,("conversion finished \"\" -> %s\n",name));
- return(True);
+ return NT_STATUS_OK;
+ }
+
+ if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) {
+ /* Start of pathname can't be "." only. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
/*
@@ -145,10 +156,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
if(saved_last_component) {
end = strrchr_m(name, '/');
- if(end)
+ if (end) {
pstrcpy(saved_last_component, end + 1);
- else
+ } else {
pstrcpy(saved_last_component, name);
+ }
}
/*
@@ -169,7 +181,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) {
*pst = st;
- return True;
+ return NT_STATUS_OK;
}
/*
@@ -177,10 +189,22 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
*/
if (SMB_VFS_STAT(conn,name,&st) == 0) {
+ /* Ensure we catch all names with in "/."
+ this is disallowed under Windows. */
+ const char *p = strstr(name, "/."); /* mb safe. */
+ if (p) {
+ if (p[2] == '/') {
+ /* Error code within a pathname. */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ } else if (p[2] == '\0') {
+ /* Error code at the end of a pathname. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ }
stat_cache_add(orig_path, name, conn->case_sensitive);
DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
*pst = st;
- return(True);
+ return NT_STATUS_OK;
}
DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));
@@ -190,19 +214,20 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* sensitive then searching won't help.
*/
- if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) &&
- !*lp_mangled_map(conn->params))
- return(False);
-
- name_has_wildcard = ms_has_wild(start);
+ if (conn->case_sensitive &&
+ !mangle_is_mangled(name, conn->params) &&
+ !*lp_mangled_map(conn->params)) {
+ return NT_STATUS_OK;
+ }
/*
* is_mangled() was changed to look at an entire pathname, not
* just a component. JRA.
*/
- if (mangle_is_mangled(start, conn->params))
+ if (mangle_is_mangled(start, conn->params)) {
component_was_mangled = True;
+ }
/*
* Now we need to recursively match the name against the real
@@ -218,16 +243,64 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
/*
* Pinpoint the end of this section of the filename.
*/
- end = strchr_m(start, '/');
+ end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */
/*
* Chop the name at this point.
*/
- if (end)
+ if (end) {
*end = 0;
+ }
- if(saved_last_component != 0)
+ if (saved_last_component != 0) {
pstrcpy(saved_last_component, end ? end + 1 : start);
+ }
+
+ /* The name cannot have a component of "." */
+
+ if (ISDOT(start)) {
+ if (end) {
+ if (allow_wcard_last_component) {
+ /* We're terminating here so we
+ * can be a little slower and get
+ * the error code right. Windows
+ * treats the last part of the pathname
+ * separately I think, so if the last
+ * component is a wildcard then we treat
+ * this ./ as "end of component" */
+
+ const char *p = strchr(end+1, '/');
+
+ if (!p && ms_has_wild(end+1)) {
+ /* Error code at the end of a pathname. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ } else {
+ /* Error code within a pathname. */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ }
+ /* Error code within a pathname. */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ } else {
+ /* Error code at the end of a pathname. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ }
+
+ /* The name cannot have a wildcard if it's not
+ the last component. */
+
+ name_has_wildcard = ms_has_wild(start);
+
+ /* Wildcard not valid anywhere. */
+ if (name_has_wildcard && !allow_wcard_last_component) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+
+ /* Wildcards never valid within a pathname. */
+ if (name_has_wildcard && end) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
/*
* Check if the name exists up to this point.
@@ -251,9 +324,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* Windows applications depend on the difference between
* these two errors.
*/
- errno = ENOTDIR;
- *bad_path = True;
- return(False);
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
if (!end) {
@@ -278,8 +349,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* later.
*/
- if (end)
+ if (end) {
pstrcpy(rest,end+1);
+ }
/* Reset errno so we can detect directory open errors. */
errno = 0;
@@ -288,7 +360,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* Try to find this part of the path in the directory.
*/
- if (ms_has_wild(start) ||
+ if (name_has_wildcard ||
!scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) {
if (end) {
/*
@@ -304,13 +376,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* Windows applications depend on the difference between
* these two errors.
*/
- *bad_path = True;
- return(False);
+ if (errno == ENOENT) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ return map_nt_error_from_unix(errno);
}
if (errno == ENOTDIR) {
- *bad_path = True;
- return(False);
+ /* Name exists but is not a directory. */
+ return map_nt_error_from_unix(ENOTDIR);
}
/*
@@ -335,7 +409,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
}
DEBUG(5,("New file %s\n",start));
- return(True);
+ return NT_STATUS_OK;
}
/*
@@ -346,7 +420,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
end = start + strlen(start);
if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) ||
!safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) {
- return False;
+ return map_nt_error_from_unix(ENAMETOOLONG);
}
*end = '\0';
} else {
@@ -367,8 +441,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
/*
* Add to the dirpath that we have resolved so far.
*/
- if (*dirpath)
+ if (*dirpath) {
pstrcat(dirpath,"/");
+ }
pstrcat(dirpath,start);
@@ -377,14 +452,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* as this can change the size.
*/
- if(!component_was_mangled && !name_has_wildcard)
+ if(!component_was_mangled && !name_has_wildcard) {
stat_cache_add(orig_path, dirpath, conn->case_sensitive);
+ }
/*
* Restore the / that we wiped out earlier.
*/
- if (end)
+ if (end) {
*end = '/';
+ }
}
/*
@@ -392,15 +469,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* as this can change the size.
*/
- if(!component_was_mangled && !name_has_wildcard)
+ if(!component_was_mangled && !name_has_wildcard) {
stat_cache_add(orig_path, name, conn->case_sensitive);
+ }
/*
* The name has been resolved.
*/
DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
- return(True);
+ return NT_STATUS_OK;
}
/****************************************************************************
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 12fd333efe..42595c033e 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -326,8 +326,8 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath,
pstring localpath;
int consumed_level = 1;
char *p;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
+ NTSTATUS status;
pstring reqpath;
if (!dp || !conn) {
@@ -349,7 +349,9 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath,
DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath));
- unix_convert(dp->reqpath,conn,0,&bad_path,&sbuf);
+ status = unix_convert(conn, dp->reqpath, False, NULL, &sbuf);
+ /* Should we terminate on status != NT_STATUS_OK ???? */
+
/* JRA... should we strlower the last component here.... ? */
pstrcpy(localpath, dp->reqpath);
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 3e64cdc2d2..94bf363fc7 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -466,7 +466,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
int info = 0;
- BOOL bad_path = False;
files_struct *fsp=NULL;
char *p = NULL;
struct timespec c_timespec;
@@ -628,18 +627,17 @@ int reply_ntcreate_and_X(connection_struct *conn,
set_posix_case_semantics(conn, file_attributes);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
-
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
/* All file access must go through check_name() */
if (!check_name(fname,conn)) {
restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
#if 0
@@ -1090,7 +1088,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
int info = 0;
- BOOL bad_path = False;
files_struct *fsp = NULL;
char *p = NULL;
BOOL extended_oplock_granted = False;
@@ -1257,15 +1254,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
/* All file access must go through check_name() */
if (!check_name(fname,conn)) {
restore_case_semantics(conn, file_attributes);
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
#if 0
@@ -1562,8 +1559,6 @@ int reply_ntcancel(connection_struct *conn,
static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs)
{
- BOOL bad_path_oldname = False;
- BOOL bad_path_newname = False;
SMB_STRUCT_STAT sbuf1, sbuf2;
pstring last_component_oldname;
pstring last_component_newname;
@@ -1577,24 +1572,12 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- /* No wildcards. */
- if (ms_has_wild(newname) || ms_has_wild(oldname)) {
- return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- }
-
if (!CAN_WRITE(conn))
return NT_STATUS_MEDIA_WRITE_PROTECTED;
- unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
- if (bad_path_oldname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_oldname[0] == '.') {
- if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Source must already exist. */
@@ -1611,16 +1594,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
return NT_STATUS_NO_SUCH_FILE;
}
- unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
- if (bad_path_newname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_newname[0] == '.') {
- if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Disallow if newname already exists. */
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index b3df8acf11..5914a3b169 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3,7 +3,7 @@
Main SMB reply routines
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Andrew Bartlett 2001
- Copyright (C) Jeremy Allison 1992-2004.
+ Copyright (C) Jeremy Allison 1992-2007.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,143 +37,6 @@ extern struct current_user current_user;
extern BOOL global_encrypted_passwords_negotiated;
/****************************************************************************
- Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
- We're assuming here that '/' is not the second byte in any multibyte char
- set (a safe assumption). '\\' *may* be the second byte in a multibyte char
- set.
-****************************************************************************/
-
-NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
-{
- char *d = destname;
- const char *s = srcname;
- NTSTATUS ret = NT_STATUS_OK;
- BOOL start_of_name_component = True;
- unsigned int num_bad_components = 0;
-
- while (*s) {
- if (IS_DIRECTORY_SEP(*s)) {
- /*
- * Safe to assume is not the second part of a mb char as this is handled below.
- */
- /* Eat multiple '/' or '\\' */
- while (IS_DIRECTORY_SEP(*s)) {
- s++;
- }
- if ((d != destname) && (*s != '\0')) {
- /* We only care about non-leading or trailing '/' or '\\' */
- *d++ = '/';
- }
-
- start_of_name_component = True;
- continue;
- }
-
- if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
- /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
-
- /*
- * No mb char starts with '.' so we're safe checking the directory separator here.
- */
-
- /* If we just added a '/' - delete it */
- if ((d > destname) && (*(d-1) == '/')) {
- *(d-1) = '\0';
- d--;
- }
-
- /* Are we at the start ? Can't go back further if so. */
- if (d <= destname) {
- ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- break;
- }
- /* Go back one level... */
- /* We know this is safe as '/' cannot be part of a mb sequence. */
- /* NOTE - if this assumption is invalid we are not in good shape... */
- /* Decrement d first as d points to the *next* char to write into. */
- for (d--; d > destname; d--) {
- if (*d == '/')
- break;
- }
- s += 2; /* Else go past the .. */
- /* We're still at the start of a name component, just the previous one. */
-
- if (num_bad_components) {
- /* Hmmm. Should we only decrement the bad_components if
- we're removing a bad component ? Need to check this. JRA. */
- num_bad_components--;
- }
-
- continue;
-
- } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
- /* Component of pathname can't be "." only. */
- ret = NT_STATUS_OBJECT_NAME_INVALID;
- num_bad_components++;
- *d++ = *s++;
- continue;
- }
- }
-
- if (!(*s & 0x80)) {
- if (*s <= 0x1f) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- switch (*s) {
- case '*':
- case '?':
- case '<':
- case '>':
- case '"':
- return NT_STATUS_OBJECT_NAME_INVALID;
- default:
- *d++ = *s++;
- break;
- }
- } else {
- size_t siz;
- /* Get the size of the next MB character. */
- next_codepoint(s,&siz);
- switch(siz) {
- case 5:
- *d++ = *s++;
- /*fall through*/
- case 4:
- *d++ = *s++;
- /*fall through*/
- case 3:
- *d++ = *s++;
- /*fall through*/
- case 2:
- *d++ = *s++;
- /*fall through*/
- case 1:
- *d++ = *s++;
- break;
- default:
- DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
- *d = '\0';
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
- if (start_of_name_component && num_bad_components) {
- num_bad_components++;
- }
- start_of_name_component = False;
- }
-
- if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
- if (num_bad_components > 1) {
- ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
- }
-
- *d = '\0';
- return ret;
-}
-
-/****************************************************************************
Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
path or anything including wildcards.
We're assuming here that '/' is not the second byte in any multibyte char
@@ -181,15 +44,19 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
set.
****************************************************************************/
-NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+NTSTATUS check_path_syntax_internal(pstring destname,
+ const pstring srcname,
+ BOOL windows_path, BOOL
+ *p_last_component_contains_wcard)
{
char *d = destname;
const char *s = srcname;
NTSTATUS ret = NT_STATUS_OK;
BOOL start_of_name_component = True;
- unsigned int num_bad_components = 0;
- *p_contains_wcard = False;
+ if (p_last_component_contains_wcard) {
+ *p_last_component_contains_wcard = False;
+ }
while (*s) {
if (IS_DIRECTORY_SEP(*s)) {
@@ -206,6 +73,10 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
}
start_of_name_component = True;
+ /* New component. */
+ if (p_last_component_contains_wcard) {
+ *p_last_component_contains_wcard = False;
+ }
continue;
}
@@ -238,36 +109,32 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
}
s += 2; /* Else go past the .. */
/* We're still at the start of a name component, just the previous one. */
-
- if (num_bad_components) {
- /* Hmmm. Should we only decrement the bad_components if
- we're removing a bad component ? Need to check this. JRA. */
- num_bad_components--;
- }
-
continue;
} else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
- /* Component of pathname can't be "." only. */
- ret = NT_STATUS_OBJECT_NAME_INVALID;
- num_bad_components++;
- *d++ = *s++;
- continue;
+ if (!windows_path) {
+ /* Eat the '.' */
+ s++;
+ continue;
+ }
}
+
}
if (!(*s & 0x80)) {
- if (*s <= 0x1f) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- if (!*p_contains_wcard) {
+ if (windows_path) {
+ if (*s <= 0x1f) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
switch (*s) {
case '*':
case '?':
case '<':
case '>':
case '"':
- *p_contains_wcard = True;
+ if (p_last_component_contains_wcard) {
+ *p_last_component_contains_wcard = True;
+ }
break;
default:
break;
@@ -295,130 +162,48 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
*d++ = *s++;
break;
default:
- DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
+ DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
*d = '\0';
return NT_STATUS_INVALID_PARAMETER;
}
}
- if (start_of_name_component && num_bad_components) {
- num_bad_components++;
- }
start_of_name_component = False;
}
- if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
- /* For some strange reason being called from findfirst changes
- the num_components number to cause the error return to change. JRA. */
- if (num_bad_components > 2) {
- ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
- }
-
*d = '\0';
return ret;
}
/****************************************************************************
- Check the path for a POSIX client.
- We're assuming here that '/' is not the second byte in any multibyte char
- set (a safe assumption).
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
+ No wildcards allowed.
****************************************************************************/
-NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
- char *d = destname;
- const char *s = srcname;
- NTSTATUS ret = NT_STATUS_OK;
- BOOL start_of_name_component = True;
-
- while (*s) {
- if (*s == '/') {
- /*
- * Safe to assume is not the second part of a mb char as this is handled below.
- */
- /* Eat multiple '/' or '\\' */
- while (*s == '/') {
- s++;
- }
- if ((d != destname) && (*s != '\0')) {
- /* We only care about non-leading or trailing '/' */
- *d++ = '/';
- }
-
- start_of_name_component = True;
- continue;
- }
-
- if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
- /* Uh oh - "/../" or "/..\0" ! */
-
- /*
- * No mb char starts with '.' so we're safe checking the directory separator here.
- */
-
- /* If we just added a '/' - delete it */
- if ((d > destname) && (*(d-1) == '/')) {
- *(d-1) = '\0';
- d--;
- }
+ return check_path_syntax_internal(destname, srcname, True, NULL);
+}
- /* Are we at the start ? Can't go back further if so. */
- if (d <= destname) {
- ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- break;
- }
- /* Go back one level... */
- /* We know this is safe as '/' cannot be part of a mb sequence. */
- /* NOTE - if this assumption is invalid we are not in good shape... */
- /* Decrement d first as d points to the *next* char to write into. */
- for (d--; d > destname; d--) {
- if (*d == '/')
- break;
- }
- s += 2; /* Else go past the .. */
- continue;
+/****************************************************************************
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
+ Wildcards allowed - p_contains_wcard returns true if the last component contained
+ a wildcard.
+****************************************************************************/
- } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
- /* Eat the '.' */
- s++;
- continue;
- }
- }
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+{
+ return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
+}
- if (!(*s & 0x80)) {
- *d++ = *s++;
- } else {
- size_t siz;
- /* Get the size of the next MB character. */
- next_codepoint(s,&siz);
- switch(siz) {
- case 5:
- *d++ = *s++;
- /*fall through*/
- case 4:
- *d++ = *s++;
- /*fall through*/
- case 3:
- *d++ = *s++;
- /*fall through*/
- case 2:
- *d++ = *s++;
- /*fall through*/
- case 1:
- *d++ = *s++;
- break;
- default:
- DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
- *d = '\0';
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
- start_of_name_component = False;
- }
+/****************************************************************************
+ Check the path for a POSIX client.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption).
+****************************************************************************/
- *d = '\0';
- return ret;
+static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+{
+ return check_path_syntax_internal(destname, srcname, False, NULL);
}
/****************************************************************************
@@ -823,7 +608,6 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
int outsize = 0;
pstring name;
BOOL ok = False;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
@@ -845,10 +629,10 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
- unix_convert(name,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, name, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBchkpth);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (check_name(name,conn)) {
@@ -871,8 +655,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
* the parent directory is valid but not the
* last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
* for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
- * if the path is invalid. This is different from set_bad_path_error()
- * in the non-NT error case.
+ * if the path is invalid.
*/
END_PROFILE(SMBchkpth);
return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
@@ -902,7 +685,6 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
int mode=0;
SMB_OFF_T size=0;
time_t mtime=0;
- BOOL bad_path = False;
char *p;
NTSTATUS status;
@@ -927,10 +709,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
mtime = 0;
ok = True;
} else {
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBgetatr);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (check_name(fname,conn)) {
if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
@@ -948,7 +730,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (!ok) {
END_PROFILE(SMBgetatr);
- return UNIXERROR(ERRDOS, ERRbadfile);
+ return UNIXERROR(ERRDOS,ERRbadfile);
}
outsize = set_message(outbuf,10,0,True);
@@ -982,7 +764,6 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
int mode;
time_t mtime;
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
char *p;
NTSTATUS status;
@@ -997,10 +778,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path || !check_name(fname, conn)) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsetatr);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (fname[0] == '.' && fname[1] == '\0') {
@@ -1012,6 +793,11 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
+ if (!check_name(fname,conn)) {
+ END_PROFILE(SMBsetatr);
+ return UNIXERROR(ERRDOS, ERRnoaccess);
+ }
+
mode = SVAL(inbuf,smb_vwv0);
mtime = srv_make_unix_date3(inbuf+smb_vwv1);
@@ -1118,7 +904,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
BOOL check_descend = False;
BOOL expect_close = False;
BOOL can_open = True;
- BOOL bad_path = False;
NTSTATUS nt_status;
BOOL mask_contains_wcard = False;
BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
@@ -1160,7 +945,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
pstrcpy(directory,path);
pstrcpy(dir2,path);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
+ nt_status = unix_convert(conn, directory, mask_contains_wcard, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ END_PROFILE(SMBsearch);
+ return ERROR_NT(nt_status);
+ }
unix_format(dir2);
if (!check_name(directory,conn))
@@ -1209,9 +998,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (dptr_num < 0) {
if(dptr_num == -2) {
END_PROFILE(SMBsearch);
- if ((errno == ENOENT) && bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- }
return UNIXERROR(ERRDOS, ERRnofids);
}
END_PROFILE(SMBsearch);
@@ -1377,7 +1163,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
time_t mtime=0;
int info;
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
int deny_mode;
@@ -1399,10 +1184,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopen);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
@@ -1486,7 +1271,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
int mtime=0;
SMB_STRUCT_STAT sbuf;
int smb_action = 0;
- BOOL bad_path = False;
files_struct *fsp;
NTSTATUS status;
SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
@@ -1518,10 +1302,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
@@ -1667,7 +1451,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int outsize = 0;
uint32 fattr = SVAL(inbuf,smb_vwv0);
struct utimbuf times;
- BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
SMB_STRUCT_STAT sbuf;
@@ -1691,10 +1474,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (fattr & aVOLID) {
@@ -1758,7 +1541,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstring fname;
int outsize = 0;
uint32 fattr = SVAL(inbuf,smb_vwv0);
- BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
int tmpfd;
@@ -1782,10 +1564,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
tmpfd = smb_mkstemp(fname);
@@ -1898,12 +1680,12 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
Check if a user is allowed to delete a file.
********************************************************************/
-static NTSTATUS can_delete(connection_struct *conn, char *fname,
- uint32 dirtype, BOOL bad_path)
+static NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype)
{
SMB_STRUCT_STAT sbuf;
uint32 fattr;
files_struct *fsp;
+ uint32 dirtype_orig = dirtype;
NTSTATUS status;
DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
@@ -1913,22 +1695,56 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname,
}
if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
- if(errno == ENOENT) {
- if (bad_path) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- } else {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
- }
return map_nt_error_from_unix(errno);
}
fattr = dos_mode(conn,fname,&sbuf);
+ if (dirtype & FILE_ATTRIBUTE_NORMAL) {
+ dirtype = aDIR|aARCH|aRONLY;
+ }
+
+ dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
+ if (!dirtype) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (!dir_check_ftype(conn, fattr, dirtype)) {
+ if (fattr & aDIR) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (dirtype_orig & 0x8000) {
+ /* These will never be set for POSIX. */
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+#if 0
+ if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
+ if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (dirtype & 0xFF00) {
+ /* These will never be set for POSIX. */
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ dirtype &= 0xFF;
+ if (!dirtype) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
/* Can't delete a directory. */
if (fattr & aDIR) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
+#endif
#if 0 /* JRATEST */
else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
@@ -1952,9 +1768,6 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname,
return NT_STATUS_CANNOT_DELETE;
}
}
- if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
- return NT_STATUS_NO_SUCH_FILE;
- }
/* On open checks the open itself will check the share mode, so
don't do it here as we'll get it wrong. */
@@ -1979,27 +1792,21 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname,
code.
****************************************************************************/
-NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
- char *name, BOOL has_wild)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
{
pstring directory;
pstring mask;
- pstring orig_name;
char *p;
int count=0;
- NTSTATUS error = NT_STATUS_OK;
- BOOL bad_path = False;
- BOOL rc = True;
+ NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf;
*directory = *mask = 0;
- rc = unix_convert(name,conn,0,&bad_path,&sbuf);
-
- /*
- * Feel my pain, this code needs rewriting *very* badly! -- vl
- */
- pstrcpy(orig_name, name);
+ status = unix_convert(conn, name, has_wild, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
p = strrchr_m(name,'/');
if (!p) {
@@ -2020,33 +1827,28 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask,conn->params))
+ if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- error = can_delete(conn,directory,dirtype,bad_path);
- if (!NT_STATUS_IS_OK(error))
- return error;
+ if (dirtype == 0) {
+ dirtype = FILE_ATTRIBUTE_NORMAL;
+ }
+ status = can_delete(conn,directory,dirtype);
+ if (!NT_STATUS_IS_OK(status))
+ return status;
if (SMB_VFS_UNLINK(conn,directory) == 0) {
count++;
}
-
} else {
struct smb_Dir *dir_hnd = NULL;
const char *dname;
- /* Ensure we check bad_path in the wcard case.
- * This may not be correct w.r.t. Windows (needs
- * smbtorture test cases which will be forthcoming)
- * but prevents us from continuing in the obvious
- * bad path case. This is merely a placeholder. JRA.
- */
-
- if (!rc && bad_path) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
if (strequal(mask,"????????.???"))
@@ -2062,12 +1864,11 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
if (dir_hnd) {
long offset = 0;
- error = NT_STATUS_NO_SUCH_FILE;
+ status = NT_STATUS_NO_SUCH_FILE;
while ((dname = ReadDirName(dir_hnd, &offset))) {
SMB_STRUCT_STAT st;
pstring fname;
- BOOL sys_direntry = False;
pstrcpy(fname,dname);
if (!is_visible_file(conn, directory, dname, &st, True)) {
@@ -2077,44 +1878,31 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
/* Quick check for "." and ".." */
if (fname[0] == '.') {
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
- if (dirtype & FILE_ATTRIBUTE_DIRECTORY) {
- sys_direntry = True;
- } else {
- continue;
- }
+ continue;
}
}
if(!mask_match(fname, mask, conn->case_sensitive))
continue;
- if (sys_direntry) {
- error = NT_STATUS_OBJECT_NAME_INVALID;
- DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
- fname, mask));
- break;
- }
-
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- error = can_delete(conn, fname, dirtype,
- bad_path);
- if (!NT_STATUS_IS_OK(error)) {
+ status = can_delete(conn, fname, dirtype);
+ if (!NT_STATUS_IS_OK(status)) {
continue;
}
- if (SMB_VFS_UNLINK(conn,fname) == 0) {
+ if (SMB_VFS_UNLINK(conn,fname) == 0)
count++;
- }
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
}
CloseDir(dir_hnd);
}
}
- if (count == 0 && NT_STATUS_IS_OK(error)) {
- error = map_nt_error_from_unix(errno);
+ if (count == 0 && NT_STATUS_IS_OK(status)) {
+ status = map_nt_error_from_unix(errno);
}
- return error;
+ return status;
}
/****************************************************************************
@@ -3774,7 +3562,6 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstring directory;
int outsize;
NTSTATUS status;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBmkdir);
@@ -3787,10 +3574,10 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
status = create_directory(conn, directory);
@@ -3939,7 +3726,7 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory)
pstrcpy(fullname, directory);
pstrcat(fullname, "/");
pstrcat(fullname, dname);
-
+
if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
break;
if(st.st_mode & S_IFDIR) {
@@ -3977,7 +3764,6 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstring directory;
int outsize = 0;
BOOL ok = False;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBrmdir);
@@ -3990,10 +3776,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
- unix_convert(directory,conn, NULL,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (check_name(directory,conn)) {
@@ -4171,24 +3957,16 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest)
NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
{
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
pstring newname_last_component;
- NTSTATUS error = NT_STATUS_OK;
+ NTSTATUS status = NT_STATUS_OK;
BOOL dest_exists;
- BOOL rcdest = True;
struct share_mode_lock *lck = NULL;
ZERO_STRUCT(sbuf);
- rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
- /* Quick check for "." and ".." */
- if (!bad_path && newname_last_component[0] == '.') {
- if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
- return NT_STATUS_ACCESS_DENIED;
- }
- }
- if (!rcdest && bad_path) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Ensure newname contains a '/' */
@@ -4250,14 +4028,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- error = can_rename(conn,newname,attrs,&sbuf);
+ status = can_rename(conn,newname,attrs,&sbuf);
- if (dest_exists && !NT_STATUS_IS_OK(error)) {
+ if (dest_exists && !NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), fsp->fsp_name,newname));
- if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
- error = NT_STATUS_ACCESS_DENIED;
- return error;
+ nt_errstr(status), fsp->fsp_name,newname));
+ if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
+ status = NT_STATUS_ACCESS_DENIED;
+ return status;
}
if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
@@ -4277,15 +4055,15 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
TALLOC_FREE(lck);
if (errno == ENOTDIR || errno == EISDIR) {
- error = NT_STATUS_OBJECT_NAME_COLLISION;
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
} else {
- error = map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
}
DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
- nt_errstr(error), fsp->fsp_name,newname));
+ nt_errstr(status), fsp->fsp_name,newname));
- return error;
+ return status;
}
/****************************************************************************
@@ -4300,12 +4078,8 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
pstring last_component_src;
pstring last_component_dest;
char *p;
- BOOL bad_path_src = False;
- BOOL bad_path_dest = False;
int count=0;
- NTSTATUS error = NT_STATUS_OK;
- BOOL rc = True;
- BOOL rcdest = True;
+ NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf1, sbuf2;
struct share_mode_lock *lck = NULL;
@@ -4314,27 +4088,14 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
- if (!rc && bad_path_src) {
- if (ms_has_wild(last_component_src))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_src[0] == '.') {
- if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, name, has_wild, last_component_src, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
-
- /* Quick check for "." and ".." */
- if (last_component_dest[0] == '.') {
- if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, newname, True, last_component_dest, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/*
@@ -4366,7 +4127,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && 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) {
@@ -4451,25 +4212,19 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- error = map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
-
- return error;
- }
+ nt_errstr(status), directory,newname));
- 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;
+ return status;
}
- error = can_rename(conn,directory,attrs,&sbuf1);
+ status = can_rename(conn,directory,attrs,&sbuf1);
- if (!NT_STATUS_IS_OK(error)) {
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
- return error;
+ nt_errstr(status), directory,newname));
+ return status;
}
/*
@@ -4505,14 +4260,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
TALLOC_FREE(lck);
if (errno == ENOTDIR || errno == EISDIR)
- error = NT_STATUS_OBJECT_NAME_COLLISION;
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
else
- error = map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
+ nt_errstr(status), directory,newname));
- return error;
+ return status;
} else {
/*
* Wildcards - process each file that matches.
@@ -4529,8 +4284,8 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
if (dir_hnd) {
long offset = 0;
- error = NT_STATUS_NO_SUCH_FILE;
-/* Was error = 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;
@@ -4556,19 +4311,19 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
continue;
if (sysdir_entry) {
- error = NT_STATUS_OBJECT_NAME_INVALID;
+ status = NT_STATUS_OBJECT_NAME_INVALID;
break;
}
- error = NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_ACCESS_DENIED;
slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
if (!vfs_object_exist(conn, fname, &sbuf1)) {
- error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status)));
continue;
}
- error = can_rename(conn,fname,attrs,&sbuf1);
- if (!NT_STATUS_IS_OK(error)) {
+ status = can_rename(conn,fname,attrs,&sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(6,("rename %s refused\n", fname));
continue;
}
@@ -4584,14 +4339,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
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++;
- error = NT_STATUS_OK;
+ status = NT_STATUS_OK;
continue;
}
if (!replace_if_exists &&
vfs_file_exist(conn,destname, NULL)) {
DEBUG(6,("file_exist %s\n", destname));
- error = NT_STATUS_OBJECT_NAME_COLLISION;
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
continue;
}
@@ -4604,7 +4359,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
if (!SMB_VFS_RENAME(conn,fname,destname)) {
rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
count++;
- error = NT_STATUS_OK;
+ status = NT_STATUS_OK;
}
TALLOC_FREE(lck);
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
@@ -4612,6 +4367,8 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
CloseDir(dir_hnd);
}
+#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))
@@ -4619,13 +4376,15 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
}
+#endif
+
}
- if (count == 0 && NT_STATUS_IS_OK(error)) {
- error = map_nt_error_from_unix(errno);
+ if (count == 0 && NT_STATUS_IS_OK(status)) {
+ status = map_nt_error_from_unix(errno);
}
- return error;
+ return status;
}
/****************************************************************************
@@ -4821,11 +4580,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int ofun = SVAL(inbuf,smb_vwv1);
int flags = SVAL(inbuf,smb_vwv2);
BOOL target_is_directory=False;
- BOOL bad_path1 = False;
- BOOL bad_path2 = False;
BOOL path_contains_wcard1 = False;
BOOL path_contains_wcard2 = False;
- BOOL rc = True;
SMB_STRUCT_STAT sbuf1, sbuf2;
NTSTATUS status;
START_PROFILE(SMBcopy);
@@ -4856,8 +4612,17 @@ 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);
- rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
- unix_convert(newname,conn,0,&bad_path2,&sbuf2);
+ status = unix_convert(conn, name, path_contains_wcard1, 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);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
target_is_directory = VALID_STAT_OF_DIR(sbuf2);
@@ -4897,7 +4662,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && 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;
@@ -4964,20 +4729,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return(UNIXERROR(ERRHRD,ERRgeneral));
}
- if (exists) {
- END_PROFILE(SMBcopy);
- return ERROR_DOS(ERRDOS,error);
- } else {
- if((errno == ENOENT) && (bad_path1 || bad_path2) &&
- !use_nt_status()) {
- /* Samba 3.0.22 has ERRDOS/ERRbadpath in the
- * DOS error code case
- */
- return ERROR_DOS(ERRDOS, ERRbadpath);
- }
- END_PROFILE(SMBcopy);
- return(UNIXERROR(ERRDOS,error));
- }
+ END_PROFILE(SMBcopy);
+ return ERROR_DOS(ERRDOS,error);
}
outsize = set_message(outbuf,1,0,True);
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 40394c3d8a..2cfb692b02 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -751,7 +751,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
SMB_INO_T inode = 0;
SMB_STRUCT_STAT sbuf;
int smb_action = 0;
- BOOL bad_path = False;
files_struct *fsp;
struct ea_list *ea_list = NULL;
uint16 flags = 0;
@@ -801,13 +800,13 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
/* XXXX we need to handle passed times, sattr and flags */
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
if (!check_name(fname,conn)) {
- return UNIXERROR(ERRDOS, ERRnoaccess);
+ return UNIXERROR(ERRDOS,ERRnoaccess);
}
if (open_ofun == 0) {
@@ -1662,7 +1661,6 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
BOOL dont_descend = False;
BOOL out_of_space = False;
int space_remaining;
- BOOL bad_path = False;
BOOL mask_contains_wcard = False;
SMB_STRUCT_STAT sbuf;
TALLOC_CTX *ea_ctx = NULL;
@@ -1720,12 +1718,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ ntstatus = unix_convert(conn, directory, mask_contains_wcard, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ return ERROR_NT(ntstatus);
}
if(!check_name(directory,conn)) {
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
p = strrchr_m(directory,'/');
@@ -2844,7 +2842,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
char *base_name;
char *p;
SMB_OFF_T pos = 0;
- BOOL bad_path = False;
BOOL delete_pending = False;
int len;
time_t create_time, mtime, atime;
@@ -2891,11 +2888,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
} else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
@@ -2933,24 +2930,24 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
if (!check_name(fname,conn)) {
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
@@ -3671,8 +3668,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
{
- BOOL bad_path_oldname = False;
- BOOL bad_path_newname = False;
SMB_STRUCT_STAT sbuf1, sbuf2;
pstring last_component_oldname;
pstring last_component_newname;
@@ -3681,21 +3676,9 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- /* No wildcards. */
- if (ms_has_wild(newname) || ms_has_wild(oldname)) {
- return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- }
-
- unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
- if (bad_path_oldname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_oldname[0] == '.') {
- if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* source must already exist. */
@@ -3707,16 +3690,9 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
return NT_STATUS_ACCESS_DENIED;
}
- unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
- if (bad_path_newname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_newname[0] == '.') {
- if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Disallow if newname already exists. */
@@ -3766,7 +3742,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
SMB_STRUCT_STAT sbuf;
pstring fname;
int fd = -1;
- BOOL bad_path = False;
files_struct *fsp = NULL;
uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
@@ -3796,7 +3771,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
pstrcpy(fname, fsp->fsp_name);
if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
} else if (fsp && fsp->print_file) {
/*
@@ -3837,9 +3812,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
/*
@@ -3848,11 +3823,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
if(!check_name(fname, conn)) {
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
}
@@ -4789,7 +4764,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
char *pdata = *ppdata;
pstring directory;
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
NTSTATUS status = NT_STATUS_OK;
struct ea_list *ea_list = NULL;
@@ -4807,9 +4781,9 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
/* Any data in this call is an EA list. */