diff -urN ../kavmilter-0.91.3.kav5/localtypes.h ../kavmilter-0.91.3/localtypes.h --- ../kavmilter-0.91.3.kav5/localtypes.h 2003-01-23 15:09:41.000000000 +0200 +++ ../kavmilter-0.91.3/localtypes.h 2004-11-17 10:24:18.000000000 +0200 @@ -53,7 +53,9 @@ unsigned _openlog :1; // System log is opened unsigned _pidfile :1; // PID file is presented unsigned _alloc_config :1; // Memory to config file allocated - unsigned :2; // Reserved bits +// unsigned :2; // Reserved bits + unsigned _defer_ok :1; + unsigned _defer_no_mbox_unspool :1; }; struct conn_flags // Connection flag structure @@ -68,11 +70,13 @@ struct mlfiPriv // Mail filter private data storage { char *mlfi_fname; // Temp/save filename + char *mlfi_fname_quarantine; // Quarantine filename char *mlfi_connectfrom; // Connect from: container char *mlfi_mailfrom; // MAIL FROM: container char *mlfi_helofrom; // HELO from: container char *mlfi_rcptto; // First RCPT TO: container FILE *mlfi_fp; // File handle + FILE *mlfi_fp_quarantine; // File handle struct tm *ptm; // Time containver char *_kavreply; // KAV reply buffer struct conn_flags _cflags; // Connection flags @@ -87,7 +91,10 @@ unsigned _isdaemon :1; // Go to daemon mode unsigned _mode_reject :1; // Default mode - REJECT unsigned _mode_discard :1; // Default mode - DISCARD - unsigned :5; // Reserved bits +// unsigned :5; // Reserved bits + unsigned :3; // Reserved bits + unsigned _defer_ok :1; + unsigned _defer_no_mbox_unspool :1; }; struct local_config // Config file description structure @@ -98,6 +105,7 @@ char *KAV_pipe; // Pipe to use with KAV char *pidfile; // PID number keeper char *temp_directory; // Directory to keep mail to check + char *quarantine_directory; // Quarantine directory short int KAV_timeout; // Timeout to connect to KAV short int sendmail_timeout; // Timeout to connect to sendmail short int debug_level; // Level of debugging messages diff -urN ../kavmilter-0.91.3.kav5/mlficatch.c ../kavmilter-0.91.3/mlficatch.c --- ../kavmilter-0.91.3.kav5/mlficatch.c 2004-11-17 10:18:23.000000000 +0200 +++ ../kavmilter-0.91.3/mlficatch.c 2004-11-17 10:45:24.000000000 +0200 @@ -147,7 +147,9 @@ // Clear initial private data structure fields priv->mlfi_fname = NULL; + priv->mlfi_fname_quarantine = NULL; priv->mlfi_fp = NULL; + priv->mlfi_fp_quarantine = NULL; priv->ptm = NULL; priv->headerlines = priv->body_parts = 0; priv->body_length = priv->recipients = 0; @@ -162,6 +164,9 @@ mlfi_cleanup(ctx, PASS_MESSAGE); return SMFIS_TEMPFAIL; } + if (_KAV_milter_config.quarantine_directory) + if ((priv->mlfi_fname_quarantine = (char *) malloc(namelen + 1)) == NULL) + syslog(LOG_ERR,"%s quarantine file name %s, failed",cannot,localid); // Allocate mamory to time repository @@ -183,9 +188,14 @@ snprintf(priv->mlfi_fname,namelen + 1, "%s/Binf_%.2d%.2d%.2d%.2d%.2d%.2d.XXXXXX",_KAV_milter_config.temp_directory, - (int) priv->ptm->tm_mday, (int) priv->ptm->tm_mon + 1, - (int) (priv->ptm->tm_year - 100), (int) priv->ptm->tm_hour, - (int) priv->ptm->tm_min, (int) priv->ptm->tm_sec); + (int) (priv->ptm->tm_year - 100), (int) priv->ptm->tm_mon + 1, (int) priv->ptm->tm_mday, + (int) priv->ptm->tm_hour, (int) priv->ptm->tm_min, (int) priv->ptm->tm_sec); + + if (priv->mlfi_fname_quarantine) + snprintf(priv->mlfi_fname_quarantine,namelen + 1, + "%s/Binf_%.2d%.2d%.2d%.2d%.2d%.2d.XXXXXX",_KAV_milter_config.quarantine_directory, + (int) (priv->ptm->tm_year - 100), (int) priv->ptm->tm_mon + 1, (int) priv->ptm->tm_mday, + (int) priv->ptm->tm_hour, (int) priv->ptm->tm_min, (int) priv->ptm->tm_sec); if (_KAV_milter_config.debug_level > 50) syslog(LOG_WARNING,"constructed temp file is %s",priv->mlfi_fname); @@ -367,9 +377,11 @@ { struct mlfiPriv *priv = MLFIPRIV; char *localid = "(EOM)"; - short int retval, kavretlen = 8192, rejectlen = 256; + short int retval = 0, kavretlen = 8192, rejectlen = 256; char *reject; char *malware_name; + char *kavmilter_skip; + int kavmilter_skip_flag = 0; // Allocate memory to KAV reply @@ -392,7 +404,14 @@ // Check temp file against roaches - retval = _KAV_milter_find_roach(priv->mlfi_fname,priv->_kavreply,&kavretlen); + kavmilter_skip = smfi_getsymval(ctx, "{kavmilter_skip}"); + if (_KAV_milter_config.debug_level > 50) + syslog(LOG_ERR,"KAV: kavmilter_skip: %s",kavmilter_skip); + if ((kavmilter_skip) && (kavmilter_skip[0] != '\0')) { + kavmilter_skip_flag = 1; + syslog(LOG_ERR,"KAV: skip message scanning"); + } else + retval = _KAV_milter_find_roach(priv->mlfi_fname,priv->_kavreply,&kavretlen); // Debug messages @@ -406,6 +425,7 @@ { case 232: // File is suspicious + smfi_addheader(ctx,"X-Kaspersky-Checking","suspicious"); #ifdef _WITH_SUSPICIOUS_ priv->_cflags._infected = OK; @@ -420,7 +440,10 @@ break; #endif case 0: // Normal (non-infected) mail - smfi_addheader(ctx,"X-Kaspersky-Checking","Passed"); + if (kavmilter_skip_flag) + smfi_addheader(ctx,"X-Kaspersky-Checking","Skipped"); + else + smfi_addheader(ctx,"X-Kaspersky-Checking","Passed"); priv->_cflags._infected = NO; mlfi_cleanup(ctx,PASS_MESSAGE); @@ -450,11 +473,20 @@ case 234: // File is corrupted case 241: // Scan error has been detected case ERR: // Miscelanous errors detected - smfi_setreply(ctx,SMTPNOKAV,SMTPADDNOKAV, - "KAV engine inactive or corrupted, please try again later"); - - mlfi_cleanup(ctx,PASS_MESSAGE); - return SMFIS_TEMPFAIL; + priv->_cflags._infected = NO; + if (_KAV_milter_config._idflags._defer_ok) { +// mlfi_cleanup(ctx,PASS_MESSAGE); + mlfi_cleanup(ctx, + (_KAV_milter_config._idflags._defer_no_mbox_unspool ? RECITE_MESSAGE : PASS_MESSAGE)); + return SMFIS_CONTINUE; + } else { + smfi_setreply(ctx,SMTPNOKAV,SMTPADDNOKAV, + "KAV engine inactive or corrupted, please try again later"); +// mlfi_cleanup(ctx,PASS_MESSAGE); + mlfi_cleanup(ctx, + (_KAV_milter_config._idflags._defer_no_mbox_unspool ? RECITE_MESSAGE : PASS_MESSAGE)); + return SMFIS_TEMPFAIL; + } break; @@ -559,13 +591,65 @@ if (recite == RECITE_MESSAGE) { // TODO: here'll be code to extra save message, when need - syslog(LOG_ERR,"Cannot recite message: not implemented yet"); +// syslog(LOG_ERR,"Cannot recite message: not implemented yet"); } // Free allocated filename space if (priv->mlfi_fname != NULL) { + +// Save message to quarantine directory + + if ((priv->_cflags._infected) && (priv->mlfi_fname_quarantine)) { + int mkstemp_res; + int read_count, written_count; + char data_buffer[32768]; + + if (_KAV_milter_config.debug_level > 50) + syslog(LOG_WARNING,"constructed quarantine file is %s",priv->mlfi_fname_quarantine); + +// Open and chmod temp file + + if ((mkstemp_res = mkstemp(priv->mlfi_fname_quarantine)) == ERR ) { + syslog(LOG_ERR,"mkstemp error: %m, filename is %s", priv->mlfi_fname_quarantine); + } else { + + if (chmod(priv->mlfi_fname_quarantine, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP) == ERR) + syslog(LOG_ERR,"chmod error: %m, filename is %s", priv->mlfi_fname_quarantine); + +// Associate file stream with opened descriptor + + if ((priv->mlfi_fp_quarantine = fdopen(mkstemp_res,"w+")) == NULL) { + syslog(LOG_ERR,"fdopen error: %m, filename is %s",priv->mlfi_fname_quarantine); + close(mkstemp_res); + } else { + priv->mlfi_fp = fopen(priv->mlfi_fname, "r"); + if (priv->mlfi_fp == NULL) { + syslog(LOG_ERR,"fopen error: %m, filename is %s",priv->mlfi_fname); + } else { + do { + read_count = fread(data_buffer, 1, sizeof(data_buffer), priv->mlfi_fp); + if (read_count > 0) { + written_count = fwrite(data_buffer, 1, read_count, priv->mlfi_fp_quarantine); + if (written_count != read_count) { + syslog(LOG_ERR,"error while writing to %s",priv->mlfi_fname_quarantine); + break; + }; + }; + } while (read_count > 0); + fclose(priv->mlfi_fp); + } + priv->mlfi_fp = NULL; + } + + if (! fclose(priv->mlfi_fp_quarantine)) + syslog(LOG_ERR,"fclose error: %m, filename is %s",priv->mlfi_fname_quarantine); + } + priv->mlfi_fp_quarantine = NULL; + } + + if (recite != RECITE_MESSAGE) unlink(priv->mlfi_fname); free(priv->mlfi_fname); priv->mlfi_fname = NULL; diff -urN ../kavmilter-0.91.3.kav5/parseconfig.c ../kavmilter-0.91.3/parseconfig.c --- ../kavmilter-0.91.3.kav5/parseconfig.c 2004-11-12 10:02:58.000000000 +0200 +++ ../kavmilter-0.91.3/parseconfig.c 2004-11-17 10:24:18.000000000 +0200 @@ -79,11 +79,14 @@ { "KAVPipe", STDCHAR, NULL, NULL, &_KAV_milter_config.KAV_pipe }, { "PIDFile", STDCHAR, NULL, NULL, &_KAV_milter_config.pidfile }, { "TempDirectory", STDCHAR, NULL, NULL, &_KAV_milter_config.temp_directory }, + { "QuarantineDirectory", STDCHAR, NULL, NULL, &_KAV_milter_config.quarantine_directory }, { "KAVTimeout", STDINT, NULL, NULL, &_KAV_milter_config.KAV_timeout }, { "SendmailTimeout", STDINT, NULL, NULL, &_KAV_milter_config.sendmail_timeout }, { "DebugLevel", STDINT, NULL, NULL, &_KAV_milter_config.debug_level }, { "DaemonMode", STDBOOL, NULL, 0x1, &_KAV_milter_config._idflags }, { "InfectedAction", INFPARAM, NULL, NULL, &_KAV_milter_config._idflags }, + { "DeferOk", STDBOOL, NULL, 0x40, &_KAV_milter_config._idflags }, + { "DeferNoMboxUnspool", STDBOOL, NULL, 0x80, &_KAV_milter_config._idflags }, { "Null", NULL, NULL, NULL, NULL }, };