Broken worker: First clone of ssh does not include information

2nd maybe too
This commit is contained in:
Gerard Wagener 2010-01-19 13:57:26 +01:00
parent a515f03904
commit 8a57773fcc
2 changed files with 90 additions and 34 deletions

View file

@ -17,7 +17,10 @@ class PeriodTaks():
#Define message types #Define message types
FROM_KERNEL = 1 FROM_KERNEL = 1
TO_KERNEL = 2 TO_KERNEL = 2
def debug(self,msg):
print "WDBG ",msg
def __init__(self,outqueue,inqueue, timeout,sleeptime, logfile): def __init__(self,outqueue,inqueue, timeout,sleeptime, logfile):
self.outqueue= outqueue self.outqueue= outqueue
self.inqueue = inqueue self.inqueue = inqueue
@ -39,54 +42,79 @@ class PeriodTaks():
#Get current date if the files are older than the timeout remove them #Get current date if the files are older than the timeout remove them
t0 = int(time.strftime("%s")) t0 = int(time.strftime("%s"))
files = dircache.listdir(queue) files = dircache.listdir(queue)
mlist = []
for file in files: for file in files:
af = queue + os.sep + file af = queue + os.sep + file
self.debug("found file : %s"%af)
s = os.stat(af) s = os.stat(af)
t1 = int(s[os.path.stat.ST_CTIME]) t1 = int(s[os.path.stat.ST_CTIME])
delta = t0 - t1 delta = t0 - t1
if (delta > self.timeout): if (delta > self.timeout):
self.debug("%s exceeds threshold"%af)
#Old file was found record it #Old file was found record it
if queue == self.outqueue: if queue == self.outqueue:
msg = self.record_message(af,t1,PeriodTaks.FROM_KERNEL) msg = self.record_message(af,t1,PeriodTaks.FROM_KERNEL)
mlist.append(msg)
if queue == self.inqueue: if queue == self.inqueue:
msg = self.record_message(af,t1,PeriodTaks.TO_KERNEL) msg = self.record_message(af,t1,PeriodTaks.TO_KERNEL)
mlist.append(msg)
#Remove it #Remove it
self.aha.silent_clean(af) self.aha.silent_clean(af)
#Return the message for further processing return mlist
return msg
def clean_input_queue(self): def clean_input_queue(self):
try: try:
self.remove_old_msg(self.inqueue) self.remove_old_msg(self.inqueue)
except OSError,e: except OSError,e:
sys.stderr.write(str(e)) sys.stderr.write("%s\n"%str(e))
def maintain_process_tree(self,mlist,exportFile):
if mlist == None:
return
for msg in mlist:
self.handle_msg(msg,exportFile)
def maintain_process_tree(self,msg): def handle_msg(self,msg,exportFile):
try: try:
pid = int(msg['pid'][0]) if msg:
ppid = int(msg['ppid'][0]) type = int(msg['type'][0])
type = int(msg['type'][0]) pid = int(msg['pid'][0])
#Focus on do_execve messages ppid = int(msg['ppid'][0])
if (type == 1 ) or (type== 2): #sys_execve messages
self.ptree.searchTree(pid,ppid) if (type == 1):
#Focus on sys_close self.debug('Got sys_execve message')
if (type == 3): #Is there a new user
self.ptree.silent_remove_pid(pid) file = msg['file'][0]
except IndexError,e: self.debug('Got command: %s'%file)
if file == '/usr/sbin/sshd':
self.debug("New user found %s"%pid)
self.ptree.addUser(pid)
#Check all pids and ppids
if self.ptree.searchTree(pid,ppid):
self.ptree.annotateProcessList(msg)
self.debug("User related command")
self.ptree.exportUserListTxt(exportFile)
else:
self.debug("System related command")
#TODO free annotated list
# Remove dead processes from process tree
if (type == 3):
pid = int(msg['pid'][0])
self.ptree.silent_remove_pid(pid)
except KeyError,e:
pass pass
except ValueError,e: except ValueError,e:
pass pass
except IndexError,e:
pass
def clean_output_queue(self): def clean_output_queue(self):
try: try:
msg = self.remove_old_msg(self.outqueue) mlist = self.remove_old_msg(self.outqueue)
if msg: #Propagate message list for further processor
self.maintain_process_tree(msg) return mlist
except OSError,e: except OSError,e:
sys.stderr.write(str(e)) sys.stderr.write("%s\n"%(str(e)))
#Parse the file an put the information in a log file for later processing #Parse the file an put the information in a log file for later processing
#One log file is handier than for each message a file #One log file is handier than for each message a file
@ -106,7 +134,7 @@ class PeriodTaks():
return msg return msg
except IOError,e: except IOError,e:
sys.stderr.write('Failed to record message: %s\n'%filename) sys.stderr.write('Failed to record message: %s\n'%filename)
return None return mlist
def usage(exitcode): def usage(exitcode):
print """ print """
@ -148,12 +176,15 @@ try:
inqueue = c.get('common','inqueue') inqueue = c.get('common','inqueue')
outqueue= c.get('common','outqueue') outqueue= c.get('common','outqueue')
logfile = c.get('worker','logfile') logfile = c.get('worker','logfile')
userlistFile = c.get('worker','exportdir') + os.sep + 'userlist'
p = PeriodTaks(outqueue, inqueue, timeout,sleeptime,logfile) p = PeriodTaks(outqueue, inqueue, timeout,sleeptime,logfile)
print "Start working ..." print "Start working ..."
while True: while True:
p.clean_input_queue() p.clean_input_queue()
p.clean_output_queue() mlist = p.clean_output_queue()
p.maintain_process_tree(mlist,userlistFile)
time.sleep(sleeptime) time.sleep(sleeptime)
print "Resume ..." print "Resume ..."

View file

@ -104,14 +104,29 @@ class ProcessTrees:
self.processList = {} self.processList = {}
self.foundUser = 0 self.foundUser = 0
self.aplist = {} self.aplist = {}
#This first clone of /usr/sbin/sshd does not has the
#SSH specific environment variables
#FIXME search is only done at first level of the tree
#pid is the ssh clone for this user
def search_ssh_info(self,pid):
for child in self.processList:
if child == pid:
#Found a child of the first priviledged seperated process
if self.aplist[child].has_key('ssh_client'):
return self.aplist[child]['ssh_client']
# Retuns None if ssh related information was not found
return None
# Record additional information about processes like SSH parameters # Record additional information about processes like SSH parameters
# and timestamps etc # and timestamps etc
#TODO annotate SSH_LOGNAME #TODO annotate SSH_LOGNAME
#TODO annotate used terminal #TODO annotate used terminal
def annotateProcessList(self,msg): def annotateProcessList(self,msg):
try: try:
pid = msg['pid'][0] pid = int(msg['pid'][0])
ppid = msg['ppid'][0] ppid = int(msg['ppid'][0])
print "Annotate process ",pid
print msg
if self.aplist.has_key(pid) == False: if self.aplist.has_key(pid) == False:
#Got a new process, so create a new dictionary for meta data #Got a new process, so create a new dictionary for meta data
self.aplist[pid] = dict() self.aplist[pid] = dict()
@ -125,10 +140,12 @@ class ProcessTrees:
if ev.startswith('SSH_CLIENT='): if ev.startswith('SSH_CLIENT='):
ev = ev.replace('SSH_CLIENT=','') ev = ev.replace('SSH_CLIENT=','')
self.aplist[pid]['ssh_client'] = ev self.aplist[pid]['ssh_client'] = ev
break print"GROAAAAAAAAAAAAAAAAAAAAARRRRRRRRRRRRRRR: ",pid
# Is there a timestamp? # Is there a timestamp?
if msg.has_key('timestamp'): if msg.has_key('timestamp'):
self.aplist[pid]['timestamp'] = msg['timestamp'] self.aplist[pid]['timestamp'] = msg['timestamp']
print "annotated list"
print self.aplist
except ValueError,e: except ValueError,e:
pass pass
@ -182,13 +199,21 @@ class ProcessTrees:
for pid in self.userList.keys(): for pid in self.userList.keys():
#See if some annotation is found for this pid #See if some annotation is found for this pid
if self.aplist.has_key(pid): if self.aplist.has_key(pid):
if self.aplist[pid].has_key('ssh_client'): #Look for SSH variables in the first child process
f.write("User:%s\n"%self.aplist[pid]['ssh_client']) sshinfo = self.search_ssh_info(pid)
if self.aplist[pid].has_key('timestamp'): if sshinfo:
#Convert timestamp f.write(sshinfo)
ts = self.aplist[pid]['timestamp'] else:
obj=datetime.datetime.fromtimestamp(float(ts)) sys.stderr.write("No SSH information is there\n")
f.write("Connection date:%s\n\n"%str(obj)) if self.aplist[pid].has_key('timestamp'):
#Convert timestamp
ts = self.aplist[pid]['timestamp']
obj=datetime.datetime.fromtimestamp(float(ts))
f.write("Connection date:%s\n\n"%str(obj))
else:
f.write("No timestamp information is there\n")
else:
sys.stderr.write("No annotations found for pid: %d\n"%pid)
f.close() f.close()
except IOError,e: except IOError,e:
#TODO implement logging of internal errors #TODO implement logging of internal errors