/* * Copyright (C) 2006 Tony Sin(x) '76 * All rights reserved. * */ /* * GNU GENERAL PUBLIC LICENSE * Version 2, June 1991 * * Copyright (C) 1989, 1991 Free Software Foundation, Inc. * 675 Mass Ave, Cambridge, MA 02139, USA * Everyone is permitted to copy and distribute verbatim copies * of this license document, but changing it is not allowed. * * 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 * */ #ifdef HAVE_CONFIG_H #ifndef __main_config_h__ #define __main_config_h__ #include "../config.h" #endif #include #include #include #include #include #include #include #include #ifdef TIME_WITH_SYS_TIME #include #include #else #ifdef HAVE_SYS_TIME_H #include #else #include #endif #endif #endif #include "scan.h" #include "message.h" #include "clam.h" #include "quarantine.h" #include "exception.h" #include "util.h" cScanTask::cScanTask(int loc_sock) { int err; mail_socket = loc_sock; try { if ((err = pthread_attr_init(&thattr))) throw cException(SCAN_TASK_CLASS_NAME,SCAN_TASK_CLASS_NAME,"pthread_attr_init",err); if ((err = pthread_attr_setdetachstate(&thattr,PTHREAD_CREATE_DETACHED))) throw cException(SCAN_TASK_CLASS_NAME,SCAN_TASK_CLASS_NAME,"pthread_attr_setdetachstate",err); if ((err = pthread_create(&thid,&thattr,taskProc,(void *) this))) throw cException(SCAN_TASK_CLASS_NAME,SCAN_TASK_CLASS_NAME,"pthread_create",err); } catch(cException c_e) { syslog(LOG_ERR,"%s",c_e.str); /* signal TERM, do filterctl */ } } cScanTask::~cScanTask() { } void cScanTask::closeSocket() { if (close(mail_socket) == -1) throw cException(SCAN_TASK_CLASS_NAME,SCAN_TASK_CLASS_NAME_D,"close",errno); } int cScanTask::getSocket() { return mail_socket; } void cScanTask::getLine(char *buf) { int i = 0; char c; do { if (read(mail_socket,&c,1) == -1) { c = '\n'; throw cException(SCAN_TASK_CLASS_NAME,"getLine","read",errno); } else if (c != '\n') buf[i++] = c; } while (c != '\n'); buf[i] = '\0'; } void cScanTask::putLine(char *msg, char *vir_sign) { if (write(mail_socket,(const void *) msg,strlen(msg)) == -1) throw cException(SCAN_TASK_CLASS_NAME,"putLine","write(msg)",errno); else if ((vir_sign != NULL) && (write(mail_socket,(const void *) vir_sign,strlen(vir_sign)) == -1)) throw cException(SCAN_TASK_CLASS_NAME,"putLine","write(vir_sign)",errno); else if (write(mail_socket,(const void *) "\r\n",strlen("\r\n")) == -1) throw cException(SCAN_TASK_CLASS_NAME,"putLine","write(EOLN)",errno); } void *cScanTask::taskProc(void *arg) { cScanTask *ptr = (cScanTask *) arg; int len; fd_set locsock_read_set, locsock_write_set, locsock_exc_set; char *buf, *msg_file, *vir_name, *p; cMessage *msg; cQuarantine *qrt; cClamAv *clav; bool infected; struct timespec dummy_wait; buf = new char[BUF_LEN]; msg_file = new char[BUF_LEN]; try { dummy_wait.tv_sec = 0; dummy_wait.tv_nsec = (1000000000L / TICK_LEN) * 5; nanosleep(&dummy_wait,NULL); msg = new cMessage; qrt = new cQuarantine; clav = new cClamAv; FD_ZERO(&locsock_read_set); FD_ZERO(&locsock_write_set); FD_ZERO(&locsock_exc_set); FD_SET(ptr->getSocket(),&locsock_read_set); FD_SET(ptr->getSocket(),&locsock_write_set); FD_SET(ptr->getSocket(),&locsock_exc_set); if (select(ptr->getSocket()+1,&locsock_read_set,NULL,&locsock_exc_set,NULL) == -1) throw cException(SCAN_TASK_CLASS_NAME,"taskProc","select(read)",errno,0); if (FD_ISSET(ptr->getSocket(),&locsock_exc_set)) throw cException(SCAN_TASK_CLASS_NAME,"taskProc","select(exception on read)",0,0); do { ptr->getLine(buf); len = strlen(buf); if (len) { if ((p = strrchr(buf,'/')) == NULL) p = buf; else p++; if (p[0] == 'D') strcpy(msg_file,buf); else msg->loadControlFile(buf); } } while (len); infected = clav->scanFile((const char *) msg_file,(const char **) &vir_name); if (infected) qrt->doQuarantine(msg_file); FD_ZERO(&locsock_exc_set); FD_SET(ptr->getSocket(),&locsock_exc_set); if (select(ptr->getSocket()+1,NULL,&locsock_write_set,&locsock_exc_set,NULL) == -1) throw cException(SCAN_TASK_CLASS_NAME,"taskProc","select(write)",errno); if (FD_ISSET(ptr->getSocket(),&locsock_exc_set)) throw cException(SCAN_TASK_CLASS_NAME,"taskProc","select(exception on write)",0); ptr->putLine((char *) ((infected)? "554 Error: Virus found - Signature is " : "200 OK"),(char *) ((infected)? vir_name : NULL)); ptr->closeSocket(); syslog(((infected)? LOG_ERR : LOG_INFO),"Message %s",((infected)? "infected" : "clean")); if (infected) msg->sendMessage(vir_name); delete msg; delete qrt; delete clav; } catch(cException c_e) { syslog(LOG_ERR,"%s",c_e.str); } delete [] buf; delete [] msg_file; delete ptr; return NULL; }