From 72f9a80c7686525dd7c75addae79dd28bc65a834 Mon Sep 17 00:00:00 2001 From: Kshitij Gupta Date: Sat, 21 Sep 2013 12:36:51 +0530 Subject: [PATCH] Fixed flag reader and writer to be able to set unset flag for a specific target program also fixed tests for mini tools to be independent of existence of ntpd --- Testing/minitools_test.py | 51 +++++++++++++++++++-------------------- Tools/aa-complain | 2 +- apparmor/aa.py | 33 ++++++++++++++----------- apparmor/tools.py | 20 ++++++++------- 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/Testing/minitools_test.py b/Testing/minitools_test.py index 1497f519a..37d93326d 100644 --- a/Testing/minitools_test.py +++ b/Testing/minitools_test.py @@ -7,8 +7,10 @@ import unittest import apparmor.aa as apparmor +# Path for the program test_path = '/usr/sbin/ntpd' -local_profilename = None +# Path for the target file containing profile +local_profilename = './profiles/usr.sbin.ntpd' python_interpreter = 'python' if sys.version_info >= (3,0): @@ -18,71 +20,71 @@ class Test(unittest.TestCase): def test_audit(self): #Set ntpd profile to audit mode and check if it was correctly set - subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles ntpd'%python_interpreter, shell=True) - local_profilename = apparmor.get_profile_filename(test_path) - self.assertEqual(apparmor.get_profile_flags(local_profilename), 'audit', 'Audit flag could not be set in profile %s'%local_profilename) + str(subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles %s'%(python_interpreter, test_path), shell=True)) + + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), 'audit', 'Audit flag could not be set in profile %s'%local_profilename) #Remove audit mode from ntpd profile and check if it was correctly removed - subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles -r ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles -r %s'%(python_interpreter, test_path), shell=True) - self.assertEqual(apparmor.get_profile_flags(local_profilename), None, 'Complain flag could not be removed in profile %s'%local_profilename) + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), None, 'Complain flag could not be removed in profile %s'%local_profilename) def test_complain(self): #Set ntpd profile to complain mode and check if it was correctly set - subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/force-complain/%s'%os.path.basename(local_profilename)), True, 'Failed to create a symlink for %s in force-complain'%local_profilename) - self.assertEqual(apparmor.get_profile_flags(local_profilename), 'complain', 'Complain flag could not be set in profile %s'%local_profilename) + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), 'complain', 'Complain flag could not be set in profile %s'%local_profilename) #Set ntpd profile to enforce mode and check if it was correctly set - subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles -r ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles -r %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/force-complain/%s'%os.path.basename(local_profilename)), False, 'Failed to remove symlink for %s from force-complain'%local_profilename) self.assertEqual(os.path.islink('./profiles/disable/%s'%os.path.basename(local_profilename)), False, 'Failed to remove symlink for %s from disable'%local_profilename) - self.assertEqual(apparmor.get_profile_flags(local_profilename), None, 'Complain flag could not be removed in profile %s'%local_profilename) + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), None, 'Complain flag could not be removed in profile %s'%local_profilename) # Set audit flag and then complain flag in a profile - subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles ntpd'%python_interpreter, shell=True) - subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles %s'%(python_interpreter, test_path), shell=True) + subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/force-complain/%s'%os.path.basename(local_profilename)), True, 'Failed to create a symlink for %s in force-complain'%local_profilename) - self.assertEqual(apparmor.get_profile_flags(local_profilename), 'audit,complain', 'Complain flag could not be set in profile %s'%local_profilename) + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), 'audit,complain', 'Complain flag could not be set in profile %s'%local_profilename) #Remove complain flag first i.e. set to enforce mode - subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles -r ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-complain -d ./profiles -r %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/force-complain/%s'%os.path.basename(local_profilename)), False, 'Failed to remove symlink for %s from force-complain'%local_profilename) self.assertEqual(os.path.islink('./profiles/disable/%s'%os.path.basename(local_profilename)), False, 'Failed to remove symlink for %s from disable'%local_profilename) - self.assertEqual(apparmor.get_profile_flags(local_profilename), 'audit', 'Complain flag could not be removed in profile %s'%local_profilename) + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), 'audit', 'Complain flag could not be removed in profile %s'%local_profilename) #Remove audit flag - subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles -r ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-audit -d ./profiles -r %s'%(python_interpreter, test_path), shell=True) def test_enforce(self): #Set ntpd profile to complain mode and check if it was correctly set - subprocess.check_output('%s ./../Tools/aa-enforce -d ./profiles -r ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-enforce -d ./profiles -r %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/force-complain/%s'%os.path.basename(local_profilename)), True, 'Failed to create a symlink for %s in force-complain'%local_profilename) - self.assertEqual(apparmor.get_profile_flags(local_profilename), 'complain', 'Complain flag could not be set in profile %s'%local_profilename) + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), 'complain', 'Complain flag could not be set in profile %s'%local_profilename) #Set ntpd profile to enforce mode and check if it was correctly set - subprocess.check_output('%s ./../Tools/aa-enforce -d ./profiles ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-enforce -d ./profiles %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/force-complain/%s'%os.path.basename(local_profilename)), False, 'Failed to remove symlink for %s from force-complain'%local_profilename) self.assertEqual(os.path.islink('./profiles/disable/%s'%os.path.basename(local_profilename)), False, 'Failed to remove symlink for %s from disable'%local_profilename) - self.assertEqual(apparmor.get_profile_flags(local_profilename), None, 'Complain flag could not be removed in profile %s'%local_profilename) + self.assertEqual(apparmor.get_profile_flags(local_profilename, test_path), None, 'Complain flag could not be removed in profile %s'%local_profilename) def test_disable(self): #Disable the ntpd profile and check if it was correctly disabled - subprocess.check_output('%s ./../Tools/aa-disable -d ./profiles ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-disable -d ./profiles %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/disable/%s'%os.path.basename(local_profilename)), True, 'Failed to create a symlink for %s in disable'%local_profilename) #Enable the ntpd profile and check if it was correctly re-enabled - subprocess.check_output('%s ./../Tools/aa-disable -d ./profiles -r ntpd'%python_interpreter, shell=True) + subprocess.check_output('%s ./../Tools/aa-disable -d ./profiles -r %s'%(python_interpreter, test_path), shell=True) self.assertEqual(os.path.islink('./profiles/disable/%s'%os.path.basename(local_profilename)), False, 'Failed to remove a symlink for %s from disable'%local_profilename) @@ -104,10 +106,7 @@ if __name__ == "__main__": shutil.copytree('/etc/apparmor.d', './profiles', symlinks=True) apparmor.profile_dir='./profiles' - - # Get the profile name for the test profile using current directory/path settings - local_profilename = apparmor.get_profile_filename(test_path) - + atexit.register(clean_profile_dir) unittest.main() diff --git a/Tools/aa-complain b/Tools/aa-complain index 08d7333c4..05211eeef 100644 --- a/Tools/aa-complain +++ b/Tools/aa-complain @@ -11,5 +11,5 @@ parser.add_argument('program', type=str, nargs='+', help='name of program') args = parser.parse_args() complain = apparmor.tools.aa_tools('complain', args) - +print(args) complain.act() diff --git a/apparmor/aa.py b/apparmor/aa.py index 5ee3f748a..7210b29cb 100644 --- a/apparmor/aa.py +++ b/apparmor/aa.py @@ -237,18 +237,18 @@ def enforce(path): fatal_error(_("Can't find %s") % path) set_enforce(prof_filename, name) -def set_complain(filename, program, ): +def set_complain(filename, program): """Sets the profile to complain mode""" UI_Info(_('Setting %s to complain mode.') % program) create_symlink('force-complain', filename) - change_profile_flags(filename, 'complain', True) + change_profile_flags(filename, program, 'complain', True) def set_enforce(filename, program): """Sets the profile to enforce mode""" UI_Info(_('Setting %s to enforce mode.') % program) delete_symlink('force-complain', filename) delete_symlink('disable', filename) - change_profile_flags(filename, 'complain', False) + change_profile_flags(filename, program, 'complain', False) def delete_symlink(subdir, filename): path = filename @@ -556,7 +556,7 @@ def autodep(bin_name, pname=''): filelist[file]['include']['tunables/global'] = True write_profile_ui_feedback(pname) -def get_profile_flags(filename): +def get_profile_flags(filename, program): # To-Do # XXX If more than one profile in a file then second one is being ignored XXX # Do we return flags for both or @@ -564,13 +564,17 @@ def get_profile_flags(filename): with open_file_read(filename) as f_in: for line in f_in: if RE_PROFILE_START.search(line): - flags = RE_PROFILE_START.search(line).groups()[6] - return flags + matches = RE_PROFILE_START.search(line).groups() + profile = matches[1] or matches[3] + flags = matches[6] + if profile == program: + return flags raise AppArmorException(_('%s contains no profile')%filename) -def change_profile_flags(filename, flag, set_flag): - old_flags = get_profile_flags(filename) +def change_profile_flags(filename, program, flag, set_flag): + old_flags = get_profile_flags(filename, program) + print(old_flags) newflags = [] if old_flags: # Flags maybe white-space and/or , separated @@ -592,9 +596,9 @@ def change_profile_flags(filename, flag, set_flag): newflags = ','.join(newflags) - set_profile_flags(filename, newflags) + set_profile_flags(filename, program, newflags) -def set_profile_flags(prof_filename, newflags): +def set_profile_flags(prof_filename, program, newflags): """Reads the old profile file and updates the flags accordingly""" regex_bin_flag = re.compile('^(\s*)(("??/.+?"??)|(profile\s+("??.+?"??)))\s+((flags=)?\((.*)\)\s+)?\{\s*(#.*)?$') regex_hat_flag = re.compile('^([a-z]*)\s+([A-Z]*)\s*(#.*)?$') @@ -616,10 +620,11 @@ def set_profile_flags(prof_filename, newflags): binary = matches[1] flag = matches[6] or 'flags=' flags = matches[7] - if newflags: - line = '%s%s %s(%s) {%s\n' % (space, binary, flag, newflags, comment) - else: - line = '%s%s {%s\n' % (space, binary, comment) + if binary == program: + if newflags: + line = '%s%s %s(%s) {%s\n' % (space, binary, flag, newflags, comment) + else: + line = '%s%s {%s\n' % (space, binary, comment) else: match = regex_hat_flag.search(line) if match: diff --git a/apparmor/tools.py b/apparmor/tools.py index b2a7ce5d4..e04f41af1 100644 --- a/apparmor/tools.py +++ b/apparmor/tools.py @@ -46,16 +46,18 @@ class aa_tools: if which: program = apparmor.get_full_path(which) - if (not program or not os.path.exists(program)): + apparmor.read_profiles() + #If program does not exists on the system but its profile does + if not program and apparmor.profile_exists(p): + program = p + + if not program or not(os.path.exists(program) or apparmor.profile_exists(program)): if program and not program.startswith('/'): program = apparmor.UI_GetString(_('The given program cannot be found, please try with the fully qualified path name of the program: '), '') else: apparmor.UI_Info(_("%s does not exist, please double-check the path.")%program) sys.exit(1) - #apparmor.loadincludes() - apparmor.read_profiles() - if program and apparmor.profile_exists(program):#os.path.exists(program): if self.name == 'autodep': self.use_autodep(program) @@ -71,18 +73,18 @@ class aa_tools: elif self.name == 'disable': if not self.revert: - apparmor.UI_Info(_('Disabling %s.\n')%program) + apparmor.UI_Info(_('Disabling %s.')%program) self.disable_profile(filename) else: - apparmor.UI_Info(_('Enabling %s.\n')%program) + apparmor.UI_Info(_('Enabling %s.')%program) self.enable_profile(filename) elif self.name == 'audit': if not self.remove: - apparmor.UI_Info(_('Setting %s to audit mode.\n')%program) + apparmor.UI_Info(_('Setting %s to audit mode.')%program) else: - apparmor.UI_Info(_('Removing audit mode from %s.\n')%program) - apparmor.change_profile_flags(filename, 'audit', not self.remove) + apparmor.UI_Info(_('Removing audit mode from %s.')%program) + apparmor.change_profile_flags(filename, program, 'audit', not self.remove) elif self.name == 'complain': if not self.remove: