1# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
2#
3# Copyright (C) 2006 Red Hat
4# see file 'COPYING' for use and warranty information
5#
6# This program is free software; you can redistribute it and/or
7# modify it under the terms of the GNU General Public License as
8# published by the Free Software Foundation; version 2 only
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20import unittest
21import sepolgen.audit
22import sepolgen.refpolicy
23
24# syslog message
25audit1 = """Sep 12 08:26:43 dhcp83-5 kernel: audit(1158064002.046:4): avc:  denied  { read } for  pid=2 496 comm="bluez-pin" name=".gdm1K3IFT" dev=dm-0 ino=3601333 scontext=user_u:system_r:bluetooth_helper_t:s0-s0:c0 tcontext=system_u:object_r:xdm_tmp_t:s0 tclass=file"""
26
27# audit daemon messages
28audit2 = """type=AVC msg=audit(1158584779.745:708): avc:  denied  { dac_read_search } for  pid=8132 comm="sh" capability=2 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability"""
29
30log1 = """type=AVC msg=audit(1158584779.745:708): avc:  denied  { dac_read_search } for  pid=8132 comm="sh" capability=2 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
31type=SYSCALL msg=audit(1158584779.745:708): arch=40000003 syscall=195 success=no exit=-13 a0=80d2437 a1=bf9132f8 a2=4c56cff4 a3=0 items=0 ppid=8131 pid=8132 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="sh" exe="/bin/bash" subj=user_u:system_r:vpnc_t:s0 key=(null)
32type=AVC msg=audit(1158584779.753:709): avc:  denied  { dac_override } for  pid=8133 comm="vpnc-script" capability=1 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
33type=AVC msg=audit(1158584779.753:709): avc:  denied  { dac_read_search } for  pid=8133 comm="vpnc-script" capability=2 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
34type=SYSCALL msg=audit(1158584779.753:709): arch=40000003 syscall=195 success=no exit=-13 a0=80d2437 a1=bf910a48 a2=4c56cff4 a3=0 items=0 ppid=8132 pid=8133 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="vpnc-script" exe="/bin/bash" subj=user_u:system_r:vpnc_t:s0 key=(null)
35type=AVC msg=audit(1158584779.825:710): avc:  denied  { dac_override } for  pid=8134 comm="vpnc-script" capability=1 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
36type=AVC msg=audit(1158584779.825:710): avc:  denied  { dac_read_search } for  pid=8134 comm="vpnc-script" capability=2 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
37type=SYSCALL msg=audit(1158584779.825:710): arch=40000003 syscall=195 success=no exit=-13 a0=80d2437 a1=bf910a48 a2=4c56cff4 a3=0 items=0 ppid=8132 pid=8134 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="vpnc-script" exe="/bin/bash" subj=user_u:system_r:vpnc_t:s0 key=(null)
38type=AVC msg=audit(1158584780.793:711): avc:  denied  { dac_override } for  pid=8144 comm="sh" capability=1 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
39type=AVC msg=audit(1158584780.793:711): avc:  denied  { dac_read_search } for  pid=8144 comm="sh" capability=2 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
40type=SYSCALL msg=audit(1158584780.793:711): arch=40000003 syscall=195 success=no exit=-13 a0=80d2437 a1=bfc0ba38 a2=4c56cff4 a3=0 items=0 ppid=8131 pid=8144 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="sh" exe="/bin/bash" subj=user_u:system_r:vpnc_t:s0 key=(null)
41type=AVC msg=audit(1158584780.797:712): avc:  denied  { dac_override } for  pid=8145 comm="vpnc-script" capability=1 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
42type=AVC msg=audit(1158584780.797:712): avc:  denied  { dac_read_search } for  pid=8145 comm="vpnc-script" capability=2 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
43type=SYSCALL msg=audit(1158584780.797:712): arch=40000003 syscall=195 success=no exit=-13 a0=80d2437 a1=bfc0b188 a2=4c56cff4 a3=0 items=0 ppid=8144 pid=8145 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="vpnc-script" exe="/bin/bash" subj=user_u:system_r:vpnc_t:s0 key=(null)
44type=AVC msg=audit(1158584780.801:713): avc:  denied  { dac_override } for  pid=8146 comm="vpnc-script" capability=1 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
45type=AVC msg=audit(1158584780.801:713): avc:  denied  { dac_read_search } for  pid=8146 comm="vpnc-script" capability=2 scontext=user_u:system_r:vpnc_t:s0 tcontext=user_u:system_r:vpnc_t:s0 tclass=capability
46type=AVC_PATH msg=audit(1162850461.778:1113):  path="/etc/rc.d/init.d/innd"
47"""
48
49granted1 = """type=AVC msg=audit(1188833848.190:34): avc:  granted  { getattr } for  pid=4310 comm="ls" name="foo.pp" dev=sda5 ino=295171 scontext=user_u:system_r:unconfined_t:s0 tcontext=user_u:object_r:user_home_t:s0 tclass=file"""
50
51path1 = """type=AVC_PATH msg=audit(1162852201.019:1225):  path="/usr/lib/sa/sa1"
52"""
53
54log2 = """type=AVC_PATH msg=audit(1162852201.019:1225):  path="/usr/lib/sa/sa1"
55type=SYSCALL msg=audit(1162852201.019:1225): arch=40000003 syscall=11 success=yes exit=0 a0=87271b0 a1=8727358 a2=8727290 a3=8727008 items=0 ppid=6973 pid=6974 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="sa1" exe="/bin/bash" subj=system_u:system_r:crond_t:s0-s0:c0.c1023 key=(null)
56type=AVC msg=audit(1162852201.019:1225): avc:  denied  { execute_no_trans } for  pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file
57type=AVC msg=audit(1162852201.019:1225): avc:  denied  { execute } for  pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file"""
58
59class TestAVCMessage(unittest.TestCase):
60    def test_defs(self):
61        avc = sepolgen.audit.AVCMessage(audit1)
62        sc = sepolgen.refpolicy.SecurityContext()
63        self.assertEqual(avc.scontext, sc)
64        self.assertEqual(avc.tcontext, sc)
65        self.assertEqual(avc.tclass, "")
66        self.assertEqual(avc.accesses, [])
67
68    def test_granted(self):
69        avc = sepolgen.audit.AVCMessage(granted1)
70        avc.from_split_string(granted1.split())
71
72        self.assertEqual(avc.scontext.user, "user_u")
73        self.assertEqual(avc.scontext.role, "system_r")
74        self.assertEqual(avc.scontext.type, "unconfined_t")
75        self.assertEqual(avc.scontext.level, "s0")
76
77        self.assertEqual(avc.tcontext.user, "user_u")
78        self.assertEqual(avc.tcontext.role, "object_r")
79        self.assertEqual(avc.tcontext.type, "user_home_t")
80        self.assertEqual(avc.tcontext.level, "s0")
81
82        self.assertEqual(avc.tclass, "file")
83        self.assertEqual(avc.accesses, ["getattr"])
84
85        self.assertEqual(avc.denial, False)
86
87
88    def test_from_split_string(self):
89        # syslog message
90        avc = sepolgen.audit.AVCMessage(audit1)
91        recs = audit1.split()
92        avc.from_split_string(recs)
93
94        self.assertEqual(avc.header, "audit(1158064002.046:4):")
95        self.assertEqual(avc.scontext.user, "user_u")
96        self.assertEqual(avc.scontext.role, "system_r")
97        self.assertEqual(avc.scontext.type, "bluetooth_helper_t")
98        self.assertEqual(avc.scontext.level, "s0-s0:c0")
99
100        self.assertEqual(avc.tcontext.user, "system_u")
101        self.assertEqual(avc.tcontext.role, "object_r")
102        self.assertEqual(avc.tcontext.type, "xdm_tmp_t")
103        self.assertEqual(avc.tcontext.level, "s0")
104
105        self.assertEqual(avc.tclass, "file")
106        self.assertEqual(avc.accesses, ["read"])
107
108        self.assertEqual(avc.comm, "bluez-pin")
109
110
111        self.assertEqual(avc.denial, True)
112
113        # audit daemon message
114        avc = sepolgen.audit.AVCMessage(audit2)
115        recs = audit2.split()
116        avc.from_split_string(recs)
117
118        self.assertEqual(avc.header, "audit(1158584779.745:708):")
119        self.assertEqual(avc.scontext.user, "user_u")
120        self.assertEqual(avc.scontext.role, "system_r")
121        self.assertEqual(avc.scontext.type, "vpnc_t")
122        self.assertEqual(avc.scontext.level, "s0")
123
124        self.assertEqual(avc.tcontext.user, "user_u")
125        self.assertEqual(avc.tcontext.role, "system_r")
126        self.assertEqual(avc.tcontext.type, "vpnc_t")
127        self.assertEqual(avc.tcontext.level, "s0")
128
129        self.assertEqual(avc.tclass, "capability")
130        self.assertEqual(avc.accesses, ["dac_read_search"])
131
132        self.assertEqual(avc.comm, "sh")
133
134        self.assertEqual(avc.denial, True)
135
136class TestPathMessage(unittest.TestCase):
137    def test_from_split_string(self):
138        path = sepolgen.audit.PathMessage(path1)
139        recs = path1.split()
140        path.from_split_string(recs)
141        self.assertEqual(path.path, "/usr/lib/sa/sa1")
142
143# TODO - add tests for the other message types
144
145
146# TODO - these tests need a lot of expansion and more examples of
147# different types of log files
148class TestAuditParser(unittest.TestCase):
149    def test_parse_string(self):
150        a = sepolgen.audit.AuditParser()
151        a.parse_string(log1)
152        self.assertEqual(len(a.avc_msgs), 11)
153        self.assertEqual(len(a.compute_sid_msgs), 0)
154        self.assertEqual(len(a.invalid_msgs), 0)
155        self.assertEqual(len(a.policy_load_msgs), 0)
156        self.assertEqual(len(a.path_msgs), 1)
157
158    def test_post_process(self):
159        a = sepolgen.audit.AuditParser()
160        a.parse_string(log2)
161        self.assertEqual(len(a.avc_msgs), 2)
162        self.assertEqual(a.avc_msgs[0].path, "/usr/lib/sa/sa1")
163        self.assertEqual(a.avc_msgs[1].path, "/usr/lib/sa/sa1")
164
165    def test_parse_file(self):
166        f = open("audit.txt")
167        a = sepolgen.audit.AuditParser()
168        a.parse_file(f)
169        f.close()
170        self.assertEqual(len(a.avc_msgs), 21)
171        self.assertEqual(len(a.compute_sid_msgs), 0)
172        self.assertEqual(len(a.invalid_msgs), 0)
173        self.assertEqual(len(a.policy_load_msgs), 0)
174
175class TestGeneration(unittest.TestCase):
176    def test_generation(self):
177        parser = sepolgen.audit.AuditParser()
178        parser.parse_string(log1)
179        avs = parser.to_access()
180
181        self.assertEqual(len(avs), 1)
182
183    def test_genaration_granted(self):
184        parser = sepolgen.audit.AuditParser()
185        parser.parse_string(granted1)
186        avs = parser.to_access()
187
188        self.assertEqual(len(avs), 0)
189
190        avs = parser.to_access(only_denials=False)
191
192        self.assertEqual(len(avs), 1)
193
194