''' daemon.py - daemon starter service for sagator (c) 2005-2016 Jan ONDREJ (SAL) 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 aglib import * __all__=['chroot_execvp','chroot_execvpe','scand'] class chroot_execvp(service): ''' Execute an external command (or start an daemon). This service can be used to start external daemons used by sagator. Usage: chroot_execvp('daemon_name',args=[],pid_file='') Where: daemon_name is a string, which defines command name args are strings, which defines command line arguments pid_file is an string to filename with PID of started daemon pgrp_file is an string to a process group filename Example: chroot_execvp('/usr/sbin/clamd','-c','/etc/clamav.conf') New in version 0.7.0. ''' name='chroot_execvp()' def __init__(self,command,args=[],pid_file='',pgrp_file=''): self.CMD=[command]+list(args) self.ENV={} self.PID_FILE=pid_file self.PGRP_FILE=pgrp_file def stop(self): if self.PID_FILE: try: pid=int(open(safe.ROOT_PATH+self.PID_FILE).read()) debug.echo(1,'%s: Killing %s pid=%d' % (self.name,self.PID_FILE,pid)) os.kill(pid,signal.SIGTERM) except IOError: debug.echo(1,"%s: Can't open file %s" % (self.name,self.PID_FILE)) except OSError as err: (ec,es) = err.args debug.echo(0,"%s: kill: %s" % (self.name,es)) if self.PGRP_FILE: try: pgrp=int(open(safe.ROOT_PATH+self.PGRP_FILE).read()) debug.echo(1,'%s: Killing %s pgrp=%d' % (self.name,self.PGRP_FILE,pgrp)) os.killpg(pgrp,signal.SIGTERM) except AttributeError: # python 2.2 or later? Try to use kill command. os.system('/bin/kill -TERM -- -%d' % pgrp) except IOError: debug.echo(1,"%s: Can't open file %s" % (self.name,self.PGRP_FILE)) except OSError as err: (ec,es) = err.args debug.echo(0,"%s: killpg: %s" % (self.name,es)) def start(self): self.pid=os.fork() if self.pid==0: debug.echo(1,'%s: %s' % (self.name,self.CMD)) try: os.chroot(safe.ROOT_PATH) if self.ENV: os.execvpe(self.CMD[0],self.CMD,self.ENV) else: os.execvp(self.CMD[0],self.CMD) except OSError as err: (ec,es) = err.args debug.echo(0,"%s: WARNING: Can't start process in chroot: %s" \ % (self.name,es)) return [self.pid] class chroot_execvpe(chroot_execvp): ''' Execute an external command (or start an daemon) and update variables. This service can be used to start external daemons used by sagator. You also can set environment varibles. Usage: chroot_execvpe('daemon_name',args=[],env={}) Where: daemon_name is a string, which defines command name args are strings, which defines command line arguments env is an dictionary of environment variables pid_file is an string to filename with PID of started daemon pgrp_file is an string to a process group filename Example: chroot_execvpe('/usr/sbin/clamd',['-c','/etc/clamav.conf'], {'LANG': 'C'}) New in version 0.7.0. ''' name='chroot_execvpe()' def __init__(self,command,args=[],env={},pid_file='',pgrp_file=''): self.CMD=[command]+list(args) self.ENV=env self.PID_FILE=pid_file self.PGRP_FILE=pgrp_file class scand(chroot_execvpe): ''' Scanner daemon with a preload library ability. This service can be used to scan for viruses with an library, which can be "preloaded" as LD_PRELOAD library. Usage: scand(scanner,ld_preload='', sock='/tmp/scand.sock', pid_file='/var/run/scand.pid', as_root=False) Where: scanner is a scand scanner ld_preload is an library name, which can be preloaded with LD_PRELOAD parameter. By default by library will be preloaded. sock is path to communicate with scanner pid_file is a path to store daemon's pid file. This will be loaded at exit and this process will be killed. as_root is an boolean. Set it to True if you want to run scanners in scand as root. Example: scand(nod2pac(),ld_preload='/usr/lib/libnod32pac.so') or: scand(usrquota('mydomain.sk'),as_root=True) New in version 0.8.0. ''' name='scand()' def __init__(self,scanner,ld_preload='', sock='/tmp/scand.sock', pid_file='/var/run/scand.pid', as_root=False): self.SCANNER=scanner self.CMD=[ os.path.join( os.path.dirname(os.path.realpath(sys.argv[0])), 'scand.py' ) ] if as_root: self.CMD.append('--as-root') if ld_preload: self.ENV={'LD_PRELOAD': ld_preload} else: self.ENV={} self.SOCK=sock self.PID_FILE=pid_file def stop(self): try: pid=int(open(self.PID_FILE).read()) debug.echo(1,'%s: Killing %s pid=%d' % (self.name,self.PID_FILE,pid)) os.kill(pid,signal.SIGTERM) except IOError: debug.echo(1,"%s: Can't open file %s" % (self.name,self.PID_FILE)) except OSError as err: (ec,es) = err.args debug.echo(0,"%s: kill: %s" % (self.name,es)) except ValueError: pass # no process running def start(self): self.pid=os.fork() if self.pid==0: debug.echo(1,'%s: %s %s' % (self.name,self.CMD,self.ENV)) try: os.execvpe(self.CMD[0],self.CMD,self.ENV) except OSError as err: (ec,es) = err.args debug.echo(0,"%s: WARNING: Can't start process: %s" \ % (self.name,es)) os.wait() # wait to daemonize scand return [self.pid]