/*- * 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; }