'''
Command realscanners for sagator, version 0.5

(c) 2003-2004 Jan ONDREJ (SAL) <ondrejj(at)salstar.sk>

 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.
    
'''

from avlib import *
import re,string

__all__=['cmd','cmd_clamav','cmd_kavscanner','cmd_drweb','cmd_fprot',
         'cmd_trendmicro','cmd_bdc','cmd_uvscan','cmd_vbuster',
         'cmd_mks']

#####################################################################
### exec_any class

class cmd(ascanner):
  '''
  cmd() realscanner, used to scan over command line programs
  
  Usage: cmd(['command','arg1',...],StatusCLEAN,StatusINFECTED,RE)
  
  Where: 'command' is a string, which command to run
         'argX' are command line arguments, as last argument the
           filename is added
         StatusCLEAN may be:
           an array of integers, which defines "clean" exit codes
           an regexp, indication no virus found
         StatusINFECTED may be:
           an array of integers, which defines "virus found" exit codes
         RE is an regular expression string, which can extract virus
           names from scanner output.
  '''
  name='cmd()'
  DIR=('DIR')
  FILES=('FILES')
  def __init__(self,args,clean_status=[0],infected_status=[1],vreg=None):
      self.args=args
      if type(clean_status)==type(''):
        self.clean_status=re.compile(clean_status,re.M)
      else:
        self.clean_status=clean_status
      if type(infected_status)==type(''):
        self.infected_status=re.compile(infected_status,re.M)
      else:
        self.infected_status=infected_status
      if type(vreg)==type(''):
        self.vreg=re.compile(vreg,re.M)
      else:
        self.vreg=vreg
  def check_vname(self,ret):
      reg1=self.vreg.search(string.join(ret,''))
      if reg1:
        return reg1.group(1)
      else:
        return "UnknownVirus"
  def scanfile(self,files,dir=''):
      args=[]
      for arg in self.args:
        if arg==self.DIR:
          args.append(safe.fn(dir))
        elif arg==self.FILES:
          for f in files:
            args.append(safe.fn(f))
        else:
          args.append(arg)
      pf=popen(args)
      pf.tocmd.close()
      ret=pf.readlines()
      debug.echo(6,ret)
      pf.wait()
      pf.fromcmd.close()
      if type(self.infected_status)==type([]):
        if pf.exitstatus in self.infected_status:
          return 1.0,self.check_vname(ret),ret
      else:
        regi=self.infected_status.search(string.join(ret,''))
        if regi:
          return 1.0,self.check_vname(ret),ret
      if type(self.clean_status)==type([]):
        if pf.exitstatus in self.clean_status:
          return 0.0,'',[]
      else:
        regc=self.clean_status.search(string.join(ret,''))
        if regc:
          return 0.0,'',[]
      debug.echo(1,self.name+': command: ',string.join(args),
                 ' ExitStatus: ',str(pf.exitstatus),ret)
      raise ScannerError,self.name+' error'

class cmd_clamav(cmd):
  '''
  cmd_clamav() scanner uses clamscan command from clamav project.
  
  See http://www.clamav.net/ for more info.
  
  Usage: cmd_clamav(['command_name_with_full_path'])
  '''
  name='cmd_clamav()'
  def __init__(self,command='clamscan'):
      cmd.__init__(self,
        [command,'--stdout','--disable-summary','-r',cmd.DIR],
        [0],[1],
        '^.*?: (?!Infected Archive)(.*) FOUND$'
      )

class cmd_kavscanner(cmd):
  '''
  cmd_kavscanner() scanner uses kavscanner command from KasperskyLab
    kavscanner.
  
  See http://www.kaspersky.com/ for more info.
  
  Usage: cmd_kavscanner(['command_name_with_full_path'])
  '''
  name='cmd_kavscanner()'
  def __init__(self,command='/opt/kav/bin/kavscanner'):
      cmd.__init__(self,
        [command,'-i1','-xp',cmd.DIR],
        [0,10,15], [5,20,21,25],
        '(?:CURED|INFECTED|CUREFAILED|WARNING|SUSPICION) (.*)'
      )

class cmd_drweb(cmd):
  '''
  cmd_drweb() scanner uses drweb command from DRWEB antivirus.
  
  See http://www.sald.com/, http://drweb.imshop.de/ for more info.
  
  Usage: cmd_drweb(['command_name_with_full_path'])
  '''
  name='cmd_drweb()'
  def __init__(self,command='/usr/local/drweb/drweb'):
      cmd.__init__(self,
        [command,'-path',cmd.DIR,'-al','-go','-ot','-cn','-upn','-ok-'],
        [0,32], [1,9,33], 
        ' infected (?:with|by)(?: virus)? (.*)$'
      )

class cmd_fprot(cmd):
  '''
  cmd_fprot() scanner uses f-prot command from FRISK F-Prot antivirus.
  
  See http://www.f-prot.com/ for more info.
  
  Usage: cmd_fprot(['command_name_with_full_path'])
  '''
  name='cmd_fprot()'
  def __init__(self,command='f-prot'):
      cmd.__init__(self,
        [command,'-dumb','-archive','-packed',cmd.DIR],
        [0,8], [3,6],
        'Infection: (.+)'
      )

class cmd_trendmicro(cmd):
  '''
  cmd_trendmicro() scanner uses trendmicro command from
    Trend Micro FileScanner.
  
  See http://www.trendmicro.com/ for more info.
  
  Usage: cmd_trendmicro(['command_name_with_full_path'])
  '''
  name='cmd_trendmicro()'
  def __init__(self,command='/etc/iscan/vscan'):
      cmd.__init__(self,
        [command,'-za','-a',cmd.DIR],
        [0], 'Found virus',
        'Found virus (.+) in'
      )

class cmd_bdc(cmd):
  '''
  cmd_bdc() scanner uses bdc command from BitDefender antivirus.
  
  See http://www.bitdefender.com/ for more info.
  
  Usage: cmd_bdc(['command_name_with_full_path'])
  '''
  name='cmd_bdc()'
  def __init__(self,command='bdc'):
      cmd.__init__(self,
        [command,'--all','--arc','--mail',cmd.DIR],
        '^Infected files *:0+(?!\d)',
          '^(?:Infected files|Identified viruses|Suspect files) *:0*[1-9]',
        '(?:suspected|infected): (.*)(?:\033|$)'
      )

class cmd_uvscan(cmd):
  '''
  cmd_uvscan() scanner uses uvscan command from McAfee AntiVirus.
  
  See http://www.mcafee.com/ for more info.
  
  Usage: cmd_uvscan(['command_name_with_full_path'])
  '''
  name='cmd_uvscan()'
  def __init__(self,command='uvscan'):
      cmd.__init__(self,
        [command,'--secure','-rv','--mime','--summary','--noboot','-',cmd.DIR],
        [0], [13],
        ' the (.+) (?:virus|trojan)'
      )

class cmd_vbuster(cmd):
  '''
  cmd_vbuster() scanner uses vbuster command from VirusBuster.
  
  See http://www.virusbuster.hu/en/ for more info.
  
  Usage: cmd_vbuster(['command_name_with_full_path'])
  '''
  name='cmd_vbuster()'
  def __init__(self,command='vbscan'):
      cmd.__init__(self,
        [command,'--action=skip',cmd.DIR],
        [0,1,2,3,4,5], '(?:virus|iworm) found: ',
        "(?:virus|iworm) found: (.+) \.\.\. "
      )

class cmd_mks(cmd):
  '''
  cmd_mks() scanner uses mks antivirus
  
  See http://linux.mks.com.pl/ for more info.
  
  Usage: cmd_mks(['command_name_with_full_path' [,extra_params_array]])
  '''
  name='cmd_mks()'
  def __init__(self,command='mks32',params=[]):
      cmd.__init__(self,
        [command]+params+['--',cmd.FILES],
        [0], [1,2,4],
        "^mks_vir: \t--(?:|destroyed by |scanstring of )virus (.+)"
      )
