summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/client/client.c29
-rw-r--r--source/include/smb.h29
-rw-r--r--source/include/smb_macros.h8
-rw-r--r--source/libsmb/clifile.c13
-rw-r--r--source/libsmb/errormap.c4
-rw-r--r--source/printing/nt_printing.c38
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c10
-rw-r--r--source/smbd/dosmode.c8
-rw-r--r--source/smbd/filename.c147
-rw-r--r--source/smbd/msdfs.c6
-rw-r--r--source/smbd/nttrans.c47
-rw-r--r--source/smbd/reply.c656
-rw-r--r--source/smbd/trans2.c112
13 files changed, 450 insertions, 657 deletions
diff --git a/source/client/client.c b/source/client/client.c
index 6a741682edd..0420ff8624e 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -1709,6 +1709,34 @@ static int cmd_del(void)
}
/****************************************************************************
+ Wildcard delete some files.
+****************************************************************************/
+
+static int cmd_wdel(void)
+{
+ pstring mask;
+ pstring buf;
+ uint16 attribute = aSYSTEM | aHIDDEN;
+
+ //attribute |= aDIR | aARCH;
+ attribute = aDIR;
+
+ pstrcpy(mask,cur_dir);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("wdel <wcard>\n");
+ return 1;
+ }
+ pstrcat(mask,buf);
+
+ if (!cli_unlink_full(cli, mask, attribute)) {
+ d_printf("%s deleting remote files %s\n",cli_errstr(cli),mask);
+ }
+ return 0;
+}
+
+
+/****************************************************************************
****************************************************************************/
static int cmd_open(void)
@@ -3059,6 +3087,7 @@ static struct
{"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
{"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}},
{"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
+ {"wdel",cmd_wdel,"<mask> wildcard delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
{"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
{"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
{"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
diff --git a/source/include/smb.h b/source/include/smb.h
index 3e34e1359fa..50fe928eafc 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1233,19 +1233,22 @@ struct bitmap {
#define FILE_SHARE_DELETE 4
/* FileAttributesField */
-#define FILE_ATTRIBUTE_READONLY 0x001L
-#define FILE_ATTRIBUTE_HIDDEN 0x002L
-#define FILE_ATTRIBUTE_SYSTEM 0x004L
-#define FILE_ATTRIBUTE_DIRECTORY 0x010L
-#define FILE_ATTRIBUTE_ARCHIVE 0x020L
-#define FILE_ATTRIBUTE_NORMAL 0x080L
-#define FILE_ATTRIBUTE_TEMPORARY 0x100L
-#define FILE_ATTRIBUTE_SPARSE 0x200L
-#define FILE_ATTRIBUTE_REPARSE_POINT 0x400L
-#define FILE_ATTRIBUTE_COMPRESSED 0x800L
-#define FILE_ATTRIBUTE_OFFLINE 0x1000L
-#define FILE_ATTRIBUTE_NONINDEXED 0x2000L
-#define FILE_ATTRIBUTE_ENCRYPTED 0x4000L
+#define FILE_ATTRIBUTE_READONLY 0x0001
+#define FILE_ATTRIBUTE_HIDDEN 0x0002
+#define FILE_ATTRIBUTE_SYSTEM 0x0004
+#define FILE_ATTRIBUTE_VOLUME 0x0008
+#define FILE_ATTRIBUTE_DIRECTORY 0x0010
+#define FILE_ATTRIBUTE_ARCHIVE 0x0020
+#define FILE_ATTRIBUTE_DEVICE 0x0040
+#define FILE_ATTRIBUTE_NORMAL 0x0080
+#define FILE_ATTRIBUTE_TEMPORARY 0x0100
+#define FILE_ATTRIBUTE_SPARSE 0x0200
+#define FILE_ATTRIBUTE_REPARSE_POINT 0x0400
+#define FILE_ATTRIBUTE_COMPRESSED 0x0800
+#define FILE_ATTRIBUTE_OFFLINE 0x1000
+#define FILE_ATTRIBUTE_NONINDEXED 0x2000
+#define FILE_ATTRIBUTE_ENCRYPTED 0x4000
+
#define SAMBA_ATTRIBUTES_MASK 0x7F
/* Flags - combined with attributes. */
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index 4b4351347fc..0fa6f132db2 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -380,4 +380,12 @@ do { \
#define ADD_TO_LARGE_ARRAY(mem_ctx, type, elem, array, num, size) \
add_to_large_array((mem_ctx), sizeof(type), &(elem), (void *)(array), (num), (size));
+#ifndef ISDOT
+#define ISDOT(p) (*(p) == '.' && *((p) + 1) == '\0')
+#endif /* ISDOT */
+
+#ifndef ISDOTDOT
+#define ISDOTDOT(p) (*(p) == '.' && *((p) + 1) == '.' && *((p) + 2) == '\0')
+#endif /* ISDOTDOT */
+
#endif /* _SMB_MACROS_H */
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index ad84ec03244..16d053e5d0a 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -494,7 +494,7 @@ BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *f
Delete a file.
****************************************************************************/
-BOOL cli_unlink(struct cli_state *cli, const char *fname)
+BOOL cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
{
char *p;
@@ -507,7 +507,7 @@ BOOL cli_unlink(struct cli_state *cli, const char *fname)
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
- SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
+ SSVAL(cli->outbuf,smb_vwv0, attrs);
p = smb_buf(cli->outbuf);
*p++ = 4;
@@ -527,6 +527,15 @@ BOOL cli_unlink(struct cli_state *cli, const char *fname)
}
/****************************************************************************
+ Delete a file.
+****************************************************************************/
+
+BOOL cli_unlink(struct cli_state *cli, const char *fname)
+{
+ return cli_unlink_full(cli, fname, aSYSTEM | aHIDDEN);
+}
+
+/****************************************************************************
Create a directory.
****************************************************************************/
diff --git a/source/libsmb/errormap.c b/source/libsmb/errormap.c
index cb5e8311cad..6745c0e23a3 100644
--- a/source/libsmb/errormap.c
+++ b/source/libsmb/errormap.c
@@ -1511,6 +1511,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
{ EACCES, ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
{ ENOENT, ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND },
{ ENOTDIR, ERRDOS, ERRbadpath, NT_STATUS_NOT_A_DIRECTORY },
+ { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
{ EIO, ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR },
{ EBADF, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
{ EINVAL, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
@@ -1533,9 +1534,6 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
#ifdef EROFS
{ EROFS, ERRHRD, ERRnowrite, NT_STATUS_ACCESS_DENIED },
#endif
-#ifdef ENAMETOOLONG
- { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
-#endif
#ifdef EFBIG
{ EFBIG, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL },
#endif
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 541a60fef14..1fcd1a12338 100644
--- a/source/printing/nt_printing.c
+++ b/source/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(name, conn, 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;
@@ -1799,7 +1796,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
@@ -1825,7 +1822,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 ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1841,7 +1838,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 ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1859,7 +1856,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 ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1878,7 +1875,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 ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1906,7 +1903,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 ( !copy_file(new_name, old_name, conn,
OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
@@ -4813,7 +4810,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 )
@@ -4856,7 +4852,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);
}
@@ -4865,7 +4861,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);
}
@@ -4874,7 +4870,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);
}
@@ -4883,7 +4879,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);
}
@@ -4899,7 +4895,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/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index 0fb1629d7fa..ceba681af93 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -1791,7 +1791,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
pstring qualname;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
- BOOL bad_path;
NTSTATUS nt_status;
struct current_user user;
connection_struct *conn = NULL;
@@ -1826,8 +1825,8 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
became_user = True;
unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
- unix_convert(filename, conn, NULL, &bad_path, &st);
- if (bad_path) {
+ nt_status = unix_convert(filename, conn, NULL, &st);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", filename));
r_u->status = WERR_ACCESS_DENIED;
goto error_exit;
@@ -1906,7 +1905,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
DATA_BLOB null_pw;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
- BOOL bad_path;
NTSTATUS nt_status;
struct current_user user;
connection_struct *conn = NULL;
@@ -1941,8 +1939,8 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
became_user = True;
unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
- unix_convert(filename, conn, NULL, &bad_path, &st);
- if (bad_path) {
+ nt_status = unix_convert(filename, conn, NULL, &st);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", filename));
r_u->status = WERR_ACCESS_DENIED;
goto error_exit;
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 1172fe3e6b5..ff4291c08c8 100644
--- a/source/smbd/dosmode.c
+++ b/source/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/source/smbd/filename.c b/source/smbd/filename.c
index 1ea5228e919..56396aa2045 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -64,27 +64,27 @@ 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.
-
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
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(pstring name,connection_struct *conn,
+ char *saved_last_component,
+ SMB_STRUCT_STAT *pst)
{
SMB_STRUCT_STAT st;
char *start, *end;
@@ -96,14 +96,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 +137,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 +151,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 +176,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 +184,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 +209,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 +238,54 @@ 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) {
+ /* 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;
+ }
+ } 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);
+
+ if (name_has_wildcard && end) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
/*
* Check if the name exists up to this point.
@@ -251,9 +309,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 +334,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 +345,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 +361,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 +394,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 +405,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 +426,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 +437,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 +454,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/source/smbd/msdfs.c b/source/smbd/msdfs.c
index 1f04356b4f3..43732f75c53 100644
--- a/source/smbd/msdfs.c
+++ b/source/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(dp->reqpath,conn,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/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 0d7ebd8cc09..e5a067c4683 100644
--- a/source/smbd/nttrans.c
+++ b/source/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(fname,conn,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 set_bad_path_error(errno, bad_path, outbuf, 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(fname,conn,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 set_bad_path_error(errno, bad_path, outbuf, 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;
@@ -1585,16 +1580,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
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(oldname,conn,last_component_oldname,&sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Source must already exist. */
@@ -1611,16 +1599,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(newname,conn,last_component_newname,&sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Disallow if newname already exists. */
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 2922dc5a969..7e883f12de0 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -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,16 @@ 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_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_contains_wcard) {
+ *p_contains_wcard = False;
+ }
while (*s) {
if (IS_DIRECTORY_SEP(*s)) {
@@ -238,36 +102,34 @@ 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_contains_wcard) {
+ *p_contains_wcard = True;
+ } else {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
break;
default:
break;
@@ -295,130 +157,47 @@ 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.
+****************************************************************************/
- } 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 +602,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 +623,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(name,conn,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 +649,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 +679,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 +703,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(fname,conn,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 +724,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (!ok) {
END_PROFILE(SMBgetatr);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
+ return UNIXERROR(ERRDOS,ERRbadfile);
}
outsize = set_message(outbuf,10,0,True);
@@ -983,7 +759,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;
@@ -998,10 +773,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) {
+ status = unix_convert(fname,conn,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') {
@@ -1034,7 +809,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (!ok) {
END_PROFILE(SMBsetatr);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+ return UNIXERROR(ERRDOS, ERRnoaccess);
}
outsize = set_message(outbuf,0,0,False);
@@ -1123,7 +898,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;
@@ -1165,7 +939,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(directory,conn,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))
@@ -1214,7 +992,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (dptr_num < 0) {
if(dptr_num == -2) {
END_PROFILE(SMBsearch);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
+ return UNIXERROR(ERRDOS, ERRnofids);
}
END_PROFILE(SMBsearch);
return ERROR_DOS(ERRDOS,ERRnofids);
@@ -1379,7 +1157,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;
@@ -1401,10 +1178,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(fname,conn,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,
@@ -1488,7 +1265,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);
@@ -1520,10 +1296,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(fname,conn,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,
@@ -1669,7 +1445,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;
@@ -1693,10 +1468,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(fname,conn,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) {
@@ -1760,7 +1535,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;
@@ -1784,10 +1558,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(fname,conn,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);
@@ -1900,8 +1674,7 @@ 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;
@@ -1915,22 +1688,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 & 0x8000) {
+ /* These will never be set for POSIX. */
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ 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 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. */
@@ -1954,9 +1761,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. */
@@ -1987,14 +1791,15 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
pstring mask;
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);
+ status = unix_convert(name,conn,NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
p = strrchr_m(name,'/');
if (!p) {
@@ -2015,15 +1820,15 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
* 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;
+ status = can_delete(conn,directory,dirtype);
+ if (!NT_STATUS_IS_OK(status))
+ return status;
if (SMB_VFS_UNLINK(conn,directory) == 0) {
count++;
@@ -2032,15 +1837,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
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 == aDIR && mask[0] == '*' && mask[1] == '\0') {
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
if (strequal(mask,"????????.???"))
@@ -2056,12 +1854,11 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
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)) {
@@ -2071,28 +1868,16 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
/* 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)
@@ -2103,11 +1888,11 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
}
}
- 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;
}
/****************************************************************************
@@ -3767,7 +3552,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);
@@ -3780,10 +3564,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(directory,conn,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);
@@ -3970,7 +3754,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);
@@ -3983,10 +3766,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(directory,conn, 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)) {
@@ -3996,7 +3779,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
if (!ok) {
END_PROFILE(SMBrmdir);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
+ return UNIXERROR(ERRDOS, ERRbadpath);
}
outsize = set_message(outbuf,0,0,False);
@@ -4164,24 +3947,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(newname,conn,newname_last_component,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Ensure newname contains a '/' */
@@ -4243,14 +4018,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)) {
@@ -4270,15 +4045,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;
}
/****************************************************************************
@@ -4293,12 +4068,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;
@@ -4307,27 +4078,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(name,conn,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(newname,conn,last_component_dest,&sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/*
@@ -4359,7 +4117,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) {
@@ -4444,25 +4202,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));
+ nt_errstr(status), directory,newname));
- return error;
+ return status;
}
- 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;
- }
+ status = can_rename(conn,directory,attrs,&sbuf1);
- error = 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;
}
/*
@@ -4498,14 +4250,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.
@@ -4522,8 +4274,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;
@@ -4549,19 +4301,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;
}
@@ -4577,14 +4329,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;
}
@@ -4597,7 +4349,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));
@@ -4605,6 +4357,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))
@@ -4612,13 +4366,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;
}
/****************************************************************************
@@ -4803,11 +4559,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);
@@ -4838,8 +4591,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(name,conn,NULL,&sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(newname,conn,NULL,&sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
target_is_directory = VALID_STAT_OF_DIR(sbuf2);
@@ -4879,7 +4641,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;
@@ -4944,20 +4706,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/source/smbd/trans2.c b/source/smbd/trans2.c
index 33596f19dac..8129a24074d 100644
--- a/source/smbd/trans2.c
+++ b/source/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(fname,conn,NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
if (!check_name(fname,conn)) {
- return set_bad_path_error(errno, bad_path, outbuf, 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(directory,conn,NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ return ERROR_NT(ntstatus);
}
if(!check_name(directory,conn)) {
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
p = strrchr_m(directory,'/');
@@ -2702,25 +2700,6 @@ cap_low = 0x%x, cap_high = 0x%x\n",
return outsize;
}
-/****************************************************************************
- Utility function to set bad path error.
-****************************************************************************/
-
-int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
-{
- DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
- err, (int)bad_path ));
-
- if(err == ENOENT) {
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- } else {
- return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
- }
- }
- return UNIXERROR(def_class,def_code);
-}
-
#if defined(HAVE_POSIX_ACLS)
/****************************************************************************
Utility function to count the number of entries in a POSIX acl.
@@ -2863,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;
@@ -2910,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 set_bad_path_error(errno, bad_path, outbuf, 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 set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
@@ -2952,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(fname,conn,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 set_bad_path_error(errno, bad_path, outbuf, 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 set_bad_path_error(errno, bad_path, outbuf, 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 set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
@@ -3690,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;
@@ -3700,21 +3676,14 @@ 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;
+ status = unix_convert(oldname,conn,last_component_oldname,&sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- /* 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;
- }
+ /* No wildcards. */
+ if (ms_has_wild(oldname)) {
+ return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* source must already exist. */
@@ -3726,16 +3695,14 @@ 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;
+ status = unix_convert(newname,conn,last_component_newname,&sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- /* 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;
- }
+ /* No wildcards. */
+ if (ms_has_wild(newname)) {
+ return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* Disallow if newname already exists. */
@@ -3785,7 +3752,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;
@@ -3815,7 +3781,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 set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
} else if (fsp && fsp->print_file) {
/*
@@ -3856,9 +3822,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(fname,conn,NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
/*
@@ -3867,11 +3833,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 set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
if(!check_name(fname, conn)) {
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
}
@@ -4808,7 +4774,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;
@@ -4826,9 +4791,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(directory,conn,NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
/* Any data in this call is an EA list. */
@@ -4864,8 +4829,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
if (!check_name(directory,conn)) {
DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,
- ERRnoaccess);
+ return UNIXERROR(ERRDOS, ERRnoaccess);
}
status = create_directory(conn, directory);