libclamav, clamd: handle file exclusion in cli_ftw() (bb#1656)

0.96
Tomasz Kojm 17 years ago
parent e53ef4464b
commit 51bbedb132
  1. 4
      ChangeLog
  2. 32
      clamd/scanner.c
  3. 1
      clamd/scanner.h
  4. 2
      clamd/session.c
  5. 4
      clamdscan/proto.c
  6. 12
      libclamav/others.h
  7. 24
      libclamav/others_common.c

@ -1,3 +1,7 @@
Fri Jul 31 21:28:18 CEST 2009 (tk)
----------------------------------
* libclamav, clamd: handle file exclusion in cli_ftw() (bb#1656)
Fri Jul 31 15:29:36 EEST 2009 (edwin)
-------------------------------------
* unit_tests/check_regex.c: fix unit-test failure on Solaris

@ -143,20 +143,6 @@ int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw
return CL_SUCCESS;
}
#endif
if((opt = optget(scandata->opts, "ExcludePath"))->enabled) {
while (opt) {
/* TODO: perhaps multiscan should skip this check?
* This should work unless the user is doing something stupid like
* MULTISCAN / */
if(match_regex(filename, opt->strarg) == 1) {
if (type != TYPE_MULTISCAN)
conn_reply_single(scandata->conn, filename, "Excluded");
free(filename);
return CL_SUCCESS;
}
opt = (const struct optstruct *) opt->nextarg;
}
}
if(sb && sb->st_size == 0) { /* empty file */
if (msg == scandata->toplevel_path)
@ -247,6 +233,24 @@ int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw
return CL_SUCCESS;
}
int scan_pathchk(const char *path, struct cli_ftw_cbdata *data)
{
struct scan_cb_data *scandata = data->data;
const struct optstruct *opt;
if((opt = optget(scandata->opts, "ExcludePath"))->enabled) {
while(opt) {
if(match_regex(path, opt->strarg) == 1) {
if(scandata->type != TYPE_MULTISCAN)
conn_reply_single(scandata->conn, path, "Excluded");
return 1;
}
opt = (const struct optstruct *) opt->nextarg;
}
}
return 0;
}
int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned,
const struct cl_engine *engine,
unsigned int options, const struct optstruct *opts, int odesc, int stream)

@ -51,5 +51,6 @@ struct scan_cb_data {
int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct optstruct *opts, int odesc, int stream);
int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct optstruct *opts, char term);
int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data);
int scan_pathchk(const char *path, struct cli_ftw_cbdata *data);
#endif

@ -316,7 +316,7 @@ int command(client_conn_t *conn, int *virus)
flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
if (optget(opts, "FollowFileSymlinks")->enabled)
flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data);
ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk);
if (ret == CL_EMEM)
if(optget(opts, "ExitOnOOM")->enabled)
return -1;

@ -379,7 +379,7 @@ int serial_client_scan(char *file, int scantype, int *infected, int maxlevel, in
cdata.scantype = scantype;
data.data = &cdata;
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data);
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data, NULL);
*infected += cdata.infected;
if(ftw == CL_SUCCESS || ftw == CL_BREAK) {
@ -562,7 +562,7 @@ int parallel_client_scan(char *file, int scantype, int *infected, int maxlevel,
cdata.printok = printinfected^1;
data.data = &cdata;
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data);
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, NULL);
if(ftw != CL_SUCCESS) {
*infected += cdata.infected;

@ -374,11 +374,11 @@ void cli_dbgmsg_internal(const char *str, ...);
#endif
#if HAVE_SYSCONF_SC_PAGESIZE
static inline int cli_getpagesize() { return sysconf(_SC_PAGESIZE); }
static inline int cli_getpagesize(void) { return sysconf(_SC_PAGESIZE); }
#define HAVE_CLI_GETPAGESIZE 1
#else
#if HAVE_GETPAGESIZE
static inline int cli_getpagesize() { return getpagesize(); }
static inline int cli_getpagesize(void) { return getpagesize(); }
#define HAVE_CLI_GETPAGESIZE 1
#endif
#endif
@ -447,6 +447,12 @@ struct cli_ftw_cbdata {
*/
typedef int (*cli_ftw_cb)(struct stat *stat_buf, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data);
/*
* returns 1 if the path should be skipped and 0 otherwise
* uses callback data
*/
typedef int (*cli_ftw_pathchk)(const char *path, struct cli_ftw_cbdata *data);
/*
* returns
* CL_SUCCESS if it traversed all files and subdirs
@ -461,7 +467,7 @@ typedef int (*cli_ftw_cb)(struct stat *stat_buf, char *filename, const char *pat
* which one it is.
* If it is a file, it simply calls the callback once, otherwise recurses.
*/
int cli_ftw(char *base, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data);
int cli_ftw(char *base, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data, cli_ftw_pathchk pathchk);
const char *cli_strerror(int errnum, char* buf, size_t len);
#endif

@ -496,26 +496,25 @@ static int handle_filetype(const char *fname, int flags,
return CL_SUCCESS;
}
static int cli_ftw_dir(const char *dirname, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data);
static int handle_entry(struct dirent_data *entry, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data)
static int cli_ftw_dir(const char *dirname, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data, cli_ftw_pathchk pathchk);
static int handle_entry(struct dirent_data *entry, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data, cli_ftw_pathchk pathchk)
{
if (!entry->is_dir) {
return callback(entry->statbuf, entry->filename, entry->filename, visit_file, data);
} else {
return cli_ftw_dir(entry->dirname, flags, maxdepth, callback, data);
return cli_ftw_dir(entry->dirname, flags, maxdepth, callback, data, pathchk);
}
}
int cli_ftw(char *path, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data)
int cli_ftw(char *path, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data, cli_ftw_pathchk pathchk)
{
struct stat statbuf;
enum filetype ft = ft_unknown;
struct dirent_data entry;
int stated = 0;
int ret;
if ((flags & CLI_FTW_TRIM_SLASHES) && path[0] && path[1]) {
if (((flags & CLI_FTW_TRIM_SLASHES) || pathchk) && path[0] && path[1]) {
char *pathend;
/* trim slashes so that dir and dir/ behave the same when
* they are symlinks, and we are not following symlinks */
@ -524,6 +523,8 @@ int cli_ftw(char *path, int flags, int maxdepth, cli_ftw_cb callback, struct cli
while (pathend > path && pathend[-1] == '/') --pathend;
*pathend = '\0';
}
if(pathchk && pathchk(path, data) == 1)
return CL_SUCCESS;
ret = handle_filetype(path, flags, &statbuf, &stated, &ft, callback, data);
if (ret != CL_SUCCESS)
return ret;
@ -538,10 +539,10 @@ int cli_ftw(char *path, int flags, int maxdepth, cli_ftw_cb callback, struct cli
if (ret != CL_SUCCESS)
return ret;
}
return handle_entry(&entry, flags, maxdepth, callback, data);
return handle_entry(&entry, flags, maxdepth, callback, data, pathchk);
}
static int cli_ftw_dir(const char *dirname, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data)
static int cli_ftw_dir(const char *dirname, int flags, int maxdepth, cli_ftw_cb callback, struct cli_ftw_cbdata *data, cli_ftw_pathchk pathchk)
{
DIR *dd;
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
@ -617,6 +618,11 @@ static int cli_ftw_dir(const char *dirname, int flags, int maxdepth, cli_ftw_cb
else
sprintf(fname, "%s/%s", dirname, dent->d_name);
if(pathchk && pathchk(fname, data) == 1) {
free(fname);
continue;
}
ret = handle_filetype(fname, flags, &statbuf, &stated, &ft, callback, data);
if (ret != CL_SUCCESS) {
free(fname);
@ -674,7 +680,7 @@ static int cli_ftw_dir(const char *dirname, int flags, int maxdepth, cli_ftw_cb
qsort(entries, entries_cnt, sizeof(*entries), ftw_compare);
for (i = 0; i < entries_cnt; i++) {
struct dirent_data *entry = &entries[i];
ret = handle_entry(entry, flags, maxdepth-1, callback, data);
ret = handle_entry(entry, flags, maxdepth-1, callback, data, pathchk);
if (entry->is_dir)
free(entry->filename);
if (entry->statbuf)

Loading…
Cancel
Save