#!/usr/bin/python ''' sagator's summary reporter (c) 2005-2008 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. ''' __pychecker__ = 'unusednames=_ \ maxreturns=20 maxlines=300 \ no-local no-argsused no-stringiter no-abstract no-isliteral \ no-stdlib no-callinit no-badexcept' import sys, re, socket, gzip, urllib, email from StringIO import StringIO from avlib import * from aglib import find_service, getopt # load config try: from etc import * except ImportError,import_es: if str(import_es)[-6:]=="etc": print "ERROR! Config file not found! Exiting now." sys.exit(1) else: raise if __name__ == '__main__': # parse command line debug.set_level(DEBUG_LEVEL) safe.ROOT_PATH=CHROOT TEST_MODE=False SAVE_MARK=True SCAN_BACKWARD=1 try: opts,files=getopt.gnu_getopt(sys.argv[1:],'', ['help','debug=','test','nomark','age=']) except getopt.GetoptError,(msg,opt): print "Error:",msg sys.exit(1) for key,value in opts: if key=='--help': print "SAGATOR's reporter script" print "(c) Jan ONDREJ (SAL) " print "Licensed under GNU GPL." print "" print "Parameters: --help this help" print " --debug=X set debug level to X" print " --test do not send reports, only show info" print " --nomark do not save report marker into config" print " --age=X scan older logs X logs back" sys.exit(0) elif key=='--debug': debug.set_level(int(value)) elif key=='--test': print "Running in test mode." TEST_MODE=True SAVE_MARK=False elif key=='--nomark': SAVE_MARK=False elif key=='--age': SCAN_BACKWARD=int(value) # parse log users={} reg_marker=re.compile('^ *[0-9]+: REPORT-MARKER') reg_report=re.compile( "^ *[0-9]+: REPORT: datetime='(.+)', level='(.+)', virname='(.+)', status='(.+)', scanner='(.*)', size='([0-9]+)', sender='(.+)', recipients='(.+)', sentby_ip='(.*)', qname='(.*)'$" ) LOGFILES=[LOGFILE+x for x in \ ['.%d.gz' % i for i in range(SCAN_BACKWARD,0,-1)]+ ['.%d' % i for i in range(SCAN_BACKWARD,0,-1)]+ ['']] REPORTER_SERVICE=find_service(SRV, 'reporter()') if 'body' not in REPORTER_SERVICE.init_args.keys(): # BODY not updated, try to check if webq() service is configured try: find_service(SRV, 'webq()') # webq() service configured, update BODY REPORTER_SERVICE.BODY += \ ' Review: %s/action.html?qname=%%(QQNAME)s\n' \ % REPORTER_SERVICE.WEBQ_URL except TypeError: pass # webq() service not defined # precompile groups groups=[] for key, value in REPORTER_SERVICE.GROUPS: groups.append([re.compile(key, re.I), value]) for fname in LOGFILES: try: if fname[-3:]=='.gz': f=gzip.open(fname) else: f=open(fname) except IOError,err: if err[0]==2: continue else: raise while True: l=f.readline() if not l: break r=reg_report.search(l) if r: groups_done=[] for user in r.group(8).split(','): # find group group=user for key,value in groups: if key.search(user): group=value break if not group: continue # enpty groups are ignored elif group in groups_done: continue # already processed else: groups_done.append(group) # check include and exclude on user (not on group) if REPORTER_SERVICE.INCLUDE_FX(user): if not REPORTER_SERVICE.EXCLUDE_FX(user): try: users[group].append(r.groups()) except KeyError: users[group]=[r.groups()] elif reg_marker.search(l): users={} f.close() # save marker if len(users)>0: if SAVE_MARK: debug.set_logfile(LOGFILE) debug.echo(1,"REPORT-MARKER: sending reports to %d user(s)" % len(users)) # send reports smtp.SMTP_SERVER=SMTP_SERVER for recipient,data in users.items(): report_vars={ 'REPORT_RECIPIENT': recipient, 'BEGIN': users[recipient][0][0], 'END': users[recipient][-1][0], 'VERSION': SG_VER_REL, 'SHORTVER': version.VERSION, 'SGUSER': USER, 'RANDOM': randomchars(10), 'MYHOSTNAME': socket.gethostname(), 'MYDOMAIN': '.'.join(socket.gethostname().split('.')[1:]), 'MSG_COUNT': len(data) } report_text=StringIO() report_text.write(replace_tmpl(REPORTER_SERVICE.BEGIN,report_vars)) counter=0 for item in data: counter+=1 # read quarantine file for headers headers = {} qf = open(safe.fn(item[9]), 'r') while True: line = qf.readline() if not line: break if line[:4]=='DATA': # message header found headers = email.Parser().parse(qf, True) # headersonly break # create variables report_text.write(replace_tmpl(REPORTER_SERVICE.BODY, { 'DATETIME': item[0], 'LEVEL': item[1], 'VIRNAME': item[2], 'STATUS': item[3], 'SCANNER_NAME': item[4], 'SIZE': item[5], 'SENDER': item[6], 'RECIPIENTS': item[7], 'SUBJECT': headers.get('Subject'), 'SENTBY_IP': item[8], 'QNAME': item[9], 'QQNAME': urllib.quote_plus(item[9]), 'COUNTER': "%3d" % counter } )) report_text.write(replace_tmpl(REPORTER_SERVICE.END,report_vars)) try: if TEST_MODE: debug.echo(7,report_text.getvalue()) else: smtpc().sendmail("<%s@%s>" % (USER,socket.gethostname()), ["<%s>" % recipient], report_text.getvalue()) debug.echo(4,"reporter: Sent report to: %s [%d msgs]" % (recipient,len(data))) except: debug.echo(1,"reporter: Error sending report to: %s [%d msgs]" % (recipient,len(data))) debug.traceback(3,"reporter: ")