enum virusfilter_scanner_enum {
VIRUSFILTER_SCANNER_CLAMAV,
+ VIRUSFILTER_SCANNER_DUMMY,
VIRUSFILTER_SCANNER_FSAV,
VIRUSFILTER_SCANNER_SOPHOS
};
static const struct enum_list scanner_list[] = {
{ VIRUSFILTER_SCANNER_CLAMAV, "clamav" },
+ { VIRUSFILTER_SCANNER_DUMMY, "dummy" },
{ VIRUSFILTER_SCANNER_FSAV, "fsav" },
{ VIRUSFILTER_SCANNER_SOPHOS, "sophos" },
{ -1, NULL }
new_dir,
NULL,
NULL,
+ 0,
0);
if (smb_fname == NULL) {
goto done;
int snum = SNUM(handle->conn);
struct virusfilter_config *config = NULL;
const char *exclude_files = NULL;
+ const char *infected_files = NULL;
const char *temp_quarantine_dir_mode = NULL;
+ const char *infected_file_command = NULL;
+ const char *scan_error_command = NULL;
+ const char *quarantine_dir = NULL;
+ const char *quarantine_prefix = NULL;
+ const char *quarantine_suffix = NULL;
+ const char *rename_prefix = NULL;
+ const char *rename_suffix = NULL;
+ const char *socket_path = NULL;
char *sret = NULL;
char *tmp = NULL;
enum virusfilter_scanner_enum backend;
set_namearray(&config->exclude_files, exclude_files);
}
+ infected_files = lp_parm_const_string(
+ snum, "virusfilter", "infected files", NULL);
+ if (infected_files != NULL) {
+ set_namearray(&config->infected_files, infected_files);
+ }
+
config->cache_entry_limit = lp_parm_int(
snum, "virusfilter", "cache entry limit", 100);
snum, "virusfilter", "infected file action",
virusfilter_actions, VIRUSFILTER_ACTION_DO_NOTHING);
- config->infected_file_command = lp_parm_const_string(
+ infected_file_command = lp_parm_const_string(
snum, "virusfilter", "infected file command", NULL);
-
- config->scan_error_command = lp_parm_const_string(
+ if (infected_file_command != NULL) {
+ config->infected_file_command = talloc_strdup(
+ config,
+ infected_file_command);
+ if (config->infected_file_command == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
+ scan_error_command = lp_parm_const_string(
snum, "virusfilter", "scan error command", NULL);
+ if (scan_error_command != NULL) {
+ config->scan_error_command = talloc_strdup(config,
+ scan_error_command);
+ if (config->scan_error_command == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
config->block_access_on_error = lp_parm_bool(
snum, "virusfilter", "block access on error", false);
tmp = talloc_asprintf(config, "%s/.quarantine",
handle->conn->connectpath);
- config->quarantine_dir = lp_parm_const_string(
+ quarantine_dir = lp_parm_const_string(
snum, "virusfilter", "quarantine directory",
tmp ? tmp : "/tmp/.quarantine");
+ if (quarantine_dir != NULL) {
+ config->quarantine_dir = talloc_strdup(config, quarantine_dir);
+ if (config->quarantine_dir == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
if (tmp != config->quarantine_dir) {
TALLOC_FREE(tmp);
config->quarantine_dir_mode = mode;
}
- config->quarantine_prefix = lp_parm_const_string(
+ quarantine_prefix = lp_parm_const_string(
snum, "virusfilter", "quarantine prefix",
VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX);
+ if (quarantine_prefix != NULL) {
+ config->quarantine_prefix = talloc_strdup(config,
+ quarantine_prefix);
+ if (config->quarantine_prefix == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
- config->quarantine_suffix = lp_parm_const_string(
+ quarantine_suffix = lp_parm_const_string(
snum, "virusfilter", "quarantine suffix",
VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX);
+ if (quarantine_suffix != NULL) {
+ config->quarantine_suffix = talloc_strdup(config,
+ quarantine_suffix);
+ if (config->quarantine_suffix == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
/*
* Make sure prefixes and suffixes do not contain directory
* delimiters
*/
- sret = strstr(config->quarantine_prefix, "/");
- if (sret != NULL) {
- DBG_ERR("quarantine prefix must not contain directory "
- "delimiter(s) such as '/' (%s replaced with %s)\n",
- config->quarantine_prefix,
- VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX);
- config->quarantine_prefix =
- VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX;
- }
- sret = strstr(config->quarantine_suffix, "/");
- if (sret != NULL) {
- DBG_ERR("quarantine suffix must not contain directory "
- "delimiter(s) such as '/' (%s replaced with %s)\n",
- config->quarantine_suffix,
- VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX);
- config->quarantine_suffix =
- VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX;
+ if (config->quarantine_prefix != NULL) {
+ sret = strstr(config->quarantine_prefix, "/");
+ if (sret != NULL) {
+ DBG_ERR("quarantine prefix must not contain directory "
+ "delimiter(s) such as '/' (%s replaced with %s)\n",
+ config->quarantine_prefix,
+ VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX);
+ config->quarantine_prefix =
+ VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX;
+ }
+ }
+ if (config->quarantine_suffix != NULL) {
+ sret = strstr(config->quarantine_suffix, "/");
+ if (sret != NULL) {
+ DBG_ERR("quarantine suffix must not contain directory "
+ "delimiter(s) such as '/' (%s replaced with %s)\n",
+ config->quarantine_suffix,
+ VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX);
+ config->quarantine_suffix =
+ VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX;
+ }
}
config->quarantine_keep_tree = lp_parm_bool(
config->quarantine_keep_name = lp_parm_bool(
snum, "virusfilter", "quarantine keep name", true);
- config->rename_prefix = lp_parm_const_string(
+ rename_prefix = lp_parm_const_string(
snum, "virusfilter", "rename prefix",
VIRUSFILTER_DEFAULT_RENAME_PREFIX);
+ if (rename_prefix != NULL) {
+ config->rename_prefix = talloc_strdup(config, rename_prefix);
+ if (config->rename_prefix == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
- config->rename_suffix = lp_parm_const_string(
+ rename_suffix = lp_parm_const_string(
snum, "virusfilter", "rename suffix",
VIRUSFILTER_DEFAULT_RENAME_SUFFIX);
+ if (rename_suffix != NULL) {
+ config->rename_suffix = talloc_strdup(config, rename_suffix);
+ if (config->rename_suffix == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
/*
* Make sure prefixes and suffixes do not contain directory
* delimiters
*/
- sret = strstr(config->rename_prefix, "/");
- if (sret != NULL) {
- DBG_ERR("rename prefix must not contain directory "
- "delimiter(s) such as '/' (%s replaced with %s)\n",
- config->rename_prefix,
- VIRUSFILTER_DEFAULT_RENAME_PREFIX);
- config->rename_prefix =
- VIRUSFILTER_DEFAULT_RENAME_PREFIX;
- }
- sret = strstr(config->rename_suffix, "/");
- if (sret != NULL) {
- DBG_ERR("rename suffix must not contain directory "
- "delimiter(s) such as '/' (%s replaced with %s)\n",
- config->rename_suffix,
- VIRUSFILTER_DEFAULT_RENAME_SUFFIX);
- config->rename_suffix =
- VIRUSFILTER_DEFAULT_RENAME_SUFFIX;
+ if (config->rename_prefix != NULL) {
+ sret = strstr(config->rename_prefix, "/");
+ if (sret != NULL) {
+ DBG_ERR("rename prefix must not contain directory "
+ "delimiter(s) such as '/' (%s replaced with %s)\n",
+ config->rename_prefix,
+ VIRUSFILTER_DEFAULT_RENAME_PREFIX);
+ config->rename_prefix =
+ VIRUSFILTER_DEFAULT_RENAME_PREFIX;
+ }
+ }
+ if (config->rename_suffix != NULL) {
+ sret = strstr(config->rename_suffix, "/");
+ if (sret != NULL) {
+ DBG_ERR("rename suffix must not contain directory "
+ "delimiter(s) such as '/' (%s replaced with %s)\n",
+ config->rename_suffix,
+ VIRUSFILTER_DEFAULT_RENAME_SUFFIX);
+ config->rename_suffix =
+ VIRUSFILTER_DEFAULT_RENAME_SUFFIX;
+ }
}
config->infected_open_errno = lp_parm_int(
config->scan_error_close_errno = lp_parm_int(
snum, "virusfilter", "scan error errno on close", 0);
- config->socket_path = lp_parm_const_string(
+ socket_path = lp_parm_const_string(
snum, "virusfilter", "socket path", NULL);
+ if (socket_path != NULL) {
+ config->socket_path = talloc_strdup(config, socket_path);
+ if (config->socket_path == NULL) {
+ DBG_ERR("virusfilter-vfs: out of memory!\n");
+ return -1;
+ }
+ }
/* canonicalize socket_path */
if (config->socket_path != NULL && config->socket_path[0] != '/') {
DBG_ERR("socket path must be an absolute path. "
"Using backend default\n");
config->socket_path = NULL;
- }
+ }
if (config->socket_path != NULL) {
config->socket_path = canonicalize_absolute_path(
handle, config->socket_path);
config->io_h = virusfilter_io_new(config, connect_timeout, io_timeout);
if (config->io_h == NULL) {
- DBG_ERR("virusfilter_io_new failed");
+ DBG_ERR("virusfilter_io_new failed\n");
return -1;
}
case VIRUSFILTER_SCANNER_CLAMAV:
ret = virusfilter_clamav_init(config);
break;
+ case VIRUSFILTER_SCANNER_DUMMY:
+ ret = virusfilter_dummy_init(config);
+ break;
default:
DBG_ERR("Unhandled scanner %d\n", backend);
return -1;
q_filepath,
smb_fname->stream_name,
NULL,
+ 0,
smb_fname->flags);
if (q_smb_fname == NULL) {
action = VIRUSFILTER_ACTION_DO_NOTHING;
q_smb_fname = synthetic_smb_fname(frame, q_filepath,
smb_fname->stream_name, NULL,
+ 0,
smb_fname->flags);
if (q_smb_fname == NULL) {
action = VIRUSFILTER_ACTION_DO_NOTHING;
scan_result, scan_report);
if (!ok) {
DBG_ERR("Cannot create cache entry: "
- "virusfilter_cache_entry_new failed");
+ "virusfilter_cache_entry_new failed\n");
goto virusfilter_scan_return;
}
} else if (is_cache) {
return scan_result;
}
-static int virusfilter_vfs_open(
- struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname,
- files_struct *fsp,
- int flags,
- mode_t mode)
+static int virusfilter_vfs_openat(struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname_in,
+ struct files_struct *fsp,
+ const struct vfs_open_how *how)
{
TALLOC_CTX *mem_ctx = talloc_tos();
- struct virusfilter_config *config;
- const char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name;
+ struct virusfilter_config *config = NULL;
+ const char *cwd_fname = dirfsp->fsp_name->base_name;
virusfilter_result scan_result;
const char *fname = fsp->fsp_name->base_name;
char *dir_name = NULL;
int ret;
bool ok1;
char *sret = NULL;
+ struct smb_filename *smb_fname = NULL;
+ SMB_STRUCT_STAT sbuf = smb_fname_in->st;
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct virusfilter_config, return -1);
rename_trap_count++;
}
+ smb_fname = cp_smb_filename(mem_ctx, smb_fname_in);
+ if (smb_fname == NULL) {
+ goto virusfilter_vfs_open_fail;
+ }
+
if (is_named_stream(smb_fname)) {
DBG_INFO("Not scanned: only file backed streams can be scanned:"
" %s/%s\n", cwd_fname, fname);
goto virusfilter_vfs_open_next;
}
- if (flags & O_TRUNC) {
+ if (how->flags & O_TRUNC) {
DBG_INFO("Not scanned: Open flags have O_TRUNC: %s/%s\n",
cwd_fname, fname);
goto virusfilter_vfs_open_next;
}
- ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+ ret = SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf);
if (ret != 0) {
/*
*/
goto virusfilter_vfs_open_next;
}
- ret = S_ISREG(smb_fname->st.st_ex_mode);
+ ret = S_ISREG(sbuf.st_ex_mode);
if (ret == 0) {
DBG_INFO("Not scanned: Directory or special file: %s/%s\n",
cwd_fname, fname);
goto virusfilter_vfs_open_next;
}
if (config->max_file_size > 0 &&
- smb_fname->st.st_ex_size > config->max_file_size)
+ sbuf.st_ex_size > config->max_file_size)
{
DBG_INFO("Not scanned: file size > max file size: %s/%s\n",
cwd_fname, fname);
goto virusfilter_vfs_open_next;
}
if (config->min_file_size > 0 &&
- smb_fname->st.st_ex_size < config->min_file_size)
+ sbuf.st_ex_size < config->min_file_size)
{
DBG_INFO("Not scanned: file size < min file size: %s/%s\n",
cwd_fname, fname);
goto virusfilter_vfs_open_fail;
}
+ TALLOC_FREE(smb_fname);
+
virusfilter_vfs_open_next:
- return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+ return SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname_in, fsp, how);
virusfilter_vfs_open_fail:
+ TALLOC_FREE(smb_fname);
errno = (scan_errno != 0) ? scan_errno : EACCES;
return -1;
}
return close_result;
}
- if (is_named_stream(fsp->fsp_name)) {
+ if (fsp_is_alternate_stream(fsp)) {
if (config->scan_on_open && fsp->fsp_flags.modified) {
if (config->cache) {
DBG_DEBUG("Removing cache entry (if existent)"
return close_result;
}
- if (config->exclude_files && is_in_path(fname,
- config->exclude_files, false))
- {
+ if (is_in_path(fname, config->exclude_files, false)) {
DBG_INFO("Not scanned: exclude files: %s/%s\n",
cwd_fname, fname);
return close_result;
smb_fname,
flags);
struct virusfilter_config *config = NULL;
+ struct smb_filename *full_fname = NULL;
char *fname = NULL;
- char *cwd_fname = handle->conn->cwd_fsp->fsp_name->base_name;
+ char *cwd_fname = dirfsp->fsp_name->base_name;
if (ret != 0 && errno != ENOENT) {
return ret;
return 0;
}
- fname = smb_fname->base_name;
+ full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ smb_fname);
+ if (full_fname == NULL) {
+ return -1;
+ }
+
+ fname = full_fname->base_name;
DBG_DEBUG("Removing cache entry (if existent): fname: %s\n", fname);
virusfilter_cache_remove(config->cache, cwd_fname, fname);
+ TALLOC_FREE(full_fname);
return 0;
}
char *fname = NULL;
char *dst_fname = NULL;
char *cwd_fname = handle->conn->cwd_fsp->fsp_name->base_name;
+ struct smb_filename *full_src = NULL;
+ struct smb_filename *full_dst = NULL;
if (ret != 0) {
return ret;
return 0;
}
- fname = smb_fname_src->base_name;
- dst_fname = smb_fname_dst->base_name;
+ full_src = full_path_from_dirfsp_atname(talloc_tos(),
+ srcfsp,
+ smb_fname_src);
+ if (full_src == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ full_dst = full_path_from_dirfsp_atname(talloc_tos(),
+ dstfsp,
+ smb_fname_dst);
+ if (full_dst == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ fname = full_src->base_name;
+ dst_fname = full_dst->base_name;
DBG_DEBUG("Renaming cache entry: fname: %s to: %s\n",
fname, dst_fname);
virusfilter_cache_entry_rename(config->cache,
- cwd_fname, fname,
+ cwd_fname,
+ fname,
dst_fname);
- return 0;
+ ret = 0;
+ out:
+ TALLOC_FREE(full_src);
+ TALLOC_FREE(full_dst);
+ return ret;
}
static struct vfs_fn_pointers vfs_virusfilter_fns = {
.connect_fn = virusfilter_vfs_connect,
.disconnect_fn = virusfilter_vfs_disconnect,
- .open_fn = virusfilter_vfs_open,
+ .openat_fn = virusfilter_vfs_openat,
.close_fn = virusfilter_vfs_close,
.unlinkat_fn = virusfilter_vfs_unlinkat,
.renameat_fn = virusfilter_vfs_renameat,