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