Stellarcore.net

Stellarcore.net

I wrote the Python script to work around a problem my Endian Firewall was having with the Frox proxy service. Basically regardless of how you configured frox it would still try to virus scan a file, even if it would then ignore the results. Not a good thing when that file might be 100's of MB.

#!/usr/bin/python

#EFW Header

##################################################################
#clamdscan_wrapper.py - 
#Written by Mike Tremaine   Copyright (C) 2007
#
# 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.

#Todo: 
# Would also be nice to have logging go somewhere useful.
# Would be nice to pass dir or more then one file to be scanned

import getopt, os, sys, signal, subprocess

def usage():
   print "clamdscan_wrapper.py [-h] [--maxsize=NNN] [--allow] [--deny] [--alarm=NNN] -f targetfile"
   print "\n -h       : This list"
   print "--maxsize : Set max file size to be scanned as bytes. [Default 15000000]"
   print "--allow   : Tell scanner to allow files larger then maxsize. [Default]"
   print "--deny    : Tell scanner to deny files larger then maxsize."
   print "--alarm   : Set the alarm time in secs. [Default 180]"
   print "-f        : Not optional. The target file to be scanned."
   #Should I exit unclean?
   sys.exit(1)

def handler(signum, frame):
   #Anything we need to do on timeout do here -mgt
   print "Killing clamdscan process: ", clam_pid
   os.kill(clam_pid, 9)
   #Exit unclean
   sys.exit(1)

def run_command(secs, command):
   global clam_pid
   signal.signal(signal.SIGALRM, handler)
   signal.alarm(secs)
   try:
      p = subprocess.Popen(command, shell=True)
      clam_pid = p.pid	
      (pid,status) = os.waitpid(p.pid, 0)
   finally:
      signal.signal(signal.SIGALRM, handler)
   signal.alarm(0)
   return status

#####################################
#Main
if __name__ == '__main__':

#Defaults
#Set maxsize to scann and what to do with it 0 = pass 1 = virus
   maxsize = 15000000
   maxsize_return = 0
#Give Clamdscan 3 Mins to finish
   alarm_time = 180

#Read commandline args
   try:
      options, values = getopt.getopt(sys.argv[1:], "hf:", ["maxsize=","allow","deny","alarm="])
   except getopt.GetoptError:
      print "Arguments not understood!"
      usage()

#Override Defaults and check args
   for opt in options:
      if opt[0] == "-h":
         usage()
      if opt[0] == "--maxsize":
         #Need verify its a number
         maxsize = opt[1]
      if opt[0] == "-f":
         targetfile = opt[1]      
      if opt[0] == "--allow":
         maxsize_return = 0
      if opt[0] == "--deny":
         maxsize_return = 1
      if opt[0] == "--alarm":
         #Need verify its a number
         alarm_time = opt[1]

#Sanity checks
   if os.path.isfile(targetfile):
      pass
   else:
      print "-f %s is not a regular file" % (targetfile)
      usage()

   try:
      maxsize=int(maxsize)
   except:
      print "--maxsize=%s is not a number please check your command" % (maxsize)
      usage()

   try:
      alarm_time=int(alarm_time)
   except:
      print "--alarm=%s is not a number please check your command" % (alarm_time)
      usage()

#Size check
   if os.path.getsize(targetfile) > maxsize:
      print "%s is larger then %d not scanning" % (targetfile, maxsize)
      sys.exit(maxsize_return)

#Clamdscan commandline
   command = "/usr/bin/clamdscan %s" % (targetfile)

#Call Command with Alarm wrapper -mgt
   rtnval = run_command(alarm_time, command)

#Virus returns 256 which is too big so we will deal in 0 and 1's
   if rtnval > 0:
      sys.exit(1)
   else:
      sys.exit(0)

# vi: shiftwidth=3 tabstop=3 et