diff -urN ../kavmilter-0.91.3.kav4/findroach.c ../kavmilter-0.91.3/findroach.c --- ../kavmilter-0.91.3.kav4/findroach.c 2003-01-23 15:09:43.000000000 +0200 +++ ../kavmilter-0.91.3/findroach.c 2004-11-12 10:03:25.000000000 +0200 @@ -53,12 +53,11 @@ { int kavfd; // KAV socket descriptor char *localid = "(KAV check)"; // Local identity - time_t now; // Current time to send to KAV - char *timebuf; // Ctime_r work buffer char *querybuf; // Query buffer for KAV query char *resstr; // Result buffer for KAV response - long uintbuf = 0; // Response code buffer - int exitcode,ret; // KAV exit code + int resstr_size; + int exitcode; // KAV exit code + int result; struct sockaddr_un KAV_address; // Socket to connect to KAV // Create socket to connect to KAV data channel @@ -82,127 +81,101 @@ return ERR; } -// Allocate memory to query buffer, prepare and send query to KAV daemon +// Read KAV greeting - if ((querybuf = (char *) malloc(PATH_MAX + TEMPLENGTH + 26)) == NULL) + if ((_KAV_milter_read_socket(kavfd, reply, (size_t) *pretlen)) == ERR) { - syslog(LOG_ERR,"%s KAV query buffer %s, failed",cannot,localid); + syslog(LOG_ERR,"cannot receive greeting from KAV daemon: %m"); + close(kavfd); return ERR; } - else - timebuf = querybuf + PATH_MAX + TEMPLENGTH; - - now = time(NULL); - sprintf(querybuf,"<0>%.15s:%s",ctime_r(&now,timebuf) + 4,fname); -// Write prepared buffer +// Parse KAV greeting - if (_KAV_milter_write_socket(kavfd, querybuf, strlen(querybuf) + 1) == ERR) + if (reply[0] != '2') { - syslog(LOG_ERR,"cannot send message to KAV daemon: %m"); close(kavfd); + syslog(LOG_ERR,"aveserver is unavailable (Responded: %s): %m", ((reply[0] != 0) ? reply : (char *)"nothing")); return ERR; - } + }; -// Read KAV answer (first stage) +// Allocate memory to query buffer, prepare and send query to KAV daemon - if ((_KAV_milter_read_socket(kavfd,(char *) &uintbuf, 2)) == ERR) + if ((querybuf = (char *) malloc(PATH_MAX + TEMPLENGTH + 16)) == NULL) { - syslog(LOG_ERR,"cannot receive message from KAV daemon: %m"); - close(kavfd); + syslog(LOG_ERR,"%s KAV query buffer %s, failed",cannot,localid); return ERR; } -// Transform first stage answer and think, what can do at next stage + sprintf(querybuf,"SCAN bPQRSTUW %s\r\n",fname); - exitcode = uintbuf & (0xff - 0x30); +// Write prepared buffer - if ((uintbuf & 0x00ff) == 0x3f) //0x3f '?' +// if (_KAV_milter_write_socket(kavfd, querybuf, strlen(querybuf) + 1) == ERR) + if (_KAV_milter_write_socket(kavfd, querybuf, strlen(querybuf)) == ERR) { - syslog(LOG_ERR,"misconfigured KAV daemon, answer is 0x%x",exitcode); + syslog(LOG_ERR,"cannot send query to KAV daemon: %m"); close(kavfd); return ERR; } - if (_KAV_milter_config.debug_level > 50) - syslog(LOG_ERR,"KAV test result: 0x%x, flags: 0x%x", - (int) uintbuf & 0x00ff,(int) uintbuf & 0xff00); - -// If we have a special conditions after receiving answer - - if ((uintbuf & 0xff00) != 0) - { - -// When special condition 2, we should read size of shared memory object -// with disinfected file. We assumed, that KAV don't setup to automatic -// disinfect, and can safely ignore this special condition - - if ((uintbuf & 0x200) != 0) - { - syslog(LOG_ERR,"misconfigured KAV daemon (shm), answer is 0x%x",exitcode); - close(kavfd); - return ERR; - } - -// When special condition 1, we should read size of report, follwed they. -// We assumed, that KAV dont' setup to show Packers, OK, and other important -// but not very high :-) information +// Read KAV answer - if ((uintbuf & 0x100) != 0) - { - -// Read length itself - - if ((ret = _KAV_milter_read_socket(kavfd, - (char *) &uintbuf, sizeof(long))) == ERR) - { - syslog(LOG_ERR,"cannot receive message from KAV daemon: %m"); - close(kavfd); - return ERR; - } - - if (_KAV_milter_config.debug_level > 50) - syslog(LOG_ERR,"KAV reply string length: %d",(int) uintbuf); - -// Store reply length in external parameter to call out - - *pretlen = uintbuf; - reply[0]=0; - -// Read main KAV response, until we won't read zero bytes + exitcode = 0; + result = -1; + resstr = reply; + resstr_size = *pretlen; + while ((result != 0) && (resstr_size > 0)){ + result = _KAV_milter_read_socket(kavfd, resstr, (size_t) resstr_size); + if (result == ERR) { + syslog(LOG_ERR,"cannot receive answer from KAV daemon: %m"); + close(kavfd); + return ERR; + } else { + if (_KAV_milter_config.debug_level > 50) + syslog(LOG_ERR,"KAV test result: %s", + ((resstr[0] != 0) ? resstr : (char *)"nothing")); + if (resstr[0] == '2') { + if (strncmp(resstr, "232", 3) == 0) { + exitcode = 232; // File is suspicious + } else if ((strncmp(resstr, "221", 3) == 0) || (strncmp(resstr, "230", 3) == 0) || (strncmp(resstr, "231", 3) == 0)) { + exitcode = 230; // File is infected + } else if (strncmp(resstr, "234", 3) == 0) { + exitcode = 234; // File is corrupted + } else if (strncmp(resstr, "241", 3) == 0) { + exitcode = 241; // Scan error has been detected + } + break; + } else if ((resstr[0] == '5') || (resstr[0] == '4')) { + syslog(LOG_ERR,"unable to scan file (Responded: %s): %m", + ((resstr[0] != 0) ? resstr : (char *)"nothing")); + result = ERR; + break; + } else if (strncmp(resstr, "322", 3) == 0) { + char *malware_name = resstr+4; + char *p = strchr(resstr+4,' '); + *p = '\0'; + *pretlen = p - reply + 1; + syslog(LOG_ERR,"KAV found a virus: %s", malware_name); + exitcode = 230; // File is infected + }; + resstr += result; + resstr_size -= result; + }; + } - for(resstr = reply;uintbuf > 0;uintbuf -= ret,resstr += ret) - { - ret = _KAV_milter_read_socket(kavfd, resstr, uintbuf); - resstr[ret] = 0; - } +/* + sprintf(querybuf,"quit\r\n"); -// Print raw KAV reply text (debug information) +// Write quit command - if (*pretlen > 0) - if (_KAV_milter_config.debug_level > 50) - syslog(LOG_ERR,"read %d bytes,KAV reply (raw): %s", - (resstr - reply),reply); - } + if (_KAV_milter_write_socket(kavfd, querybuf, strlen(querybuf)) == ERR) + { + syslog(LOG_ERR,"cannot send quit command to KAV daemon: %m"); + close(kavfd); + return ERR; } - -// When we have an extended return code, we are complaining about problems -// in KAV itself - - switch (exitcode & 0xf0) - { - case 8: - syslog(LOG_ERR,"KAV internal error: Integrity failed"); - exitcode = ERR; - break; - - case 4: - syslog(LOG_ERR,"KAV internal error: Bases not found"); - exitcode = ERR; - break; - - default: ; - } +*/ // Close KAV data channel and go back to the future diff -urN ../kavmilter-0.91.3.kav4/mlficatch.c ../kavmilter-0.91.3/mlficatch.c --- ../kavmilter-0.91.3.kav4/mlficatch.c 2003-01-23 15:09:44.000000000 +0200 +++ ../kavmilter-0.91.3/mlficatch.c 2004-11-17 10:18:23.000000000 +0200 @@ -214,6 +214,7 @@ priv->_cflags._tempsave = OK; +/* // Store connection address and HELO host (if available) if (fprintf(priv->mlfi_fp, @@ -223,7 +224,9 @@ mlfi_cleanup(ctx, PASS_MESSAGE); return SMFIS_TEMPFAIL; } +*/ +/* // Store MAIL FROM: indentation. if (fprintf(priv->mlfi_fp, "MAIL FROM: %s\n",priv->mlfi_mailfrom) == EOF) @@ -231,6 +234,7 @@ mlfi_cleanup(ctx, PASS_MESSAGE); return SMFIS_TEMPFAIL; } +*/ // Walk through... @@ -257,6 +261,7 @@ priv->_cflags._firstrcpt = OK; else ; +/* // Log all RCPT TO: tries to message tracing part of message dump if (fprintf(priv->mlfi_fp, "RCPT TO: %s\n",argv[0]) == EOF) @@ -265,6 +270,7 @@ return SMFIS_TEMPFAIL; } else +*/ priv->recipients++; // Walk through... @@ -282,12 +288,14 @@ // If it is a first header, close Message tracing if (!priv->_cflags._firstheader) +/* if (fprintf(priv->mlfi_fp,"----------------\n\n") == EOF) { syslog(LOG_ERR,"fprintf %s failed: %m",localid); return SMFIS_TEMPFAIL; } else +*/ priv->_cflags._firstheader = OK; else ; @@ -360,11 +368,8 @@ struct mlfiPriv *priv = MLFIPRIV; char *localid = "(EOM)"; short int retval, kavretlen = 8192, rejectlen = 256; - char *ispoint,*stppoint; - char *reasons[2] = { "infected", "suspicion" }; - char *notes[2] = { "DANGER", "WARNING" }; - char *thisreason, *thisnote; char *reject; + char *malware_name; // Allocate memory to KAV reply @@ -397,25 +402,23 @@ // Check return code and take appropriate action - switch(retval & 0x0f) + switch(retval) { - case 6: // Infected object was deleted - case 5: // All objects were disinfected - case 4: // Known virus(es) were detected - case 2: // Modified or damaged virus detected + + case 232: // File is suspicious +#ifdef _WITH_SUSPICIOUS_ priv->_cflags._infected = OK; - thisreason = reasons[0]; - thisnote = notes[0]; - break; +// Note about virus infected mail with sender and recipient - case 3: // Suspicious object was found - priv->_cflags._infected = OK; + syslog(LOG_ERR,"suspicion! mail from %s to %s", + priv->mlfi_mailfrom,priv->mlfi_rcptto); - thisreason = reasons[1]; - thisnote = notes[1]; - break; + bzero(reject,rejectlen); + strcpy(reject,"KAV: Message suspicious"); + break; +#endif case 0: // Normal (non-infected) mail smfi_addheader(ctx,"X-Kaspersky-Checking","Passed"); @@ -425,20 +428,30 @@ break; - case 8: // Corrupted files were found - case 7: // KAV files are corrupted - case ERR: // Miscelanous errors detected - smfi_setreply(ctx,SMTPNOKAV,SMTPADDNOKAV, - "KAV engine inactive or corrupted, please try again later"); + case 221: // File was infected and has been cured + case 230: // File is infected + case 231: // File is infected and can't be cured + priv->_cflags._infected = OK; - mlfi_cleanup(ctx,PASS_MESSAGE); - return SMFIS_TEMPFAIL; +// Note about virus infected mail with sender and recipient + + malware_name = priv->_kavreply; + if (strncmp(malware_name, "322-", 4) == 0) malware_name += 4; + syslog(LOG_ERR,"infected! mail from %s to %s %s", + priv->mlfi_mailfrom,priv->mlfi_rcptto,malware_name); + + bzero(reject,rejectlen); + strcpy(reject,"KAV: Message infected: "); + memset(reject + 18, NULL, rejectlen - 18); + strncpy(reject + 18, malware_name, rejectlen - 18); break; - case 1: // I/O error, when process mail by KAV - smfi_setreply(ctx,SMTPIOERR,SMTPADDIOERR, - "I/O error when processing mail occured, check your mail"); + 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; @@ -446,7 +459,7 @@ break; default: // Unknown response code, why? - syslog(LOG_ERR,"unrecognized KAV return code: %d", retval & 0x0f); + syslog(LOG_ERR,"unrecognized KAV return code: %d", retval); mlfi_cleanup(ctx,PASS_MESSAGE); return SMFIS_TEMPFAIL; @@ -456,35 +469,6 @@ if (priv->_cflags._infected) { - bzero(reject,rejectlen); - strcpy(reject,"Message "); - -// Find in message a phrase, beginning from words "infected" or "suspicion" -// to type it in mail log file. Than find end of virus name, when can't do -// this, avoid segfault, use first 16 chars from name -// Bugfix: old daemon versions (reported about 3.135.3) hasn't space after -// virus name, instead they has '\n' immediately. We try to find '\n', when -// couldn't find space. - - if ((ispoint = strstr(priv->_kavreply,thisreason)) == NULL) - ispoint = "(null)"; - else - if ((stppoint = - strchr(ispoint + strlen(thisreason) + 2,' ')) == NULL) - if ((stppoint = - strchr(ispoint + strlen(thisreason) + 2,'\n')) == NULL) - { - if (_KAV_milter_config.debug_level > 50) - syslog(LOG_ERR,"End of virus name not found, avoid crash, use 16 chars"); - stppoint = ispoint + strlen(thisreason) + 18; - } - else ; - else ; - -// Note about virus infected mail with sender and recipient - - syslog(LOG_ERR,"%s! mail from %s to %s %s",thisnote, - priv->mlfi_mailfrom,priv->mlfi_rcptto,ispoint); // Depend on mode, reject this message with reject code or silently discard @@ -496,21 +480,13 @@ else if (_KAV_milter_config._idflags._mode_reject) { - priv->_cflags._infected = OK; - memset(reject + 8, NULL, rejectlen - 8); - strncpy(reject + 8, ispoint, stppoint - ispoint); // Some more debugging messages if (_KAV_milter_config.debug_level > 20) - { syslog(LOG_ERR,"Message is: \"%s %s %s\"", SMTPREJECT, SMTPADDREJECT, reject); - syslog(LOG_ERR,"Message buffer: 0x%x, computed length %d", - (int) &reject, stppoint - ispoint); - } - smfi_setreply(ctx, SMTPREJECT, SMTPADDREJECT, reject); mlfi_cleanup(ctx, PASS_MESSAGE); return SMFIS_REJECT;