Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit 06fff14d authored by Rob Swindell's avatar Rob Swindell 💬

More uniform safe/illegal/allowed filename (for upload) determination

sbbs_t::checkfname() now checks the file.can too.
new filedat.c functions:
- safest_filename() - not currently used
- illegal_filename() - returns true for a highly-suspicious (e.g. hack attempt) filename
- allowed_filename() - returns true if the filename is good for upload (assumed to be already checked to be legal as well).

Importantly, filenames beginning or ending in a '.' are now unallowed:
- 'dot files' are hidden (by default) on *nix
- files ending in a '.' are problematic on Windows
parent 8635d798
Pipeline #2351 failed with stage
in 6 minutes and 35 seconds
......@@ -138,24 +138,14 @@ extern "C" BOOL filematch(const char *filename, const char *filespec)
/*****************************************************************************/
/* Checks the filename 'fname' for invalid symbol or character sequences */
/*****************************************************************************/
bool sbbs_t::checkfname(char *fname)
bool sbbs_t::checkfname(const char *fname)
{
int c=0,d;
if(fname[0]=='-'
|| strcspn(fname,ILLEGAL_FILENAME_CHARS)!=strlen(fname)
|| strstr(fname, "..") != NULL) {
lprintf(LOG_WARNING,"Suspicious filename attempt: '%s'",fname);
hacklog((char *)"Filename", fname);
return(false);
}
d=strlen(fname);
while(c<d) {
if(fname[c]<=' ' || fname[c]&0x80)
return(false);
c++;
if(illegal_filename(fname) || trashcan(fname, "file")) {
lprintf(LOG_WARNING, "Suspicious filename attempt: '%s'", fname);
hacklog("Filename", fname);
return false;
}
return(true);
return allowed_filename(fname);
}
long sbbs_t::delfiles(const char *inpath, const char *spec, size_t keep)
......
......@@ -1235,3 +1235,46 @@ char* cmdstr(scfg_t* cfg, user_t* user, const char* instr, const char* fpath
return(cmd);
}
/****************************************************************************/
/* Is this filename made up of only the "safest" characters? */
/****************************************************************************/
bool safest_filename(const char* fname)
{
return strspn(fname, SAFEST_FILENAME_CHARS) == strlen(fname);
}
/****************************************************************************/
/* Is this filename highly-suspicious? */
/****************************************************************************/
bool illegal_filename(const char *fname)
{
size_t len = strlen(fname);
if(*fname == '-')
return true;
if(strcspn(fname, ILLEGAL_FILENAME_CHARS) != len)
return true;
if(strstr(fname, "..") != NULL)
return true;
return false;
}
/*****************************************************************************/
/* Checks the filename 'fname' for invalid symbol or character sequences */
/*****************************************************************************/
bool allowed_filename(const char *fname)
{
size_t len = strlen(fname);
if(len < 1)
return false;
for(size_t i = 0; i < len; i++) {
if(fname[i] <= ' ')
return false;
}
if(*fname == '.' // leading dot hides files on *nix
|| fname[len - 1] == '.') // a trailing dot is a problem for Win32
return false;
return true;
}
......@@ -57,6 +57,9 @@ DLLEXPORT bool hashfile(scfg_t*, file_t*);
DLLEXPORT bool addfile(scfg_t*, uint dirnum, file_t*, const char* extdesc, client_t*);
DLLEXPORT bool removefile(scfg_t*, uint dirnum, const char* filename);
DLLEXPORT char* format_filename(const char* fname, char* buf, size_t, bool pad);
DLLEXPORT bool safest_filename(const char* fname);
DLLEXPORT bool illegal_filename(const char* fname);
DLLEXPORT bool allowed_filename(const char* fname);
DLLEXPORT bool extract_diz(scfg_t*, file_t*, str_list_t diz_fname, char* path, size_t);
DLLEXPORT char* read_diz(const char* path, struct sauce_charinfo*);
DLLEXPORT char* format_diz(const char* src, char* dest, size_t maxlen, int width, bool ice_color);
......
......@@ -4565,8 +4565,7 @@ static void ctrl_thread(void* arg)
continue;
}
}
if(*p=='-'
|| strcspn(p,ILLEGAL_FILENAME_CHARS)!=strlen(p)
if(illegal_filename(p)
|| trashcan(&scfg,p,"file")) {
lprintf(LOG_WARNING,"%04d <%s> !ILLEGAL FILENAME ATTEMPT by %s [%s]: %s"
,sock, user.alias, host_name, host_ip, p);
......@@ -4574,6 +4573,12 @@ static void ctrl_thread(void* arg)
ftp_hacklog("FTP FILENAME", user.alias, cmd, host_name, &ftp.client_addr);
continue;
}
if(!allowed_filename(p)) {
lprintf(LOG_WARNING,"%04d <%s> !UNALLOWED FILENAME ATTEMPT by %s [%s]: %s"
,sock, user.alias, host_name, host_ip, p);
sockprintf(sock,sess,"553 Unallowed filename attempt");
continue;
}
SAFEPRINTF2(fname,"%s%s",scfg.dir[dir]->path,p);
if((!append && filepos==0 && fexist(fname))
|| (startup->options&FTP_OPT_INDEX_FILE
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment