diff --git a/aha/aha-worker.py b/aha/aha-worker.py index 3748da67c2c..74f27440c44 100644 --- a/aha/aha-worker.py +++ b/aha/aha-worker.py @@ -17,7 +17,10 @@ class PeriodTaks(): #Define message types FROM_KERNEL = 1 TO_KERNEL = 2 - + + def debug(self,msg): + print "WDBG ",msg + def __init__(self,outqueue,inqueue, timeout,sleeptime, logfile): self.outqueue= outqueue self.inqueue = inqueue @@ -39,54 +42,79 @@ class PeriodTaks(): #Get current date if the files are older than the timeout remove them t0 = int(time.strftime("%s")) files = dircache.listdir(queue) + mlist = [] for file in files: af = queue + os.sep + file + self.debug("found file : %s"%af) s = os.stat(af) t1 = int(s[os.path.stat.ST_CTIME]) delta = t0 - t1 if (delta > self.timeout): + self.debug("%s exceeds threshold"%af) #Old file was found record it if queue == self.outqueue: msg = self.record_message(af,t1,PeriodTaks.FROM_KERNEL) + mlist.append(msg) if queue == self.inqueue: msg = self.record_message(af,t1,PeriodTaks.TO_KERNEL) + mlist.append(msg) #Remove it self.aha.silent_clean(af) - #Return the message for further processing - return msg + return mlist def clean_input_queue(self): try: self.remove_old_msg(self.inqueue) 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: - pid = int(msg['pid'][0]) - ppid = int(msg['ppid'][0]) - type = int(msg['type'][0]) - #Focus on do_execve messages - if (type == 1 ) or (type== 2): - self.ptree.searchTree(pid,ppid) - #Focus on sys_close - if (type == 3): - self.ptree.silent_remove_pid(pid) - except IndexError,e: + if msg: + type = int(msg['type'][0]) + pid = int(msg['pid'][0]) + ppid = int(msg['ppid'][0]) + #sys_execve messages + if (type == 1): + self.debug('Got sys_execve message') + #Is there a new user + file = msg['file'][0] + 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 except ValueError,e: pass - - + except IndexError,e: + pass + def clean_output_queue(self): try: - msg = self.remove_old_msg(self.outqueue) - if msg: - self.maintain_process_tree(msg) - + mlist = self.remove_old_msg(self.outqueue) + #Propagate message list for further processor + return mlist 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 #One log file is handier than for each message a file @@ -106,7 +134,7 @@ class PeriodTaks(): return msg except IOError,e: sys.stderr.write('Failed to record message: %s\n'%filename) - return None + return mlist def usage(exitcode): print """ @@ -148,12 +176,15 @@ try: inqueue = c.get('common','inqueue') outqueue= c.get('common','outqueue') logfile = c.get('worker','logfile') + userlistFile = c.get('worker','exportdir') + os.sep + 'userlist' + p = PeriodTaks(outqueue, inqueue, timeout,sleeptime,logfile) print "Start working ..." while True: p.clean_input_queue() - p.clean_output_queue() + mlist = p.clean_output_queue() + p.maintain_process_tree(mlist,userlistFile) time.sleep(sleeptime) print "Resume ..." diff --git a/aha/ahalib.py b/aha/ahalib.py index 2b2b59dfec4..05d30906d4f 100644 --- a/aha/ahalib.py +++ b/aha/ahalib.py @@ -104,14 +104,29 @@ class ProcessTrees: self.processList = {} self.foundUser = 0 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 # and timestamps etc #TODO annotate SSH_LOGNAME #TODO annotate used terminal def annotateProcessList(self,msg): try: - pid = msg['pid'][0] - ppid = msg['ppid'][0] + pid = int(msg['pid'][0]) + ppid = int(msg['ppid'][0]) + print "Annotate process ",pid + print msg if self.aplist.has_key(pid) == False: #Got a new process, so create a new dictionary for meta data self.aplist[pid] = dict() @@ -125,10 +140,12 @@ class ProcessTrees: if ev.startswith('SSH_CLIENT='): ev = ev.replace('SSH_CLIENT=','') self.aplist[pid]['ssh_client'] = ev - break + print"GROAAAAAAAAAAAAAAAAAAAAARRRRRRRRRRRRRRR: ",pid # Is there a timestamp? if msg.has_key('timestamp'): self.aplist[pid]['timestamp'] = msg['timestamp'] + print "annotated list" + print self.aplist except ValueError,e: pass @@ -182,13 +199,21 @@ class ProcessTrees: for pid in self.userList.keys(): #See if some annotation is found for this pid if self.aplist.has_key(pid): - if self.aplist[pid].has_key('ssh_client'): - f.write("User:%s\n"%self.aplist[pid]['ssh_client']) - 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)) + #Look for SSH variables in the first child process + sshinfo = self.search_ssh_info(pid) + if sshinfo: + f.write(sshinfo) + else: + sys.stderr.write("No SSH information is there\n") + 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() except IOError,e: #TODO implement logging of internal errors