From a9c594d5bc01d4502b3b5fbf509285c914f0bca4 Mon Sep 17 00:00:00 2001 From: Kshitij Gupta Date: Fri, 9 Aug 2013 16:49:01 +0530 Subject: [PATCH] fixed test encoded data for log entries --- Testing/aa_test.py | 22 +++++++++++++------- apparmor/aa.py | 52 +++++++++++++++++++++++++--------------------- apparmor/common.py | 3 ++- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/Testing/aa_test.py b/Testing/aa_test.py index d005b355e..8bbeb63ea 100644 --- a/Testing/aa_test.py +++ b/Testing/aa_test.py @@ -13,17 +13,25 @@ class Test(unittest.TestCase): def test_parse_event(self): - event = 'type=AVC msg=audit(1345027352.096:499): apparmor="ALLOWED" operation="rename_dest" parent=6974 profile="/usr/sbin/httpd2-prefork//vhost_balmar" name=2F686F6D652F7777772F62616C6D61722E646174616E6F766F322E64652F68747470646F63732F6A6F6F6D6C612F696D616765732F6B75656368656E2F666F746F20322E6A7067 pid=20143 comm="httpd2-prefork" requested_mask="wc" denied_mask="wc" fsuid=30 ouid=30' + event = 'type=AVC msg=audit(1345027352.096:499): apparmor="ALLOWED" operation="rename_dest" parent=6974 profile="/usr/sbin/httpd2-prefork//vhost_foo" name=2F686F6D652F7777772F666F6F2E6261722E696E2F68747470646F63732F61707061726D6F722F696D616765732F746573742F696D61676520312E6A7067 pid=20143 comm="httpd2-prefork" requested_mask="wc" denied_mask="wc" fsuid=30 ouid=30' parsed_event = apparmor.aa.parse_event(event) - print(parsed_event) + self.assertEqual(parsed_event['name'], '/home/www/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg', 'Incorrectly parsed/decoded name') + self.assertEqual(parsed_event['profile'], '/usr/sbin/httpd2-prefork//vhost_foo', 'Incorrectly parsed/decode profile name') + self.assertEqual(parsed_event['aamode'], 'PERMITTING') - event = 'type=AVC msg=audit(1322614912.304:857): apparmor="ALLOWED" operation="getattr" parent=16001 profile=74657374207370616365 name=74657374207370616365 pid=17011 comm="bash" requested_mask="r" denied_mask="r" fsuid=0 ouid=0' - parsed_event = apparmor.aa.parse_event(event) - print(parsed_event) + #print(parsed_event) - event = 'type=AVC msg=audit(1322614918.292:4376): apparmor="ALLOWED" operation="file_perm" parent=16001 profile=74657374207370616365 name="/home/jj/.bash_history" pid=17011 comm="bash" requested_mask="w" denied_mask="w" fsuid=0 ouid=1000' + #event = 'type=AVC msg=audit(1322614912.304:857): apparmor="ALLOWED" operation="getattr" parent=16001 profile=74657374207370616365 name=74657374207370616365 pid=17011 comm="bash" requested_mask="r" denied_mask="r" fsuid=0 ouid=0' + #parsed_event = apparmor.aa.parse_event(event) + #print(parsed_event) + + event = 'type=AVC msg=audit(1322614918.292:4376): apparmor="ALLOWED" operation="file_perm" parent=16001 profile=666F6F20626172 name="/home/foo/.bash_history" pid=17011 comm="bash" requested_mask="w" denied_mask="w" fsuid=0 ouid=1000' parsed_event = apparmor.aa.parse_event(event) - print(parsed_event) + self.assertEqual(parsed_event['name'], '/home/foo/.bash_history', 'Incorrectly parsed/decoded name') + self.assertEqual(parsed_event['profile'], 'foo bar', 'Incorrectly parsed/decode profile name') + self.assertEqual(parsed_event['aamode'], 'PERMITTING') + + #print(parsed_event) def test_modes_to_string(self): diff --git a/apparmor/aa.py b/apparmor/aa.py index bbc850042..6f467372e 100644 --- a/apparmor/aa.py +++ b/apparmor/aa.py @@ -21,7 +21,7 @@ import apparmor.severity import LibAppArmor from apparmor.common import (AppArmorException, error, debug, msg, - open_file_read, readkey, valid_path, + open_file_read, valid_path, hasher, open_file_write, convert_regexp, DebugLogger) from apparmor.ui import * @@ -2957,19 +2957,19 @@ def parse_profile_data(data, file, do_include): initial_comment = '' RE_PROFILE_START = re.compile('^(("??\/.+?"??)|(profile\s+("??.+?"??)))\s+((flags=)?\((.+)\)\s+)*\{\s*(#.*)?$') RE_PROFILE_END = re.compile('^\}\s*(#.*)?$') - RE_PROFILE_CAP = re.compile('^(audit\s+)?(deny\s+)?capability\s+(\S+)\s*,\s*(#.*)?$') + RE_PROFILE_CAP = re.compile('^(audit\s+)?(allow\s+|deny\s+)?capability\s+(\S+)\s*,\s*(#.*)?$') #RE_PROFILE_SET_CAP = re.compile('^set capability\s+(\S+)\s*,\s*(#.*)?$') - RE_PROFILE_LINK = re.compile('^(audit\s+)?(deny\s+)?link\s+(((subset)|(<=))\s+)?([\"\@\/].*?"??)\s+->\s*([\"\@\/].*?"??)\s*,\s*(#.*)?$') + RE_PROFILE_LINK = re.compile('^(audit\s+)?(allow\s+|deny\s+)?link\s+(((subset)|(<=))\s+)?([\"\@\/].*?"??)\s+->\s*([\"\@\/].*?"??)\s*,\s*(#.*)?$') RE_PROFILE_CHANGE_PROFILE = re.compile('^change_profile\s+->\s*("??.+?"??),(#.*)?$') RE_PROFILE_ALIAS = re.compile('^alias\s+("??.+?"??)\s+->\s*("??.+?"??)\s*,(#.*)?$') - RE_PROFILE_RLIMIT = re.compile('^set\s+rlimit\s+(.+)\s+<=\s*(.+)\s*,(#.*)?$') - RE_PROFILE_BOOLEAN = re.compile('^(\$\{?[[:alpha:]][[:alnum:]_]*\}?)\s*=\s*(true|false)\s*,?\s*(#.*)?$', flags=re.IGNORECASE) + RE_PROFILE_RLIMIT = re.compile('^set\s+rlimit\s+(.+)\s+(<=)?\s*(.+)\s*,(#.*)?$') + RE_PROFILE_BOOLEAN = re.compile('^(\$\{?\w*\}?)\s*=\s*(true|false)\s*,?\s*(#.*)?$', flags=re.IGNORECASE) RE_PROFILE_VARIABLE = re.compile('^(@\{?\w+\}?)\s*(\+?=)\s*(@*.+?)\s*,?\s*(#.*)?$') - RE_PROFILE_CONDITIONAL = re.compile('^if\s+(not\s+)?(\$\{?[[:alpha:]][[:alnum:]_]*\}?)\s*\{\s*(#.*)?$') - RE_PROFILE_CONDITIONAL_VARIABLE = re.compile('^if\s+(not\s+)?defined\s+(@\{?[[:alpha:]][[:alnum:]_]+\}?)\s*\{\s*(#.*)?$') - RE_PROFILE_CONDITIONAL_BOOLEAN = re.compile('^if\s+(not\s+)?defined\s+(\$\{?[[:alpha:]][[:alnum:]_]+\}?)\s*\{\s*(#.*)?$') - RE_PROFILE_PATH_ENTRY = re.compile('^(audit\s+)?(deny\s+)?(owner\s+)?([\"\@\/].*?)\s+(\S+)(\s+->\s*(.*?))?\s*,\s*(#.*)?$') - RE_PROFILE_NETWORK = re.compile('^(audit\s+)?(deny\s+)?network(.*)\s*(#.*)?$') + RE_PROFILE_CONDITIONAL = re.compile('^if\s+(not\s+)?(\$\{?\w*\}?)\s*\{\s*(#.*)?$') + RE_PROFILE_CONDITIONAL_VARIABLE = re.compile('^if\s+(not\s+)?defined\s+(@\{?\w+\}?)\s*\{\s*(#.*)?$') + RE_PROFILE_CONDITIONAL_BOOLEAN = re.compile('^if\s+(not\s+)?defined\s+(\$\{?\w+\}?)\s*\{\s*(#.*)?$') + RE_PROFILE_PATH_ENTRY = re.compile('^(audit\s+)?(allow\s+|deny\s+)?(owner\s+)?([\"@/].*?)\s+(\S+)(\s+->\s*(.*?))?\s*,\s*(#.*)?$') + RE_PROFILE_NETWORK = re.compile('^(audit\s+)?(allow\s+|deny\s+)?network(.*)\s*(#.*)?$') RE_PROFILE_CHANGE_HAT = re.compile('^\^(\"??.+?\"??)\s*,\s*(#.*)?$') RE_PROFILE_HAT_DEF = re.compile('^\^(\"??.+?\"??)\s+((flags=)?\((.+)\)\s+)*\{\s*(#.*)?$') if do_include: @@ -3059,7 +3059,7 @@ def parse_profile_data(data, file, do_include): audit = True allow = 'allow' - if matches[1]: + if matches[1] and matches[1].strip() == 'deny': allow = 'deny' capability = matches[2] @@ -3087,7 +3087,7 @@ def parse_profile_data(data, file, do_include): audit = True allow = 'allow' - if matches[1]: + if matches[1] and matches[1].strip() == 'deny': allow = 'deny' subset = matches[3] @@ -3133,7 +3133,7 @@ def parse_profile_data(data, file, do_include): raise AppArmorException('Syntax Error: Unexpected rlimit entry found in file: %s line: %s' % (file, lineno+1)) from_name = matches[0] - to_name = matches[1] + to_name = matches[2] profile_data[profile][hat]['rlimit'][from_name] = to_name @@ -3188,7 +3188,7 @@ def parse_profile_data(data, file, do_include): audit = True allow = 'allow' - if matches[1]: + if matches[1] and matches[1].strip() == 'deny': allow = 'deny' user = False @@ -3258,17 +3258,18 @@ def parse_profile_data(data, file, do_include): if matches[0]: audit = True allow = 'allow' - if matches[1]: + if matches[1] and matches[1].strip() == 'deny': allow = 'deny' network = matches[2] - - if re.search('\s+(\S+)\s+(\S+)\s*,\s*(#.*)?$', network): - nmatch = re.search('\s+(\S+)\s+(\S+)\s*,\s*(#.*)?$', network).groups() + RE_NETWORK_FAMILY_TYPE = re.compile('\s+(\S+)\s+(\S+)\s*,$') + RE_NETWORK_FAMILY = re.compile('\s+(\S+)\s*,$') + if RE_NETWORK_FAMILY_TYPE.search(network): + nmatch = RE_NETWORK_FAMILY_TYPE.search(network).groups() fam, typ = nmatch[:2] profile_data[profile][hat][allow]['netdomain']['rule'][fam][typ] = True profile_data[profile][hat][allow]['netdomain']['audit'][fam][typ] = audit - elif re.search('\s+(\S+)\s*,\s*(#.*)?$', network): - fam = re.search('\s+(\S+)\s*,\s*(#.*)?$', network).groups()[0] + elif RE_NETWORK_FAMILY.search(network): + fam = RE_NETWORK_FAMILY.search(network).groups()[0] profile_data[profile][hat][allow]['netdomain']['rule'][fam] = True profile_data[profile][hat][allow]['netdomain']['audit'][fam] = audit else: @@ -3306,7 +3307,8 @@ def parse_profile_data(data, file, do_include): if initial_comment: profile_data[profile][hat]['initial_comment'] = initial_comment initial_comment = '' - + if filelist[file]['profiles'][profile].get(hat, False): + raise AppArmorException('Error: Multiple definitions for hat %s in profile %s.' %(hat, profile)) filelist[file]['profiles'][profile][hat] = True elif line[0] == '#': @@ -3339,11 +3341,12 @@ def parse_profile_data(data, file, do_include): # End of file reached but we're stuck in a profile if profile and not do_include: - raise AppArmorException('Syntax Error: Reached end of file %s while inside profile %s' % (file, profile)) + raise AppArmorException("Syntax Error: Missing '}' . Reached end of file %s while inside profile %s" % (file, profile)) return profile_data def separate_vars(vs): + """Returns a list of all the values for a variable""" data = [] #data = [i.strip('"') for i in vs.split()] @@ -3362,12 +3365,13 @@ def is_active_profile(pname): return False def store_list_var(var, list_var, value, var_operation): + """Store(add new variable or add values to variable) the variables encountered in the given list_var""" vlist = separate_vars(value) if var_operation == '=': if not var.get(list_var, False): var[list_var] = set(vlist) else: - print('Ignoring: New definition for variable for:',list_var,'=', value, 'operation was:',var_operation,'old value=', var[list_var]) + print('Ignored: New definition for variable for:',list_var,'=', value, 'operation was:',var_operation,'old value=', var[list_var]) pass #raise AppArmorException('An existing variable redefined') else: @@ -3401,7 +3405,7 @@ def write_header(prof_data, depth, name, embedded_hat, write_flags): data = [] name = quote_if_needed(name) - if (not embedded_hat and re.search('^[^\/]|^"[^\/]', name)) or (embedded_hat and re.search('^[^^]' ,name)): + if (not embedded_hat and re.search('^[^/]|^"[^/]', name)) or (embedded_hat and re.search('^[^^]' ,name)): name = 'profile %s' % name if write_flags and prof_data['flags']: diff --git a/apparmor/common.py b/apparmor/common.py index ed4a8d10c..85d91404f 100644 --- a/apparmor/common.py +++ b/apparmor/common.py @@ -191,7 +191,8 @@ def convert_regexp(regexp): class DebugLogger: def __init__(self, module_name=__name__): - logging.basicConfig(filename='/var/log/apparmor/logprof.log') + #logging.basicConfig(filename='/var/log/apparmor/logprof.log') + logging.basicConfig(filename='/home/kshitij/logprof.log') self.logger = logging.getLogger(module_name) self.debugging = True if os.getenv('LOGPROF_DEBUG', False):