from twisted.internet.protocol import DatagramProtocol
from twisted.internet import wxreactor, task, threads
from buzhug import TS_Base
from PythonCard import model, dialog
import smtplib, time, re, os.path, pickle, syslogConf, sys
import socket
from email.mime.text import MIMEText
#import variables from syslog.conf
configs = pickle.load(open("syslog.conf", 'r'))
import syslogConf
guiList = []
db = TS_Base(configs["dbName"]).create(('srcIP', str), ('hostName', str), ('time', str), ('priority', int), ('facility', str), ('message', str), mode="open")
highQueue = ""
medQueue = ""
class MainWindow(model.Background):
def on_initialize(self, event):
global guiList
global configs
guiList = self.components.MultiColumnList
guiList.SetColumnWidth(0, 130)
guiList.SetColumnWidth(1, 145)
guiList.SetColumnWidth(2, 100)
guiList.SetColumnWidth(3, 50)
guiList.SetColumnWidth(4, 175)
guiList.SetColumnWidth(5, 445)
self.confWindow = model.childWindow(self, syslogConf.ConfWindow)
def on_menuFileConfig_select(self, event):
self.confWindow.visible = True
def on_menuFileClear_select(self, event):
guiList.items = []
def on_menuLogsSave_select(self, event):
wildcard = "LOG file *.log)|*.log|All Files (*.*)|*.*"
result = dialog.saveFileDialog(wildcard=wildcard)
dbPurge(result.paths[0])
def on_menuLogsLoadDatabase_select(self, event):
guiList.items = []
for record in db:
cleaned = []
for item in record:
cleaned.append(item.strip("-").rstrip())
index = guiList.InsertStringItem(0, cleaned[4])
guiList.SetStringItem(index, 1, cleaned[3])
guiList.SetStringItem(index, 2, cleaned[2])
guiList.SetStringItem(index, 3, cleaned[6].split("-")[1])
guiList.SetStringItem(index, 4, cleaned[6])
guiList.SetStringItem(index, 5, cleaned[7].split("\\n")[0])
def on_menuLogsLoadFile_select(self, sevent):
guiList.items = []
wildcard = "LOG file (*.log)|*.log|All Files (*.*)|*.*"
selFile = dialog.openFileDialog(wildcard=wildcard)
if selFile.accepted is True:
logFile = open(selFile.paths[0], "r")
for line in logFile:
sysList = line.split("; ", 5)
guiList.InsertStringItem(0, sysList[2])
guiList.SetStringItem(0, 1, sysList[1])
guiList.SetStringItem(0, 2, sysList[0])
guiList.SetStringItem(0, 3, sysList[3])
guiList.SetStringItem(0, 4, sysList[4])
guiList.SetStringItem(0, 5, sysList[5])
#db.insert(sysList[0], sysList[1], sysList[2], int(sysList[3]), sysList[4], sysList[5])
logFile.close()
def on_menuAboutAbout_select(self, event):
result = dialog.alertDialog(self, "Syslog Server v. 1.2\nDeveloped by William Huba\nc. 2009", "About")
class SyslogInput(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
sysList = data.split(": ")
sysList.append(int(sysList[2].split("-")[1]))
#Reverse DNS lookup runs deferred, call processData when done
defHost = threads.deferToThread(self.getHostName, host)
defHost.addCallback(self.processData, (host, sysList))
def getHostName(self, host):
try:
return socket.gethostbyaddr(host)[0].rstrip(".ciscocomcalo")
except:
return "Unknown"
def processData(self, hostName, (host, sysList)):
global guiList
global highQueue
global medQueue
#add to database
db.insert(host, hostName, sysList[1], sysList[4], sysList[2], sysList[3].rstrip())
#print to list in gui
index = guiList.InsertStringItem(0, sysList[1])
guiList.SetStringItem(index, 1, hostName)
guiList.SetStringItem(index, 2, host)
guiList.SetStringItem(index, 3, str(sysList[4]))
guiList.SetStringItem(index, 4, sysList[2])
guiList.SetStringItem(index, 5, sysList[3])
#notification for high and medium priority
sysMsg = "Time: " + sysList[1] + "\nSourced from: " + hostName + " (" + host + ")\nFacility: " + sysList[2] + "\nMessage: " + sysList[3] + "\n\n\n"
if sysList[4] <= configs["minPriHigh"]:
highQueue += sysMsg
elif sysList[4] <= configs["minPriMed"]:
medQueue += sysMsg
def emailAlert(priority):
global highQueue
global medQueue
if priority == "high" and not highQueue == "":
msg = MIMEText(highQueue)
msg['Subject'] = configs["emailSubj"]
msg['From'] = configs["emailFrom"]
msg['To'] = configs["emailToHigh"]
mailServ = smtplib.SMTP(configs["relay"])
mailServ.sendmail(configs["emailFrom"], [configs["emailToHigh"]], msg.as_string())
mailServ.quit()
highQueue = ""
elif priority == "medium" and medQueue != "":
msg = MIMEText(medQueue)
msg['Subject'] = configs["emailSubj"]
msg['From'] = configs["emailFrom"]
msg['To'] = configs["emailToMed"]
mailServ = smtplib.SMTP(configs["relay"])
mailServ.sendmail(configs["emailFrom"], [configs["emailToMed"]], msg.as_string())
mailServ.quit()
medQueue = ""
else:
return
def dbPurge(fName):
#writes all db entries to a text file and wipes db
file = open(fName, "w")
for record in db:
list = re.split(" [a-zA-Z]+:", str(record).strip("<>"))
del list[0]
file.write("; ".join([i for i in list]))
file.write("\n")
db.delete(record)
file.close()
db.cleanup()
def autoClean():
if time.localtime().tm_wday == configs["cleanDay"] and time.localtime().tm_hour == configs["cleanHour"]:
dbPurge(os.path.join("Logs", time.strftime("%y%b%d.log")))
if __name__ == '__main__':
wxreactor.install()
from twisted.internet import reactor
app = model.Application(MainWindow)
cleanLoop = task.LoopingCall(autoClean)
highEmailLoop = task.LoopingCall(emailAlert, "high")
medEmailLoop = task.LoopingCall(emailAlert, "medium")
reactor.registerWxApp(app)
reactor.listenUDP(514, SyslogInput())
cleanLoop.start(2700.0)
highEmailLoop.start(float(configs["highTime"])*60)
medEmailLoop.start(float(configs["medTime"])*60)
reactor.run()
db.close()