diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py index 00ee6ca31..5346f2fb9 100644 --- a/utils/apparmor/aa.py +++ b/utils/apparmor/aa.py @@ -1928,55 +1928,6 @@ def add_to_options(options, newpath): default_option = options.index(newpath) + 1 return (options, default_option) -def glob_path(newpath): - """Glob the given file path""" - if newpath[-1] == '/': - if newpath[-4:] == '/**/' or newpath[-3:] == '/*/': - # /foo/**/ and /foo/*/ => /**/ - newpath = re.sub('/[^/]+/\*{1,2}/$', '/**/', newpath) # re.sub('/[^/]+/\*{1,2}$/', '/\*\*/', newpath) - elif re.search('/[^/]+\*\*[^/]*/$', newpath): - # /foo**/ and /foo**bar/ => /**/ - newpath = re.sub('/[^/]+\*\*[^/]*/$', '/**/', newpath) - elif re.search('/\*\*[^/]+/$', newpath): - # /**bar/ => /**/ - newpath = re.sub('/\*\*[^/]+/$', '/**/', newpath) - else: - newpath = re.sub('/[^/]+/$', '/*/', newpath) - else: - if newpath[-3:] == '/**' or newpath[-2:] == '/*': - # /foo/** and /foo/* => /** - newpath = re.sub('/[^/]+/\*{1,2}$', '/**', newpath) - elif re.search('/[^/]*\*\*[^/]+$', newpath): - # /**foo and /foor**bar => /** - newpath = re.sub('/[^/]*\*\*[^/]+$', '/**', newpath) - elif re.search('/[^/]+\*\*$', newpath): - # /foo** => /** - newpath = re.sub('/[^/]+\*\*$', '/**', newpath) - else: - newpath = re.sub('/[^/]+$', '/*', newpath) - return newpath - -def glob_path_withext(newpath): - """Glob given file path with extension""" - # match /**.ext and /*.ext - match = re.search('/\*{1,2}(\.[^/]+)$', newpath) - if match: - # /foo/**.ext and /foo/*.ext => /**.ext - newpath = re.sub('/[^/]+/\*{1,2}\.[^/]+$', '/**' + match.groups()[0], newpath) - elif re.search('/[^/]+\*\*[^/]*\.[^/]+$', newpath): - # /foo**.ext and /foo**bar.ext => /**.ext - match = re.search('/[^/]+\*\*[^/]*(\.[^/]+)$', newpath) - newpath = re.sub('/[^/]+\*\*[^/]*\.[^/]+$', '/**' + match.groups()[0], newpath) - elif re.search('/\*\*[^/]+\.[^/]+$', newpath): - # /**foo.ext => /**.ext - match = re.search('/\*\*[^/]+(\.[^/]+)$', newpath) - newpath = re.sub('/\*\*[^/]+\.[^/]+$', '/**' + match.groups()[0], newpath) - else: - match = re.search('(\.[^/]+)$', newpath) - if match: - newpath = re.sub('/[^/]+(\.[^/]+)$', '/*' + match.groups()[0], newpath) - return newpath - def delete_duplicates(profile, incname): deleted = 0 # Allow rules covered by denied rules shouldn't be deleted diff --git a/utils/apparmor/aare.py b/utils/apparmor/aare.py index 3f410b45e..e7a9a8f52 100644 --- a/utils/apparmor/aare.py +++ b/utils/apparmor/aare.py @@ -79,6 +79,57 @@ class AARE(object): else: raise AppArmorBug('AARE.is_equal() called with unknown object: %s' % str(expression)) + def glob_path(self): + '''Glob the given file or directory path''' + if self.regex[-1] == '/': + if self.regex[-4:] == '/**/' or self.regex[-3:] == '/*/': + # /foo/**/ and /foo/*/ => /**/ + newpath = re.sub('/[^/]+/\*{1,2}/$', '/**/', self.regex) # re.sub('/[^/]+/\*{1,2}$/', '/\*\*/', self.regex) + elif re.search('/[^/]+\*\*[^/]*/$', self.regex): + # /foo**/ and /foo**bar/ => /**/ + newpath = re.sub('/[^/]+\*\*[^/]*/$', '/**/', self.regex) + elif re.search('/\*\*[^/]+/$', self.regex): + # /**bar/ => /**/ + newpath = re.sub('/\*\*[^/]+/$', '/**/', self.regex) + else: + newpath = re.sub('/[^/]+/$', '/*/', self.regex) + else: + if self.regex[-3:] == '/**' or self.regex[-2:] == '/*': + # /foo/** and /foo/* => /** + newpath = re.sub('/[^/]+/\*{1,2}$', '/**', self.regex) + elif re.search('/[^/]*\*\*[^/]+$', self.regex): + # /**foo and /foor**bar => /** + newpath = re.sub('/[^/]*\*\*[^/]+$', '/**', self.regex) + elif re.search('/[^/]+\*\*$', self.regex): + # /foo** => /** + newpath = re.sub('/[^/]+\*\*$', '/**', self.regex) + else: + newpath = re.sub('/[^/]+$', '/*', self.regex) + return AARE(newpath, False) + + def glob_path_withext(self): + '''Glob given file path with extension + Files without extensions and directories won't be changed''' + # match /**.ext and /*.ext + match = re.search('/\*{1,2}(\.[^/]+)$', self.regex) + if match: + # /foo/**.ext and /foo/*.ext => /**.ext + newpath = re.sub('/[^/]+/\*{1,2}\.[^/]+$', '/**' + match.groups()[0], self.regex) + elif re.search('/[^/]+\*\*[^/]*\.[^/]+$', self.regex): + # /foo**.ext and /foo**bar.ext => /**.ext + match = re.search('/[^/]+\*\*[^/]*(\.[^/]+)$', self.regex) + newpath = re.sub('/[^/]+\*\*[^/]*\.[^/]+$', '/**' + match.groups()[0], self.regex) + elif re.search('/\*\*[^/]+\.[^/]+$', self.regex): + # /**foo.ext => /**.ext + match = re.search('/\*\*[^/]+(\.[^/]+)$', self.regex) + newpath = re.sub('/\*\*[^/]+\.[^/]+$', '/**' + match.groups()[0], self.regex) + else: + newpath = self.regex + match = re.search('(\.[^/]+)$', self.regex) + if match: + newpath = re.sub('/[^/]+(\.[^/]+)$', '/*' + match.groups()[0], self.regex) + return AARE(newpath, False) + def convert_expression_to_aare(expression): '''convert an expression (taken from audit.log) to an AARE string''' diff --git a/utils/test/test-aare.py b/utils/test/test-aare.py index 25d36cd4a..11b948f42 100644 --- a/utils/test/test-aare.py +++ b/utils/test/test-aare.py @@ -243,6 +243,117 @@ class TestAAREDeepcopy(AATest): self.assertEqual(params.orig_regex, dup.orig_regex) self.assertEqual(params.orig_regex, dup.orig_regex) +class TestAAREglobPath(AATest): + tests = [ + # _run_test() will also run each test with '/' appended + # regex expected AARE.regex + ('/foo/bar/baz**', '/foo/bar/**'), + ('/foo/bar/**baz', '/foo/bar/**'), + ('/foo/bar/fo**baz', '/foo/bar/**'), + ('/foo/bar/**foo**', '/foo/bar/**'), + ('/foo/bar/**f?o**', '/foo/bar/**'), + ('/foo/bar/**fo[a-z]**', '/foo/bar/**'), + + ('/foo/bar/baz', '/foo/bar/*'), + ('/foo/bar/baz*', '/foo/bar/*'), + ('/foo/bar/*baz', '/foo/bar/*'), + ('/foo/bar/fo*baz', '/foo/bar/*'), + ('/foo/bar/*foo*', '/foo/bar/*'), + + ('/foo/bar/b[a-z]z', '/foo/bar/*'), + ('/foo/bar/{bar,baz}', '/foo/bar/*'), + ('/foo/bar/{bar,ba/z}', '/foo/bar/{bar,ba/*'), # XXX + ('/foo/*/baz', '/foo/*/*'), + + ('/foo/bar/**', '/foo/**'), + ('/foo/bar/*', '/foo/**'), + + ('/foo/**/*', '/foo/**'), + ('/foo/*/**', '/foo/**'), + ('/foo/*/*', '/foo/**'), + + ] + + def _run_test(self, params, expected): + # test for files + oldpath = AARE(params, True) + newpath = oldpath.glob_path() + self.assertEqual(expected, newpath.regex) + + # test for directories + oldpath = AARE(params + '/', True) + newpath = oldpath.glob_path() + self.assertEqual(expected + '/', newpath.regex) + +class TestAAREglobPathWithExt(AATest): + tests = [ + # _run_test() will also run each test with '/' appended + # regex expected AARE.regex + + # no extension - shouldn't change + ('/foo/bar/baz**', '/foo/bar/baz**'), + ('/foo/bar/**baz', '/foo/bar/**baz'), + ('/foo/bar/fo**baz', '/foo/bar/fo**baz'), + ('/foo/bar/**foo**', '/foo/bar/**foo**'), + ('/foo/bar/**f?o**', '/foo/bar/**f?o**'), + ('/foo/bar/**fo[a-z]**', '/foo/bar/**fo[a-z]**'), + + ('/foo/bar/baz', '/foo/bar/baz'), + ('/foo/bar/baz*', '/foo/bar/baz*'), + ('/foo/bar/*baz', '/foo/bar/*baz'), + ('/foo/bar/fo*baz', '/foo/bar/fo*baz'), + ('/foo/bar/*foo*', '/foo/bar/*foo*'), + + ('/foo/bar/b[a-z]z', '/foo/bar/b[a-z]z'), + ('/foo/bar/{bar,baz}', '/foo/bar/{bar,baz}'), + ('/foo/bar/{bar,ba/z}', '/foo/bar/{bar,ba/z}'), + ('/foo/*/baz', '/foo/*/baz'), + + ('/foo/bar/**', '/foo/bar/**'), + ('/foo/bar/*', '/foo/bar/*'), + + ('/foo/**/*', '/foo/**/*'), + ('/foo/*/**', '/foo/*/**'), + ('/foo/*/*', '/foo/*/*'), + + # with extension added + ('/foo/bar/baz**.xy', '/foo/bar/**.xy'), + ('/foo/bar/**baz.xy', '/foo/bar/**.xy'), + ('/foo/bar/fo**baz.xy', '/foo/bar/**.xy'), + ('/foo/bar/**foo**.xy', '/foo/bar/**.xy'), + ('/foo/bar/**f?o**.xy', '/foo/bar/**.xy'), + ('/foo/bar/**fo[a-z]**.xy', '/foo/bar/**.xy'), + + ('/foo/bar/baz.xy', '/foo/bar/*.xy'), + ('/foo/bar/baz*.xy', '/foo/bar/*.xy'), + ('/foo/bar/*baz.xy', '/foo/bar/*.xy'), + ('/foo/bar/fo*baz.xy', '/foo/bar/*.xy'), + ('/foo/bar/*foo*.xy', '/foo/bar/*.xy'), + + ('/foo/bar/b[a-z]z.xy', '/foo/bar/*.xy'), + ('/foo/bar/{bar,baz}.xy', '/foo/bar/*.xy'), + ('/foo/bar/{bar,ba/z}.xy', '/foo/bar/{bar,ba/*.xy'), # XXX + ('/foo/*/baz.xy', '/foo/*/*.xy'), + + ('/foo/bar/**.xy', '/foo/**.xy'), + ('/foo/bar/*.xy', '/foo/**.xy'), + + ('/foo/**/*.xy', '/foo/**.xy'), + ('/foo/*/**.xy', '/foo/**.xy'), + ('/foo/*/*.xy', '/foo/**.xy'), + ] + + def _run_test(self, params, expected): + # test for files + oldpath = AARE(params, True) + newpath = oldpath.glob_path_withext() + self.assertEqual(expected, newpath.regex) + + # test for directories - should be kept unchanged + oldpath = AARE(params + '/', True) + newpath = oldpath.glob_path_withext() + self.assertEqual(params + '/', newpath.regex) # note that we compare to params, not expected here + setup_all_loops(__name__) if __name__ == '__main__':