havp/scanners/drwebscanner.cpp
changeset 0 8baf084f58c5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/havp/scanners/drwebscanner.cpp	Wed Jun 18 16:16:36 2014 +0200
@@ -0,0 +1,322 @@
+/***************************************************************************
+                          drwebscanner.cpp  -  description
+                             -------------------
+    begin                : Sa Feb 12 2005
+    copyright            : (C) 2005 by Christian Hilgers
+    email                : christian@hilgers.ag
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "drwebscanner.h"
+
+/* drweb-clients-4.33-sources */
+
+/* -- SCAN_COMMANDS -------------------------------------------------- */
+#define DRWEBD_SCAN_CMD             (1)     /* scan file, buffer or diskfile */
+#define DRWEBD_VERSION_CMD          (2)     /* get daemon version */
+#define DRWEBD_BASEINFO_CMD         (3)     /* get info about viruses bases */
+#define DRWEBD_IDSTRING_CMD         (4)     /* get id-string of daemon */
+#define DRWEBD_SCANPART_CMD         (5)     /* scan part of diskfile */
+#define DRWEBD_SPAMCHECK_CMD        (6)     /* check mail by anti-spam */
+#define DRWEBD_GET_UUID_CMD         (7)     /* get daemon uuid (unique for each customer) */
+
+/* -- SCAN_OPTIONS ---------------------------------------------------- */
+#define DRWEBD_RETURN_VIRUSES       (1<<0)   /* ask daemon return to us viruses names from report */
+#define DRWEBD_RETURN_REPORT        (1<<1)   /* ask daemon return to us return report line */
+#define DRWEBD_RETURN_CODES         (1<<2)   /* ask daemon return to us return codes */
+#define DRWEBD_HEURISTIC_ON         (1<<3)   /* enables heuristic in finding module */
+#define DRWEBD_RULE_FILTER_ON       (1<<5)   /* Unix only: enables FilterRules in daemon */
+#define DRWEBD_INFECTED_CURE        (1<<6)   /* Unix only: try to cure infected files - if fails file decided incureable */ 
+#define DRWEBD_INFECTED_MOVE        (1<<7)   /* move infected files */
+#define DRWEBD_INFECTED_RENAME      (1<<8)   /* just rename infected files */
+#define DRWEBD_INFECTED_DELETE      (1<<9)   /* delete infected files */
+#define DRWEBD_INCURABLE_MOVE       (1<<10)  /* move incureable files */
+#define DRWEBD_INCURABLE_RENAME     (1<<11)  /* just rename incureable files */
+#define DRWEBD_INCURABLE_DELETE     (1<<12)  /* delete incureable files */
+#define DRWEBD_SUSPECTED_MOVE       (1<<13)  /* move suspicious files */
+#define DRWEBD_SUSPECTED_RENAME     (1<<14)  /* just rename suspicious files */
+#define DRWEBD_SUSPECTED_DELETE     (1<<15)  /* delete suspicious files */
+#define DRWEBD_ARCHIVE_MOVE         (1<<16)  /* move archive with infected/suspected files */
+#define DRWEBD_ARCHIVE_RENAME       (1<<17)  /* rename archive with infected/suspected files */
+#define DRWEBD_ARCHIVE_DELETE       (1<<18)  /* delete archive with infected/suspected files */
+#define DRWEBD_IS_MAIL              (1<<19)  /* Unix only: say to daemon that format is "archive MAIL" */
+#define DRWEBD_DONT_CHANGEMAIL      (1<<21)  /* Unix only: say to daemon that mail file cannot be changed */
+#define DRWEBD_RETURN_SHORT_VIRUSES (1<<22)  /* ask daemon return to us pairs of virusnames and infection type {K|M|S} */
+#define DRWEBD_RETURN_FILTER_RULE   (1<<23)  /* ask daemon return to us filtering rule that has been altered */
+#define DRWEBD_HAVE_ENVELOPE        (1<<24)  /* say to daemon that filter will send mail envelope */
+#define DRWEBD_CHECK_ARX            (1<<25)  /* Windows only: say to WinEngine scans into archives (RAR,ZIP etc) */
+#define DRWEBD_USE_TCPNODELAY       (1<<26)  /* use TCP_NODELAY option */
+#define DRWEBD_HAVE_EXTENDED        (1<<31)  /* client knows about extended options */
+
+/* -- SCAN_EXTENDED_OPTIONS ------------------------------------------- */
+#define DRWEBD_EXT_ADWARE_IGNORE    (1<<1)   /* ignore adware */
+#define DRWEBD_EXT_ADWARE_MOVE      (1<<2)   /* move adware */
+#define DRWEBD_EXT_ADWARE_RENAME    (1<<3)   /* rename adware */
+#define DRWEBD_EXT_ADWARE_DELETE    (1<<4)   /* delete adware */
+#define DRWEBD_EXT_DIALER_IGNORE    (1<<5)   /* ignore adware */
+#define DRWEBD_EXT_DIALER_MOVE      (1<<6)   /* move adware */
+#define DRWEBD_EXT_DIALER_RENAME    (1<<7)   /* rename adware */
+#define DRWEBD_EXT_DIALER_DELETE    (1<<8)   /* delete adware */
+#define DRWEBD_EXT_JOKE_IGNORE      (1<<9)   /* ignore adware */
+#define DRWEBD_EXT_JOKE_MOVE        (1<<10)   /* move adware */
+#define DRWEBD_EXT_JOKE_RENAME      (1<<11)   /* rename adware */
+#define DRWEBD_EXT_JOKE_DELETE      (1<<12)   /* delete adware */
+#define DRWEBD_EXT_RISKWARE_IGNORE  (1<<13)   /* ignore adware */
+#define DRWEBD_EXT_RISKWARE_MOVE    (1<<14)   /* move adware */
+#define DRWEBD_EXT_RISKWARE_RENAME  (1<<15)   /* rename adware */
+#define DRWEBD_EXT_RISKWARE_DELETE  (1<<16)   /* delete adware */
+#define DRWEBD_EXT_HACKTOOL_IGNORE  (1<<17)   /* ignore adware */
+#define DRWEBD_EXT_HACKTOOL_MOVE    (1<<18)   /* move adware */
+#define DRWEBD_EXT_HACKTOOL_RENAME  (1<<19)   /* rename adware */
+#define DRWEBD_EXT_HACKTOOL_DELETE  (1<<20)   /* delete adware */
+
+/* -- SCAN_RESULT ----------------------------------------------------- */
+#define DERR_NOERROR                (0)     /*= 0x00000000 */
+#define DERR_READ_ERR               (1<<0)  /*= 0x00000001 */
+#define DERR_WRITE_ERR              (1<<1)  /*= 0x00000002 */               
+#define DERR_NOMEMORY               (1<<2)  /*= 0x00000004 */            
+#define DERR_CRC_ERROR              (1<<3)  /*= 0x00000008 */            
+#define DERR_READSOCKET             (1<<4)  /*= 0x00000010 */             
+#define DERR_KNOWN_VIRUS            (1<<5)  /*= 0x00000020 */            
+#define DERR_UNKNOWN_VIRUS          (1<<6)  /*= 0x00000040 */               
+#define DERR_VIRUS_MODIFICATION     (1<<7)  /*= 0x00000080 */             
+#define DERR_HAVE_CURED             (1<<8)  /*= 0x00000100 */             
+#define DERR_TIMEOUT                (1<<9)  /*= 0x00000200 */              
+#define DERR_SYMLINK                (1<<10) /*= 0x00000400 */            
+#define DERR_NO_REGFILE             (1<<11) /*= 0x00000800 */             
+#define DERR_SKIPPED                (1<<12) /*= 0x00001000 */           
+#define DERR_TOO_BIG                (1<<13) /*= 0x00002000 */            
+#define DERR_TOO_COMPRESSED         (1<<14) /*= 0x00004000 */           
+#define DERR_BAD_CALL               (1<<15) /*= 0x00008000 */            
+#define DERR_EVAL_KEY               (1<<16) /*= 0x00010000 */            
+#define DERR_FILTER_REJECT          (1<<17) /*= 0x00020000 */           
+#define DERR_ARCHIVE_LEVEL          (1<<18) /*= 0x00040000 */
+#define DERR_HAVE_DELETED           (1<<19) /*= 0x00080000 */
+#define DERR_IS_CLEAN               (1<<20) /*= 0x00100000 */
+#define DERR_LICENSE_ERROR          (1<<21) /*= 0x00200000 */
+#define DERR_ADWARE                 (1<<22) /*= 0x00400000 */
+#define DERR_DIALER                 (1<<23) /*= 0x00800000 */
+#define DERR_JOKE                   (1<<24) /*= 0x01000000 */
+#define DERR_RISKWARE               (1<<25) /*= 0x02000000 */
+#define DERR_HACKTOOL               (1<<26) /*= 0x04000000 */
+#define DERR_MASK                   (0x0FFFFFFF)
+#define DERR_NON_DAEMON_ERROR       (~DERR_MASK)
+#define DERR_INFECTED               (DERR_KNOWN_VIRUS | DERR_VIRUS_MODIFICATION)
+#define DERR_SUSPICIOUS             (DERR_UNKNOWN_VIRUS)
+#define DERR_MALWARE                (DERR_ADWARE | DERR_DIALER | DERR_JOKE | DERR_RISKWARE | DERR_HACKTOOL)
+#define DERR_VIRUS_MASK             (DERR_INFECTED | DERR_SUSPICIOUS | DERR_MALWARE)
+#define DERR_SKIP_OBJECT            (DERR_SYMLINK | DERR_NO_REGFILE | DERR_SKIPPED | DERR_CRC_ERROR | DERR_TIMEOUT)
+#define DERR_ARCHIVE_RESTRICTION    (DERR_TOO_BIG | DERR_TOO_COMPRESSED | DERR_ARCHIVE_LEVEL)
+#define DERR_DAEMON_ERROR           (DERR_READ_ERR | DERR_WRITE_ERR | DERR_NOMEMORY | DERR_READSOCKET | DERR_BAD_CALL)
+
+
+bool DrwebScanner::InitDatabase()
+{
+    return true;
+}
+
+
+int DrwebScanner::ReloadDatabase()
+{
+    return 0;
+}
+
+
+string DrwebScanner::Scan( const char *FileName )
+{
+    if ( ConnectScanner() == false )
+    {
+        ScannerAnswer = "2Could not connect to scanner socket";
+        return ScannerAnswer;
+    }
+
+    //Construct command for scanner
+    int scan_cmd = htonl( DRWEBD_SCAN_CMD );
+    int scan_flags = htonl( Opts );
+    int scan_slen = htonl( strlen(FileName) );
+    int scan_null = htonl( 0x0000 );
+
+    if ( Scanner.Send( (const char*)&scan_cmd, sizeof(scan_cmd) ) == false ||
+         Scanner.Send( (const char*)&scan_flags, sizeof(scan_flags) ) == false ||
+         Scanner.Send( (const char*)&scan_slen, sizeof(scan_slen) ) == false ||
+         Scanner.Send( FileName, strlen(FileName) ) == false ||
+         Scanner.Send( (const char*)&scan_null, sizeof(scan_null) ) == false )
+    {
+        Scanner.Close();
+        LogFile::ErrorMessage("Drweb: Could not write command to scanner\n");
+        ScannerAnswer = "2Scanner connection failed";
+        return ScannerAnswer;
+    }
+
+    int scan_rc, scan_vnum;
+    ssize_t read;
+
+    if ( (read = recv( Scanner.sock_fd, &scan_rc, sizeof(scan_rc), 0 )) != sizeof(scan_rc) )
+    {
+        Scanner.Close();
+        LogFile::ErrorMessage("Drweb: Could not read scanner response (rc, read: %d errno: %d)\n", read, errno);
+        ScannerAnswer = "2Could not read scanner response";
+        return ScannerAnswer;
+    }
+    if ( (read = recv( Scanner.sock_fd, &scan_vnum, sizeof(scan_vnum), 0 )) != sizeof(scan_vnum) )
+    {
+        Scanner.Close();
+        LogFile::ErrorMessage("Drweb: Could not read scanner response (vnum, read: %d errno: %d)\n", read, errno);
+        ScannerAnswer = "2Could not read scanner response";
+        return ScannerAnswer;
+    }
+
+    scan_rc = ntohl(scan_rc);
+    scan_vnum = ntohl(scan_vnum);
+
+    if ( scan_rc == DERR_IS_CLEAN ||
+         scan_rc & DERR_ARCHIVE_RESTRICTION ||
+         scan_rc & DERR_SKIP_OBJECT
+         )
+    {
+        Scanner.Close();
+        ScannerAnswer = "0Clean";
+        return ScannerAnswer;
+    }
+
+    char code[512];
+    memset(&code, 0, sizeof(code));
+    snprintf(code, 500, "%d", scan_rc);
+    string Code = code;
+
+    if (scan_rc & DERR_INFECTED || scan_rc & DERR_SUSPICIOUS ||
+        (Params::GetConfigBool("DRWEBMALWARE") && scan_rc & DERR_MALWARE) )
+    {
+        ScannerAnswer = "1unknown (" + Code + ")";
+        string VirusNames = "";
+
+        for (int i=0;i<scan_vnum;i++)
+        {
+            char vname[256];
+            memset(&vname, 0, sizeof(vname));
+
+            if ( (read = recv( Scanner.sock_fd, &scan_slen, sizeof(scan_slen), 0 )) != sizeof(scan_slen) )
+            {
+                Scanner.Close();
+                LogFile::ErrorMessage("Drweb: Could not read scanner response (vnamelen, read: %d errno: %d)\n", read, errno);
+                return ScannerAnswer;
+            }
+
+            scan_slen = ntohl(scan_slen);
+            if ( scan_slen > 250 ) scan_slen = 250;
+
+            if ( (read = recv( Scanner.sock_fd, &vname, scan_slen, 0 )) != scan_slen )
+            {
+                Scanner.Close();
+                LogFile::ErrorMessage("Drweb: Could not read scanner response (vname, read: %d errno: %d)\n", read, errno);
+                return ScannerAnswer;
+            }
+
+            string tmp = vname;
+            if (i==0) { VirusNames = tmp; } else { VirusNames += ", " + tmp; }
+        }
+
+        SearchReplace( VirusNames, "infected with ", "" );
+        if ( VirusNames != "" ) ScannerAnswer = "1" + VirusNames;
+    }
+    else if (scan_rc & DERR_DAEMON_ERROR)
+    {
+        if (scan_rc & DERR_READ_ERR)
+        {
+            ScannerAnswer = "2Daemon could not read tempfile";
+        }
+        else
+        {
+            ScannerAnswer = "2Daemon error (" + Code + ")";
+        }
+    }
+    else
+    {
+        ScannerAnswer = "2Unknown error (" + Code + ")";
+    }
+
+    Scanner.Close();
+    return ScannerAnswer;
+}
+
+
+void DrwebScanner::FreeDatabase()
+{
+}
+
+
+bool DrwebScanner::ConnectScanner()
+{
+    bool SockAnswer;
+
+    if ( UseSocket )
+    {
+        SockAnswer = Scanner.ConnectToSocket( Params::GetConfigString("DRWEBSOCKET"), 1 );
+    }
+    else
+    {
+        SockAnswer = Scanner.ConnectToServer();
+    }
+
+    if ( SockAnswer == false )
+    {
+        //Prevent log flooding, show error only once per minute
+        if ( (LastError == 0) || (LastError + 60 < time(NULL)) )
+        {
+            LogFile::ErrorMessage("Drweb: Could not connect to scanner! Scanner down?\n");
+            LastError = time(NULL);
+        }
+
+        return false;
+    }
+
+    return true;
+}
+
+
+//Constructor
+DrwebScanner::DrwebScanner()
+{
+    ScannerName = "Drweb Socket Scanner";
+    ScannerNameShort = "Drweb";
+
+    LastError = 0;
+
+    if ( Params::GetConfigString("DRWEBSERVER") != "" )
+    {
+        UseSocket = false;
+
+        if ( Scanner.SetDomainAndPort( Params::GetConfigString("DRWEBSERVER"), Params::GetConfigInt("DRWEBPORT") ) == false )
+        {
+            LogFile::ErrorMessage("Drweb: Could not resolve scanner host\n");
+        }
+    }
+    else
+    {
+        UseSocket = true;
+    }
+
+    Opts = DRWEBD_RETURN_VIRUSES;
+
+    if ( Params::GetConfigBool("DRWEBHEURISTIC") == true )
+    {
+        Opts = Opts | DRWEBD_HEURISTIC_ON;
+    }
+
+    ScannerAnswer.reserve(100);
+}
+
+
+//Destructor
+DrwebScanner::~DrwebScanner()
+{
+}
+