def _run_test(self, params, expected):
        logfile = '%s.in' % params
        profile_dummy_file = 'AATest_does_exist'

        # we need to find out the profile name and aamode (complain vs. enforce mode) so that the test can access the correct place in storage
        parser = ReadLog('', '', '', '')
        parsed_event = parser.parse_event(read_file(logfile))

        if not parsed_event:  # AA_RECORD_INVALID
            return

        if params.split('/')[-1] in log_to_profile_skip:
            return

        aamode = parsed_event['aamode']

        if aamode in [
                'AUDIT', 'STATUS', 'HINT'
        ]:  # ignore some event types  # XXX maybe we shouldn't ignore AUDIT events?
            return

        if aamode not in ['PERMITTING', 'REJECTING']:
            raise Exception('Unexpected aamode %s' % parsed_event['aamode'])

        # cleanup apparmor.aa storage
        apparmor.aa.log = dict()
        apparmor.aa.aa = apparmor.aa.hasher()
        apparmor.aa.prelog = apparmor.aa.hasher()

        profile = parsed_event['profile']
        hat = profile
        if '//' in profile:
            profile, hat = profile.split('//')

        apparmor.aa.existing_profiles = {profile: profile_dummy_file}

        log_reader = ReadLog(dict(), logfile, apparmor.aa.existing_profiles,
                             '')
        log = log_reader.read_log('')

        for root in log:
            apparmor.aa.handle_children('', '',
                                        root)  # interactive for exec events!

        log_dict = apparmor.aa.collapse_log()

        apparmor.aa.filelist = apparmor.aa.hasher()
        apparmor.aa.filelist[profile_dummy_file]['profiles'][profile] = True

        new_profile = apparmor.aa.serialize_profile(log_dict[aamode][profile],
                                                    profile, None)

        expected_profile = read_file('%s.profile' % params)

        if params.split('/')[-1] in log_to_profile_known_failures:
            self.assertNotEqual(new_profile, expected_profile)  # known failure
        else:
            self.assertEqual(new_profile, expected_profile)
Example #2
0
    def _test_change_profile_flags(self, profile, old_flags, flags_to_change, set_flag, expected_flags, whitespace='', comment='',
                        more_rules='', expected_more_rules='@-@-@',
                        check_new_flags=True, profile_name='/foo'):
        if old_flags:
            old_flags = ' %s' % old_flags

        if expected_flags:
            expected_flags = ' flags=(%s)' % (expected_flags)
        else:
            expected_flags = ''

        if expected_more_rules == '@-@-@':
            expected_more_rules = more_rules

        if comment:
            comment = ' %s' % comment

        dummy_profile_content = '  #include <abstractions/base>\n  capability chown,\n  /bar r,'
        prof_template = '%s%s%s {%s\n%s\n%s\n}\n'
        old_prof = prof_template % (whitespace, profile, old_flags,      comment, more_rules,          dummy_profile_content)
        new_prof = prof_template % (whitespace, profile, expected_flags, comment, expected_more_rules, dummy_profile_content)

        self.file = write_file(self.tmpdir, 'profile', old_prof)
        change_profile_flags(self.file, profile_name, flags_to_change, set_flag)
        if check_new_flags:
            real_new_prof = read_file(self.file)
            self.assertEqual(new_prof, real_new_prof)
Example #3
0
    def _test_set_flags(self, profile, old_flags, new_flags, whitespace='', comment='',
                        more_rules='', expected_more_rules='@-@-@',
                        expected_flags='@-@-@', check_new_flags=True, profile_name='/foo'):
        if old_flags:
            old_flags = ' %s' % old_flags

        if expected_flags == '@-@-@':
            expected_flags = new_flags

        if expected_flags:
            expected_flags = ' flags=(%s)' % (expected_flags)
        else:
            expected_flags = ''

        if expected_more_rules == '@-@-@':
            expected_more_rules = more_rules

        if comment:
            comment = ' %s' % comment

        dummy_profile_content = '  #include <abstractions/base>\n  capability chown,\n  /bar r,'
        prof_template = '%s%s%s {%s\n%s\n%s\n}\n'
        old_prof = prof_template % (whitespace, profile, old_flags,      comment, more_rules,          dummy_profile_content)
        new_prof = prof_template % (whitespace, profile, expected_flags, comment, expected_more_rules, dummy_profile_content)

        self.file = write_file(self.tmpdir, 'profile', old_prof)
        set_profile_flags(self.file, profile_name, new_flags)
        if check_new_flags:
            real_new_prof = read_file(self.file)
            self.assertEqual(new_prof, real_new_prof)
Example #4
0
    def test_cleanprof(self):
        input_file = 'cleanprof_test.in'
        output_file = 'cleanprof_test.out'
        #We position the local testfile
        shutil.copy('./%s'%input_file, self.profile_dir)
        #Our silly test program whose profile we wish to clean
        cleanprof_test = '/usr/bin/a/simple/cleanprof/test/profile'

        subprocess.check_output('%s ./../aa-cleanprof  --no-reload -d %s -s %s' % (python_interpreter, self.profile_dir, cleanprof_test), shell=True)

        #Strip off the first line (#modified line)
        subprocess.check_output('sed -i 1d %s/%s' % (self.profile_dir, input_file), shell=True)

        exp_content = read_file('./%s' % output_file)
        real_content = read_file('%s/%s' % (self.profile_dir, input_file))
        self.maxDiff = None
        self.assertEqual(exp_content, real_content, 'Failed to cleanup profile properly')
Example #5
0
    def test_cleanprof(self):
        input_file = 'cleanprof_test.in'
        output_file = 'cleanprof_test.out'
        #We position the local testfile
        shutil.copy('./%s'%input_file, self.profile_dir)
        #Our silly test program whose profile we wish to clean
        cleanprof_test = '/usr/bin/a/simple/cleanprof/test/profile'

        subprocess.check_output('%s ./../aa-cleanprof  --no-reload -d %s -s %s' % (python_interpreter, self.profile_dir, cleanprof_test), shell=True)

        #Strip off the first line (#modified line)
        subprocess.check_output('sed -i 1d %s/%s' % (self.profile_dir, input_file), shell=True)

        exp_content = read_file('./%s' % output_file)
        real_content = read_file('%s/%s' % (self.profile_dir, input_file))
        self.maxDiff = None
        self.assertEqual(exp_content, real_content, 'Failed to cleanup profile properly')
Example #6
0
    def test_change_profile_flags_no_profile_found(self):
        # test behaviour if the file doesn't contain any profile
        orig_prof = '# /comment flags=(complain) {\n# }'
        self.file = write_file(self.tmpdir, 'profile', orig_prof)

        with self.assertRaises(AppArmorException):
            change_profile_flags(self.file, None, 'audit', True)

        # the file should not be changed
        real_new_prof = read_file(self.file)
        self.assertEqual(orig_prof, real_new_prof)
Example #7
0
    def test_change_profile_flags_other_profile(self):
        # test behaviour if the file doesn't contain the specified /foo profile
        orig_prof = '/no-such-profile flags=(complain) {\n}'
        self.file = write_file(self.tmpdir, 'profile', orig_prof)

        with self.assertRaises(AppArmorException):
            change_profile_flags(self.file, '/foo', 'audit', True)

        # the file should not be changed
        real_new_prof = read_file(self.file)
        self.assertEqual(orig_prof, real_new_prof)
Example #8
0
    def test_set_flags_no_profile_found(self):
        # test behaviour if the file doesn't contain any profile
        orig_prof = '# /comment flags=(complain) {\n# }'
        self.file = write_file(self.tmpdir, 'profile', orig_prof)

        with self.assertRaises(AppArmorBug):
            set_profile_flags(self.file, None, 'audit')

        # the file should not be changed
        real_new_prof = read_file(self.file)
        self.assertEqual(orig_prof, real_new_prof)
Example #9
0
    def test_set_flags_other_profile(self):
        # test behaviour if the file doesn't contain the specified /foo profile
        orig_prof = '/no-such-profile flags=(complain) {\n}'
        self.file = write_file(self.tmpdir, 'profile', orig_prof)

        with self.assertRaises(AppArmorBug):
            set_profile_flags(self.file, '/foo', 'audit')

        # the file should not be changed
        real_new_prof = read_file(self.file)
        self.assertEqual(orig_prof, real_new_prof)
Example #10
0
    def _run_test(self, params, expected):
        logfile = '%s.in' % params

        if params.split('/')[-1] in log_to_profile_skip:
            return

        profile, new_profile = logfile_to_profile(logfile)
        if profile is None:
            return

        expected_profile = read_file('%s.profile' % params)

        if params.split('/')[-1] in log_to_profile_known_failures:
            self.assertNotEqual(new_profile, expected_profile)  # known failure
        else:
            self.assertEqual(new_profile, expected_profile)
Example #11
0
def logfile_to_profile(logfile):
    profile_dummy_file = 'AATest_does_exist'

    # we need to find out the profile name and aamode (complain vs. enforce mode) so that the test can access the correct place in storage
    parser = ReadLog('', '', '')
    parsed_event = parser.parse_event(read_file(logfile))

    if not parsed_event:  # AA_RECORD_INVALID
        return None, 'INVALID'

    aamode = parsed_event['aamode']

    if aamode in [
            'AUDIT', 'STATUS', 'HINT'
    ]:  # ignore some event types  # XXX maybe we shouldn't ignore AUDIT events?
        return None, aamode

    if aamode not in ['PERMITTING', 'REJECTING']:
        raise Exception('Unexpected aamode %s' % parsed_event['aamode'])

    # cleanup apparmor.aa storage
    apparmor.aa.log = dict()
    apparmor.aa.aa = apparmor.aa.hasher()

    profile, hat = split_name(parsed_event['profile'])

    apparmor.aa.active_profiles = ProfileList()

    # optional for now, might be needed one day
    # if profile.startswith('/'):
    #     apparmor.aa.active_profiles.add_profile(profile_dummy_file, profile, profile)
    # else:
    apparmor.aa.active_profiles.add_profile(profile_dummy_file, profile, '')

    log_reader = ReadLog(logfile, apparmor.aa.active_profiles, '')
    hashlog = log_reader.read_log('')

    apparmor.aa.ask_exec(hashlog)
    apparmor.aa.ask_addhat(hashlog)

    log_dict = apparmor.aa.collapse_log(hashlog, ignore_null_profiles=False)

    if profile != hat:
        # log event for a child profile means log_dict only contains the child profile
        # initialize parent profile in log_dict as ProfileStorage to ensure writing the profile doesn't fail
        # (in "normal" usage outside of this test, log_dict will not be handed over to serialize_profile())

        if log_dict[aamode][profile][profile] != {}:
            raise Exception(
                'event for child profile, but parent profile was initialized nevertheless. Logfile: %s'
                % logfile)

        log_dict[aamode][profile][profile] = apparmor.aa.ProfileStorage(
            'TEST DUMMY for empty parent profile', profile_dummy_file,
            'logfile_to_profile()')

    log_is_empty = True

    for tmpaamode in hashlog:
        for tmpprofile in hashlog[tmpaamode]:
            for tmpruletype in hashlog[tmpaamode][tmpprofile]:
                if tmpruletype == 'final_name' and hashlog[tmpaamode][
                        tmpprofile]['final_name'] == tmpprofile:
                    continue  # final_name is a copy of the profile name (may be changed by ask_exec(), but that won't happen in this test)
                if hashlog[tmpaamode][tmpprofile][tmpruletype]:
                    log_is_empty = False

    if logfile.split('/')[-1][:-3] in log_to_profile_known_empty_log:
        # unfortunately this function might be called outside Unittest.TestCase, therefore we can't use assertEqual / assertNotEqual
        if log_is_empty == False:
            raise Exception(
                'got non-empty log for logfile in log_to_profile_known_empty_log: %s %s'
                % (logfile, hashlog))
    else:
        if log_is_empty == True:
            raise Exception(
                'got empty log for logfile not in log_to_profile_known_empty_log: %s %s'
                % (logfile, hashlog))

    new_profile = apparmor.aa.serialize_profile(log_dict[aamode][profile],
                                                profile, {})

    return profile, new_profile