diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/nttrans.c | 22 | ||||
-rw-r--r-- | source3/smbd/reply.c | 96 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 6 |
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; |