/*
*
* POP3-Virusscan-Proxy
*
* (C) 2002 by Folke Ashberg <folke@ashberg.de>
*
* $Id: scanner_basic.c,v 1.14 2002/06/11 23:09:16 folke Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <pcre.h>
#include "pop3vscan.h"
struct configuration_t * config;
static int scan(struct proxycontext *p, char ** virname){
int ret;
char * command;
int len;
FILE * scanner;
char line[4096];
pcre * rx;
const char *pcre_error;
int pcre_erroffset;
int offsets[50];
#define VISIZE 1000
char *vi=malloc(VISIZE);
int vipos = 0;
do_log(LOG_DEBUG, "Basic scanner says hello");
if (config->virusregexp){
rx = pcre_compile(config->virusregexp, PCRE_UNGREEDY /* | PCRE_CASELESS */ ,
&pcre_error, &pcre_erroffset, NULL);
if (!rx) {
/* should not happemd, because init1 has already tested and set to NULL on error */
do_log(LOG_WARNING, "Ouch! Can't compile regular expression: %s (char %i)",
pcre_error, pcre_erroffset);
}
} else {
rx=NULL;
}
len=strlen(config->virusscanner) + strlen(p->scanthis) + 1 + strlen(" '' 2>&1");
command=malloc(len+1);
snprintf(command, len, "%s '%s' 2>&1", config->virusscanner, p->scanthis);
do_log(LOG_DEBUG, "popen %s", command);
if ((scanner=popen(command, "r"))==NULL){
do_log(LOG_ALERT, "Can't start scanner '%s' !!!", command);
return SCANNER_RET_ERR;
}
vi[0]='\0';
*virname=vi;
while ((fgets(line, 4095, scanner))!=NULL){
line[strlen(line)-1]='\0';
do_log(LOG_DEBUG, "ScannerLine: '%s'", line);
if (rx){
ret = pcre_exec(rx, NULL, line, strlen(line), 0, 0, offsets, 50);
if (ret > config->virusregexpsub){
len=pcre_copy_substring(line, offsets, ret, config->virusregexpsub, vi+vipos, VISIZE - vipos -4 );
if (len>0) vipos+=len;
vi[vipos]=' '; vipos++;
vi[vipos]='&'; vipos++;
vi[vipos]=' '; vipos++;
}
}
}
ret=pclose(scanner);
free(command);
if (vipos > 3) vi[vipos-3]='\0';
do_log(LOG_DEBUG, "vi : '%s'", vi);
if (rx) pcre_free(rx);
if (!WIFEXITED(ret)){
do_log(LOG_ALERT, "Scanner returned abnormal signal (%i)", ret);
return SCANNER_RET_ERR;
} else
do_log(LOG_DEBUG, "Scanner returned signal %i", WEXITSTATUS(ret));
ret=WEXITSTATUS(ret);
if (ret==config->viruscode)
return SCANNER_RET_VIRUS; /* contains a virus */
if (ret!=0){
do_log(LOG_ALERT,
"WARNING: Your scanner returned neither 0 "
"nor viruscode (%i), but %i",
config->viruscode, ret);
return SCANNER_RET_ERR;
}
do_log(LOG_DEBUG, "Basic scanner says goodbye");
return SCANNER_RET_OK; /* all ok, no virus */
}
static int init1(void){
pcre * rx;
const char *pcre_error;
int pcre_erroffset;
if (strlen(NONULL(config->virusscanner))<1){
do_log(LOG_CRIT, "no scanner was defined. scanning completely disabled");
return -1;
}
if (strlen(NONULL(config->virusregexp))>0){
rx = pcre_compile(config->virusregexp, PCRE_UNGREEDY /* | PCRE_CASELESS */ ,
&pcre_error, &pcre_erroffset, NULL);
if (!rx) {
do_log(LOG_WARNING, "Can't compile regular expression: %s (char %i). Virusnames can't be extracted",
pcre_error, pcre_erroffset);
config->virusregexp=NULL;
} else {
do_log(LOG_DEBUG, "RX compiled succesfully");
pcre_free(rx);
}
} else {
config->virusregexp=NULL;
do_log(LOG_WARNING, "No Regular Expression given! Virusnames can't be extracted");
}
return 0;
}
scanner_t scanner_basic = {
"basic", /* name */
"Basic file invocation scanner", /* description */
&init1, /* init1 (once, afer startup) */
NULL, /* init2 (every connection before first mail) */
&scan, /* scan */
NULL, /* uninit2 */
NULL, /* uninit1 */
1 /* dirscan */
};
syntax highlighted by Code2HTML, v. 0.9.1