summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/nttrans.c22
-rw-r--r--source3/smbd/reply.c96
-rw-r--r--source3/smbd/vfs.c6
3 files changed, 115 insertions, 9 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index d747e84a3a..a37ae5548f 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -73,7 +73,6 @@ static char *nttrans_realloc(char **ptr, size_t size)
return tptr;
}
-
/****************************************************************************
Send the required number of replies back.
We assume all fields other than the data fields are
@@ -263,6 +262,15 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
}
/****************************************************************************
+ Is it an NTFS stream name ?
+****************************************************************************/
+
+BOOL is_ntfs_stream_name(const char *fname)
+{
+ return (strchr_m(fname, ':') != NULL) ? True : False;
+}
+
+/****************************************************************************
Save case statics.
****************************************************************************/
@@ -668,7 +676,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':')) {
+ if( is_ntfs_stream_name(fname)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
@@ -717,7 +725,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':')) {
+ if( is_ntfs_stream_name(fname)) {
#ifdef HAVE_SYS_QUOTAS
if ((fake_file_type=is_fake_file(fname))!=FAKE_FILE_TYPE_NONE) {
@@ -1329,8 +1337,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':'))
+ if( is_ntfs_stream_name(fname)) {
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
return ERROR_DOS(ERRDOS,ERRbadfid);
}
@@ -1369,8 +1378,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':'))
+ if( is_ntfs_stream_name(fname)) {
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
}
/*
@@ -1854,7 +1864,7 @@ int reply_ntrename(connection_struct *conn,
return ERROR_NT(status);
}
- if( strchr_m(oldname, ':')) {
+ if( is_ntfs_stream_name(oldname)) {
/* Can't rename a stream. */
END_PROFILE(SMBntrename);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 8cccd9b568..e1131c56ed 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -281,6 +281,100 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
}
/****************************************************************************
+ 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).
+****************************************************************************/
+
+NTSTATUS check_path_syntax_posix(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--;
+ }
+
+ /* 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;
+
+ } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
+ /* Eat the '.' */
+ s++;
+ continue;
+ }
+ }
+
+ if (!(*s & 0x80)) {
+ *d++ = *s++;
+ } else {
+ switch(next_mb_char_size(s)) {
+ case 4:
+ *d++ = *s++;
+ case 3:
+ *d++ = *s++;
+ case 2:
+ *d++ = *s++;
+ 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;
+ }
+
+ *d = '\0';
+ return ret;
+}
+
+/****************************************************************************
Pull a string and check the path - provide for error return.
****************************************************************************/
@@ -3529,7 +3623,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unix_convert(directory,conn,0,&bad_path,&sbuf);
- if( strchr_m(directory, ':')) {
+ if( is_ntfs_stream_name(directory)) {
DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
END_PROFILE(SMBmkdir);
return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index dee29f4796..ade28f9bee 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -227,13 +227,15 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
return False;
}
- if(!backends) static_init_vfs;
+ if(!backends) {
+ static_init_vfs;
+ }
DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
module_name = smb_xstrdup(vfs_object);
- p = strchr(module_name, ':');
+ p = strchr_m(module_name, ':');
if (p) {
*p = 0;