2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-10-07 13:37:49 +00:00

Merge in Kshitij Gupta <kgupta8592@gmail.com>'s rewrite of the

logprof/genprof and related utilities in python. Because the branch that
was worked on was not based on the apparmor tree, not all of the history
can be maintained for files that are not newly created or entirely
rewritten in the branch.

(This merge also includes a subsequent commit to the branch
I was merging from which includes my missed bzr add of
utils/apparmor/translations.py)
This commit is contained in:
Steve Beattie
2014-02-12 15:54:00 -08:00
46 changed files with 9574 additions and 37 deletions

185
utils/apparmor/tools.py Normal file
View File

@@ -0,0 +1,185 @@
# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# ----------------------------------------------------------------------
import gettext
import os
import sys
import apparmor.aa as apparmor
from apparmor.common import user_perm
# setup module translations
from apparmor.translations import init_translation
_ = init_translation()
class aa_tools:
def __init__(self, tool_name, args):
self.name = tool_name
self.profiledir = args.dir
self.profiling = args.program
self.check_profile_dir()
self.silent = None
if tool_name in ['audit', 'complain']:
self.remove = args.remove
elif tool_name == 'disable':
self.revert = args.revert
self.disabledir = apparmor.profile_dir + '/disable'
self.check_disable_dir()
elif tool_name == 'autodep':
self.force = args.force
self.aa_mountpoint = apparmor.check_for_apparmor()
elif tool_name == 'cleanprof':
self.silent = args.silent
def check_profile_dir(self):
if self.profiledir:
apparmor.profile_dir = apparmor.get_full_path(self.profiledir)
if not os.path.isdir(apparmor.profile_dir):
raise apparmor.AppArmorException("%s is not a directory." % self.profiledir)
if not user_perm(apparmor.profile_dir):
raise apparmor.AppArmorException("Cannot write to profile directory: %s" % (apparmor.profile_dir))
def check_disable_dir(self):
if not os.path.isdir(self.disabledir):
raise apparmor.AppArmorException("Can't find AppArmor disable directory %s" % self.disabledir)
def act(self):
for p in self.profiling:
if not p:
continue
program = None
if os.path.exists(p):
program = apparmor.get_full_path(p).strip()
else:
which = apparmor.which(p)
if which:
program = apparmor.get_full_path(which)
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.") % p)
sys.exit(1)
if self.name == 'autodep' and program and os.path.exists(program):
self.use_autodep(program)
elif program and apparmor.profile_exists(program):
if self.name == 'cleanprof':
self.clean_profile(program, p)
else:
filename = apparmor.get_profile_filename(program)
if not os.path.isfile(filename) or apparmor.is_skippable_file(filename):
apparmor.UI_Info(_('Profile for %s not found, skipping') % p)
elif self.name == 'disable':
if not self.revert:
apparmor.UI_Info(_('Disabling %s.') % program)
self.disable_profile(filename)
else:
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.') % program)
else:
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:
apparmor.set_complain(filename, program)
else:
apparmor.set_enforce(filename, program)
#apparmor.set_profile_flags(filename, self.name)
else:
# One simply does not walk in here!
raise apparmor.AppArmorException('Unknown tool: %s' % self.name)
cmd_info = apparmor.cmd([apparmor.parser, filename, '-I%s' % apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])
#cmd_info = apparmor.cmd(['cat', filename, '|', apparmor.parser, '-I%s'%apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])
if cmd_info[0] != 0:
raise apparmor.AppArmorException(cmd_info[1])
else:
if '/' not in p:
apparmor.UI_Info(_("Can't find %s in the system path list. If the name of the application\nis correct, please run 'which %s' as a user with correct PATH\nenvironment set up in order to find the fully-qualified path and\nuse the full path as parameter.") % (p, p))
else:
apparmor.UI_Info(_("%s does not exist, please double-check the path.") % p)
sys.exit(1)
def clean_profile(self, program, p):
filename = apparmor.get_profile_filename(program)
import apparmor.cleanprofile as cleanprofile
prof = cleanprofile.Prof(filename)
cleanprof = cleanprofile.CleanProf(True, prof, prof)
deleted = cleanprof.remove_duplicate_rules(program)
apparmor.UI_Info(_("\nDeleted %s rules.") % deleted)
apparmor.changed[program] = True
if filename:
if not self.silent:
q = apparmor.hasher()
q['title'] = 'Changed Local Profiles'
q['headers'] = []
q['explanation'] = _('The local profile for %s in file %s was changed. Would you like to save it?') % (program, filename)
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
while ans != 'CMD_SAVE_CHANGES':
ans, arg = apparmor.UI_PromptUser(q)
if ans == 'CMD_SAVE_CHANGES':
apparmor.write_profile_ui_feedback(program)
apparmor.reload_base(program)
elif ans == 'CMD_VIEW_CHANGES':
#oldprofile = apparmor.serialize_profile(apparmor.original_aa[program], program, '')
newprofile = apparmor.serialize_profile(apparmor.aa[program], program, '')
apparmor.display_changes_with_comments(filename, newprofile)
else:
apparmor.write_profile_ui_feedback(program)
apparmor.reload_base(program)
else:
raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.') % p)
def use_autodep(self, program):
apparmor.check_qualifiers(program)
if os.path.exists(apparmor.get_profile_filename(program) and not self.force):
apparmor.UI_Info('Profile for %s already exists - skipping.' % program)
else:
apparmor.autodep(program)
if self.aa_mountpoint:
apparmor.reload(program)
def enable_profile(self, filename):
apparmor.delete_symlink('disable', filename)
def disable_profile(self, filename):
apparmor.create_symlink('disable', filename)