113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# Copyright (C) 2006 Red Hat
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# see file 'COPYING' for use and warranty information
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# This program is free software; you can redistribute it and/or
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# modify it under the terms of the GNU General Public License as
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# published by the Free Software Foundation; version 2 only
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# This program is distributed in the hope that it will be useful,
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# but WITHOUT ANY WARRANTY; without even the implied warranty of
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# GNU General Public License for more details.
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# You should have received a copy of the GNU General Public License
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# along with this program; if not, write to the Free Software
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleimport re
21df45dcdf3db2d02930bbd095f6e9bc4f3eafdf3fDan Walshimport sys
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23fd00e882c4886124008cf473e4a9af1dd7a93b68Robert Kuskafrom . import refpolicy
24fd00e882c4886124008cf473e4a9af1dd7a93b68Robert Kuskafrom . import access
2560956ac7ec5ad9cdf3eb3e338f7a61511cae73b3Robert Kuskafrom . import util
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# Convenience functions
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2803cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walshdef get_audit_boot_msgs():
2903cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    """Obtain all of the avc and policy load messages from the audit
3003cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    log. This function uses ausearch and requires that the current
3103cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    process have sufficient rights to run ausearch.
3203cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh
3303cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    Returns:
3403cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh       string contain all of the audit messages returned by ausearch.
3503cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    """
3603cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    import subprocess
3703cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    import time
3803cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    fd=open("/proc/uptime", "r")
3903cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    off=float(fd.read().split()[0])
4003cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    fd.close
4103cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    s = time.localtime(time.time() - off)
42a2a50eaaec750af192d4a8b37f5022242e30f06erhatdan    bootdate = time.strftime("%x", s)
4303cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    boottime = time.strftime("%X", s)
4403cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    output = subprocess.Popen(["/sbin/ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START,SELINUX_ERR", "-ts", bootdate, boottime],
4503cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh                              stdout=subprocess.PIPE).communicate()[0]
4660956ac7ec5ad9cdf3eb3e338f7a61511cae73b3Robert Kuska    if util.PY3:
4760956ac7ec5ad9cdf3eb3e338f7a61511cae73b3Robert Kuska        output = util.decode_input(output)
4803cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh    return output
4903cd8c2d47eb5ad3d7242ac1a0c71adc1e16ad89Daniel J Walsh
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindledef get_audit_msgs():
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Obtain all of the avc and policy load messages from the audit
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    log. This function uses ausearch and requires that the current
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    process have sufficient rights to run ausearch.
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    Returns:
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       string contain all of the audit messages returned by ausearch.
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    import subprocess
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    output = subprocess.Popen(["/sbin/ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START,SELINUX_ERR"],
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                              stdout=subprocess.PIPE).communicate()[0]
6160956ac7ec5ad9cdf3eb3e338f7a61511cae73b3Robert Kuska    if util.PY3:
6260956ac7ec5ad9cdf3eb3e338f7a61511cae73b3Robert Kuska        output = util.decode_input(output)
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    return output
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindledef get_dmesg_msgs():
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Obtain all of the avc and policy load messages from /bin/dmesg.
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    Returns:
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       string contain all of the audit messages returned by dmesg.
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    import subprocess
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    output = subprocess.Popen(["/bin/dmesg"],
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                              stdout=subprocess.PIPE).communicate()[0]
7460956ac7ec5ad9cdf3eb3e338f7a61511cae73b3Robert Kuska    if util.PY3:
7560956ac7ec5ad9cdf3eb3e338f7a61511cae73b3Robert Kuska        output = util.decode_input(output)
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    return output
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# Classes representing audit messages
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass AuditMessage:
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Base class for all objects representing audit messages.
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    AuditMessage is a base class for all audit messages and only
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    provides storage for the raw message (as a string) and a
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    parsing function that does nothing.
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, message):
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.message = message
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.header = ""
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def from_split_string(self, recs):
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """Parse a string that has been split into records by space into
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        an audit message.
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        This method should be overridden by subclasses. Error reporting
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        should be done by raise ValueError exceptions.
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for msg in recs:
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            fields = msg.split("=")
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if len(fields) != 2:
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                if msg[:6] == "audit(":
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    self.header = msg
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    return
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                else:
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    continue
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if fields[0] == "msg":
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.header = fields[1]
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                return
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass InvalidMessage(AuditMessage):
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Class representing invalid audit messages. This is used to differentiate
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    between audit messages that aren't recognized (that should return None from
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    the audit message parser) and a message that is recognized but is malformed
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    in some way.
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, message):
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.__init__(self, message)
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass PathMessage(AuditMessage):
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Class representing a path message"""
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, message):
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.__init__(self, message)
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.path = ""
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def from_split_string(self, recs):
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.from_split_string(self, recs)
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for msg in recs:
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            fields = msg.split("=")
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if len(fields) != 2:
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                continue
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if fields[0] == "path":
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.path = fields[1][1:-1]
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                return
1375c3211bccad45be0f546dbf976200142d1e4959dEric Parisimport selinux.audit2why as audit2why
1385c3211bccad45be0f546dbf976200142d1e4959dEric Paris
1395c3211bccad45be0f546dbf976200142d1e4959dEric Parisavcdict = {}
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass AVCMessage(AuditMessage):
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """AVC message representing an access denial or granted message.
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    This is a very basic class and does not represent all possible fields
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    in an avc message. Currently the fields are:
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       scontext - context for the source (process) that generated the message
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       tcontext - context for the target
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       tclass - object class for the target (only one)
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       comm - the process name
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       exe - the on-disc binary
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       path - the path of the target
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       access - list of accesses that were allowed or denied
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       denial - boolean indicating whether this was a denial (True) or granted
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle          (False) message.
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    An example audit message generated from the audit daemon looks like (line breaks
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    added):
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       'type=AVC msg=audit(1155568085.407:10877): avc:  denied  { search } for
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       pid=677 comm="python" name="modules" dev=dm-0 ino=13716388
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       scontext=user_u:system_r:setroubleshootd_t:s0
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       tcontext=system_u:object_r:modules_object_t:s0 tclass=dir'
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    An example audit message stored in syslog (not processed by the audit daemon - line
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    breaks added):
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       'Sep 12 08:26:43 dhcp83-5 kernel: audit(1158064002.046:4): avc:  denied  { read }
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       for  pid=2 496 comm="bluez-pin" name=".gdm1K3IFT" dev=dm-0 ino=3601333
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       scontext=user_u:system_r:bluetooth_helper_t:s0-s0:c0
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       tcontext=system_u:object_r:xdm_tmp_t:s0 tclass=file
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, message):
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.__init__(self, message)
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.scontext = refpolicy.SecurityContext()
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.tcontext = refpolicy.SecurityContext()
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.tclass = ""
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.comm = ""
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.exe = ""
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.path = ""
178077e8635173ae51576ee6c27eb7c6d12243294e9Dan Walsh        self.name = ""
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.accesses = []
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.denial = True
1815c3211bccad45be0f546dbf976200142d1e4959dEric Paris        self.type = audit2why.TERULE
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __parse_access(self, recs, start):
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # This is kind of sucky - the access that is in a space separated
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # list like '{ read write }'. This doesn't fit particularly well with splitting
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # the string on spaces. This function takes the list of recs and a starting
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # position one beyond the open brace. It then adds the accesses until it finds
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # the close brace or the end of the list (which is an error if reached without
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # seeing a close brace).
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        found_close = False
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        i = start
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if i == (len(recs) - 1):
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            raise ValueError("AVC message in invalid format [%s]\n" % self.message)
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        while i < len(recs):
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if recs[i] == "}":
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found_close = True
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                break
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.accesses.append(recs[i])
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            i = i + 1
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if not found_close:
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            raise ValueError("AVC message in invalid format [%s]\n" % self.message)
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        return i + 1
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def from_split_string(self, recs):
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.from_split_string(self, recs)
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # FUTURE - fully parse avc messages and store all possible fields
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # Required fields
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        found_src = False
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        found_tgt = False
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        found_class = False
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        found_access = False
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for i in range(len(recs)):
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if recs[i] == "{":
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                i = self.__parse_access(recs, i + 1)
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found_access = True
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                continue
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif recs[i] == "granted":
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.denial = False
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            fields = recs[i].split("=")
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if len(fields) != 2:
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                continue
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if fields[0] == "scontext":
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.scontext = refpolicy.SecurityContext(fields[1])
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found_src = True
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif fields[0] == "tcontext":
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.tcontext = refpolicy.SecurityContext(fields[1])
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found_tgt = True
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif fields[0] == "tclass":
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.tclass = fields[1]
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found_class = True
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif fields[0] == "comm":
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.comm = fields[1][1:-1]
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif fields[0] == "exe":
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.exe = fields[1][1:-1]
238077e8635173ae51576ee6c27eb7c6d12243294e9Dan Walsh            elif fields[0] == "name":
239077e8635173ae51576ee6c27eb7c6d12243294e9Dan Walsh                self.name = fields[1][1:-1]
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if not found_src or not found_tgt or not found_class or not found_access:
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            raise ValueError("AVC message in invalid format [%s]\n" % self.message)
2435c3211bccad45be0f546dbf976200142d1e4959dEric Paris        self.analyze()
2445c3211bccad45be0f546dbf976200142d1e4959dEric Paris
2455c3211bccad45be0f546dbf976200142d1e4959dEric Paris    def analyze(self):
2465c3211bccad45be0f546dbf976200142d1e4959dEric Paris        tcontext = self.tcontext.to_string()
2475c3211bccad45be0f546dbf976200142d1e4959dEric Paris        scontext = self.scontext.to_string()
2485c3211bccad45be0f546dbf976200142d1e4959dEric Paris        access_tuple = tuple( self.accesses)
249628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris        self.data = []
250628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris
2515c3211bccad45be0f546dbf976200142d1e4959dEric Paris        if (scontext, tcontext, self.tclass, access_tuple) in avcdict.keys():
252628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris            self.type, self.data = avcdict[(scontext, tcontext, self.tclass, access_tuple)]
2535c3211bccad45be0f546dbf976200142d1e4959dEric Paris        else:
254628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris            self.type, self.data = audit2why.analyze(scontext, tcontext, self.tclass, self.accesses);
2555c3211bccad45be0f546dbf976200142d1e4959dEric Paris            if self.type == audit2why.NOPOLICY:
2565c3211bccad45be0f546dbf976200142d1e4959dEric Paris                self.type = audit2why.TERULE
2575c3211bccad45be0f546dbf976200142d1e4959dEric Paris            if self.type == audit2why.BADTCON:
2585c3211bccad45be0f546dbf976200142d1e4959dEric Paris                raise ValueError("Invalid Target Context %s\n" % tcontext)
2595c3211bccad45be0f546dbf976200142d1e4959dEric Paris            if self.type == audit2why.BADSCON:
2605c3211bccad45be0f546dbf976200142d1e4959dEric Paris                raise ValueError("Invalid Source Context %s\n" % scontext)
2615c3211bccad45be0f546dbf976200142d1e4959dEric Paris            if self.type == audit2why.BADSCON:
2625c3211bccad45be0f546dbf976200142d1e4959dEric Paris                raise ValueError("Invalid Type Class %s\n" % self.tclass)
2635c3211bccad45be0f546dbf976200142d1e4959dEric Paris            if self.type == audit2why.BADPERM:
2645c3211bccad45be0f546dbf976200142d1e4959dEric Paris                raise ValueError("Invalid permission %s\n" % " ".join(self.accesses))
2655c3211bccad45be0f546dbf976200142d1e4959dEric Paris            if self.type == audit2why.BADCOMPUTE:
2665c3211bccad45be0f546dbf976200142d1e4959dEric Paris                raise ValueError("Error during access vector computation")
2675c3211bccad45be0f546dbf976200142d1e4959dEric Paris
268628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris            if self.type == audit2why.CONSTRAINT:
2694a674abd341bf6847d5f245d57b42f4fd0786123Dan Walsh                self.data = [ self.data ]
270628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris                if self.scontext.user != self.tcontext.user:
2714a674abd341bf6847d5f245d57b42f4fd0786123Dan Walsh                    self.data.append(("user (%s)" % self.scontext.user, 'user (%s)' % self.tcontext.user))
272628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris                if self.scontext.role != self.tcontext.role and self.tcontext.role != "object_r":
2734a674abd341bf6847d5f245d57b42f4fd0786123Dan Walsh                    self.data.append(("role (%s)" % self.scontext.role, 'role (%s)' % self.tcontext.role))
274628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris                if self.scontext.level != self.tcontext.level:
2754a674abd341bf6847d5f245d57b42f4fd0786123Dan Walsh                    self.data.append(("level (%s)" % self.scontext.level, 'level (%s)' % self.tcontext.level))
276628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris
277628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris            avcdict[(scontext, tcontext, self.tclass, access_tuple)] = (self.type, self.data)
2785c3211bccad45be0f546dbf976200142d1e4959dEric Paris
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass PolicyLoadMessage(AuditMessage):
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Audit message indicating that the policy was reloaded."""
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, message):
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.__init__(self, message)
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass DaemonStartMessage(AuditMessage):
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Audit message indicating that a daemon was started."""
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, message):
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.__init__(self, message)
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.auditd = False
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def from_split_string(self, recs):
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.from_split_string(self, recs)
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if "auditd" in recs:
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.auditd = True
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass ComputeSidMessage(AuditMessage):
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Audit message indicating that a sid was not valid.
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    Compute sid messages are generated on attempting to create a security
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    context that is not valid. Security contexts are invalid if the role is
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    not authorized for the user or the type is not authorized for the role.
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    This class does not store all of the fields from the compute sid message -
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    just the type and role.
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, message):
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.__init__(self, message)
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.invalid_context = refpolicy.SecurityContext()
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.scontext = refpolicy.SecurityContext()
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.tcontext = refpolicy.SecurityContext()
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.tclass = ""
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def from_split_string(self, recs):
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        AuditMessage.from_split_string(self, recs)
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if len(recs) < 10:
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            raise ValueError("Split string does not represent a valid compute sid message")
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        try:
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.invalid_context = refpolicy.SecurityContext(recs[5])
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.scontext = refpolicy.SecurityContext(recs[7].split("=")[1])
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.tcontext = refpolicy.SecurityContext(recs[8].split("=")[1])
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.tclass = recs[9].split("=")[1]
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        except:
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            raise ValueError("Split string does not represent a valid compute sid message")
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def output(self):
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        return "role %s types %s;\n" % (self.role, self.type)
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle# Parser for audit messages
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass AuditParser:
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """Parser for audit messages.
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    This class parses audit messages and stores them according to their message
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    type. This is not a general purpose audit message parser - it only extracts
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    selinux related messages.
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    Each audit messages are stored in one of four lists:
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       avc_msgs - avc denial or granted messages. Messages are stored in
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle          AVCMessage objects.
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       comput_sid_messages - invalid sid messages. Messages are stored in
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle          ComputSidMessage objects.
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       invalid_msgs - selinux related messages that are not valid. Messages
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle          are stored in InvalidMessageObjects.
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle       policy_load_messages - policy load messages. Messages are stored in
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle          PolicyLoadMessage objects.
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    These lists will be reset when a policy load message is seen if
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    AuditParser.last_load_only is set to true. It is assumed that messages
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    are fed to the parser in chronological order - time stamps are not
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    parsed.
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    """
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, last_load_only=False):
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.__initialize()
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.last_load_only = last_load_only
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __initialize(self):
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.avc_msgs = []
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.compute_sid_msgs = []
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.invalid_msgs = []
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.policy_load_msgs = []
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.path_msgs = []
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.by_header = { }
363df45dcdf3db2d02930bbd095f6e9bc4f3eafdf3fDan Walsh        self.check_input_file = False
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # Low-level parsing function - tries to determine if this audit
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # message is an SELinux related message and then parses it into
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # the appropriate AuditMessage subclass. This function deliberately
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # does not impose policy (e.g., on policy load message) or store
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # messages to make as simple and reusable as possible.
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    #
37113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # Return values:
37213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    #   None - no recognized audit message found in this line
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    #
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    #   InvalidMessage - a recognized but invalid message was found.
37513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    #
37613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    #   AuditMessage (or subclass) - object representing a parsed
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    #      and valid audit message.
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __parse_line(self, line):
379ed51e23f159a6af69d0b1ed89b1e237ed180aa21Vit Mojzis        # strip("\x1c\x1d\x1e\x85") is only needed for python2
380ed51e23f159a6af69d0b1ed89b1e237ed180aa21Vit Mojzis        # since str.split() in python3 already does this
381ed51e23f159a6af69d0b1ed89b1e237ed180aa21Vit Mojzis        rec = [x.strip("\x1c\x1d\x1e\x85") for x in line.split()]
38213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for i in rec:
38313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            found = False
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if i == "avc:" or i == "message=avc:" or i == "msg='avc:":
38513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                msg = AVCMessage(line)
38613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found = True
38713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif i == "security_compute_sid:":
38813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                msg = ComputeSidMessage(line)
38913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found = True
390a3ccf607a2137a2bdfd21b21502803d02a1ea530Stephen Smalley            elif i == "type=MAC_POLICY_LOAD" or i == "type=1403":
39113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                msg = PolicyLoadMessage(line)
39213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found = True
39313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif i == "type=AVC_PATH":
39413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                msg = PathMessage(line)
39513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found = True
39613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            elif i == "type=DAEMON_START":
39713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                msg = DaemonStartMessage(list)
39813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                found = True
39913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if found:
401df45dcdf3db2d02930bbd095f6e9bc4f3eafdf3fDan Walsh                self.check_input_file = True
40213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                try:
40313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    msg.from_split_string(rec)
40413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                except ValueError:
40513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    msg = InvalidMessage(line)
40613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                return msg
40713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        return None
40813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # Higher-level parse function - take a line, parse it into an
41013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # AuditMessage object, and store it in the appropriate list.
41113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # This function will optionally reset all of the lists when
41213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # it sees a load policy message depending on the value of
41313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # self.last_load_only.
41413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __parse(self, line):
41513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        msg = self.__parse_line(line)
41613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if msg is None:
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            return
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # Append to the correct list
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if isinstance(msg, PolicyLoadMessage):
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if self.last_load_only:
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.__initialize()
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        elif isinstance(msg, DaemonStartMessage):
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            # We initialize every time the auditd is started. This
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            # is less than ideal, but unfortunately it is the only
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            # way to catch reboots since the initial policy load
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            # by init is not stored in the audit log.
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if msg.auditd and self.last_load_only:
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.__initialize()
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.policy_load_msgs.append(msg)
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        elif isinstance(msg, AVCMessage):
43213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.avc_msgs.append(msg)
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        elif isinstance(msg, ComputeSidMessage):
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.compute_sid_msgs.append(msg)
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        elif isinstance(msg, InvalidMessage):
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.invalid_msgs.append(msg)
43713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        elif isinstance(msg, PathMessage):
43813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.path_msgs.append(msg)
43913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        # Group by audit header
44113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if msg.header != "":
44215a7553d2274a351fb1098f7bfab86346c5a04b8Robert Kuska            if msg.header in self.by_header:
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.by_header[msg.header].append(msg)
44413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            else:
44513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                self.by_header[msg.header] = [msg]
44613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # Post processing will add additional information from AVC messages
44913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # from related messages - only works on messages generated by
45013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    # the audit system.
45113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __post_process(self):
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for value in self.by_header.values():
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            avc = []
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            path = None
45513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            for msg in value:
45613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                if isinstance(msg, PathMessage):
45713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    path = msg
45813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                elif isinstance(msg, AVCMessage):
45913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    avc.append(msg)
46013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if len(avc) > 0 and path:
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                for a in avc:
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    a.path = path.path
46313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
46413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def parse_file(self, input):
46513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """Parse the contents of a file object. This method can be called
46613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        multiple times (along with parse_string)."""
46713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        line = input.readline()
46813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        while line:
46913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.__parse(line)
47013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            line = input.readline()
471df45dcdf3db2d02930bbd095f6e9bc4f3eafdf3fDan Walsh        if not self.check_input_file:
472df45dcdf3db2d02930bbd095f6e9bc4f3eafdf3fDan Walsh            sys.stderr.write("Nothing to do\n")
473df45dcdf3db2d02930bbd095f6e9bc4f3eafdf3fDan Walsh            sys.exit(0)
47413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.__post_process()
47513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
47613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def parse_string(self, input):
47713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """Parse a string containing audit messages - messages should
47813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        be separated by new lines. This method can be called multiple
47913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        times (along with parse_file)."""
48013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        lines = input.split('\n')
48113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for l in lines:
48213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            self.__parse(l)
48313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.__post_process()
48413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def to_role(self, role_filter=None):
48613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """Return RoleAllowSet statements matching the specified filter
48713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        Filter out types that match the filer, or all roles
48913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        Params:
49113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle           role_filter - [optional] Filter object used to filter the
49213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle              output.
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        Returns:
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle           Access vector set representing the denied access in the
49513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle           audit logs parsed by this object.
49613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """
49713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        role_types = access.RoleTypeSet()
49813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for cs in self.compute_sid_msgs:
49913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if not role_filter or role_filter.filter(cs):
50013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                role_types.add(cs.invalid_context.role, cs.invalid_context.type)
50113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        return role_types
50313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def to_access(self, avc_filter=None, only_denials=True):
50513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """Convert the audit logs access into a an access vector set.
50613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        Convert the audit logs into an access vector set, optionally
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        filtering the restults with the passed in filter object.
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        Filter objects are object instances with a .filter method
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        that takes and access vector and returns True if the message
51213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        should be included in the final output and False otherwise.
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        Params:
51513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle           avc_filter - [optional] Filter object used to filter the
51613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle              output.
51713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        Returns:
51813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle           Access vector set representing the denied access in the
51913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle           audit logs parsed by this object.
52013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        """
52113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        av_set = access.AccessVectorSet()
52213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        for avc in self.avc_msgs:
52313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if avc.denial != True and only_denials:
52413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                continue
52513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            if avc_filter:
52613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                if avc_filter.filter(avc):
52713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                    av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
528628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris                               avc.accesses, avc, avc_type=avc.type, data=avc.data)
52913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            else:
53013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle                av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
531628bcc69e23d96cec308bae5c70bebdeebeeeeccEric Paris                           avc.accesses, avc, avc_type=avc.type, data=avc.data)
53213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        return av_set
53313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass AVCTypeFilter:
53513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, regex):
53613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.regex = re.compile(regex)
53713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def filter(self, avc):
53913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if self.regex.match(avc.scontext.type):
54013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            return True
54113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if self.regex.match(avc.tcontext.type):
54213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            return True
54313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        return False
54413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
54513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleclass ComputeSidTypeFilter:
54613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def __init__(self, regex):
54713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        self.regex = re.compile(regex)
54813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
54913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    def filter(self, avc):
55013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if self.regex.match(avc.invalid_context.type):
55113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            return True
55213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if self.regex.match(avc.scontext.type):
55313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            return True
55413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        if self.regex.match(avc.tcontext.type):
55513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle            return True
55613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle        return False
55713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
559