From 358cc7fb2c4a28ec2d786f87445a966c55f55652 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Thu, 13 Jul 2006 23:50:43 +0000 Subject: * Add support for passing emails * Bring in some changes from proxsmtp --- ChangeLog | 2 ++ configure.in | 4 +-- doc/clamsmtpd.8 | 2 +- doc/clamsmtpd.conf | 4 +-- doc/clamsmtpd.conf.5 | 19 +++++++++---- src/clamsmtpd.c | 77 +++++++++++++++++++++++++++++++++++++++++++++------- 6 files changed, 87 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 29954be..6e15b4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 1.7 - Fix crasher when connection goes down unexpectedly. + - Add support for letting virus emails pass. + - Better message for 'busy' [Akihiro Sagawa] 1.6 [2005-10-21] - IMPORTANT: Removed support for listening on ports under < 1024 diff --git a/configure.in b/configure.in index 7d2c4be..00d1003 100644 --- a/configure.in +++ b/configure.in @@ -36,8 +36,8 @@ dnl Nate Nielsen dnl dnl Process this file with autoconf to produce a configure script. -AC_INIT(clamsmtp, 1.6.91, nielsen@memberwebs.com) -AM_INIT_AUTOMAKE(clamsmtp, 1.6.91) +AC_INIT(clamsmtp, 1.6.93, nielsen@memberwebs.com) +AM_INIT_AUTOMAKE(clamsmtp, 1.6.93) LDFLAGS="$LDFLAGS -L/usr/local/lib" CFLAGS="$CFLAGS -I/usr/local/include" diff --git a/doc/clamsmtpd.8 b/doc/clamsmtpd.8 index 3a87066..ee8d08c 100644 --- a/doc/clamsmtpd.8 +++ b/doc/clamsmtpd.8 @@ -127,7 +127,7 @@ original destination after being scanned. .Pp When doing transparent proxying for outgoing email it's probably a good idea to turn on bounce notifications using the -.Ar Bounce +.Ar Action: bounce setting. Also note that some features (such as SSL/TLS) will not be available when going through the transparent proxy. .Pp diff --git a/doc/clamsmtpd.conf b/doc/clamsmtpd.conf index 934289d..c50dcc6 100644 --- a/doc/clamsmtpd.conf +++ b/doc/clamsmtpd.conf @@ -37,8 +37,8 @@ OutAddress: 10026 # Directory for temporary files #TempDirectory: /tmp -# Whether or not to bounce email (default is to silently drop) -#Bounce: off +# What to do when we see a virus (use 'bounce' or 'pass' or 'drop' +#Action: drop # Whether or not to keep virus files #Quarantine: off diff --git a/doc/clamsmtpd.conf.5 b/doc/clamsmtpd.conf.5 index 13268d1..29abe55 100644 --- a/doc/clamsmtpd.conf.5 +++ b/doc/clamsmtpd.conf.5 @@ -68,14 +68,21 @@ directory of the clamsmtp distribution. .Sh SETTINGS The various settings are as follows: .Bl -tag -width Fl -.It Ar Bounce -When this flag is set +.It Ar Action +This option controls what .Xr clamsmtpd 8 -actively rejects messages with viruses. This may cause the sender to receive -a message back notifying them of the virus. In most cases this is not a good -idea since many viruses spoof sender addresses. +does when it finds a virus. The options are: +.Bl -inset +.It Ar bounce +Bounce the email. In most cases this is not a good idea since many viruses +spoof sender addresses. +.It Ar drop +Silently drop the email. Recommended. +.It Ar pass +Pass on the email. Inserts an 'X-Virus-Infected' header. +.El .Pp -[ Default: off ] +[ Default: drop ] .It Ar ClamAddress Specifies the address to connect to .Xr clamd 8 diff --git a/src/clamsmtpd.c b/src/clamsmtpd.c index 93d773f..52921dc 100644 --- a/src/clamsmtpd.c +++ b/src/clamsmtpd.c @@ -58,6 +58,12 @@ * STRUCTURES */ +enum { + ACTION_DROP, + ACTION_BOUNCE, + ACTION_PASS +}; + typedef struct clstate { /* Settings ------------------------------- */ @@ -65,9 +71,10 @@ typedef struct clstate const char* clamname; const char* directory; /* The directory for temp files */ const char* virusaction; /* Program to run when event occurs */ - int bounce; /* Send back a reject line */ + int action; /* Which action to take on a virus */ int quarantine; /* Leave virus files in temp dir */ int debug_files; /* Leave all files in temp dir */ + const char* header; /* A header to include in emails */ } clstate_t; @@ -102,6 +109,7 @@ clctx_t; #define DEFAULT_CONFIG CONF_PREFIX "/clamsmtpd.conf" #define DEFAULT_CLAMAV "/var/run/clamav/clamd" #define DEFAULT_HEADER "X-Virus-Scanned: ClamAV using ClamSMTP" +#define VIRUS_HEADER "X-Virus-Infected: Virus Detected!" /* ----------------------------------------------------------------------- * CONFIGURATION OPTIONS @@ -122,11 +130,17 @@ clctx_t; #define CFG_DIRECTORY "TempDirectory" #define CFG_HEADER "Header" #define CFG_SCANHEADER "ScanHeader" +#define CFG_HEADER "Header" #define CFG_BOUNCE "Bounce" +#define CFG_ACTION "Action" #define CFG_QUARANTINE "Quarantine" #define CFG_DEBUGFILES "DebugFiles" #define CFG_VIRUSACTION "VirusAction" +#define VAL_BOUNCE "bounce" +#define VAL_DROP "drop" +#define VAL_PASS "pass" + /* ----------------------------------------------------------------------- * GLOBALS */ @@ -208,7 +222,7 @@ int main(int argc, char* argv[]) warnargs = 1; break; - /* Don't daemonize */ + /* Don't daemonize */ case 'd': dbg_level = strtol(optarg, &t, 10); if(*t) /* parse error */ @@ -366,7 +380,7 @@ int cb_check_data(spctx_t* sp) * and transfer the file to it. */ case 0: - if(sp_done_data(sp) == -1) + if(sp_done_data(sp, g_clstate.header) == -1) return -1; break; @@ -380,9 +394,25 @@ int cb_check_data(spctx_t* sp) /* Any special post operation actions on the virus */ virus_action(ctx, virus); - if(sp_fail_data(sp, g_clstate.bounce ? - SMTP_DATAVIRUS : SMTP_DATAVIRUSOK) == -1) - return -1; + switch(g_clstate.action) + { + case ACTION_DROP: + if(sp_fail_data(sp, SMTP_DATAVIRUSOK) == -1) + return -1; + break; + case ACTION_BOUNCE: + if(sp_fail_data(sp, SMTP_DATAVIRUS) == -1) + return -1; + break; + case ACTION_PASS: + if(sp_done_data(sp, VIRUS_HEADER) == -1) + return -1; + break; + default: + ASSERT(0 && "Invalid action"); + break; + } + break; default: @@ -403,11 +433,21 @@ int cb_parse_option(const char* name, const char* value) return 1; } - /* COMPAT: Parse old header option */ + /* COMPAT: Parse old header option */ else if(strcasecmp(CFG_SCANHEADER, name) == 0) { warnx("please use \"Header\" option instead of \"ScanHeader\""); - return sp_parse_option(CFG_HEADER, value); + g_clstate.header = trim_start(value); + if(strlen(g_clstate.header) == 0) + g_clstate.header = NULL; + } + + else if(strcasecmp(CFG_HEADER, name) == 0) + { + g_clstate.header = trim_start(value); + if(strlen(g_clstate.header) == 0) + g_clstate.header = NULL; + return 1; } else if(strcasecmp(CFG_DIRECTORY, name) == 0) @@ -416,17 +456,34 @@ int cb_parse_option(const char* name, const char* value) return 1; } + /* COMPAT: Subsumed by the 'Action' option */ else if(strcasecmp(CFG_BOUNCE, name) == 0) { - if((g_clstate.bounce = strtob(value)) == -1) + int bounce = strtob(value); + if(bounce == -1) errx(2, "invalid value for " CFG_BOUNCE); + if(bounce) + g_clstate.action = ACTION_BOUNCE; + warnx("please use \"Action\" option instead of \"Bounce\""); return 1; } + else if(strcasecmp(CFG_ACTION, name) == 0) + { + if(strcasecmp(VAL_BOUNCE, value) == 0) + g_clstate.action = ACTION_BOUNCE; + else if(strcasecmp(VAL_DROP, value) == 0) + g_clstate.action = ACTION_DROP; + else if(strcasecmp(VAL_PASS, value) == 0) + g_clstate.action = ACTION_PASS; + else + errx(2, "invalid value for " CFG_ACTION); + } + else if(strcasecmp(CFG_QUARANTINE, name) == 0) { if((g_clstate.quarantine = strtob(value)) == -1) - errx(2, "invalid value for " CFG_BOUNCE); + errx(2, "invalid value for " CFG_QUARANTINE); return 1; } -- cgit v1.2.3