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

Commits (5)
......@@ -512,6 +512,10 @@ void sbbs_t::batch_upload()
SAFEPRINTF2(src, "%s%s", cfg.temp_dir,dirent->d_name);
if(isdir(src))
continue;
if(!checkfname(dirent->d_name)) {
bprintf(text[BadFilename], dirent->d_name);
continue;
}
SAFEPRINTF2(dest, "%s%s", cfg.dir[cfg.upload_dir]->path, dirent->d_name);
if(fexistcase(dest)) {
bprintf(text[FileAlreadyOnline], dirent->d_name);
......@@ -520,9 +524,9 @@ void sbbs_t::batch_upload()
if(mv(src, dest, /* copy: */false))
continue;
bputs(text[SearchingForDupes]);
uint x,y;
for(x=0;x<usrlibs;x++) {
progress(text[SearchingForDupes], x, usrlibs, 1);
for(y=0;y<usrdirs[x];y++)
if(cfg.dir[usrdir[x][y]]->misc&DIR_DUPES
&& findfile(&cfg,usrdir[x][y], dirent->d_name, NULL))
......
......@@ -130,7 +130,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
if(mode&WM_FILE) {
if(!checkfname(title)) {
bputs(text[BadFilename]);
bprintf(text[BadFilename], title);
(void)remove(msgpath);
return(false);
}
......
......@@ -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
......
......@@ -57,7 +57,7 @@ extern "C" BOOL hacklog(scfg_t* cfg, const char* prot, const char* user, const c
return true;
}
BOOL sbbs_t::hacklog(char* prot, char* text)
BOOL sbbs_t::hacklog(const char* prot, const char* text)
{
return ::hacklog(&cfg, prot, useron.alias, text, client_name, &client_addr);
}
......
......@@ -1040,7 +1040,7 @@ public:
bool removefile(smb_t*, file_t*);
bool movefile(smb_t*, file_t*, int newdir);
char * getfilespec(char *str);
bool checkfname(char *fname);
bool checkfname(const char *fname);
bool addtobatdl(file_t*);
bool clearbatdl(void);
bool clearbatul(void);
......@@ -1099,7 +1099,7 @@ public:
bool errormsg_inside;
void errormsg(int line, const char* function, const char *source, const char* action, const char *object
,long access=0, const char *extinfo=NULL);
BOOL hacklog(char* prot, char* text);
BOOL hacklog(const char* prot, const char* text);
/* qwk.cpp */
ulong qwkmail_last;
......
......@@ -276,10 +276,9 @@ bool sbbs_t::upload(uint dirnum)
f.dir=curdirnum=dirnum;
bputs(text[Filename]);
if(getstr(fname, sizeof(fname) - 1, 0) < 1 || strchr(fname,'?') || strchr(fname,'*')
|| !checkfname(fname) || (trashcan(fname,"file") && !dir_op(dirnum))) {
if(getstr(fname, sizeof(fname) - 1, 0) < 1 || strchr(fname,'?') || strchr(fname,'*') || !checkfname(fname)) {
if(fname[0])
bputs(text[BadFilename]);
bprintf(text[BadFilename], fname);
return(false);
}
if(dirnum==cfg.sysop_dir)
......
......@@ -486,7 +486,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
}
if((mode&WM_FILE) && !checkfname(subj)) {
free(buf);
bputs(text[BadFilename]);
bprintf(text[BadFilename], subj);
return(false);
}
if(!(mode&(WM_EMAIL|WM_NETMAIL)) && cfg.sub[subnum]->misc&SUB_QNET
......
......@@ -757,7 +757,7 @@ long delfiles(const char *inpath, const char *spec, size_t keep)
else
strcpy(path,inpath);
strcat(path,spec);
glob(path,0,NULL,&g);
glob(path, GLOB_PERIOD, NULL, &g);
free(path);
if(keep >= g.gl_pathc)
return 0;
......