#!/usr/bin/python3 ''' sagator's summary reporter (c) 2005-2008,2018-2019 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 __future__ import print_function import sys, re, socket, gzip, email from avlib import * from aglib import find_service, getopt # load config try: from etc import * except ImportError as 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 as err: (msg,opt) = err.args 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 list(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 as 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 list(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': 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: ")