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