Hello, the AARE class is meant to handle the internals of path AppArmor regexes at various places / rule types (filename, signal peer etc.). The goal is to use it in rule classes to hide all regex magic, so that the rule class can just use the match() method.
Expanding variables is on my TODO list - the parameter already exists, but they aren't handled or expanded yet. (AFAIK the existing code also doesn't do that.) The reason for delaying re.compile to match() is performance - I'd guess a logprof run match()es only for profiles with existing log events, so we can save 90% of the re.compile() calls. Another possible optimization (also on my TODO list) is to check if the given path is a regex (contains {...,...}, [...], *, **, ?) or if we can do a plain string comparison. The patch also includes some tests which should give you an idea how the class will be used. Note: This is a proof-of-concept patch. I won't object if someone sends an ack, but the main goal of this mail is to get feedback if the way I've chosen looks sane or if I should change some things ;-) [ POC_aare-class-and-tests.diff ] === modified file ./utils/apparmor/aare.py --- utils/apparmor/aare.py 2015-10-04 23:27:26.940248676 +0200 +++ utils/apparmor/aare.py 2015-10-20 19:58:45.330137525 +0200 @@ -0,0 +1,46 @@ +# ---------------------------------------------------------------------- +# Copyright (C) 2015 Christian Boltz <appar...@cboltz.de> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of version 2 of the GNU General Public +# License as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ---------------------------------------------------------------------- + +import re + +from apparmor.common import convert_regexp, AppArmorException + +class AARE(object): + '''AARE (AppArmor Regular Expression) wrapper class''' + + def __init__(self, regex, variables, is_path): + '''create an AARE instance for the given AppArmor regex, using the specified variables when matching. + If is_path is true, the regex is expected to be a path and therefore must start with / or a variable.''' + + if is_path: + if regex.startswith('/'): + pass + elif regex.startswith('@{'): + pass # XXX ideally check variable content - each part must start with / - or another variable, which must start with / + else: + raise AppArmorException("Path doesn't start with / or variable: %s" % regex) + + self.regex = regex + + self.regex_compiled = None # done on first use in match() - that saves us some re.compile() calls + self.variables = variables # XXX not used yet + + def match(self, expression): + '''check if a given expression matches the regex''' + + if self.regex_compiled is None: + self.regex_compiled = re.compile(convert_regexp(self.regex)) + + return self.regex_compiled.match(expression) + === modified file ./utils/test/test-aare.py --- utils/test/test-aare.py 2015-10-11 20:56:56.817732630 +0200 +++ utils/test/test-aare.py 2015-10-20 19:55:44.731555468 +0200 @@ -14,7 +14,8 @@ from common_test import AATest, setup_all_loops import re -from apparmor.common import convert_regexp +from apparmor.common import convert_regexp, AppArmorException +from apparmor.aare import AARE class TestConvert_regexp(AATest): tests = [ @@ -117,6 +118,32 @@ parsed_regex = re.compile(convert_regexp(regex)) self.assertEqual(bool(parsed_regex.search(path)), expected, 'Incorrectly Parsed regex: %s' %regex) + aare_obj = AARE(regex, set(), True) + self.assertEqual(bool(aare_obj.match(path)), expected, 'Incorrectly parsed AARE object: %s' % regex) + + def test_multi_usage(self): + aare_obj = AARE('/foo/*', set(), True) + self.assertTrue(aare_obj.match('/foo/bar')) + self.assertFalse(aare_obj.match('/foo/bar/')) + self.assertTrue(aare_obj.match('/foo/asdf')) + +class TestAAREIsPath(AATest): + def test_path(self): + aare_obj = AARE('/foo*', set(), True) + self.assertTrue(aare_obj.match('/foobar')) + + def test_path_var(self): + aare_obj = AARE('@{PROC}/', set(), True) + self.assertFalse(aare_obj.match('/foobar')) + + def test_non_path(self): + aare_obj = AARE('foo*', set(), False) + self.assertTrue(aare_obj.match('foobar')) + + def test_path_missing_slash(self): + with self.assertRaises(AppArmorException): + AARE('foo*', set(), True) + setup_all_loops(__name__) if __name__ == '__main__': Regards, Christian Boltz -- Übrigens gibt es jetzt eine Briefmarke von Bill Gates. Leider klebt die nicht so richtig. Eine unabhängige Kommission hat inzwischen festgestellt, daß die Leute immer auf die falsche Seite spucken. -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor