
* autologout : script nazi pour tuer les gens en provenance du serveur BDE, s'pô juste. * syncmail : CVS is from the past * wwho : ça a pas l'air furieusement utile, et en plus comme l'encoding est pas déclaré, on peut même pas le lancer.
231 lines
6.8 KiB
Python
Executable file
231 lines
6.8 KiB
Python
Executable file
#! /usr/bin/env python
|
|
import os,string, getopt,time,sys,struct
|
|
""" usage : wwho [date] [-b secs (backwards)] [-p precision (sec/m/h/d)] [-l (last)]
|
|
[-a (all last msgs)] [-f wtmp_file] [-d (debug)]
|
|
DATE (2000 May 22 06:12:08)
|
|
|
|
wfile : idem, except : [-a (access)] FILE
|
|
|
|
ça marche. mais la recherche ds le wtmp pour construire _sessions_ est
|
|
pas du tout optimale -> lent pour un gros wtmp.
|
|
Améliorations à prévoir..
|
|
"""
|
|
optlist, args = getopt.getopt(sys.argv[1:], "adlb:p:f:")
|
|
|
|
date=""
|
|
emul_last=0
|
|
all_last=0
|
|
debug=0
|
|
datesec=0
|
|
precision=2
|
|
utmpF="/var/log/wtmp"
|
|
if len(args)>0 :
|
|
date=args[0]
|
|
print "cmd_line_date : %s" %date
|
|
for i in optlist :
|
|
if i[0] =='-l' : emul_last=1
|
|
if i[0] =='-a' : all_last=1
|
|
if i[0] =='-d' : debug=1
|
|
if i[0] =='-b' : datesec=time.time()-float(i[1])
|
|
if i[0] =='-p' : precision=float(i[1])
|
|
if i[0] =='-f' : utmpF=i[1]
|
|
if debug : print "Option found : "+repr(i)
|
|
|
|
if debug : print " argv[0] : %s" % sys.argv[0]
|
|
|
|
if not datesec :
|
|
if date :
|
|
if string.lower(os.path.basename(sys.argv[0]))=="wfile.py" :
|
|
datesec=os.path.getmtime(date) #modif time
|
|
if all_last : #access time
|
|
datesec=os.stat(date)[7]
|
|
# datesec=os.path.getatime(date) #BUG ! donne mtime !
|
|
all_last=0
|
|
print " Chosen file Time : %s" \
|
|
%time.ctime(datesec)
|
|
else :
|
|
t=time.strptime(date,"%Y %b %d %H:%M:%S")
|
|
#we still have to guess the DaylightSsavingTime flag -> -1
|
|
t2=[ t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],-1]
|
|
datesec = time.mktime(t2)
|
|
else : datesec =time.time()
|
|
|
|
def unpackstr(s, i=0):
|
|
for c in s:
|
|
if c == '\000': break
|
|
i = i + 1
|
|
return s[:i]
|
|
|
|
def msectime(secs,usecs) :
|
|
t=time.localtime(secs)
|
|
s=time.strftime("%d %b %Y %T",t)
|
|
s=s+ ( ".%06d"%usecs )[0:4]
|
|
#s=s+ time.strftime(" %z %Z",time.localtime(secs))
|
|
return s
|
|
|
|
|
|
if debug : print " Date : %s // datesec : "% date + repr(datesec)
|
|
print "Finding who were here at %s, with precision %fs."\
|
|
% (msectime(datesec,0),precision)
|
|
|
|
# the C struct declaration (on AIX 4.2.1)
|
|
# char ut_user[8];
|
|
# char ut_id[14];
|
|
# char ut_line[12];
|
|
# short ut_type;
|
|
# pid_t ut_pid; (int)
|
|
# short ut_exit.e_termination;
|
|
# short ut_exit.e_exit;
|
|
# time_t ut_time; (long)
|
|
# char ut_host[16];
|
|
# the format string to represent that structure
|
|
|
|
""" cf utmp.h , ou man utmp :
|
|
#define UT_LINESIZE 32
|
|
#define UT_NAMESIZE 32
|
|
#define UT_HOSTSIZE 256
|
|
|
|
/* The structure describing the status of a terminated process. This
|
|
type is used in `struct utmp' below. */
|
|
struct exit_status
|
|
{
|
|
short int e_termination; /* Process termination status. */
|
|
short int e_exit; /* Process exit status. */
|
|
};
|
|
|
|
/* The structure describing an entry in the user accounting database. */
|
|
struct utmp
|
|
{
|
|
short int ut_type; /* Type of login. */
|
|
pid_t ut_pid; /* Process ID of login process. */
|
|
char ut_line[UT_LINESIZE=32]; /* Devicename. */
|
|
char ut_id[4]; /* Inittab ID. */
|
|
char ut_user[UT_NAMESIZE=32]; /* Username. */
|
|
char ut_host[UT_HOSTSIZE=256]; /* Hostname for remote login. */
|
|
struct exit_status ut_exit; /* Exit status of a process marked
|
|
as DEAD_PROCESS. */
|
|
long int ut_session; /* Session ID, used for windowing. */
|
|
struct timeval ut_tv; /* Time entry was made. */
|
|
int32_t ut_addr_v6[4]; /* Internet address of remote host. */
|
|
char __unused[20]; /* Reserved for future use. */
|
|
};
|
|
"""
|
|
fmt="hi32s4s32s256shhlii4i20s"
|
|
#fmt="2s4s32s4s32s256s4s8s8s16s20s"
|
|
|
|
""" constants (for ut_type):
|
|
"""
|
|
UT_EMPTY = 0
|
|
UT_RUN_LVL = 1
|
|
UT_BOOT_TIME = 2
|
|
UT_NEW_TIME = 3
|
|
UT_OLD_TIME = 4
|
|
UT_INIT_PROCESS = 5
|
|
UT_LOGIN_PROCESS = 6
|
|
UT_USER_PROCESS = 7
|
|
UT_DEAD_PROCESS = 8
|
|
UT_ACCOUNTING = 9
|
|
record_size = struct.calcsize(fmt)
|
|
# read who is logged on to a UNIX system
|
|
file = open(utmpF, 'rb')
|
|
|
|
sessions={}
|
|
suspects=[]
|
|
|
|
def evdisp(event,zt,rev) :
|
|
( ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ) =event
|
|
if not zt :
|
|
if zt_t: zt=msectime(zt_t,zt_ut)
|
|
else : zt=" -stillNow-"
|
|
if rev :
|
|
t=zt;
|
|
zt=msectime(ut_t,ut_ut)
|
|
else :
|
|
t=msectime(ut_t,ut_ut)
|
|
return '%-8s %-8s %d/%-2d/%-6d %-4s [%-24s]=>[%-24s] (%s)' % \
|
|
(u, l, typ,1,p, id, t, zt, h)
|
|
|
|
def rewind(sessions,n,criter,event) :
|
|
i=n
|
|
( ut_time,ut_utime,zt_time,zt_utime,user,line,host,pid,sessid,type) =event
|
|
i0=1
|
|
while i>i0 :
|
|
i=i-1
|
|
closethis=0
|
|
if criter=='all' :
|
|
closethis=1
|
|
if criter =='line':
|
|
closethis=(sessions[i][5] == line)
|
|
if closethis : i0=i
|
|
|
|
if closethis :
|
|
( ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ)=ev=sessions[i]
|
|
if zt_t !=0 :
|
|
if criter=='all' : continue
|
|
if all_last :
|
|
s="-ERR: "
|
|
s=s+evdisp(ev,"",1)
|
|
else :
|
|
ev=sessions[i]=( ut_t,ut_ut,ut_time,ut_utime,u,l,h,p,id,typ)
|
|
if all_last :
|
|
s="-CLOS "
|
|
s=s+evdisp(ev,"",1)
|
|
if all_last :
|
|
print s
|
|
|
|
block = file.read(record_size)
|
|
n=1
|
|
while block:
|
|
( type,pid,line,id,user,host,exit_1,exit_2,ut_session,ut_time,ut_utime,\
|
|
ip1,ip2,ip3,ip4,unused) = \
|
|
struct.unpack(fmt, block)
|
|
user = unpackstr(user) # remove the null characters
|
|
line = unpackstr(line)
|
|
host = unpackstr(host)
|
|
id = unpackstr(id)
|
|
|
|
event = ( ut_time,ut_utime,0,0,user,line,host,pid,id,type)
|
|
|
|
if type and all_last :
|
|
s='USER: '
|
|
s=s+evdisp(event," -n/a-",0)
|
|
print s
|
|
if user in ['LOGIN','reboot','shutdown'] :
|
|
"Crash & such : everybody logs off.."
|
|
rewind(sessions,n,'all',event)
|
|
|
|
if type == 7 and user :
|
|
sessions[n]=event
|
|
n=n+1
|
|
|
|
if type == 8 :
|
|
rewind(sessions,n,'line',event)
|
|
|
|
block=file.read(record_size)
|
|
file.close()
|
|
|
|
print "Number of entries : %d" %n
|
|
|
|
evs=sessions.values()
|
|
evs.sort(lambda x, y: cmp(y[0]+y[1]*1e-7,x[0]+x[1]*1e-7) )
|
|
i=0
|
|
for ev in evs:
|
|
i=i+1
|
|
(ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ)=ev
|
|
if emul_last : print evdisp(ev,"",0)
|
|
if datesec <360000 :
|
|
# secret feature : giving a near-epoch date does that :
|
|
if precision >0 and zt_t-ut_t < precision : continue
|
|
if precision <0 and zt_t-ut_t > -precision : continue
|
|
else :
|
|
if datesec + precision < ut_t : continue
|
|
if zt_t !=0 and zt_t + precision <datesec : continue
|
|
if emul_last : print "----SUSPECT"
|
|
suspects.append(ev)
|
|
|
|
print "\nAnd Now the \"suspects\" :"
|
|
|
|
suspects.sort(lambda x, y: cmp(x[2]-x[0], y[2]-y[0]))
|
|
for ev in suspects :
|
|
(ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ)=ev
|
|
print evdisp(ev,"",0)
|