Update of /cvsroot/openantivirus/samba-vscan/antivir
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30758/antivir
Added Files:
Tag: VSCAN_0_3
Makefile vscan-antivir.c vscan-antivir.conf vscan-antivir.h
vscan-antivir_core.c vscan-antivir_core.h
Log Message:
added support for AntiVir, contributed by the H+BEDV folks. Param parsing
not yet up-to-date for sheduled 0.3.6 release
--- NEW FILE: vscan-antivir.h ---
#ifndef __VSCAN_ANTIVIR_H_
#define __VSCAN_ANTIVIR_H_
#include "vscan-global.h"
/* Configuration Section :-) */
/* program name for scanner process */
#define VSCAN_ANTIVIR_PROGRAM_NAME "/usr/lib/AntiVir/antivir"
/* enable scan in archive files */
#define VSCAN_AVARCH_ENABLED 0
/* maximum compression ratio of files in archive */
#define VSCAN_AVARCH_MAXRATIO 150
/* maximum archived file size (in bytes) */
#define VSCAN_AVARCH_MAXFILESIZE (1024 * 1048576)
/* maximum recursion level */
#define VSCAN_AVARCH_MAXRECLEVEL 5
/* non virus types of alerts (all off by default) */
#define VSCAN_AVDETECT_DIALER 0
#define VSCAN_AVDETECT_GAME 0
#define VSCAN_AVDETECT_JOKE 0
#define VSCAN_AVDETECT_PMS 0
#define VSCAN_AVDETECT_SPY 0
#define VSCAN_AVDETECT_ALLTYPES 0
/* default location of samba-style configuration file (needs Samba >= 2.2.4
or Samba 3.0 */
#define PARAMCONF "/etc/samba/vscan-antivir.conf"
/* False = log only concerning 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 True
#endif
/* True = deny access in case of scanning failure */
#ifndef VSCAN_DENY_ACCESS_ON_ERROR
# define VSCAN_DENY_ACCESS_ON_ERROR True
#endif
/* True = deny access in case of minor 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 alerts found
*/
#ifndef VSCAN_SEND_WARNING_MESSAGE
# define VSCAN_SEND_WARNING_MESSAGE True
#endif
/* default concerning 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 ""
/* End Configuration Section */
/* functions by vscan-antivir_core */
/* user connects to a share (might startup scanner daemon) */
int vscan_antivir_connect(void);
/* prepare a scan (might open a socket) */
int vscan_antivir_init(void);
/* scan a file */
int vscan_antivir_scanfile(int sockfd, char *scan_file, char *client_ip);
/* end a scan (might close a socket) */
void vscan_antivir_end(int sockfd);
/* user disconnects from a share (might shutdown scanner daemon) */
void vscan_antivir_disconnect(void);
#endif /* __VSCAN_ANTIVIR_H_ */
--- NEW FILE: vscan-antivir_core.c ---
/*
* $Id: vscan-antivir_core.c,v 1.1.2.1 2004/11/17 19:21:04 reniar Exp $
*
* Core Interface for the H+BEDV AntiVir Scanner
*
* Copyright (C) Rainer Link, 2001-2002
* OpenAntiVirus.org
<rainer-pBPPa8WU5k41Tgt60Rntydi2O/JbrIOy@xxxxxxxxxxxxxxxx>
* Dariusz Markowicz
<dariusz-UZsDlYnqr8oyTh+JdRw4UA@xxxxxxxxxxxxxxxx>, 2003
* H+BEDV Datentechnik GmbH
<unix_support-qmGPETzO5JyELgA04lAiVw@xxxxxxxxxxxxxxxx>, 2004
*
* This software is licensed under the GNU General Public License (GPL)
* See: http://www.gnu.org/copyleft/gpl.html
*
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/* use select(2) or poll(2) to drain antivir(1)'s greeting after process
* startup? we default to poll(2) since we cannot guarantee the file
* descriptor to be <= 1023 */
#undef USE_SELECT
#if defined USE_SELECT
#include <sys/select.h>
#else
#include <sys/poll.h>
#endif
#include "vscan-global.h"
#include "vscan-antivir_core.h"
/* used when scanning files */
extern BOOL verbose_file_logging;
extern BOOL send_warning_message;
/* used to startup the scanner process */
extern fstring antivir_program_name;
extern BOOL antivir_arch_scan_enable;
extern int antivir_arch_max_ratio;
extern ssize_t antivir_arch_max_size;
extern int antivir_arch_max_recursion;
extern int antivir_detect_dialer;
extern int antivir_detect_game;
extern int antivir_detect_joke;
extern int antivir_detect_pms;
extern int antivir_detect_spy;
extern int antivir_detect_alltypes;
/* used to manage the scanner process */
static int conn_count = 0;
static int antivir_fd_write = -1;
static int antivir_fd_read = -1;
static FILE *antivir_file_read = NULL;
static pid_t antivir_scanner_pid = 0;
static int connect_to_scanner(void);
static void disconnect_from_scanner(void);
/* user connects to a share (might startup scanner daemon) */
int vscan_antivir_connect(void) {
/* only act on the very first connection for this smbd process */
conn_count++;
if (conn_count > 1)
return(0);
if (connect_to_scanner() < 0)
return(-1);
return(0);
}
/* user disconnects from a share (might shutdown scanner daemon) */
void vscan_antivir_disconnect(void) {
conn_count--;
if (conn_count == 0)
disconnect_from_scanner();
}
/*
* introduces a scan request, (re)connect to the scanner process;
* returns -1 on error or 0 on success
*/
int vscan_antivir_init(void)
{
int rc;
rc = connect_to_scanner();
return(rc);
}
/*
* If an alert was found, logs the filename and concern into syslog
*/
void vscan_antivir_log_alert(char *concerning_file, char *results, char
*client_ip) {
vscan_syslog_alert("ALERT - Scan result: found '%s' in file '%s',
client: '%s'", results, concerning_file, client_ip);
if ( send_warning_message )
vscan_send_warning_message(concerning_file, results, client_ip);
}
/*
* avoid non printables in the scanner communication protocol
* XXX: does the condition need further splitting on EBCDIC machines?
* but OTOH isprint(3) does not really match what we would need here
*/
static int needsescape(const char c) {
return(((c <= ' ') || (c > '~') || (c == '\\')) ? 1 : 0);
#if 0
/* will this do better / more portable? */
if (c == '\\')
return(1);
if (isspace((int)c))
return(1);
if (isprint((int)c))
return(0);
return(1);
#endif
}
/*
* Scans a file (NOT a directory) for concerns
*
* Gets the vscan_antivir_init() return value (not really needed), the name of
* the file to scan and an IP to send notification to
*
* Returns
* -2 on minor error,
* -1 on error,
* 0 if nothing was found,
* 1 if a concern was found
*/
int vscan_antivir_scanfile(int sockfd, char *scan_file, char *client_ip) {
char *request;
size_t len;
int bEsc;
char escbuff[5]; /* "\\xNN" plus NUL */
char buff[1024];
char *p1, *p2;
/* (re)connect to the scanner process */
if (connect_to_scanner() < 0)
return(-1);
/* prepare antivir command (SCAN request) */
/* +1 is for '\0' termination --metze */
/* +3 for every special (non printable) char (escape) */
len = strlen("SCAN:") + strlen(scan_file) + strlen("\n") + 1;
bEsc = 0;
for (p1 = scan_file; (p1 != NULL) && (*p1 != '\0'); p1++) {
if (needsescape(*p1)) {
len += 3;
bEsc++;
}
}
request = (char *)malloc(len);
if (NULL == request) {
vscan_syslog("ERROR: can not allocate memory");
return -1; /* error allocating memory */
}
safe_strcpy(request, "SCAN:", len-1);
if (! bEsc) {
/* simple concatenation of the complete filename */
safe_strcat(request, scan_file, len-1);
} else {
/* a more expensive approach to avoid non printable chars in
the protocol */
/* XXX TODO optimization (memcpy() with a fork?) */
for (p1 = scan_file; (p1 != NULL) && (*p1 != '\0'); p1++) {
if (needsescape(*p1)) {
snprintf(escbuff, sizeof(escbuff), "\\x%02X",
(*((unsigned char *)p1)) & 0xFF);
} else {
/* there must be an easier way to accomplish
this :) */
snprintf(escbuff, sizeof(escbuff), "%c", *p1);
}
safe_strcat(request, escbuff, len - 1);
}
}
snprintf(escbuff, sizeof(escbuff), "\n");
safe_strcat(request, escbuff, len - 1);
if (verbose_file_logging)
vscan_syslog("INFO: Scanning file : '%s'", scan_file);
/* send request */
len = write(antivir_fd_write, request, strlen(request));
if (len != strlen(request)) {
free(request);
vscan_syslog("ERROR: can not write to the antivir socket");
return -1; /* error writing to the antivir socket */
}
free(request);
request = NULL;
/* get response (in a loop, we might have to skip some lines) */
do {
memset(buff, 0, sizeof(buff));
p1 = fgets((char *)&buff, sizeof(buff), antivir_file_read);
if (p1 == NULL)
break;
/* remove trailing spaces */
p1 = buff + strlen(buff);
while ((p1 > buff) && (isspace((int)*(p1-1)))) {
p1--;
*p1 = '\0';
}
/* an updater might have restarted our scanner process */
if (strncmp(buff, "Running in DEMO mode.", strlen("Running in
DEMO mode.")) == 0) {
/* log a warning? */
continue;
}
if (strncmp(buff, "BANNER ", strlen("BANNER ")) == 0) {
continue;
}
/*
* we got a response to our request;
* do NOT close the scanner, reuse it for multiple scans
*/
/* split response into keyword and (optional) parameter */
p1 = buff;
p2 = strchr(p1, ':');
if (p2 == NULL)
p2 = p1 + strlen(p1);
if (*p2 == ':') {
*p2 = '\0';
p2++;
}
while (isspace((int)*p2))
p2++;
/* found an alert */
if (strcmp(p1, "FOUND") == 0) {
vscan_antivir_log_alert(scan_file, p2, client_ip);
return 1;
/* file good */
} else if (strcmp(p1, "OK") == 0) {
if (verbose_file_logging) {
vscan_syslog("INFO: file %s is clean",
scan_file);
}
return 0;
/* no explicit check for "ERROR", caught here, too */
} else {
if (verbose_file_logging) {
vscan_syslog("ERROR: file %s not found, not
readable or an error occured", scan_file);
}
return -2;
}
} while (0);
/* read error or EOF, close the scanner process */
disconnect_from_scanner();
vscan_syslog("ERROR: can not get result from antivir");
return -1;
}
/*
* ends a scan request
*
* gets the vscan_antivir_init() return value (not really needed)
*/
void vscan_antivir_end(int sockfd) {
/* leave the connection open, we will reuse it for the
* next file to scan and close it on (last) disconnect
*/
/* EMPTY */
}
/*
* connect or reconnect to a scanner process;
* returns -1 on errors, non negative codes otherwise
*/
static int connect_to_scanner(void) {
int execargc;
char *execargv[16];
int rc;
int fdreq[2];
int fdrsp[2];
pid_t pid;
char buff[256];
struct timeval tv;
int fd;
/*
* check if the scanner process is alive (handles dangling
* connections); we do not strictly need this but I want to
* avoid SIGPIPEs (we're in a shared object, attached to an
* smbd(8) process -- would SIG_IGN be appropriate? read(2)
* and fgets(3) would return errors, anyway ...)
*/
if ((antivir_scanner_pid != 0) && (kill(antivir_scanner_pid, 0) != 0))
disconnect_from_scanner();
/* shortcut for "already (completely) open?" */
if ((antivir_fd_write != -1) && (antivir_fd_read != -1) &&
(antivir_file_read != NULL) && (antivir_scanner_pid != 0))
return(0);
/* one of the parameters might be wrong, close what is left open (if
any) */
disconnect_from_scanner();
/* open up a new scanner process ... */
#define DEL_CMD_WORDS do { \
while (execargc > 0) { \
execargc--; \
free(execargv[execargc]); \
} \
} while (0)
#define ADD_CMD_WORD(word) do { \
char *copy; \
\
if (word != NULL) { \
copy = strdup(word); \
if (copy == NULL) { \
DEL_CMD_WORDS; \
return(-1); \
} \
} else { \
copy = NULL; \
} \
execargv[execargc] = copy; \
execargc++; \
if (execargc >= sizeof(execargv) / sizeof(execargv[0])) { \
DEL_CMD_WORDS; \
disconnect_from_scanner(); \
return(-1); \
} \
execargv[execargc] = NULL; \
} while (0)
/* ... build a command line ... */
{
execargc = 0;
ADD_CMD_WORD(antivir_program_name);
ADD_CMD_WORD("--samba-vscan");
if (antivir_arch_scan_enable) {
char printbuff[40];
ADD_CMD_WORD("--scan-in-archive");
/* for some reason the %z format spec did not work :( */
snprintf(printbuff, sizeof(printbuff),
"--archive-max-size=%lld", (long long)antivir_arch_max_size);
ADD_CMD_WORD(printbuff);
snprintf(printbuff, sizeof(printbuff),
"--archive-max-recursion=%d", antivir_arch_max_recursion);
ADD_CMD_WORD(printbuff);
snprintf(printbuff, sizeof(printbuff),
"--archive-max-ratio=%d", antivir_arch_max_ratio);
ADD_CMD_WORD(printbuff);
}
/* optionally add a "--temp=" option? */
if (antivir_detect_alltypes)
ADD_CMD_WORD("--alltypes");
if (antivir_detect_dialer)
ADD_CMD_WORD("--with-dialer");
if (antivir_detect_game)
ADD_CMD_WORD("--with-game");
if (antivir_detect_joke)
ADD_CMD_WORD("--with-joke");
if (antivir_detect_pms)
ADD_CMD_WORD("--with-pms");
if (antivir_detect_spy)
ADD_CMD_WORD("--with-spy");
}
/* ... setup a communication pipe ... */
rc = pipe(fdreq);
if (rc < 0) {
DEL_CMD_WORDS;
disconnect_from_scanner();
return(-1);
}
rc = pipe(fdrsp);
if (rc < 0) {
DEL_CMD_WORDS;
disconnect_from_scanner();
return(-1);
}
/* ... fork off the process ... */
pid = fork();
switch (pid) {
case -1: /* failure */
DEL_CMD_WORDS;
disconnect_from_scanner();
return(-1);
case 0: /* the child (scanner) */
/* redirect stdin */
rc = dup2(fdreq[0], STDIN_FILENO);
if (rc == -1)
exit(1);
close(fdreq[0]); /* redirected */
fdreq[0] = -1;
close(fdreq[1]); /* not needed */
fdreq[1] = -1;
/* redirect stdout */
rc = dup2(fdrsp[1], STDOUT_FILENO);
if (rc == -1)
exit(1);
close(fdrsp[1]); /* redirected */
fdrsp[1] = -1;
close(fdrsp[0]); /* not needed */
fdrsp[0] = -1;
/* redirect stderr */
fclose(stderr); freopen("/dev/null", "w", stderr);
/* close all fds */
/* XXX how to portably get the max fd?
* fd = open("/dev/null", O_RDONLY);
* does not work reliably in the smbd(8) case,
* since there is a gap in the fd sequence
*/
fd = 1024; /* aux upper limit */
while (fd > STDERR_FILENO) {
close(fd);
fd--;
}
/* execute the scanner process */
rc = execvp(execargv[0], execargv);
/* UNREACH */
exit(1);
default: /* parent (samba-vscan) */
/* release the command line */
DEL_CMD_WORDS;
/* get the read/write handles to the scanner process */
close(fdreq[0]); fdreq[0] = -1;
antivir_fd_write = fdreq[1];
close(fdrsp[1]); fdrsp[1] = -1;
antivir_fd_read = fdrsp[0];
/* drain banners / greetings / help or synopsis on errors / etc
*/
tv.tv_sec = 1; tv.tv_usec = 0;
do {
ssize_t ct;
#if defined USE_SELECT
fd_set r;
FD_ZERO(&r);
FD_SET(antivir_fd_read, &r);
rc = select(antivir_fd_read + 1, &r, NULL, NULL, &tv);
tv.tv_sec = 0; tv.tv_usec = 0;
if (rc < 0) {
vscan_syslog("ERROR: Can not read from scanner
- %s", strerror(errno));
disconnect_from_scanner();
return -1;
}
if (rc == 0)
break;
if (! FD_ISSET(antivir_fd_read, &r))
break;
#else /* USE_SELECT */
struct pollfd pfd[1];
memset(pfd, 0, sizeof(pfd));
pfd[0].fd = antivir_fd_read;
pfd[0].events = POLLIN;
rc = poll(pfd, 1, tv.tv_sec * 1000);
tv.tv_sec = 0; tv.tv_usec = 0;
if (rc < 0) {
vscan_syslog("ERROR: Can not read from scanner
- %s", strerror(errno));
disconnect_from_scanner();
return -1;
}
if (rc == 0)
break;
#endif /* USE_SELECT */
ct = read(antivir_fd_read, buff, sizeof(buff));
if (ct <= 0) {
vscan_syslog("ERROR: Can not read from scanner
- %s", strerror(errno));
disconnect_from_scanner();
return -1;
}
} while (1);
/* convert "int fd" to "FILE *" for fgets(3) */
antivir_file_read = fdopen(antivir_fd_read, "r");
if (antivir_file_read == NULL) {
vscan_syslog("ERROR: Can not read from scanner - %s",
strerror(errno));
disconnect_from_scanner();
return -1;
}
/* scanner process gone after the greeting? */
if (kill(pid, 0) != 0) {
vscan_syslog("ERROR: scanner disappeared at connect
time");
disconnect_from_scanner();
return(-1);
}
antivir_scanner_pid = pid;
/* connection setup done, now we're happy */
return(0);
}
/* UNREACH */
return(-1);
}
/*
* invalidate the scanner process
* (detach and clear vars after use or failure)
*/
static void disconnect_from_scanner(void) {
if (antivir_fd_write != -1) {
close(antivir_fd_write);
antivir_fd_write = -1;
}
/* XXX drain possible input? */
if (antivir_file_read != NULL) {
fclose(antivir_file_read);
antivir_file_read = NULL;
antivir_fd_read = -1;
} else if (antivir_fd_read != -1) {
close(antivir_fd_read);
antivir_fd_read = -1;
}
antivir_scanner_pid = 0;
}
--- NEW FILE: vscan-antivir_core.h ---
#ifndef __VSCAN_ANTIVIR_CORE_H_
#define __VSCAN_ANTIVIR_CORE_H_
#include "vscan-antivir.h"
#endif /* __VSCAN_ANTIVIR_CORE_H */
--- NEW FILE: Makefile ---
#
# Makefile for vscan-antivir, part of samba-vscan
#
# $Id: Makefile,v 1.1.2.1 2004/11/17 19:21:04 reniar Exp $
#
# 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-antivir.so
SOURCES = $(SMBVS_GLB)/vscan-functions.c $(SMBVS_GLB)/vscan-message.c
$(SMBVS_GLB)/vscan-quarantine.c $(SMBVS_GLB)/vscan-fileaccesslog.c
vscan-antivir.c vscan-antivir_core.c vscan-antivir.h vscan-antivir_core.h
OBJS = vscan-functions.lo vscan-message.lo vscan-quarantine.lo
vscan-fileaccesslog.lo vscan-antivir.lo vscan-antivir_core.lo
LIBS =
# Default target
all: $(VFS_OBJS)
vscan-antivir.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-antivir_core.c
$(LIBTOOL) $(CC) $(CPPFLAGS) $(CFLAGS) -c vscan-antivir.c
$(LIBTOOL) $(CC) -shared $(LDFLAGS) $(LIBS) $(OBJS) -o vscan-antivir.so
# Misc targets
clean:
rm -rf .libs
rm -f core *~ *% *.bak *.so *.lo *.o
--- NEW FILE: vscan-antivir.conf ---
[samba-vscan]
; run-time configuration for vscan-samba using
; antivir
; all options are 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 files containing
; an alert 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 antivir fails, should access to file be denied?
; (default: yes)
deny access on error = yes
; if daemon failes with a minor error (corruption, etc.),
; should access to file be denied?
; (default: yes)
deny access on minor error = yes
; send a warning message via Windows Messenger service
; when an alert was found?
; (default: yes)
send warning message = yes
; what to do with a file containing an alert
; quarantine: try to move to quantine directory; delete it if moving fails
; delete: delete concerning file
; nothing: do nothing (default)
concerning file action = quarantine
; where to put concerning files - you really want to change this!
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. (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 =
; executable name of antivir (default: /usr/lib/AntiVir/antivir)
antivir program name = /usr/lib/AntiVir/antivir
; enable scan of archive files
antivir scan in archive = no
; maximum compression ratio of files in archive (default: 150)
antivir max ratio in archive = 150
; maximum archived file size, in bytes (default: 1 GB)
antivir max archived file size = 1073741824
; maximum recursion level (default: 5)
antivir max recursion level = 5
; detect non virus alerts, too, i.e. different kinds of unwanted software
; (default: off)
antivir detect dialer = no
antivir detect game = no
antivir detect joke = no
antivir detect pms = no
antivir detect spy = no
; a cumulative switch to enable *all* of the above categories
antivir detect alltypes = no
--- NEW FILE: vscan-antivir.c ---
/*
* $Id: vscan-antivir.c,v 1.1.2.1 2004/11/17 19:21:04 reniar Exp $
*
* virusscanning VFS module for samba. Log concerning files via syslog
* facility and block access using the H+BEDV AntiVir scanner.
*
* Copyright (C) Rainer Link, 2001-2003
* OpenAntiVirus.org
<rainer-pBPPa8WU5k41Tgt60Rntydi2O/JbrIOy@xxxxxxxxxxxxxxxx>
* Dariusz Markowicz
<dariusz-UZsDlYnqr8oyTh+JdRw4UA@xxxxxxxxxxxxxxxx>, 2003
* Copyright (C) Stefan (metze) Metzmacher, 2003
* <metze-pz2UNc6q77cb1SvskN2V4Q@xxxxxxxxxxxxxxxx>
* Copyright (C) H+BEDV Datentechnik GmbH, 2004
* <unix_support-qmGPETzO5JyELgA04lAiVw@xxxxxxxxxxxxxxxx>
*
* based on the audit VFS module by
* Copyright (C) Tim Potter, 1999-2000
* Copyright (C) Alexander Bokovoy, 2002
*
*
* Credits to
* - Dave Collier-Brown for his VFS tutorial
(http://www.geocities.com/orville_torpid/papers/vfs_tutorial.html)
* - REYNAUD Jean-Samuel for helping me to solve some general Samba VFS issues
at the first place
* - Simon Harrison for his solution without Samba VFS
(http://www.smh.uklinux.net/linux/sophos.html)
* - the whole Samba Team :)
*
* 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-antivir.h"
#include "vscan-vfs.h"
#define VSCAN_MODULE_STR "vscan-antivir"
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 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 True
*/
BOOL deny_access_on_error; /* if communication to the scanner fails,
should access to any file be denied? */
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? */
enum infected_file_action_enum concerning_file_action; /* what to do with
concerning files;
defaults to quarantine
*/
fstring quarantine_dir; /* directory for concerning files */
fstring quarantine_prefix; /* prefix for concerning files */
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 */
fstring antivir_program_name; /* name of antivir executable */
BOOL antivir_arch_scan_enable; /* archive related settings for the AntiVir
scanner */
int antivir_arch_max_ratio;
ssize_t antivir_arch_max_size;
int antivir_arch_max_recursion;
BOOL antivir_detect_dialer; /* non virus type alerts related settings for
the AntiVir scanner */
BOOL antivir_detect_game;
BOOL antivir_detect_joke;
BOOL antivir_detect_pms;
BOOL antivir_detect_spy;
BOOL antivir_detect_alltypes;
/* module version */
static const char module_id[]=VSCAN_MODULE_STR" "SAMBA_VSCAN_VERSION_STR;
static BOOL do_parameter(const char *param, const char *value)
{
if ( StrCaseCmp("max file size", param) == 0 ) {
max_size = atoll(value);
/* the %z format spec for size_t does not work :( */
DEBUG(3, ("max file size is: %lld\n", (long long)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("concerning file action", param) == 0)
#if 1 /* for compatibility */
|| (StrCaseCmp("infected file action", param) == 0)
#endif
) {
if (StrCaseCmp("quarantine", value) == 0) {
concerning_file_action = INFECTED_QUARANTINE;
} else if (StrCaseCmp("delete", value) == 0) {
concerning_file_action = INFECTED_DELETE;
} else if (StrCaseCmp("nothing", value) == 0) {
concerning_file_action = INFECTED_DO_NOTHING;
} else {
DEBUG(2, ("samba-vscan: badly formed concerning file
action in configuration file, parameter %s\n", value));
}
DEBUG(3, ("concerning file action is: %d\n",
concerning_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 file types is: %s\n", exclude_file_types));
} else if ( StrCaseCmp("antivir program name", param) == 0) {
fstrcpy(antivir_program_name, value);
DEBUG(3, ("antivir program name is %s\n",
antivir_program_name));
} else if ( StrCaseCmp("antivir scan in archive", param) == 0) {
set_boolean(&antivir_arch_scan_enable, value);
DEBUG(3, ("antivir scan in archive is %d\n",
antivir_arch_scan_enable));
} else if ( StrCaseCmp("antivir max ratio in archive", param) == 0) {
antivir_arch_max_ratio = atoi(value);
DEBUG(3, ("antivir max ratio in archive is %d\n",
antivir_arch_max_ratio));
} else if ( StrCaseCmp("antivir max archived file size", param) == 0) {
antivir_arch_max_size = atoll(value);
DEBUG(3, ("antivir max archived file size is %lld\n", (long
long)antivir_arch_max_size));
} else if ( StrCaseCmp("antivir max recursion level", param) == 0) {
antivir_arch_max_recursion = atoi(value);
DEBUG(3, ("antivir max recursion level is %d\n",
antivir_arch_max_recursion));
} else if ( StrCaseCmp("antivir detect dialer", param) == 0) {
set_boolean(&antivir_detect_dialer, value);
DEBUG(3, ("antivir detect dialer is %d\n",
antivir_detect_dialer));
} else if ( StrCaseCmp("antivir detect game", param) == 0) {
set_boolean(&antivir_detect_game, value);
DEBUG(3, ("antivir detect game is %d\n", antivir_detect_game));
} else if ( StrCaseCmp("antivir detect joke", param) == 0) {
set_boolean(&antivir_detect_joke, value);
DEBUG(3, ("antivir detect joke is %d\n", antivir_detect_joke));
} else if ( StrCaseCmp("antivir detect pms", param) == 0) {
set_boolean(&antivir_detect_pms, value);
DEBUG(3, ("antivir detect pms is %d\n", antivir_detect_pms));
} else if ( StrCaseCmp("antivir detect spy", param) == 0) {
set_boolean(&antivir_detect_spy, value);
DEBUG(3, ("antivir detect spy is %d\n", antivir_detect_spy));
} else if ( StrCaseCmp("antivir detect alltypes", param) == 0) {
set_boolean(&antivir_detect_alltypes, value);
DEBUG(3, ("antivir detect alltypes is %d\n",
antivir_detect_alltypes));
} else
DEBUG(3, ("unknown parameter: %s\n", param));
/* return False; ? */
return True;
}
static BOOL do_section(const char *section)
{
/* simply return true, there's only one section :-) */
return True;
}
/* Implementation of vfs_ops. */
#if (SMB_VFS_INTERFACE_VERSION >= 6)
static int vscan_connect(vfs_handle_struct *handle, connection_struct *conn,
const char *svc, const char *user)
#else
static int vscan_connect(struct connection_struct *conn, PROTOTYPE_CONST char
*svc, PROTOTYPE_CONST char *user)
#endif
{
#if (SAMBA_VERSION_MAJOR==2 && SAMBA_VERSION_RELEASE>=4) ||
SAMBA_VERSION_MAJOR==3
#if !(SMB_VFS_INTERFACE_VERSION >= 6)
pstring opts_str;
PROTOTYPE_CONST char *p;
#endif
#endif
int retval;
#if (SMB_VFS_INTERFACE_VERSION >= 6)
vscan_syslog("samba-vscan (%s) connected (Samba 3.0), (c) by Rainer
Link, OpenAntiVirus.org", module_id);
#endif
/* 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 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);
/* name of AntiVir executable file */
fstrcpy(antivir_program_name, VSCAN_ANTIVIR_PROGRAM_NAME);
/* AntiVir archive related settings */
antivir_arch_scan_enable = VSCAN_AVARCH_ENABLED;
antivir_arch_max_ratio = VSCAN_AVARCH_MAXRATIO;
antivir_arch_max_size = VSCAN_AVARCH_MAXFILESIZE;
antivir_arch_max_recursion = VSCAN_AVARCH_MAXRECLEVEL;
/* AntiVir non virus alerts related settings */
antivir_detect_dialer = VSCAN_AVDETECT_DIALER;
antivir_detect_game = VSCAN_AVDETECT_GAME;
antivir_detect_joke = VSCAN_AVDETECT_JOKE;
antivir_detect_pms = VSCAN_AVDETECT_PMS;
antivir_detect_spy = VSCAN_AVDETECT_SPY;
antivir_detect_alltypes = VSCAN_AVDETECT_ALLTYPES;
vscan_syslog("INFO: connect to service %s by user %s",
svc, user);
#if (SAMBA_VERSION_MAJOR==2 && SAMBA_VERSION_RELEASE>=4) ||
SAMBA_VERSION_MAJOR==3
#if (SMB_VFS_INTERFACE_VERSION >= 6)
fstrcpy(config_file,
lp_parm_const_string(SNUM(conn),VSCAN_MODULE_STR,"config-file",PARAMCONF));
#else
pstrcpy(opts_str, (const char*) lp_vfs_options(SNUM(conn)));
if( !*opts_str ) {
DEBUG(3, ("samba-vscan: no configuration file set - using
default value (%s).\n", lp_vfs_options(SNUM(conn))));
} else {
p = opts_str;
if ( next_token(&p, config_file, "=", sizeof(config_file)) ) {
trim_string(config_file, " ", " ");
if ( !strequal("config-file", config_file) ) {
DEBUG(3, ("samba-vscan - connect: options %s is
not config-file\n", config_file));
/* setting default value */
fstrcpy(config_file, PARAMCONF);
} else {
if ( !next_token(&p, config_file,"
\n",sizeof(config_file)) ) {
DEBUG(3, ("samba-vscan - connect: no
option after config-file=\n"));
/* setting default value */
fstrcpy(config_file, PARAMCONF);
} else {
trim_string(config_file, " ", " ");
DEBUG(3, ("samba-vscan - connect:
config file name is %s\n", config_file));
}
}
}
}
#endif /* #if (SMB_VFS_INTERFACE_VERSION >= 6)*/
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);
#endif
/* 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);
/* tell core we have a(nother) session, ignore return code */
(void)vscan_antivir_connect();
#if (SMB_VFS_INTERFACE_VERSION >= 6)
return SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
#else
return default_vfs_ops.connect(conn, svc, user);
#endif
}
#if (SMB_VFS_INTERFACE_VERSION >= 6)
static void vscan_disconnect(vfs_handle_struct *handle, connection_struct *conn)
#else/* Samba 3.0 alphaX */
static void vscan_disconnect(struct connection_struct *conn)
#endif
{
/* tell core the (one) session has gone */
vscan_antivir_disconnect();
vscan_syslog("INFO: disconnected");
lrufiles_destroy_all();
filetype_close();
#if (SMB_VFS_INTERFACE_VERSION >= 6)
SMB_VFS_NEXT_DISCONNECT(handle, conn);
#else
default_vfs_ops.disconnect(conn);
#endif
}
#if (SMB_VFS_INTERFACE_VERSION >= 6)
static int vscan_open(vfs_handle_struct *handle, connection_struct *conn, const
char *fname, int flags, mode_t mode)
#else
static int vscan_open(struct connection_struct *conn, PROTOTYPE_CONST char
*fname, int flags, mode_t mode)
#endif
{
int retval, must_be_checked;
SMB_STRUCT_STAT stat_buf;
int sockfd;
pstring filepath;
char client_ip[CLIENT_IP_SIZE];
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));
#if (SMB_VFS_INTERFACE_VERSION >= 6)
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
#else
return default_vfs_ops.open(conn, fname, flags, mode);
#endif
}
#if (SMB_VFS_INTERFACE_VERSION >= 6)
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 ( (default_vfs_ops.stat(conn, fname, &stat_buf)) != 0 ) /* an
error occured */
return default_vfs_ops.open(conn, fname, flags, mode);
#endif
else if ( S_ISDIR(stat_buf.st_mode) ) /* is it a directory? */
#if (SMB_VFS_INTERFACE_VERSION >= 6)
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
#else
return default_vfs_ops.open(conn, fname, flags, mode);
#endif
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 */
#if (SMB_VFS_INTERFACE_VERSION >= 6)
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
#else
return default_vfs_ops.open(conn, fname, flags, mode);
#endif
else if ( filetype_skipscan(filepath) == 1 ) {
if ( verbose_file_logging )
vscan_syslog("File '%s' not scanned as file type is on
exclude list", filepath);
#if (SMB_VFS_INTERFACE_VERSION >= 6)
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
#else
return default_vfs_ops.open(conn, fname, flags, mode);
#endif
} else
{
/* prepare file scan, (re)open connection to the scanner */
sockfd = vscan_antivir_init();
if ( sockfd == -1 && 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 if ( sockfd >= 0 ) {
/* we now have a scanner */
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
containing an alert */
/* deny access */
if ( verbose_file_logging )
vscan_syslog("File '%s' has already
been scanned and marked as containing an alert. Not scanned any more. Access
denied", filepath);
/* postprocess file scan */
vscan_antivir_end(sockfd);
/* deny access */
errno = EACCES;
return -1;
} else if ( must_be_checked == 0 ) {
/* file has already been checked, not marked as
containing an alert and not modified */
if ( verbose_file_logging )
vscan_syslog("File '%s' has already
been scanned, not marked as containing an alert and not modified. Not scanned
anymore. Access granted", filepath);
/* postprocess file scan */
vscan_antivir_end(sockfd);
/* grant access */
#if (SMB_VFS_INTERFACE_VERSION >= 6)
return SMB_VFS_NEXT_OPEN(handle, conn, fname,
flags, mode);
#else
return default_vfs_ops.open(conn, fname, flags,
mode);
#endif
}
/* ok, we must check the file */
/* scan file */
retval = vscan_antivir_scanfile(sockfd, filepath,
client_ip);
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);
vscan_antivir_end(sockfd);
/* 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);
/* to be safe, remove file from lrufiles */
lrufiles_delete(filepath);
/* deny access */
errno = EACCES;
return -1;
} else if ( retval == 1 ) {
/* an alert was found */
vscan_antivir_end(sockfd);
/* do action ... */
#if (SMB_VFS_INTERFACE_VERSION >= 6)
rc = vscan_do_infected_file_action(handle,
conn, filepath, quarantine_dir, quarantine_prefix, concerning_file_action);
#else
rc =
vscan_do_infected_file_action(&default_vfs_ops, conn, filepath, quarantine_dir,
quarantine_prefix, concerning_file_action);
#endif
/* add/update file. mark file as containing an
alert! */
lrufiles_add(filepath, stat_buf.st_mtime, True);
/* alert 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);
}
}
/* scan done, post process file scan */
vscan_antivir_end(sockfd);
}
#if (SMB_VFS_INTERFACE_VERSION >= 6)
return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
#else
return default_vfs_ops.open(conn, fname, flags, mode);
#endif
}
#if (SMB_VFS_INTERFACE_VERSION >= 6)
static int vscan_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
#else
static int vscan_close(struct files_struct *fsp, int fd)
#endif
{
pstring filepath;
int retval, rv, rc;
int sockfd;
char client_ip[CLIENT_IP_SIZE];
/* First close the file */
#if (SMB_VFS_INTERFACE_VERSION >= 6)
retval = SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
#else
retval = default_vfs_ops.close(fsp, fd);
#endif
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;
}
sockfd = vscan_antivir_init();
if ( sockfd >= 0 ) {
safe_strcpy(client_ip, fsp->conn->client_address,
CLIENT_IP_SIZE -1);
/* scan only file, do nothing */
rv = vscan_antivir_scanfile(sockfd, filepath, client_ip);
vscan_antivir_end(sockfd);
if ( rv == 1 ) {
/* alert was found */
#if (SMB_VFS_INTERFACE_VERSION >= 6)
rc = vscan_do_infected_file_action(handle, fsp->conn,
filepath, quarantine_dir, quarantine_prefix, concerning_file_action);
#else
rc = vscan_do_infected_file_action(&default_vfs_ops,
fsp->conn, filepath, quarantine_dir, quarantine_prefix, concerning_file_action);
#endif
}
}
return retval;
}
#if (SMB_VFS_INTERFACE_VERSION >= 6)
/* Samba 3.0 */
NTSTATUS init_module(void)
{
NTSTATUS ret;
ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, VSCAN_MODULE_STR,
vscan_ops);
openlog("smbd_"VSCAN_MODULE_STR, LOG_PID, SYSLOG_FACILITY);
vscan_syslog("samba-vscan (%s) registered (Samba 3.0), (c) by Rainer
Link, OpenAntiVirus.org", module_id);
DEBUG(5,("samba-vscan (%s) registered (Samba 3.0), (c) by Rainer Link,
OpenAntiVirus.org\n", module_id));
return ret;
}
#else
/* VFS initialisation function. Return initialised vfs_ops structure
back to SAMBA. */
#if SAMBA_VERSION_MAJOR==3
/* Samba 3.0 alphaX */
vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,
struct smb_vfs_handle_struct *vfs_handle)
#else
/* Samba 2.2.x */
#if SAMBA_VERSION_RELEASE>=4
/* Samba 2.2.4 */
struct vfs_ops *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops)
#elif SAMBA_VERSION_RELEASE==2
/* Samba 2.2.2 / Samba 2.2.3 !!! */
struct vfs_ops *vfs_init(int* Version, struct vfs_ops *ops)
#elif SAMBA_VERSION_RELEASE==1
/* Samba 2.2.1 */
struct vfs_ops *vfs_module_init(int *vfs_version)
#else
/* Samba 2.2.0 */
struct vfs_ops *vfs_init(int *vfs_version)
#endif
#endif
{
#if SAMBA_VERSION_MAJOR!=3
#if SAMBA_VERSION_RELEASE>=4
/* Samba 2.2.4 */
struct vfs_ops tmp_ops;
#endif
#endif
openlog("smbd_"VSCAN_MODULE_STR, LOG_PID, SYSLOG_FACILITY);
#if SAMBA_VERSION_MAJOR==3
/* Samba 3.0 alphaX */
*vfs_version = SMB_VFS_INTERFACE_VERSION;
vscan_syslog("samba-vscan (%s) loaded (Samba 3.x), (c) by Rainer Link,
OpenAntiVirus.org", module_id);
#else
/* Samba 2.2.x */
#if SAMBA_VERSION_RELEASE>=4
/* Samba 2.2.4 */
*vfs_version = SMB_VFS_INTERFACE_VERSION;
vscan_syslog("samba-vscan (%s) loaded (Samba >=2.2.4), (c) by Rainer
Link, OpenAntiVirus.org", module_id);
#elif SAMBA_VERSION_RELEASE==2
/* Samba 2.2.2 / Samba 2.2.3 !!! */
*Version = SMB_VFS_INTERFACE_VERSION;
vscan_syslog("samba-vscan (%s) loaded (Samba 2.2.2/2.2.3), (c) by
Rainer Link, OpenAntiVirus.org", module_id);
#else
/* Samba 2.2.1 / Samba 2.2.0 */
*vfs_version = SMB_VFS_INTERFACE_VERSION;
vscan_syslog("samba-vscan (%s) loaded (Samba 2.2.0/2.2.1), (c) by
Rainer Link, OpenAntiVirus.org",
module_id);
#endif
#endif
#if SAMBA_VERSION_MAJOR==3
/* Samba 3.0 alphaX */
DEBUG(3, ("Initialising default vfs hooks\n"));
memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
/* Remember vfs_handle for further allocation and referencing of
private information in vfs_handle->data
*/
vscan_handle = vfs_handle;
return vscan_ops;
#else
/* Samba 2.2.x */
#if SAMBA_VERSION_RELEASE>=4
/* Samba 2.2.4 */
*vfs_version = SMB_VFS_INTERFACE_VERSION;
memcpy(&tmp_ops, def_vfs_ops, sizeof(struct vfs_ops));
tmp_ops.connect = vscan_connect;
tmp_ops.disconnect = vscan_disconnect;
tmp_ops.open = vscan_open;
tmp_ops.close = vscan_close;
memcpy(&vscan_ops, &tmp_ops, sizeof(struct vfs_ops));
return(&vscan_ops);
#else
/* Samba 2.2.3-2.2.0 */
return(&vscan_ops);
#endif
#endif
}
#if SAMBA_VERSION_MAJOR==3
/* VFS finalization function */
void vfs_done(connection_struct *conn)
{
DEBUG(3, ("Finalizing default vfs hooks\n"));
}
#endif
#endif /* #if (SMB_VFS_INTERFACE_VERSION >= 6) */
-------------------------------------------------------
This SF.Net email is sponsored by: InterSystems CACHE
FREE OODBMS DOWNLOAD - A multidimensional database that combines
robust object and relational technologies, making it a perfect match
for Java, C++,COM, XML, ODBC and JDBC. www.intersystems.com/match8
|