Hello, the reviews for r76..79 are attached. (No complaints about r76 and r78.)
Regards, Christian Boltz -- >> Microsoft-Compatible Spongiforme Encephalitis? > Setzt das nicht Hirn voraus? Irgendwo müssen doch all die Beschwörungsformeln hin, die man als MCSE auswendig lernen muß. Ein schwammförmiges Gehirn scheint mir dafür durchaus geeignet ... [Aran Kuntze, Gerhard Schromm und Martin Bienwald in dasr]
------------------------------------------------------------ revno: 79 committer: Kshitij Gupta <kgupta8...@gmail.com branch nick: apparmor-profile-tools timestamp: Mon 2013-09-23 21:00:36 +0530 message: (no message) === modified file 'apparmor/aa.py' --- apparmor/aa.py 2013-09-23 14:02:25 +0000 +++ apparmor/aa.py 2013-09-23 15:30:36 +0000 @@ -3030,8 +3030,12 @@ def set_allow_str(allow): if allow == 'deny': return 'deny ' - else: + elif allow == 'allow': return 'allow ' + elif allow == '': + return '' + else: + raise AppArmorException(_("Invalid allow string: %(allow)s")) # looks good (in theory), but in practise it seems all function calls pass in 'allow', not '' # which means we still get all lines prefixed with 'allow ' :-( # # Please change it to elif allow == 'allow': return '' # (better no "allow" than having "allow" everywhere ;-) vim:ft=diff
------------------------------------------------------------ revno: 77 committer: Kshitij Gupta <kgupta8...@gmail.com branch nick: apparmor-profile-tools timestamp: Mon 2013-09-23 19:32:25 +0530 message: Added first version of aa-mergeprof, does not include the check for conflicting ix rules yet === modified file 'apparmor/tools.py' --- apparmor/tools.py 2013-09-22 17:21:30 +0000 +++ apparmor/tools.py 2013-09-23 14:02:25 +0000 @@ -123,7 +123,7 @@ q = apparmor.hasher() q['title'] = 'Changed Local Profiles' q['headers'] = [] - q['explanation'] = _('The following local profiles were changed. Would you like to save them?') + q['explanation'] = _('The local profile for %s in file %s was changed. Would you like to save it?') %(program, filename) # good idea, but # - you should use %(program)s and %(filename)s instead of %s # - a \n wouldn't hurt ;-) # review of aa-mergeprof postponed until ask_the_question() is re-integrated into aa.py (as discussed on IRC) # # in other words: ignore everything below this line ;-) === modified file 'Tools/aa-mergeprof' --- Tools/aa-mergeprof 2013-09-22 22:17:15 +0000 +++ Tools/aa-mergeprof 2013-09-23 14:02:25 +0000 @@ -16,39 +18,70 @@ def main(): mergeprofiles = Merge(profiles) #Get rid of common/superfluous stuff mergeprofiles.clear_common() + if not args.auto: + mergeprofiles.ask_the_questions('other') + + mergeprofiles.clear_common() + print("base") + mergeprofiles.ask_the_questions('base') + + q = apparmor.aa.hasher() + q['title'] = 'Changed Local Profiles' + q['headers'] = [] + q['explanation'] = _('The following local profiles were changed. Would you like to save them?') + q['functions'] = ['CMD_SAVE_CHANGES', 'CMD_VIEW_CHANGES', 'CMD_ABORT'] + q['default'] = 'CMD_VIEW_CHANGES' + q['options'] = [] + q['selected'] = 0 + p =None + ans = '' + arg = None + programs = list(mergeprofiles.user.aa.keys()) + program = programs[0] + while ans != 'CMD_SAVE_CHANGES': + ans, arg = apparmor.aa.UI_PromptUser(q) + if ans == 'CMD_SAVE_CHANGES': + apparmor.aa.write_profile_ui_feedback(program) + apparmor.aa.reload_base(program) + elif ans == 'CMD_VIEW_CHANGES': + for program in programs: + apparmor.aa.original_aa[program] = apparmor.aa.deepcopy(apparmor.aa.aa[program]) + #oldprofile = apparmor.serialize_profile(apparmor.original_aa[program], program, '') + newprofile = apparmor.aa.serialize_profile(mergeprofiles.user.aa[program], program, '') + apparmor.aa.display_changes_with_comments(mergeprofiles.user.filename, newprofile) + @@ -64,453 +97,526 @@ + def ask_the_questions(self, other): + if other == 'other': + other = self.other + else: + other = self.base + #print(other.aa) + + #Add the file-wide includes from the other profile to the user profile + done = False + options = list(map(lambda inc: '#include <%s>' %inc, sorted(other.filelist[other.filename]['include'].keys()))) + q = apparmor.aa.hasher() + q['options'] = options + default_option = 1 + q['selected'] = default_option - 1 + q['headers'] = [_('File includes'), _('Select the ones you wish to add')] + q['functions'] = ['CMD_ALLOW', 'CMD_IGNORE_ENTRY', 'CMD_ABORT', 'CMD_FINISHED'] + q['default'] = 'CMD_ALLOW' + while not done and options: + ans, selected = apparmor.aa.UI_PromptUser(q) + if ans == 'CMD_IGNORE_ENTRY': + done = True + elif ans == 'CMD_ALLOW': + selection = options[selected] + inc = apparmor.aa.re_match_include(selection) + self.user.filelist[self.user.filename]['include'][inc] = True + options.pop(selected) + apparmor.aa.UI_Info(_('Adding %s to the file.') % selection) + + + sev_db = apparmor.aa.sev_db + if not sev_db: + sev_db = apparmor.severity.Severity(apparmor.aa.CONFDIR + '/severity.db', _('unknown')) + for profile in sorted(other.aa.keys()): + for hat in sorted(other.aa[profile].keys()): + #Add the includes from the other profile to the user profile + done = False + options = list(map(lambda inc: '#include <%s>' %inc, sorted(other.aa[profile][hat]['include'].keys()))) + q = apparmor.aa.hasher() + q['options'] = options + default_option = 1 + q['selected'] = default_option - 1 + q['headers'] = [_('File includes'), _('Select the ones you wish to add')] + q['functions'] = ['CMD_ALLOW', 'CMD_IGNORE_ENTRY', 'CMD_ABORT', 'CMD_FINISHED'] + q['default'] = 'CMD_ALLOW' + while not done and options: + ans, selected = apparmor.aa.UI_PromptUser(q) + if ans == 'CMD_IGNORE_ENTRY': + done = True + elif ans == 'CMD_ALLOW': + selection = options[selected] + inc = apparmor.aa.re_match_include(selection) + deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc) + self.user.aa[profile][hat]['include'][inc] = True + options.pop(selected) + apparmor.aa.UI_Info(_('Adding %s to the file.') % selection) + if deleted: + apparmor.aa.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) + + #Add the capabilities + for allow in ['allow', 'deny']: + if other.aa[profile][hat].get(allow, False): + continue + for capability in sorted(other.aa[profile][hat][allow]['capability'].keys()): + severity = sev_db.rank('CAP_%s' % capability) + default_option = 1 + options = [] + newincludes = apparmor.aa.match_cap_includes(self.user.aa[profile][hat], capability) + q = apparmor.aa.hasher() + if newincludes: + options += list(map(lambda inc: '#include <%s>' %inc, sorted(set(newincludes)))) + + if options: + options.append('capability %s' % capability) + q['options'] = [options] + q['selected'] = default_option - 1 + + q['headers'] = [_('Profile'), apparmor.aa.combine_name(profile, hat)] + q['headers'] += [_('Capability'), capability] + q['headers'] += [_('Severity'), severity] + + audit_toggle = 0 + + q['functions'] = ['CMD_ALLOW', 'CMD_DENY', 'CMD_IGNORE_ENTRY', 'CMD_ABORT', 'CMD_FINISHED'] + + q['default'] = 'CMD_ALLOW' + + done = False + while not done: + ans, selected = apparmor.aa.UI_PromptUser(q) + # Ignore the log entry + if ans == 'CMD_IGNORE_ENTRY': + done = True + break + + if ans == 'CMD_ALLOW': + selection = '' + if options: + selection = options[selected] + match = apparmor.aa.re_match_include(selection) + if match: + deleted = False + inc = match + deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc) + self.user.aa[profile][hat]['include'][inc] = True + + apparmor.aa.UI_Info(_('Adding %s to profile.') % selection) + if deleted: + apparmor.aa.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) + + self.user.aa[profile][hat]['allow']['capability'][capability]['set'] = True + self.user.aa[profile][hat]['allow']['capability'][capability]['audit'] = other.aa[profile][hat]['allow']['capability'][capability]['audit'] + + apparmor.aa.changed[profile] = True + + apparmor.aa.UI_Info(_('Adding capability %s to profile.'), capability) + done = True + + elif ans == 'CMD_DENY': + self.user.aa[profile][hat]['deny']['capability'][capability]['set'] = True + apparmor.aa.changed[profile] = True + + apparmor.aa.UI_Info(_('Denying capability %s to profile.') % capability) + done = True + else: + done = False + + # Process all the path entries. + for allow in ['allow', 'deny']: + for path in sorted(other.aa[profile][hat][allow]['path'].keys()): + #print(path, other.aa[profile][hat][allow]['path'][path]) + mode = other.aa[profile][hat][allow]['path'][path]['mode'] + # Lookup modes from profile + allow_mode = set() + allow_audit = set() + deny_mode = set() + deny_audit = set() + + fmode, famode, fm = apparmor.aa.rematchfrag(self.user.aa[profile][hat], 'allow', path) + if fmode: + allow_mode |= fmode + if famode: + allow_audit |= famode + + cm, cam, m = apparmor.aa.rematchfrag(self.user.aa[profile][hat], 'deny', path) + if cm: + deny_mode |= cm + if cam: + deny_audit |= cam + + imode, iamode, im = apparmor.aa.match_prof_incs_to_path(self.user.aa[profile][hat], 'allow', path) + if imode: + allow_mode |= imode + if iamode: + allow_audit |= iamode + + cm, cam, m = apparmor.aa.match_prof_incs_to_path(self.user.aa[profile][hat], 'deny', path) + if cm: + deny_mode |= cm + if cam: + deny_audit |= cam + + if deny_mode & apparmor.aa.AA_MAY_EXEC: + deny_mode |= apparmor.aamode.ALL_AA_EXEC_TYPE + + # Mask off the denied modes + mode = mode - deny_mode + + # If we get an exec request from some kindof event that generates 'PERMITTING X' + # check if its already in allow_mode + # if not add ix permission + if mode & apparmor.aa.AA_MAY_EXEC: + # Remove all type access permission + mode = mode - apparmor.aamode.ALL_AA_EXEC_TYPE + if not allow_mode & apparmor.aa.AA_MAY_EXEC: + mode |= apparmor.aa.str_to_mode('ix') + + # m is not implied by ix + + ### If we get an mmap request, check if we already have it in allow_mode + ##if mode & AA_EXEC_MMAP: + ## # ix implies m, so we don't need to add m if ix is present + ## if contains(allow_mode, 'ix'): + ## mode = mode - AA_EXEC_MMAP + + if not mode: + continue + + matches = [] + + if fmode: + apparmor.aa.matches.append(fm) + + if imode: + apparmor.aa.matches.append(im) + + if not apparmor.aa.mode_contains(allow_mode, mode): + default_option = 1 + options = [] + newincludes = [] + include_valid = False + + for incname in apparmor.aa.include.keys(): + include_valid = False + # If already present skip + if self.user.aa[profile][hat][incname]: + continue + if incname.startswith(apparmor.aa.profile_dir): + incname = incname.replace(apparmor.aa.profile_dir+'/', '', 1) + + include_valid = apparmor.aa.valid_include('', incname) + + if not include_valid: + continue + + cm, am, m = apparmor.aa.match_include_to_path(incname, 'allow', path) + + if cm and apparmor.aa.mode_contains(cm, mode): + dm = apparmor.aa.match_include_to_path(incname, 'deny', path)[0] + # If the mode is denied + if not mode & dm: + if not list(filter(lambda s: '/**' == s, m)): + newincludes.append(incname) + # Add new includes to the options + if newincludes: + options += list(map(lambda s: '#include <%s>' % s, sorted(set(newincludes)))) + # We should have literal the path in options list too + options.append(path) + # Add any the globs matching path from logprof + globs = apparmor.aa.glob_common(path) + if globs: + matches += globs + # Add any user entered matching globs + for user_glob in apparmor.aa.user_globs: + if apparmor.aa.matchliteral(user_glob, path): + matches.append(user_glob) + + matches = list(set(matches)) + if path in matches: + matches.remove(path) + + options += apparmor.aa.order_globs(matches, path) + default_option = len(options) + + sev_db.unload_variables() + sev_db.load_variables(apparmor.aa.get_profile_filename(profile)) + severity = sev_db.rank(path, apparmor.aa.mode_to_str(mode)) + sev_db.unload_variables() + + audit_toggle = 0 + owner_toggle = 0 + if apparmor.aa.cfg['settings']['default_owner_prompt']: + owner_toggle = apparmor.aa.cfg['settings']['default_owner_prompt'] + done = False + while not done: + q = apparmor.aa.hasher() + q['headers'] = [_('Profile'), apparmor.aa.combine_name(profile, hat), + _('Path'), path] + + if allow_mode: + mode |= allow_mode + tail = '' + s = '' + prompt_mode = None + if owner_toggle == 0: + prompt_mode = apparmor.aa.flatten_mode(mode) + tail = ' ' + _('(owner permissions off)') + elif owner_toggle == 1: + prompt_mode = mode + elif owner_toggle == 2: + prompt_mode = allow_mode | apparmor.aa.owner_flatten_mode(mode - allow_mode) + tail = ' ' + _('(force new perms to owner)') + else: + prompt_mode = apparmor.aa.owner_flatten_mode(mode) + tail = ' ' + _('(force all rule perms to owner)') + + if audit_toggle == 1: + s = apparmor.aa.mode_to_str_user(allow_mode) + if allow_mode: + s += ', ' + s += 'audit ' + apparmor.aa.mode_to_str_user(prompt_mode - allow_mode) + tail + elif audit_toggle == 2: + s = 'audit ' + apparmor.aa.mode_to_str_user(prompt_mode) + tail + else: + s = apparmor.aa.mode_to_str_user(prompt_mode) + tail + + q['headers'] += [_('Old Mode'), apparmor.aa.mode_to_str_user(allow_mode), + _('New Mode'), s] + + else: + s = '' + tail = '' + prompt_mode = None + if audit_toggle: + s = 'audit' + if owner_toggle == 0: + prompt_mode = apparmor.aa.flatten_mode(mode) + tail = ' ' + _('(owner permissions off)') + elif owner_toggle == 1: + prompt_mode = mode + else: + prompt_mode = apparmor.aa.owner_flatten_mode(mode) + tail = ' ' + _('(force perms to owner)') + + s = apparmor.aa.mode_to_str_user(prompt_mode) + q['headers'] += [_('Mode'), s] + + q['headers'] += [_('Severity'), severity] + q['options'] = options + q['selected'] = default_option - 1 + q['functions'] = ['CMD_ALLOW', 'CMD_DENY', 'CMD_IGNORE_ENTRY', 'CMD_GLOB', + 'CMD_GLOBEXT', 'CMD_NEW', 'CMD_ABORT', + 'CMD_FINISHED', 'CMD_OTHER'] + + q['default'] = 'CMD_ALLOW' + + + ans, selected = apparmor.aa.UI_PromptUser(q) + + if ans == 'CMD_IGNORE_ENTRY': + done = True + break + + if ans == 'CMD_OTHER': + audit_toggle, owner_toggle = apparmor.aa.UI_ask_mode_toggles(audit_toggle, owner_toggle, allow_mode) + elif ans == 'CMD_USER_TOGGLE': + owner_toggle += 1 + if not allow_mode and owner_toggle == 2: + owner_toggle += 1 + if owner_toggle > 3: + owner_toggle = 0 + elif ans == 'CMD_ALLOW': + path = options[selected] + done = True + match = apparmor.aa.re_match_include(path) + if match: + inc = match + deleted = 0 + deleted = apparmor.aa.delete_duplicates(aa[profile][hat], inc) + self.user.aa[profile][hat]['include'][inc] = True + apparmor.aa.changed[profile] = True + apparmor.aa.UI_Info(_('Adding %s to profile.') % path) + if deleted: + apparmor.aa.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) + + else: + if self.user.aa[profile][hat]['allow']['path'][path].get('mode', False): + mode |= self.user.aa[profile][hat]['allow']['path'][path]['mode'] + deleted = [] + for entry in self.user.aa[profile][hat]['allow']['path'].keys(): + if path == entry: + continue + + if apparmor.aa.matchregexp(path, entry): + if apparmor.aa.mode_contains(mode, self.user.aa[profile][hat]['allow']['path'][entry]['mode']): + deleted.append(entry) + for entry in deleted: + self.user.aa[profile][hat]['allow']['path'].pop(entry) + deleted = len(deleted) + + if owner_toggle == 0: + mode = apparmor.aa.flatten_mode(mode) + #elif owner_toggle == 1: + # mode = mode + elif owner_toggle == 2: + mode = allow_mode | apparmor.aa.owner_flatten_mode(mode - allow_mode) + elif owner_toggle == 3: + mode = apparmor.aa.owner_flatten_mode(mode) + + self.user.aa[profile][hat]['allow']['path'][path]['mode'] = self.user.aa[profile][hat]['allow']['path'][path].get('mode', set()) | mode + + tmpmode = set() + if audit_toggle == 1: + tmpmode = mode- allow_mode + elif audit_toggle == 2: + tmpmode = mode + + self.user.aa[profile][hat]['allow']['path'][path]['audit'] = self.user.aa[profile][hat]['allow']['path'][path].get('audit', set()) | tmpmode + + apparmor.aa.changed[profile] = True + + apparmor.aa.UI_Info(_('Adding %s %s to profile') % (path, apparmor.aa.mode_to_str_user(mode))) + if deleted: + apparmor.aa.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) + + elif ans == 'CMD_DENY': + path = options[selected].strip() + # Add new entry? + self.user.aa[profile][hat]['deny']['path'][path]['mode'] = self.user.aa[profile][hat]['deny']['path'][path].get('mode', set()) | (mode - allow_mode) + + self.user.aa[profile][hat]['deny']['path'][path]['audit'] = self.user.aa[profile][hat]['deny']['path'][path].get('audit', set()) + + apparmor.aa.changed[profile] = True + + done = True + + elif ans == 'CMD_NEW': + arg = options[selected] + if not apparmor.aa.re_match_include(arg): + ans = apparmor.aa.UI_GetString(_('Enter new path: '), arg) +# if ans: +# if not matchliteral(ans, path): +# ynprompt = _('The specified path does not match this log entry:\n\n Log Entry: %s\n Entered Path: %s\nDo you really want to use this path?') % (path,ans) +# key = apparmor.aa.UI_YesNo(ynprompt, 'n') +# if key == 'n': +# continue + apparmor.aa.user_globs.append(ans) + options.append(ans) + default_option = len(options) + + elif ans == 'CMD_GLOB': + newpath = options[selected].strip() + if not apparmor.aa.re_match_include(newpath): + newpath = apparmor.aa.glob_path(newpath) + + if newpath not in options: + options.append(newpath) + default_option = len(options) + else: + default_option = options.index(newpath) + 1 + + elif ans == 'CMD_GLOBEXT': + newpath = options[selected].strip() + if not apparmor.aa.re_match_include(newpath): + newpath = apparmor.aa.glob_path_withext(newpath) + + if newpath not in options: + options.append(newpath) + default_option = len(options) + else: + default_option = options.index(newpath) + 1 + + elif re.search('\d', ans): + default_option = ans + + # + for allow in ['allow', 'deny']: + for family in sorted(other.aa[profile][hat][allow]['netdomain']['rule'].keys()): + # severity handling for net toggles goes here + print(family) + for sock_type in sorted(other.aa[profile][hat][allow]['netdomain']['rule'][family].keys()): + if apparmor.aa.profile_known_network(self.user.aa[profile][hat], family, sock_type): + continue + default_option = 1 + options = [] + newincludes = apparmor.aa.match_net_includes(self.user.aa[profile][hat], family, sock_type) + q = apparmor.aa.hasher() + if newincludes: + options += list(map(lambda s: '#include <%s>'%s, sorted(set(newincludes)))) + if True:#options: + options.append('network %s %s' % (family, sock_type)) + q['options'] = options + q['selected'] = default_option - 1 + + q['headers'] = [_('Profile'), apparmor.aa.combine_name(profile, hat)] + q['headers'] += [_('Network Family'), family] + q['headers'] += [_('Socket Type'), sock_type] + + audit_toggle = 0 + q['functions'] = ['CMD_ALLOW', 'CMD_DENY', 'CMD_IGNORE_ENTRY', 'CMD_AUDIT_NEW', + 'CMD_ABORT', 'CMD_FINISHED'] + + q['default'] = 'CMD_ALLOW' + + done = False + while not done: + ans, selected = apparmor.aa.UI_PromptUser(q) + if ans == 'CMD_IGNORE_ENTRY': + done = True + break + + if ans.startswith('CMD_AUDIT'): + audit_toggle = not audit_toggle + audit = '' + if audit_toggle: + audit = 'audit' + q['functions'] = ['CMD_ALLOW', 'CMD_DENY', 'CMD_AUDIT_OFF', + 'CMD_ABORT', 'CMD_FINISHED'] + else: + q['functions'] = ['CMD_ALLOW', 'CMD_DENY', 'CMD_AUDIT_NEW', + 'CMD_ABORT', 'CMD_FINISHED'] + q['headers'] = [_('Profile'), apparmor.aa.combine_name(profile, hat)] + q['headers'] += [_('Network Family'), audit + family] + q['headers'] += [_('Socket Type'), sock_type] + + elif ans == 'CMD_ALLOW': + #print(options, selected) + selection = options[selected] + done = True + if apparmor.aa.re_match_include(selection): #re.search('#include\s+<.+>$', selection): + inc = apparmor.aa.re_match_include(selection) #re.search('#include\s+<(.+)>$', selection).groups()[0] + deleted = 0 + deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc) + + self.user.aa[profile][hat]['include'][inc] = True + + apparmor.aa.changed[profile] = True + + apparmor.aa.UI_Info(_('Adding %s to profile') % selection) + if deleted: + apparmor.aa.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) + + else: + self.user.aa[profile][hat]['allow']['netdomain']['audit'][family][sock_type] = audit_toggle + self.user.aa[profile][hat]['allow']['netdomain']['rule'][family][sock_type] = True + + apparmor.aa.changed[profile] = True + + apparmor.aa.UI_Info(_('Adding network access %s %s to profile.') % (family, sock_type)) + + elif ans == 'CMD_DENY': + done = True + self.user.aa[profile][hat]['deny']['netdomain']['rule'][family][sock_type] = True + apparmor.aa.changed[profile] = True + apparmor.aa.UI_Info(_('Denying network access %s %s to profile') % (family, sock_type)) + + else: + done = False + + vim:ft=diff
-- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor