/*-
* Copyright (c) 2002 Granch Ltd. All rigts reserved.
*
* All or some portions of this file are derived from material licensed
* to the Grahcn Ltd. and are reproduced herein with the permission of
* Granch Ltd.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE GRANCH LTD. AND THEIR CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author : Rashid N. Achilov E-Mail shelton@granch.ru
*
* @(#)findroach.c 0.91.3 (Granch Ltd.) 23/01/03
*/
/*------------------------------------------------------------------------
Kaspersky Anti-Virus mail filter, based on libmilter API
UNIX FreeBSD 4.6 version
Find a roach in a mail message.
--------------------------------------------------------------------------*/
#include "kavmilter.h"
#include "externals.h"
#include "functions.h"
// Find roaches in mail message (and probaply, find nothing :-) )
short int _KAV_milter_find_roach(char *fname,char *reply,short int *pretlen)
{
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
struct sockaddr_un KAV_address; // Socket to connect to KAV
// Create socket to connect to KAV data channel
bzero((char *) &KAV_address,sizeof(KAV_address));
KAV_address.sun_family = AF_UNIX;
strncpy(KAV_address.sun_path,_KAV_milter_config.KAV_pipe,sizeof(KAV_address.sun_path) - 1);
if ((kavfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
syslog(LOG_ERR,"create socket in %s error: %m",localid);
return ERR;
}
// Connect to KAV data channel
if (connect(kavfd,(struct sockaddr *)(&KAV_address),
sizeof(KAV_address.sun_family) + strlen(KAV_address.sun_path) + 1) != 0)
{
syslog(LOG_ERR,"connect to KAV socket in %s error: %m",localid);
return ERR;
}
// Allocate memory to query buffer, prepare and send query to KAV daemon
if ((querybuf = (char *) malloc(PATH_MAX + TEMPLENGTH + 26)) == NULL)
{
syslog(LOG_ERR,"%s KAV query buffer %s, failed",cannot,localid);
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
if (_KAV_milter_write_socket(kavfd, querybuf, strlen(querybuf) + 1) == ERR)
{
syslog(LOG_ERR,"cannot send message to KAV daemon: %m");
close(kavfd);
return ERR;
}
// Read KAV answer (first stage)
if ((_KAV_milter_read_socket(kavfd,(char *) &uintbuf, 2)) == ERR)
{
syslog(LOG_ERR,"cannot receive message from KAV daemon: %m");
close(kavfd);
return ERR;
}
// Transform first stage answer and think, what can do at next stage
exitcode = uintbuf & (0xff - 0x30);
if ((uintbuf & 0x00ff) == 0x3f) //0x3f '?'
{
syslog(LOG_ERR,"misconfigured KAV daemon, answer is 0x%x",exitcode);
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
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
for(resstr = reply;uintbuf > 0;uintbuf -= ret,resstr += ret)
{
ret = _KAV_milter_read_socket(kavfd, resstr, uintbuf);
resstr[ret] = 0;
}
// Print raw KAV reply text (debug information)
if (*pretlen > 0)
if (_KAV_milter_config.debug_level > 50)
syslog(LOG_ERR,"read %d bytes,KAV reply (raw): %s",
(resstr - reply),reply);
}
}
// 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
close(kavfd);
return exitcode;
}
syntax highlighted by Code2HTML, v. 0.9.1