/***************************************************************************
* *
* Zabit: Content and attachment filter for qmail. *
* Version 0.7.1 *
* http://www.enderunix.org/zabit *
* *
* Copyright (C) 2004 by N.Ersen SISECI *
* siseci@enderunix.org *
* *
* 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 <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include "zabit.h"
#include "scan.h"
#include "log.h"
#include "attach.h"
extern int searchbinary;
extern int scanonly;
extern int donotlog;
int bnstrstr(char *src, char *dest, long ssize, int threshold)
{
long i;
long j;
char c1;
char c2;
long count = 0;
long bssize;
bssize = ssize;
if (bssize < strlen(dest))
return 0;
for (i = 0; i < bssize - strlen(dest) + 1; i++) {
for (j = 0; j < strlen(dest); j++) {
c1 = *(src + i + j);
c2 = *(dest + j);
if (caseinsensitive) {
c1 = toupper(c1);
c2 = toupper(c2);
}
if (c1 != c2) {
i = i + j;
break;
} else {
if (j == (strlen(dest) - 1)) {
i = i + j;
count++;
}
#ifndef DEBUG
/* this makes a bit faster */
if (count >= threshold)
return threshold;
#endif
}
}
}
#ifdef DEBUG
if (count >= threshold)
return count;
#endif
return 0;
}
int scanmailfile(char *fname, char *workingdir)
{
char filename[MAXFILENAMELEN * 2];
if ((strlen(fname) > MAXFILENAMELEN)
|| (strlen(workingdir) > MAXFILENAMELEN)) {
printf("Long File name: %s/%s\n", workingdir, fname);
return ERRORTMP;
}
snprintf(filename, 511, "%s/%s", workingdir, fname);
return scanfile(filename);
}
int scanmaildir(char *dirname, int recursive)
{
DIR *dirp;
struct dirent *entp;
char newdir[512];
int fromfile;
int fromdir;
struct stat statbuf;
#ifdef DEBUG
printf("Next Scan Dir: %s\n", dirname);
#endif
dirp = opendir(dirname);
if (dirp != NULL) {
while ((entp = readdir(dirp)) != NULL) {
if ((strcmp(entp->d_name, "."))
&& (strcmp(entp->d_name, ".."))) {
snprintf(newdir, 511, "%s/%s", dirname,
entp->d_name);
if (stat(newdir, &statbuf)) {
printf("%s: %s\n", strerror(errno),
newdir);
return ERRORTMP;
}
if (S_ISREG(statbuf.st_mode)) {
#ifdef DEBUG
printf("Content Scan: File: %s\n", entp->d_name);
#endif
fromfile =
scanmailfile(entp->d_name, dirname);
if (fromfile)
return SPAMMAIL;
}
if (S_ISDIR(statbuf.st_mode) && recursive) {
#ifdef DEBUG
printf("Content Scan: Dir: %s\n", entp->d_name);
#endif
fromdir =
scanmaildir(newdir, recursive);
if (fromdir)
return SPAMMAIL;
}
}
} /* while */
closedir(dirp);
} else {
printf("Can not open DIR: %s\n", dirname);
return ERRORTMP;
}
return 0;
}
int scanfile(char *filename)
{
char bigbuf[BIGBUFSIZE];
int gecen;
int mailfile;
int i;
long ssize;
long bssize;
struct tm *ptr;
time_t tm;
char timestr[32];
memset(bigbuf, 0, BIGBUFSIZE);
if (checkdisablefilename(filename) == 0) return 0;
if ((mailfile = open(filename, O_RDONLY)) != -1) {
i = read(mailfile, bigbuf, BIGBUFSIZE);
ssize = i;
if (ssize > 0) {
if (searchbinary)
bssize = ssize;
else
bssize = strlen(bigbuf);
for (i = 0; i < entrycount; i++) {
gecen =
bnstrstr(bigbuf, wordlist[i].word, bssize,
wordlist[i].count);
if (gecen >= wordlist[i].count) {
tm = time(NULL);
ptr = localtime(&tm);
snprintf(timestr, 31, "%s", asctime(ptr));
timestr[strlen(timestr) - 1] = 0;
#ifndef DEBUG
snprintf(log_buffer, LOGBUFFERSIZE + 32,
"%s Word '%s' Found. File: %s . Mail Rejected\n",
timestr, wordlist[i].word,
filename);
#else
snprintf(log_buffer, LOGBUFFERSIZE + 32,
"%s Word '%s' Found. File: %s : Count: %d Mail Rejected.\n",
timestr, wordlist[i].word,
filename, gecen);
#endif
printf("%s", log_buffer);
if (donotlog == 0)
write_log(log_buffer);
if (scanonly == 0)
return SPAMMAIL;
else
return 0;
}
}
}
close(mailfile);
} else {
printf("Can't Open: %s\n", filename);
return ERRORTMP;
}
return 0;
}
int scandirfilenames(char *dirname, int recursive)
{
DIR *dirp;
struct dirent *entp;
char newdir[512];
int fromfile;
int fromdir;
struct stat statbuf;
#ifdef DEBUG
printf("Next Scan Dir: %s\n", dirname);
#endif
dirp = opendir(dirname);
if (dirp != NULL) {
while ((entp = readdir(dirp)) != NULL) {
if ((strcmp(entp->d_name, "."))
&& (strcmp(entp->d_name, ".."))) {
snprintf(newdir, 511, "%s/%s", dirname,
entp->d_name);
if (stat(newdir, &statbuf)) {
printf("%s: %s\n", strerror(errno), newdir);
return ERRORTMP;
}
if (S_ISREG(statbuf.st_mode)) {
#ifdef DEBUG
printf("File Name Scan: File: %s\n", entp->d_name);
#endif
fromfile = checkfilename(entp->d_name);
if (fromfile)
return SPAMMAIL;
}
if (S_ISDIR(statbuf.st_mode) && recursive) {
#ifdef DEBUG
printf("File Name Scan: Dir: %s\n", entp->d_name);
#endif
fromdir = scandirfilenames(newdir, recursive);
if (fromdir)
return SPAMMAIL;
}
}
} /* while */
closedir(dirp);
} else {
printf("Can not open DIR: %s\n", dirname);
return ERRORTMP;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1