Update of /cvsroot/openantivirus/samba-vscan/f-secure
In directory sc8-pr-cvs1:/tmp/cvs-serv13408/f-secure
Added Files:
Tag: VSCAN_0_3
Makefile README.fsecure vscan-fsav.c vscan-fsav.conf
vscan-fsav.h vscan-fsav_core.c vscan-fsav_core.h
Log Message:
added; support for F-Secure Anti-Virus. Contributed by Oliver Jehle
--- NEW FILE: Makefile ---
#
# Makefile for vscan-fprotd, part of samba-vscan
#
#
# Variables
CC = gcc
LIBTOOL = libtool
SAMBA_SRC = ../../../../source
SAMBA_INCL = ../../../../source/include
UBIQX_SRC = ../../../../source/ubiqx
SMBWR_SRC = ../../../../source/smbwrapper
SMBVS_INCL = ../include
SMBVS_GLB = ../global
CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -I$(SMBVS_INCL) -Wall -g -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -fPIC
VFS_OBJS = vscan-fsav.so
SOURCES = $(SMBVS_GLB)/vscan-functions.c $(SMBVS_GLB)/vscan-message.c $(SMBVS_GLB)/vscan-quarantine.c $(SMBVS_GLB)/vscan-fileaccesslog.c vscan-fsav.c vscan-fsav.h
OBJS = vscan-functions.lo vscan-message.lo vscan-quarantine.lo vscan-fileaccesslog.lo vscan-fprotd.lo vscan-fprotd_core.lo
LIBS =
# Default target
all: $(VFS_OBJS)
vscan-fsav.so: $(SOURCES)
$(LIBTOOL) $(CC) $(CFLAGS) -c $(SMBVS_GLB)/vscan-functions.c
$(LIBTOOL) $(CC) $(CFLAGS) -c $(SMBVS_GLB)/vscan-message.c
$(LIBTOOL) $(CC) $(CFLAGS) -c $(SMBVS_GLB)/vscan-quarantine.c
$(LIBTOOL) $(CC) $(CFLAGS) -c $(SMBVS_GLB)/vscan-fileaccesslog.c
$(LIBTOOL) $(CC) $(CPPFLAGS) $(CFLAGS) -c vscan-fsav.c
$(LIBTOOL) $(CC) -shared $(LDFLAGS) $(LIBS) $(OBJS) -o vscan-fsav.so
# Misc targets
clean:
rm -rf .libs
rm -f core *~ *% *.bak *.so *.lo *.o
--- NEW FILE: README.fsecure ---
fsecure - support for samba
**********************************
[Introduction]
* vscan-fsav - for use with fsecure antivirs for linux
[Installation]
vscan-fsav normally comes with the installation defaults of f-secure, if not
overriden by the configuration file or paramter.
[Credits]
I'd like to thank Rainer Link and all others supporting and adding features to samba-vscan.
Also thanks to the inventor of the great strace tool make it possible to find out, how to
use f-secure antivirus.
[History]
2002-12-04 inital version dropped
[License]
This software is licensed under the GNU General Public License (GPL)
See COPYING or http://www.gnu.org/copyleft/gpl.html
--- NEW FILE: vscan-fsav.c ---
/*
* $Id: vscan-fsav.c,v 1.1.2.1 2003/12/04 16:31:13 reniar Exp $
*
* Virusscanning VFS module for samba.
* Log infected files via syslog
* facility and block access using fsecure antivirus
*
* Copyright (C) Monex AG Oliver Jehle, 2003
*
* based on the existing F-PROT module by
* Copyright (C) Rainer Link, 2001-2003
* Copyright (C) Stefan (metze) Metzmacher, 2003
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "vscan-global.h"
#include "vscan-vfs.h"
#include "vscan-fsav.h"
static const char module_id[] =
VSCAN_MODULE_STR " " SAMBA_VSCAN_VERSION_STR;
fstring config_file; /* location of config file, either
PARAMCONF or as set via vfs options
*/
ssize_t max_size; /* do not scan files greater than max_size
if max_size = 0, scan any file
*/
BOOL fsav_userinstance; /* start own fsavd for each user */
pstring fsav_config_file; /* location of config file */
pstring fsav_socket; /* socketname */
pstring fsav_db_dir; /* location of the database dir */
pstring fsav_binary; /* location of the fsavd deamon */
pstring fsav_user; /* needed only for userinstance socket name */
BOOL fsav_archive; /* scan archives */
BOOL fsav_mime; /* scan archives */
int fsav_maxnested; /* maximum level archives */
int fsav_timeout; /* scan timeout */
BOOL verbose_file_logging; /* log ever file access */
BOOL scan_on_open; /* scan a file before it is opened
Defaults to True
*/
BOOL scan_on_close; /* scan a new file put on share or
if file was modified
Defaults to False
*/
BOOL deny_access_on_error; /* if connection to daemon fails, should access to any
file be denied? Defaults to True
*/
BOOL deny_access_on_minor_error; /* if daemon returns non-critical error,
should access to the file be denied? */
BOOL send_warning_message; /* send a warning message using the windows
messenger service? */
fstring quarantine_dir; /* directory for infected files */
fstring quarantine_prefix; /* prefix for infected files */
enum infected_file_action_enum infected_file_action; /* what to do with infected files;
defaults to quarantine */
int max_lrufiles; /* specified the maximum entries in lrufiles list */
time_t lrufiles_invalidate_time; /* specified the time in seconds after the lifetime
of an entry is expired and entry will be invalidated */
pstring exclude_file_types; /* list of file types which should be excluded from scanning */
static BOOL do_parameter(const char *param, const char *value)
{
if (StrCaseCmp("max file size", param) == 0) {
/* FIXME: sanity check missing! what, if value is out of range?
atoi returns int - what about LFS? atoi should be avoided!
*/
max_size = atoi(value);
DEBUG(3, ("max file size is: %d\n", max_size));
} else if (StrCaseCmp("verbose file logging", param) == 0) {
set_boolean(&verbose_file_logging, value);
DEBUG(3,
("verbose file logging is: %d\n",
verbose_file_logging));
} else if (StrCaseCmp("scan on open", param) == 0) {
set_boolean(&scan_on_open, value);
DEBUG(3, ("scan on open: %d\n", scan_on_open));
} else if (StrCaseCmp("scan on close", param) == 0) {
set_boolean(&scan_on_close, value);
DEBUG(3, ("scan on close is: %d\n", scan_on_close));
} else if (StrCaseCmp("deny access on error", param) == 0) {
set_boolean(&deny_access_on_error, value);
DEBUG(3,
("deny access on error is: %d\n",
deny_access_on_error));
} else if (StrCaseCmp("deny access on minor error", param) == 0) {
set_boolean(&deny_access_on_minor_error, value);
DEBUG(3,
("deny access on minor error is: %d\n",
deny_access_on_minor_error));
} else if (StrCaseCmp("send warning message", param) == 0) {
set_boolean(&send_warning_message, value);
DEBUG(3,
("send warning message is: %d\n",
send_warning_message));
} else if (StrCaseCmp("infected file action", param) == 0) {
if (StrCaseCmp("quarantine", value) == 0) {
infected_file_action = INFECTED_QUARANTINE;
} else if (StrCaseCmp("delete", value) == 0) {
infected_file_action = INFECTED_DELETE;
} else if (StrCaseCmp("nothing", value) == 0) {
infected_file_action = INFECTED_DO_NOTHING;
} else {
DEBUG(2,
("samba-vscan: badly formed infected file action in configuration file, parameter %s\n",
value));
}
DEBUG(3,
("infected file action is: %d\n",
infected_file_action));
} else if (StrCaseCmp("quarantine directory", param) == 0) {
fstrcpy(quarantine_dir, value);
DEBUG(3,
("quarantine directory is: %s\n", quarantine_dir));
} else if (StrCaseCmp("quarantine prefix", param) == 0) {
fstrcpy(quarantine_prefix, value);
DEBUG(3,
("quarantine prefix is: %s\n", quarantine_prefix));
} else if (StrCaseCmp("max lru files entries", param) == 0) {
max_lrufiles = atoi(value);
DEBUG(3, ("max lru files entries is: %d\n", max_lrufiles));
} else if (StrCaseCmp("lru file entry lifetime", param) == 0) {
lrufiles_invalidate_time = atol(value);
DEBUG(3,
("lru file entry lifetime is: %li\n",
(long) lrufiles_invalidate_time));
} else if (StrCaseCmp("exclude file types", param) == 0) {
pstrcpy(exclude_file_types, value);
DEBUG(3, ("Exclude list is: %s\n", exclude_file_types));
} else if (StrCaseCmp("fsav user instance", param) == 0) {
set_boolean(&fsav_userinstance, value);
DEBUG(3,
("fsav user instance is: %d\n", fsav_userinstance));
} else if (StrCaseCmp("fsav config file", param) == 0) {
pstrcpy(fsav_config_file, value);
DEBUG(3, ("fsav config file is: %s\n", fsav_config_file));
} else if (StrCaseCmp("fsav binary", param) == 0) {
pstrcpy(fsav_binary, value);
DEBUG(3, ("fsav binary: %s\n", fsav_binary));
} else if (StrCaseCmp("fsav db dir ", param) == 0) {
pstrcpy(fsav_db_dir, value);
DEBUG(3, ("fsav db dir is: %s\n", fsav_db_dir));
} else if (StrCaseCmp("fsav socket", param) == 0) {
pstrcpy(fsav_socket, value);
DEBUG(3, ("fsav socket is: %s\n", fsav_socket));
} else if (StrCaseCmp("fsav mime scan", param) == 0) {
set_boolean(&fsav_mime, value);
DEBUG(3, ("fsav mime scan is : %d\n", fsav_mime));
} else if (StrCaseCmp("fsav archive scan", param) == 0) {
set_boolean(&fsav_archive, value);
DEBUG(3, ("fsav archive scan is : %d\n", fsav_mime));
} else if (StrCaseCmp("fsav max nested level", param) == 0) {
fsav_maxnested = atoi(value);
DEBUG(3,
("fsav max nested level is : %i\n", fsav_maxnested));
} else if (StrCaseCmp("fsav timeout", param) == 0) {
fsav_timeout = atoi(value);
DEBUG(3, ("fsav timeout is : %i\n", fsav_timeout));
} else
DEBUG(3, ("unknown parameter: %s\n", param));
return True;
}
static BOOL do_section(const char *section)
{
/* simply return true, there's only one section :-) */
return True;
}
/* Implementation of vfs_ops. */
static int vscan_connect(vfs_handle_struct * handle,
connection_struct * conn, const char *svc,
const char *user)
{
int retval;
vscan_syslog
("samba-vscan (%s) connected (Samba 3.0), (c) by Rainer Link, OpenAntiVirus.org",
module_id);
/* set default value for configuration files */
fstrcpy(config_file, PARAMCONF);
/* set default value for max file size */
max_size = VSCAN_MAX_SIZE;
/* set default value for file logging */
verbose_file_logging = VSCAN_VERBOSE_FILE_LOGGING;
/* set default value for scan on open() */
scan_on_open = VSCAN_SCAN_ON_OPEN;
/* set default value for scan on close() */
scan_on_close = VSCAN_SCAN_ON_CLOSE;
/* set default value for deny access on error */
deny_access_on_error = VSCAN_DENY_ACCESS_ON_ERROR;
/* set default value for deny access on minor error */
deny_access_on_minor_error = VSCAN_DENY_ACCESS_ON_MINOR_ERROR;
/* set default value for send warning message */
send_warning_message = VSCAN_SEND_WARNING_MESSAGE;
/* set default value for infected file action */
infected_file_action = VSCAN_INFECTED_FILE_ACTION;
/* set default value for quarantine directory */
fstrcpy(quarantine_dir, VSCAN_QUARANTINE_DIRECTORY);
/* set default value for quarantine prefix */
fstrcpy(quarantine_prefix, VSCAN_QUARANTINE_PREFIX);
/* set default value for maximum lrufile entries */
max_lrufiles = VSCAN_MAX_LRUFILES;
/* time after an entry is considered as expired */
lrufiles_invalidate_time = VSCAN_LRUFILES_INVALIDATE_TIME;
/* file type exclude ist */
pstrcpy(exclude_file_types, VSCAN_FT_EXCLUDE_LIST);
/* fsav specific defaults */
set_boolean(&fsav_userinstance, "yes");
fsav_timeout = 0; /* fsav default is 0 */
fsav_maxnested = 5; /* fsav default is 5 */
set_boolean(&fsav_archive, "yes");
set_boolean(&fsav_mime, "yes");
pstrcpy(fsav_config_file, "/etc/fsav.conf");
pstrcpy(fsav_socket, "/tmp/.fsav");
pstrcpy(fsav_db_dir, "/var/opt/f-secure/fsav/databases/");
pstrcpy(fsav_binary, "/opt/f-secure/fsav/bin/fsavd");
pstrcpy(fsav_user, user);
vscan_syslog("INFO: connect to service %s by user %s", svc, user);
fstrcpy(config_file,
lp_parm_const_string(SNUM(conn), VSCAN_MODULE_STR,
"config-file", PARAMCONF));
retval = pm_process(config_file, do_section, do_parameter);
DEBUG(10, ("pm_process returned %d\n", retval));
if (!retval)
vscan_syslog
("ERROR: could not parse configuration file '%s'. File not found or not read-able. Using compiled-in defaults",
config_file);
/* initialise lrufiles list */
DEBUG(5, ("init lrufiles list\n"));
lrufiles_init(max_lrufiles, lrufiles_invalidate_time);
/* initialise filetype */
DEBUG(5, ("init file type\n"));
filetype_init(0, exclude_file_types);
return SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
}
static void vscan_disconnect(vfs_handle_struct * handle,
connection_struct * conn)
{
vscan_syslog("INFO: disconnected");
lrufiles_destroy_all();
filetype_close();
SMB_VFS_NEXT_DISCONNECT(handle, conn);
}
static int vscan_open(vfs_handle_struct * handle, connection_struct * conn,
const char *fname, int flags, mode_t mode)
{
int retval, must_be_checked;
SMB_STRUCT_STAT stat_buf;
pstring filepath;
char client_ip[CLIENT_IP_SIZE];
fsav_handle *fsav;
int rc;
/* Assemble complete file path */
pstrcpy(filepath, conn->connectpath);
pstrcat(filepath, "/");
pstrcat(filepath, fname);
/* scan files while opening? */
if (!scan_on_open) {
DEBUG(3,
("samba-vscan - open: File '%s' not scanned as scan_on_open is not set\n",
fname));
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
}
if ((SMB_VFS_NEXT_STAT(handle, conn, fname, &stat_buf)) != 0) /* an error occured */
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
else if (S_ISDIR(stat_buf.st_mode)) /* is it a directory? */
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
else if ((stat_buf.st_size > max_size) && (max_size > 0)) /* file is too large */
vscan_syslog
("INFO: File %s is larger than specified maximum file size! Not scanned!",
fname);
else if (stat_buf.st_size == 0) /* do not scan empty files */
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
else if (filetype_skipscan(filepath) == 1) {
if (verbose_file_logging)
vscan_syslog
("File '%s' not scanned as file type is on exclude list",
filepath);
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
} else {
fsav = fsav_create_handle();
if (fsav) {
fsav->userinstance = fsav_userinstance;
fsav->maxnested = fsav_maxnested;
fsav->archive = fsav_archive;
fsav->timeout = fsav_timeout;
fsav->mime = fsav_mime;
fsav->binary = fsav_binary;
fsav->config_file = fsav_config_file;
fsav->db_dir = fsav_db_dir;
fsav->socket = fsav_socket;
fsav->user = fsav_user;
if (fsav_connect_handle(fsav) != 0) {
fsav_free_handle(fsav);
fsav = NULL;
}
}
if (!fsav && deny_access_on_error) {
/* an error occured - can not communicate to daemon - deny access */
vscan_syslog
("ERROR: can not communicate to daemon - access denied");
errno = EACCES;
return -1;
} else {
/* get client IP */
safe_strcpy(client_ip, conn->client_address,
CLIENT_IP_SIZE - 1);
/* must file actually be scanned? */
must_be_checked =
lrufiles_must_be_checked(filepath,
stat_buf.st_mtime);
if (must_be_checked == -1) {
/* file has already been checked and marked as infected */
/* deny access */
if (verbose_file_logging)
vscan_syslog
("File '%s' has already been scanned and marked as infected. Not scanned any more. Access denied",
filepath);
/* close handle */
fsav_free_handle(fsav);
/* deny access */
errno = EACCES;
return -1;
} else if (must_be_checked == 0) {
/* file has already been checked,
not marked as infected and not modified */
if (verbose_file_logging)
vscan_syslog
("File '%s' has already been scanned, not marked as infected and not modified. Not scanned anymore. Access granted",
filepath);
/* close handle */
fsav_free_handle(fsav);
/* grant access */
return SMB_VFS_NEXT_OPEN(handle, conn,
fname, flags,
mode);
}
/* ok, we must check the file */
/* scan file */
retval = fsav_scan(fsav, filepath);
if (retval == 2 && deny_access_on_minor_error) {
/* a minor error occured - deny access */
vscan_syslog
("ERROR: daemon failed with a minor error - access to file %s denied",
fname);
/* close handle */
fsav_free_handle(fsav);
/* to be safe, remove file from lrufiles */
lrufiles_delete(filepath);
/* deny access */
errno = EACCES;
return -1;
} else if (retval == 1 && deny_access_on_error) {
/* an error occured - can not communicate to daemon - deny access */
vscan_syslog
("ERROR: can not communicate to daemon - access to file %s denied",
fname);
/* close handle */
fsav_free_handle(fsav);
/* to be safe, remove file from lrufiles */
lrufiles_delete(filepath);
/* deny access */
errno = EACCES;
return -1;
} else if (retval == 1) {
fsav_free_handle(fsav);
/* do action ... */
rc = vscan_do_infected_file_action(handle,
conn,
filepath,
quarantine_dir,
quarantine_prefix,
infected_file_action);
/* add/update file. mark file as infected! */
lrufiles_add(filepath, stat_buf.st_mtime,
True);
/* virus found, deny acces */
errno = EACCES;
return -1;
} else if (retval == 0) {
/* file is clean, add to lrufiles */
lrufiles_add(filepath, stat_buf.st_mtime,
False);
}
}
/* close handle */
fsav_free_handle(fsav);
}
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
}
static int vscan_close(vfs_handle_struct * handle, files_struct * fsp,
int fd)
{
fsav_handle *fsav;
pstring filepath;
int retval, rv, rc;
char client_ip[CLIENT_IP_SIZE];
/* First close the file */
retval = SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
if (!scan_on_close) {
DEBUG(3,
("samba-vscan - close: File '%s' not scanned as scan_on_close is not set\n",
fsp->fsp_name));
return retval;
}
/* get the file name */
pstrcpy(filepath, fsp->conn->connectpath);
pstrcat(filepath, "/");
pstrcat(filepath, fsp->fsp_name);
/* Don't scan directorys */
if (fsp->is_directory)
return retval;
if (!fsp->modified) {
if (verbose_file_logging)
vscan_syslog
("INFO: file %s was not modified - not scanned",
filepath);
return retval;
}
/* don't scan files which are in the list of exclude file types */
if (filetype_skipscan(filepath) == 1) {
if (verbose_file_logging)
vscan_syslog
("File '%s' not scanned as file type is on exclude list",
filepath);
return retval;
}
/* scan only file, do nothing */
fsav = fsav_create_handle();
if (fsav) {
fsav->userinstance = fsav_userinstance;
fsav->maxnested = fsav_maxnested;
fsav->archive = fsav_archive;
fsav->timeout = fsav_timeout;
fsav->mime = fsav_mime;
fsav->binary = fsav_binary;
fsav->config_file = fsav_config_file;
fsav->db_dir = fsav_db_dir;
fsav->socket = fsav_socket;
fsav->user = fsav_user;
if (fsav_connect_handle(fsav) != 0) {
fsav_free_handle(fsav);
fsav = NULL;
}
}
if (fsav) {
safe_strcpy(client_ip, fsp->conn->client_address,
CLIENT_IP_SIZE - 1);
rv = fsav_scan(fsav, filepath);
if (rv == 1) {
/* virus was found */
rc = vscan_do_infected_file_action(handle,
fsp->conn,
filepath,
quarantine_dir,
quarantine_prefix,
infected_file_action);
}
}
return retval;
}
NTSTATUS init_module(void)
{
NTSTATUS ret;
ret =
smb_register_vfs(SMB_VFS_INTERFACE_VERSION, VSCAN_MODULE_STR,
vscan_ops);
DEBUG(5,
("samba-vscan (%s) registered (Samba 3.0), (c) by Rainer Link, OpenAntiVirus.org\n",
module_id));
openlog("smbd_" VSCAN_MODULE_STR, LOG_PID, SYSLOG_FACILITY);
return ret;
}
/*
* init done
*/
void vfs_done(connection_struct * conn)
{
DEBUG(3, ("Finalizing default vfs hooks\n"));
}
--- NEW FILE: vscan-fsav.conf ---
[samba-vscan]
; run-time configure options for vscan-samba using
; F-Secure Daemon. All options set to default values
; do not scan files larger than X bytes. If set to 0 (default),
; this feature is disable (i.e. all files are scanned)
max file size = 0
; log all file access (yes/no). If set to yes, every access will
; be logged. If set to no (default), only access to infected files
; will be logged
verbose file logging = no
; if set to yes (default), a file will be scanned while opening
scan on open = yes
; if set to yes, a file will be scanned while closing (default is yes)
scan on close = yes
; if communication to daemon fails, should access to file denied?
; (default: yes)
deny access on error = yes
; if daemon files with a minor error (corruption, etc.),
; should access to file denied?
; (default: yes)
deny access on minor error = yes
; send a warning message via Windows Messenger service
; when virus is found?
; (default: yes)
send warning message = yes
; what to do with an infected file
; quarantine: try to move to quantine directory; delete it if moving fails
; delete: delete infected file
; nothing: do nothing
infected file action = quarantine
; where to put infected files - you really want to change this!
; it has to be on the same physical device as the share!
quarantine directory = /tmp
; prefix for files in quarantine
quarantine prefix = vir-
; as Windows tries to open a file multiple time in a (very) short time
; of period, samba-vscan use a last recently used file mechanism to avoid
; multiple scans of a file. This setting specified the maximum number of
; elements of the last recently used file list. If set to 0, this
; mechanism is disabled completely (default: 100)
max lru files entries = 100
; an entry is invalidad after lru file entry lifetime (in seconds).
; (Default: 5)
lru file entry lifetime = 5
; exclude files from being scanned based on the MIME-type! Semi-colon
; seperated list (default: empty list). Use this with care!
exclude file types =
;
; if you start a fsav for each user, then you have dedicated scanner mode
; else you have to start a scanning deamon for all users
;
; user deamons are stopped after 30 seconds inactivity.. and restarted again.
; this value is hardcoded by fsecure.. i'm sorry
;
fsav userinstance = yes;
;
; which fsecure config file should be used
;
fsav config file = /etc/fsav.conf
;
; which fsecure binary file should be used
; must be the server part, not the client
;
fsav binary = /opt/fsecure/fsav/bin/fsavd
;
; which fsecure config file should be used
;
fsav db dir = /var/opt/f-secure/fsav/databases
;
; which socket prefix should be used, for the not dedicated mode, the
; socket name of the central scanning deamon
;
fsav socket = /tmp/.fsav
;
; scan archives, normaly on
;
fsav archive = yes
;
; scan mime, normaly on
;
fsav mime = yes
;
; scan depth in archives
;
fsav maxnested = 5
;
; scan timeout (0) disable it... default
;
fsav timeout = 0
--- NEW FILE: vscan-fsav.h ---
/*
* $Id: vscan-fsav.h,v 1.1.2.1 2003/12/04 16:31:13 reniar Exp $
*
* Virusscanning VFS module for samba.
* Log infected files via syslog
* facility and block access using fsecure antivirus
*
* Copyright (C) Monex AG Oliver Jehle, 2003
*
* based on the existing F-PROT module by
* Copyright (C) Rainer Link, 2001-2003
* Copyright (C) Stefan (metze) Metzmacher, 2003
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __VSCAN_FSAV_H_
#define __VSCAN_FSAV_H_
#include "vscan-fsav_core.h"
/* default location of samba-style configuration file (needs Samba >= 2.2.4 or Samba 3.0 */
#define PARAMCONF "/etc/samba/vscan-fsav.conf"
#define VSCAN_MODULE_STR "vscan-fsav"
/* False = log only infected file, True = log every file access */
#ifndef VSCAN_VERBOSE_FILE_LOGGING
# define VSCAN_VERBOSE_FILE_LOGGING False
#endif
/* if a file is bigger than VSCAN_MAX_SIZE it won't be scanned. Has to be
specified in bytes! If it set to 0, the file size check is disabled */
#ifndef VSCAN_MAX_SIZE
# define VSCAN_MAX_SIZE 0
#endif
/* True = scan files on open */
#ifndef VSCAN_SCAN_ON_OPEN
# define VSCAN_SCAN_ON_OPEN True
#endif
/* True = scan files on close */
#ifndef VSCAN_SCAN_ON_CLOSE
# define VSCAN_SCAN_ON_CLOSE False
#endif
/* True = deny access in case of virus scanning failure */
#ifndef VSCAN_DENY_ACCESS_ON_ERROR
# define VSCAN_DENY_ACCESS_ON_ERROR True
#endif
/* True = deny access in case of minor virus scanning failure */
#ifndef VSCAN_DENY_ACCESS_ON_MINOR_ERROR
# define VSCAN_DENY_ACCESS_ON_MINOR_ERROR True
#endif
/* True = send a warning message via window messenger service for viruses found */
#ifndef VSCAN_SEND_WARNING_MESSAGE
# define VSCAN_SEND_WARNING_MESSAGE True
#endif
/* default infected file action */
#define VSCAN_INFECTED_FILE_ACTION INFECTED_QUARANTINE
/* default quarantine settings; hopefully the user changes this */
#define VSCAN_QUARANTINE_DIRECTORY "/tmp"
#define VSCAN_QUARANTINE_PREFIX "vir-"
/* set default value for maximum lrufile entries */
#define VSCAN_MAX_LRUFILES 100
/* time after an entry is considered as expired */
#define VSCAN_LRUFILES_INVALIDATE_TIME 5
/* MIME-types of files to be exluded from scanning; that's an
semi-colon seperated list */
#define VSCAN_FT_EXCLUDE_LIST ""
#endif /* __VSCAN_FSAV_H */
--- NEW FILE: vscan-fsav_core.c ---
/*
* $Id: vscan-fsav_core.c,v 1.1.2.1 2003/12/04 16:31:13 reniar Exp $
*
* virusscanning module for samba. provides helper methods to call fsecure
*
* Copyright (C) Monex AG Oliver Jehle, 2003
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "vscan-global.h"
#include "vscan-fsav.h"
static const char module_id[] = VSCAN_MODULE_STR " " SAMBA_VSCAN_VERSION_STR;
/**
* create handle
*
* all functions use a handle
*/
fsav_handle *fsav_create_handle()
{
fsav_handle *h;
DEBUG(5, ("samba-vscan (%s) create handle\n", module_id));
h = (fsav_handle *) malloc(sizeof(fsav_handle));
if (!h)
return h;
h->server =
(struct sockaddr_un *) malloc(sizeof(struct sockaddr_un));
if (!h->server) {
fsav_free_handle(h);
return NULL;
}
/* allocate buffer for result */
h->buffer = (char *) malloc((BUFFERSIZE + 1));
if (!h->buffer) {
fsav_free_handle(h);
return NULL;
}
/* allocate buffer for receive */
h->recv_buffer = (char *) malloc(RCVSIZE + 1);
if (!h->recv_buffer) {
fsav_free_handle(h);
return NULL;
}
DEBUG(5, ("samba-vscan (%s) create handle success\n", module_id));
return h;
}
/**
* free a handle
*
* release all storage areas and close sockets
*/
void fsav_free_handle(fsav_handle * h)
{
DEBUG(5, ("samba-vscan (%s) free handle\n", module_id));
if (!h)
return;
/* close socket */
if (h->sockd)
close(h->sockd);
/* release all used storage */
if (h->server)
free(h->server);
if (h->buffer)
free(h->buffer);
if (h->recv_buffer)
free(h->recv_buffer);
free(h);
}
/**
* clean handle
*
* clean all buffers and fields
*/
void fsav_clean_handle(fsav_handle * h)
{
if (!h)
return;
h->infected = 0;
h->fail = 0;
h->configured = 0;
if (h->buffer)
memset(h->buffer, 0, BUFFERSIZE);
if (h->recv_buffer)
memset(h->recv_buffer, 0, RCVSIZE);
}
/**
* kill a running fsav daemon
*
* try to kill a running fsavd, looks like you have to delete the socket
*/
void fsav_kill(fsav_handle * h)
{
if (!h)
return;
fsav_socket_name_create(h);
DEBUG(5,
("samba-vscan (%s) kill fsavd %s\n ", module_id,
h->server->sun_path));
unlink(h->server->sun_path);
}
/**
* starting a new fsav daemon
*
*/
void fsav_start(fsav_handle * h)
{
pid_t pid;
int status;
if (!h)
return;
fsav_socket_name_create(h);
fsav_kill(h);
DEBUG(5,
("samba-vscan (%s) master start fsavd %s\n ", module_id,
h->server->sun_path));
pid = fork();
if (pid < 0) {
DEBUG(5,
("samba-vscan (%s) master cannot fork for start fsavd %s\n ",
module_id, h->server->sun_path));
return;
}
if (pid > 0) {
waitpid(pid, &status, 0);
DEBUG(5,
("samba-vscan (%s) master wait finished %i\n ",
module_id, pid));
} else {
DEBUG(5,
("samba-vscan (%s) start slave start %i\n ",
module_id, pid));
fsav_daemonize(h);
exit(0);
}
}
/**
* daemonize the fsav daemon
*
* to ensure, that fsav is not making problems sending signals and other things,
* run it in a separate session, try to give up all filedescriptors hold
*
*/
void fsav_daemonize(fsav_handle * h)
{
pid_t pid;
int status;
int rc;
char socket[256];
char config[256];
char dbdir[256];
char binary[256];
char command[256];
int maxfd = 0;
DEBUG(5,
("samba-vscan (%s) slave start fsav %s\n", module_id,
h->server->sun_path));
snprintf(socket, 255, "--socketname=%s", h->server->sun_path);
snprintf(config, 255, "--configfile=%s", h->config_file);
snprintf(dbdir, 255, "--databasedirectory=%s", h->db_dir);
snprintf(binary, 255, "%s", h->binary);
signal(SIGALRM, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
pid = fork();
if (pid < 0) {
DEBUG(5,
("samba-vscan (%s) slave cannot fork %s (%i)\n ",
module_id, strerror(errno), errno));
exit(1);
}
if (pid > 0) {
DEBUG(5,
("samba-vscan (%s) slave wait %i\n ", module_id,
pid));
waitpid(pid, NULL, 0);
DEBUG(5,
("samba-vscan (%s) slave wait finished %i\n ",
module_id, pid));
return;
} else {
DEBUG(5,
("samba-vscan (%s) slave(%i) starting %s %s %s %s \n ",
module_id, pid, binary, config, socket, dbdir));
/*
* close all filedescriptors before calling fsav
*/
maxfd = open("/dev/null", O_RDONLY);
for (; maxfd > 2; maxfd--)
close(maxfd);
fsav_free_handle(h);
/*
* switch user id of the fsavd process to the effective user id, else we cant connect
*/
setreuid(geteuid(), geteuid());
setsid();
rc = execlp(binary, binary, config, socket, dbdir,
"--standalone", (char *) 0);
if (rc != 0) {
DEBUG(5,
("samba-vscan (%s) slave cannot execlp %s (%i)\n ",
module_id, strerror(errno), errno));
}
exit(0);
}
}
/**
* scan a file
*
*/
int fsav_scan(fsav_handle * h, char *file)
{
if (!h)
return 1;
DEBUG(5, ("samba-vscan (%s) scan %s\n ", module_id, file));
fsav_clean_handle(h);
snprintf(h->buffer, BUFFERSIZE, "SCAN\t%s\n", file);
if (fsav_process(h))
return 2;
if (h->infected) {
h->rc = 1;
} else {
if (h->fail)
h->rc = 2;
else
h->rc = 0;
}
DEBUG(5,
("samba-vscan (%s) scan %s rc=(%i) buffer=%s\n", module_id,
file, h->rc, h->buffer));
if (h->rc == 1)
vscan_syslog("samba-vscan (%s) found virus in %s",
module_id, file);
return h->rc;
}
/**
* create socket name
*
*/
void fsav_socket_name_create(fsav_handle * h)
{
if (h->userinstance) {
snprintf(h->server->sun_path, sizeof(h->server->sun_path)
, "%s-%s", h->socket, h->user);
} else {
snprintf(h->server->sun_path, sizeof(h->server->sun_path)
, "%s", h->socket);
}
}
/**
* create socket
*
*/
void fsav_socket_create(fsav_handle * h)
{
if (!h)
return;
/*
* set the correct socketname
*/
fsav_socket_name_create(h);
DEBUG(5,
("samba-vscan (%s) socket_create %s \n", module_id,
h->server->sun_path));
h->server->sun_family = AF_UNIX;
h->sockd = socket(AF_UNIX, SOCK_STREAM, 0);
if (h->sockd < 0) {
vscan_syslog
("samba-vscan (%s) socket_create cannot connect %s",
module_id, h->server->sun_path);
h->rc = 2;
}
DEBUG(5,
("samba-vscan (%s) socket_create done %s \n", module_id,
h->server->sun_path));
return;
}
/**
* connect handle
*
* connect to a fsav instance, if not successfull and in userinstance mode, try
* start a new instance
*
*/
int fsav_connect_handle(fsav_handle * h)
{
int rc;
DEBUG(5, ("samba-vscan (%s) connect handle check\n", module_id));
if (!h)
return 1;
fsav_socket_create(h);
if (h->sockd < 0) {
DEBUG(5,
("samba-vscan (%s) socket_create not successfull\n",
module_id));
h->rc = 2;
return h->rc;
}
DEBUG(5, ("samba-vscan (%s) connect try connect \n", module_id));
rc = connect(h->sockd, (struct sockaddr *) h->server,
sizeof(struct sockaddr_un));
if (rc != 0 && h->userinstance) {
DEBUG(5,
("samba-vscan (%s) connect try restart and connect \n",
module_id));
fsav_start(h);
rc = connect(h->sockd, (struct sockaddr *) h->server,
sizeof(struct sockaddr_un));
}
DEBUG(5,
("samba-vscan (%s) connect done rc=%i \n", module_id, rc));
if (rc != 0) {
DEBUG(5,
("samba-vscan (%s) connect returns %s(%i) \n",
module_id, strerror(errno), errno));
return rc;
}
rc = fsav_configure(h, "ARCHIVE", h->archive) != 0;
if (rc != 0) {
DEBUG(5,
("samba-vscan (%s) connect configure archive (%i) \n",
module_id, rc));
return rc;
}
rc = fsav_configure(h, "TIMEOUT", h->timeout);
if (rc != 0) {
DEBUG(5,
("samba-vscan (%s) connect configure timeout (%i) \n",
module_id, rc));
return rc;
}
rc = fsav_configure(h, "MAXARCH", h->maxnested);
if (rc != 0) {
DEBUG(5,
("samba-vscan (%s) connect configure maxarch (%i) \n",
module_id, rc));
return rc;
}
rc = fsav_configure(h, "MIME", h->mime);
if (rc != 0) {
DEBUG(5,
("samba-vscan (%s) connect configure mime (%i) \n",
module_id, rc));
return rc;
}
return rc;
}
/**
* configure
*
* send configure commands to the fsav instance
*/
int fsav_configure(fsav_handle * h, char *option, int value)
{
DEBUG(5, ("samba-vscan (%s) configure \n ", module_id));
if (!h)
return 1;
fsav_clean_handle(h);
snprintf(h->buffer, BUFFERSIZE, "CONFIGURE\t%s\t%i\n", option,
value);
if (fsav_process(h))
return 2;
if (h->configured)
h->rc = 0;
else
h->rc = 1;
DEBUG(5,
("samba-vscan (%s) configure return %i\n ", module_id,
h->rc));
return h->rc;
}
/**
* process
*
* send a command to fsav and handle the result
*/
int fsav_process(fsav_handle * h)
{
char *end;
char *t;
char *ptrptr;
int bl;
DEBUG(5,
("samba-vscan (%s) process write %s\n ", module_id,
h->buffer));
h->rc = 0;
if (write(h->sockd, h->buffer, strlen(h->buffer)) <= 0) {
h->rc = 1;
return h->rc;
}
fsav_clean_handle(h);
DEBUG(5,
("samba-vscan (%s) process read %s\n ", module_id,
h->buffer));
memset(h->buffer, 0, BUFFERSIZE);
t = h->buffer;
end = h->buffer;
while (read(h->sockd, h->recv_buffer, RCVSIZE - 1)) {
bl = strlen(h->buffer);
/*
* check if buffer ends with end of line, all possible values for us ends with a newline
*/
for (t = h->buffer + bl;
t > end && strncmp(t, "\n", 1) != 0; t--);
/*
* trim buffer ... only last line is needed
*/
if (t > end && strncmp(t, "\n", 1) == 0) {
snprintf(h->buffer, BUFFERSIZE, "%s", t + 1);
t = h->buffer;
end = t;
} else {
end = h->buffer + bl - 1;
}
/*
* add receive buffer to global buffer
*/
pstrcat(h->buffer, h->recv_buffer);
/*
* search for tokens
*/
if (strstr(h->buffer, "INFECTED"))
h->infected = 1;
if (strstr(h->buffer, "FAILURE"))
h->fail = 1;
if (strstr(h->buffer, "Server configured"))
h->configured = 1;
/*
* fsav terminates with a point.
*/
if (strstr(h->buffer, ".\n"))
break;
memset(h->recv_buffer, 0, RCVSIZE);
}
DEBUG(5,
("samba-vscan (%s) process read end infected: %i fail: %i configured: %i buffer: %s \n ",
module_id, h->infected, h->fail, h->configured, h->buffer));
end = (char *) index(h->buffer, '.');
if (!end) {
h->rc = 1;
DEBUG(5,
("samba-vscan (%s) process point not found return %i\n ",
module_id, h->rc));
return h->rc;
}
h->rc = 0;
DEBUG(5,
("samba-vscan (%s) process return %i\n ", module_id, h->rc));
return h->rc;
}
--- NEW FILE: vscan-fsav_core.h ---
/*
* $Id: vscan-fsav_core.h,v 1.1.2.1 2003/12/04 16:31:13 reniar Exp $
*
* virusscanning module for samba. provides helper methods to call fsecure
*
* Copyright (C) Monex AG Oliver Jehle, 2003
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __VSCAN_FSAV_CORE_H_
#define __VSCAN_FSAV_CORE_H_
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#define BUFFERSIZE 2047
#define RCVSIZE 1023
/*
* comm structure
*/
typedef struct fsav_handle {
struct sockaddr_un *server;
int rc;
int sockd;
short userinstance;
short configured;
short infected;
short fail;
short archive;
short maxnested;
short timeout;
short mime;
char *buffer;
char *recv_buffer;
char *config_file; /* location of config file */
char *db_dir; /* location of the database dir*/
char *binary; /* location of the fsavd deamon */
char *user;
char *socket;
} fsav_handle;
fsav_handle * fsav_create_handle();
void fsav_start(fsav_handle *h);
void fsav_daemonize(fsav_handle *h);
void fsav_kill(fsav_handle *h);
void fsav_free_handle(fsav_handle *h);
void fsav_clean_handle(fsav_handle *h);
void fsav_socket_create(fsav_handle *h);
void fsav_socket_name_create(fsav_handle *h);
int fsav_connect_handle(fsav_handle *h);
int fsav_configure(fsav_handle *h,char *option, int value);
int fsav_scan(fsav_handle *h, char *file);
int fsav_process(fsav_handle *h);
#endif /* __VSCAN_FSAV_H */
-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive? Does it
help you create better code? SHARE THE LOVE, and help us help
YOU! Click Here: http://sourceforge.net/donate/
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.