audit-commands.py (Source)

#!/usr/bin/env python
import sys
import re
import shlex
import pwd
def main ():
    for event in get_events(sys.stdin):
        exec_ = parse_exec(event)
        cwd = parse_cwd(event)
        auid = uid_to_name(parse_auid(event))
        euid = uid_to_name(parse_euid(event))
        event_id = parse_event_id(event)
        
        if exec_:
            args_s = ' '.join(exec_['args'])
            if auid != euid:
                print '%s [%s->%s %s] %s' % (event_id, auid, euid, cwd, args_s)
            else:
                print '%s [%s %s] %s' % (event_id, auid, cwd, args_s)
def parse_event_id (event):
    if event:
        return event[0]['id']
def uid_to_name (uid):
    if uid:
        uid = int(uid)
        try:
            user = pwd.getpwuid(uid)[0]
        except KeyError:
            user = uid
    else:
        user = uid
    return user
def parse_auid (event):
    for log in event:
        if log['type'] == 'SYSCALL':
            return log['data']['auid']
def parse_euid (event):
    for log in event:
        if log['type'] == 'SYSCALL':
            return log['data']['euid']
def parse_cwd (event):
    for log in event:
        if log['type'] == 'CWD':
            return parse_value(log['data']['cwd'])
def parse_exec (event):
    exec_ = {}
    execve_data = {}
    for log in event:
        if log['type'] == 'EXECVE':
            execve_data.update(log['data'])
    if execve_data:
        exec_['args'] = parse_args(execve_data)
    return exec_
def parse_args (data):
    argc = int(data['argc'])
    args = []
    for i in range(argc):
        key = 'a%i' % i
        try:
            value = data[key]
        except KeyError:
            value = '<unknown>'
        else:
            value = parse_value(value)
        args.append(value)
    return args
def parse_value (value):
    if value.startswith('"') and value.endswith('"'):
        return value[1:-1]
    else:
        value = value.decode('hex')
        if '\n' in value:
            return '<multiline>'
        else:
            return value
def get_events (ausearch):
    event = []
    for match in re.finditer(r'type=([A-Z]+) msg=audit\(([0-9\.:/ ]+)\): +(.*?)(?=\n|$)', ausearch.read()):
        type_, event_id, data, = match.groups()
        entry = {'type': type_, 'id': event_id, 'data': parse_data(data)}
        if event and event_id != event[0]['id']:
            yield event
            event = [entry]
        else:
            event.append(entry)
    if event:
        yield event
def parse_data (data_s):
    data = {}
    key_fragments = []
    for kv in shlex.split(data_s, posix=False):
        try:
            key_fragment, value = kv.split('=', 1)
        except ValueError:
            key_fragments.append(kv)
        key_fragments.append(key_fragment)
        key = ' '.join(key_fragments)
        key_fragments = []
        data[key] = value
    return data
main()