Merge lp:~sbeattie/apparmor-profile-tools/pre-merger-cleanups into lp:apparmor-profile-tools

Proposed by Steve Beattie
Status: Merged
Merge reported by: Steve Beattie
Merged at revision: not available
Proposed branch: lp:~sbeattie/apparmor-profile-tools/pre-merger-cleanups
Merge into: lp:apparmor-profile-tools
Diff against target: 2957 lines (+481/-465)
20 files modified
Tools/aa-audit (+4/-3)
Tools/aa-autodep (+5/-4)
Tools/aa-cleanprof (+5/-4)
Tools/aa-complain (+4/-3)
Tools/aa-disable (+4/-3)
Tools/aa-enforce (+4/-3)
Tools/aa-genprof (+4/-3)
Tools/aa-logprof (+4/-3)
Tools/aa-mergeprof (+4/-3)
Tools/aa-unconfined (+4/-3)
apparmor/__init__.py (+0/-15)
apparmor/aa.py (+310/-284)
apparmor/aamode.py (+9/-9)
apparmor/common.py (+11/-19)
apparmor/config.py (+7/-7)
apparmor/logparser.py (+31/-27)
apparmor/severity.py (+18/-19)
apparmor/tools.py (+26/-21)
apparmor/ui.py (+27/-31)
apparmor/yasti.py (+0/-1)
To merge this branch: bzr merge lp:~sbeattie/apparmor-profile-tools/pre-merger-cleanups
Reviewer Review Type Date Requested Status
Kshitij Gupta Pending
Review via email: mp+205701@code.launchpad.net

Description of the change

Here are some simple cleanups in preparation for merging the new profile tools into trunk.

To post a comment you must log in.
Revision history for this message
Christian Boltz (cboltz) wrote :

Hello,

Am Dienstag, 11. Februar 2014 schrieb Steve Beattie:
> Steve Beattie has proposed merging
> lp:~sbeattie/apparmor-profile-tools/pre-merger-cleanups into
> lp:apparmor-profile-tools.
>
> Requested reviews:
> Kshitij Gupta (kgupta8592)
>
> For more details, see:
> https://code.launchpad.net/~sbeattie/apparmor-profile-tools/pre-merger
> -cleanups/+merge/205701
>
> Here are some simple cleanups in preparation for merging the new
> profile tools into trunk.

I had a look at the changes (hint: they are easier to read if you check
the individual commits, for example via the "For more details" link
above - for the pep8 commit, you might want to ignore whitespace
changes) and they all look good.

The only detail I don't like too much is that the changed translation
handling adds some lines to all aa-* tools - but that's something we
should fix with one of the next commits.

To sum it up: Kshitij, IMHO you can merge this :-)
or to say it in a more formal way:
Acked-by: Christian Boltz <email address hidden>

I'd recommend to merge it _before_ commiting my patches - Steve's
changes affect more lines, which also means the risk of merge conflicts
is quite big if you commit my patches first.

Regards,

Christian Boltz
--
Unix: Alles ist ein File, und was kein File ist, hat sich gefaelligst
als ein solches zu tarnen. [Wolfgang Weisselberg in linux-liste]

100. By Steve Beattie

Simplify the work tools and modules need to do to get the shared
translations. External utilities can still use their own textdomains
if they have strings that are not part of the apparmor-utils catalog.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Tools/aa-audit'
--- Tools/aa-audit 2014-02-01 01:34:08 +0000
+++ Tools/aa-audit 2014-02-12 00:39:55 +0000
@@ -15,11 +15,12 @@
15import argparse15import argparse
16import traceback16import traceback
1717
18from apparmor.common import init_translations
19init_translations()
20
21import apparmor.tools18import apparmor.tools
2219
20# setup module translations
21from apparmor.translations import init_translation
22_ = init_translation()
23
23parser = argparse.ArgumentParser(description=_('Switch the given programs to audit mode'))24parser = argparse.ArgumentParser(description=_('Switch the given programs to audit mode'))
24parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))25parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
25parser.add_argument('-r', '--remove', action='store_true', help=_('remove audit mode'))26parser.add_argument('-r', '--remove', action='store_true', help=_('remove audit mode'))
2627
=== modified file 'Tools/aa-autodep'
--- Tools/aa-autodep 2013-10-21 21:36:23 +0000
+++ Tools/aa-autodep 2014-02-12 00:39:55 +0000
@@ -14,11 +14,12 @@
14# ----------------------------------------------------------------------14# ----------------------------------------------------------------------
15import argparse15import argparse
1616
17from apparmor.common import init_translations
18init_translations()
19
20import apparmor.tools17import apparmor.tools
2118
19# setup module translations
20from apparmor.translations import init_translation
21_ = init_translation()
22
22parser = argparse.ArgumentParser(description=_('Generate a basic AppArmor profile by guessing requirements'))23parser = argparse.ArgumentParser(description=_('Generate a basic AppArmor profile by guessing requirements'))
23parser.add_argument('--force', type=str, help=_('overwrite existing profile'))24parser.add_argument('--force', type=str, help=_('overwrite existing profile'))
24parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))25parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
@@ -27,4 +28,4 @@
2728
28autodep = apparmor.tools.aa_tools('autodep', args)29autodep = apparmor.tools.aa_tools('autodep', args)
2930
30autodep.act()
31\ No newline at end of file31\ No newline at end of file
32autodep.act()
3233
=== modified file 'Tools/aa-cleanprof'
--- Tools/aa-cleanprof 2013-10-21 21:36:23 +0000
+++ Tools/aa-cleanprof 2014-02-12 00:39:55 +0000
@@ -14,11 +14,12 @@
14# ----------------------------------------------------------------------14# ----------------------------------------------------------------------
15import argparse15import argparse
1616
17from apparmor.common import init_translations
18init_translations()
19
20import apparmor.tools17import apparmor.tools
2118
19# setup module translations
20from apparmor.translations import init_translation
21_ = init_translation()
22
22parser = argparse.ArgumentParser(description=_('Cleanup the profiles for the given programs'))23parser = argparse.ArgumentParser(description=_('Cleanup the profiles for the given programs'))
23parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))24parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
24parser.add_argument('program', type=str, nargs='+', help=_('name of program'))25parser.add_argument('program', type=str, nargs='+', help=_('name of program'))
@@ -27,4 +28,4 @@
2728
28clean = apparmor.tools.aa_tools('cleanprof', args)29clean = apparmor.tools.aa_tools('cleanprof', args)
2930
30clean.act()
31\ No newline at end of file31\ No newline at end of file
32clean.act()
3233
=== modified file 'Tools/aa-complain'
--- Tools/aa-complain 2013-12-29 09:42:30 +0000
+++ Tools/aa-complain 2014-02-12 00:39:55 +0000
@@ -14,11 +14,12 @@
14# ----------------------------------------------------------------------14# ----------------------------------------------------------------------
15import argparse15import argparse
1616
17from apparmor.common import init_translations
18init_translations()
19
20import apparmor.tools17import apparmor.tools
2118
19# setup module translations
20from apparmor.translations import init_translation
21_ = init_translation()
22
22parser = argparse.ArgumentParser(description=_('Switch the given program to complain mode'))23parser = argparse.ArgumentParser(description=_('Switch the given program to complain mode'))
23parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))24parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
24parser.add_argument('-r', '--remove', action='store_true', help=_('remove complain mode'))25parser.add_argument('-r', '--remove', action='store_true', help=_('remove complain mode'))
2526
=== modified file 'Tools/aa-disable'
--- Tools/aa-disable 2013-10-21 21:36:23 +0000
+++ Tools/aa-disable 2014-02-12 00:39:55 +0000
@@ -14,11 +14,12 @@
14# ----------------------------------------------------------------------14# ----------------------------------------------------------------------
15import argparse15import argparse
1616
17from apparmor.common import init_translations
18init_translations()
19
20import apparmor.tools17import apparmor.tools
2118
19# setup module translations
20from apparmor.translations import init_translation
21_ = init_translation()
22
22parser = argparse.ArgumentParser(description=_('Disable the profile for the given programs'))23parser = argparse.ArgumentParser(description=_('Disable the profile for the given programs'))
23parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))24parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
24parser.add_argument('-r', '--revert', action='store_true', help=_('enable the profile for the given programs'))25parser.add_argument('-r', '--revert', action='store_true', help=_('enable the profile for the given programs'))
2526
=== modified file 'Tools/aa-enforce'
--- Tools/aa-enforce 2013-10-21 21:36:23 +0000
+++ Tools/aa-enforce 2014-02-12 00:39:55 +0000
@@ -14,11 +14,12 @@
14# ----------------------------------------------------------------------14# ----------------------------------------------------------------------
15import argparse15import argparse
1616
17from apparmor.common import init_translations
18init_translations()
19
20import apparmor.tools17import apparmor.tools
2118
19# setup module translations
20from apparmor.translations import init_translation
21_ = init_translation()
22
22parser = argparse.ArgumentParser(description=_('Switch the given program to enforce mode'))23parser = argparse.ArgumentParser(description=_('Switch the given program to enforce mode'))
23parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))24parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
24parser.add_argument('-r', '--remove', action='store_true', help=_('switch to complain mode'))25parser.add_argument('-r', '--remove', action='store_true', help=_('switch to complain mode'))
2526
=== modified file 'Tools/aa-genprof'
--- Tools/aa-genprof 2013-12-29 09:42:30 +0000
+++ Tools/aa-genprof 2014-02-12 00:39:55 +0000
@@ -19,11 +19,12 @@
19import subprocess19import subprocess
20import sys20import sys
2121
22from apparmor.common import init_translations
23init_translations()
24
25import apparmor.aa as apparmor22import apparmor.aa as apparmor
2623
24# setup module translations
25from apparmor.translations import init_translation
26_ = init_translation()
27
27def sysctl_read(path):28def sysctl_read(path):
28 value = None29 value = None
29 with open(path, 'r') as f_in:30 with open(path, 'r') as f_in:
3031
=== modified file 'Tools/aa-logprof'
--- Tools/aa-logprof 2013-12-29 09:42:30 +0000
+++ Tools/aa-logprof 2014-02-12 00:39:55 +0000
@@ -15,11 +15,12 @@
15import argparse15import argparse
16import os16import os
1717
18from apparmor.common import init_translations
19init_translations()
20
21import apparmor.aa as apparmor18import apparmor.aa as apparmor
2219
20# setup module translations
21from apparmor.translations import init_translation
22_ = init_translation()
23
23parser = argparse.ArgumentParser(description=_('Process log entries to generate profiles'))24parser = argparse.ArgumentParser(description=_('Process log entries to generate profiles'))
24parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))25parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
25parser.add_argument('-f', '--file', type=str, help=_('path to logfile'))26parser.add_argument('-f', '--file', type=str, help=_('path to logfile'))
2627
=== modified file 'Tools/aa-mergeprof'
--- Tools/aa-mergeprof 2013-10-21 21:36:23 +0000
+++ Tools/aa-mergeprof 2014-02-12 00:39:55 +0000
@@ -15,14 +15,15 @@
15import argparse15import argparse
16import sys16import sys
1717
18from apparmor.common import init_translations
19init_translations()
20
21import apparmor.aa18import apparmor.aa
22import apparmor.aamode19import apparmor.aamode
23import apparmor.severity20import apparmor.severity
24import apparmor.cleanprofile as cleanprofile21import apparmor.cleanprofile as cleanprofile
2522
23# setup module translations
24from apparmor.translations import init_translation
25_ = init_translation()
26
26parser = argparse.ArgumentParser(description=_('Perform a 3way merge on the given profiles'))27parser = argparse.ArgumentParser(description=_('Perform a 3way merge on the given profiles'))
27parser.add_argument('mine', type=str, help=_('your profile'))28parser.add_argument('mine', type=str, help=_('your profile'))
28parser.add_argument('base', type=str, help=_('base profile'))29parser.add_argument('base', type=str, help=_('base profile'))
2930
=== modified file 'Tools/aa-unconfined'
--- Tools/aa-unconfined 2013-12-29 09:42:30 +0000
+++ Tools/aa-unconfined 2014-02-12 00:39:55 +0000
@@ -17,11 +17,12 @@
17import re17import re
18import sys18import sys
1919
20from apparmor.common import init_translations
21init_translations()
22
23import apparmor.aa as apparmor20import apparmor.aa as apparmor
2421
22# setup module translations
23from apparmor.translations import init_translation
24_ = init_translation()
25
25parser = argparse.ArgumentParser(description=_("Lists unconfined processes having tcp or udp ports"))26parser = argparse.ArgumentParser(description=_("Lists unconfined processes having tcp or udp ports"))
26parser.add_argument("--paranoid", action="store_true", help=_("scan all processes from /proc"))27parser.add_argument("--paranoid", action="store_true", help=_("scan all processes from /proc"))
27args = parser.parse_args()28args = parser.parse_args()
2829
=== modified file 'apparmor/__init__.py'
--- apparmor/__init__.py 2013-12-19 21:42:58 +0000
+++ apparmor/__init__.py 2014-02-12 00:39:55 +0000
@@ -1,24 +1,9 @@
1# ------------------------------------------------------------------1# ------------------------------------------------------------------
2#2#
3# Copyright (C) 2011-2012 Canonical Ltd.3# Copyright (C) 2011-2012 Canonical Ltd.
4# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
5#4#
6# This program is free software; you can redistribute it and/or5# This program is free software; you can redistribute it and/or
7# modify it under the terms of version 2 of the GNU General Public6# modify it under the terms of version 2 of the GNU General Public
8# License published by the Free Software Foundation.7# License published by the Free Software Foundation.
9#8#
10# ------------------------------------------------------------------9# ------------------------------------------------------------------
11import gettext
12import locale
13
14def init_localisation():
15 locale.setlocale(locale.LC_ALL, '')
16 #If a correct locale has been provided set filename else let an IOError be raised
17 filename = '/usr/share/locale/%s/LC_MESSAGES/apparmor-utils.mo' % locale.getlocale()[0]
18 try:
19 trans = gettext.GNUTranslations(open(filename, 'rb'))
20 except IOError:
21 trans = gettext.NullTranslations()
22 trans.install()
23
24init_localisation()
2510
=== modified file 'apparmor/aa.py'
--- apparmor/aa.py 2014-02-01 00:44:05 +0000
+++ apparmor/aa.py 2014-02-12 00:39:55 +0000
@@ -13,11 +13,11 @@
13# ----------------------------------------------------------------------13# ----------------------------------------------------------------------
14# No old version logs, only 2.6 + supported14# No old version logs, only 2.6 + supported
15from __future__ import with_statement15from __future__ import with_statement
16import gettext
16import inspect17import inspect
17import os18import os
18import re19import re
19import shutil20import shutil
20import stat
21import subprocess21import subprocess
22import sys22import sys
23import time23import time
@@ -33,12 +33,20 @@
33from copy import deepcopy33from copy import deepcopy
3434
35from apparmor.common import (AppArmorException, error, debug, msg, cmd,35from apparmor.common import (AppArmorException, error, debug, msg, cmd,
36 open_file_read, valid_path,36 open_file_read, valid_path, hasher,
37 hasher, open_file_write, convert_regexp, DebugLogger)37 open_file_write, convert_regexp, DebugLogger)
3838
39from apparmor.ui import *39import apparmor.ui as aaui
4040
41from apparmor.aamode import *41from apparmor.aamode import (str_to_mode, mode_to_str, contains, split_mode,
42 mode_to_str_user, mode_contains, AA_OTHER,
43 flatten_mode, owner_flatten_mode)
44
45from apparmor.yasti import SendDataToYast, GetDataFromYast, shutdown_yast
46
47# setup module translations
48from apparmor.translations import init_translation
49_ = init_translation()
4250
43# Setup logging incase of debugging is enabled51# Setup logging incase of debugging is enabled
44debug_logger = DebugLogger('aa')52debug_logger = DebugLogger('aa')
@@ -67,7 +75,7 @@
6775
68existing_profiles = dict()76existing_profiles = dict()
6977
70seen_events = 0 # was our78seen_events = 0 # was our
71# To store the globs entered by users so they can be provided again79# To store the globs entered by users so they can be provided again
72user_globs = []80user_globs = []
7381
@@ -76,7 +84,7 @@
76t = hasher() # dict()84t = hasher() # dict()
77transitions = hasher()85transitions = hasher()
78aa = hasher() # Profiles originally in sd, replace by aa86aa = hasher() # Profiles originally in sd, replace by aa
79original_aa = hasher()87original_aa = hasher()
80extras = hasher() # Inactive profiles from extras88extras = hasher() # Inactive profiles from extras
81### end our89### end our
82log = []90log = []
@@ -85,11 +93,11 @@
85seen = hasher() # dir()93seen = hasher() # dir()
86profile_changes = hasher()94profile_changes = hasher()
87prelog = hasher()95prelog = hasher()
88log_dict = hasher()#dict()96log_dict = hasher() # dict()
89changed = dict()97changed = dict()
90created = []98created = []
91skip = hasher()99skip = hasher()
92helpers = dict() # Preserve this between passes # was our100helpers = dict() # Preserve this between passes # was our
93### logprof ends101### logprof ends
94102
95filelist = hasher() # File level variables and stuff in config files103filelist = hasher() # File level variables and stuff in config files
@@ -110,7 +118,7 @@
110 return False118 return False
111 size = os.stat(file).st_size119 size = os.stat(file).st_size
112 # Limit to checking files under 100k for the sake of speed120 # Limit to checking files under 100k for the sake of speed
113 if size >100000:121 if size > 100000:
114 return False122 return False
115 with open_file_read(file, encoding='ascii') as f_in:123 with open_file_read(file, encoding='ascii') as f_in:
116 for line in f_in:124 for line in f_in:
@@ -128,11 +136,11 @@
128 caller = inspect.stack()[1][3]136 caller = inspect.stack()[1][3]
129137
130 # If caller is SendDataToYast or GetDatFromYast simply exit138 # If caller is SendDataToYast or GetDatFromYast simply exit
131 if caller == 'SendDataToYast' or caller== 'GetDatFromYast':139 if caller == 'SendDataToYast' or caller == 'GetDatFromYast':
132 sys.exit(1)140 sys.exit(1)
133141
134 # Else tell user what happened142 # Else tell user what happened
135 UI_Important(message)143 aaui.UI_Important(message)
136 shutdown_yast()144 shutdown_yast()
137 sys.exit(1)145 sys.exit(1)
138146
@@ -164,7 +172,7 @@
164172
165def which(file):173def which(file):
166 """Returns the executable fullpath for the file, None otherwise"""174 """Returns the executable fullpath for the file, None otherwise"""
167 if sys.version_info >= (3,3):175 if sys.version_info >= (3, 3):
168 return shutil.which(file)176 return shutil.which(file)
169 env_dirs = os.getenv('PATH').split(':')177 env_dirs = os.getenv('PATH').split(':')
170 for env_dir in env_dirs:178 for env_dir in env_dirs:
@@ -238,33 +246,33 @@
238def complain(path):246def complain(path):
239 """Sets the profile to complain mode if it exists"""247 """Sets the profile to complain mode if it exists"""
240 prof_filename, name = name_to_prof_filename(path)248 prof_filename, name = name_to_prof_filename(path)
241 if not prof_filename :249 if not prof_filename:
242 fatal_error(_("Can't find %s") % path)250 fatal_error(_("Can't find %s") % path)
243 set_complain(prof_filename, name)251 set_complain(prof_filename, name)
244252
245def enforce(path):253def enforce(path):
246 """Sets the profile to enforce mode if it exists"""254 """Sets the profile to enforce mode if it exists"""
247 prof_filename, name = name_to_prof_filename(path)255 prof_filename, name = name_to_prof_filename(path)
248 if not prof_filename :256 if not prof_filename:
249 fatal_error(_("Can't find %s") % path)257 fatal_error(_("Can't find %s") % path)
250 set_enforce(prof_filename, name)258 set_enforce(prof_filename, name)
251259
252def set_complain(filename, program):260def set_complain(filename, program):
253 """Sets the profile to complain mode"""261 """Sets the profile to complain mode"""
254 UI_Info(_('Setting %s to complain mode.') % program)262 aaui.UI_Info(_('Setting %s to complain mode.') % program)
255 create_symlink('force-complain', filename)263 create_symlink('force-complain', filename)
256 change_profile_flags(filename, program, 'complain', True)264 change_profile_flags(filename, program, 'complain', True)
257265
258def set_enforce(filename, program):266def set_enforce(filename, program):
259 """Sets the profile to enforce mode"""267 """Sets the profile to enforce mode"""
260 UI_Info(_('Setting %s to enforce mode.') % program)268 aaui.UI_Info(_('Setting %s to enforce mode.') % program)
261 delete_symlink('force-complain', filename)269 delete_symlink('force-complain', filename)
262 delete_symlink('disable', filename)270 delete_symlink('disable', filename)
263 change_profile_flags(filename, program, 'complain', False)271 change_profile_flags(filename, program, 'complain', False)
264272
265def delete_symlink(subdir, filename):273def delete_symlink(subdir, filename):
266 path = filename274 path = filename
267 link = re.sub('^%s'%profile_dir, '%s/%s'%(profile_dir, subdir), path)275 link = re.sub('^%s' % profile_dir, '%s/%s' % (profile_dir, subdir), path)
268 if link != path and os.path.islink(link):276 if link != path and os.path.islink(link):
269 os.remove(link)277 os.remove(link)
270278
@@ -272,13 +280,13 @@
272 path = filename280 path = filename
273 bname = os.path.basename(filename)281 bname = os.path.basename(filename)
274 if not bname:282 if not bname:
275 raise AppArmorException(_('Unable to find basename for %s.')%filename)283 raise AppArmorException(_('Unable to find basename for %s.') % filename)
276 #print(filename)284 #print(filename)
277 link = re.sub('^%s'%profile_dir, '%s/%s'%(profile_dir, subdir), path)285 link = re.sub('^%s' % profile_dir, '%s/%s' % (profile_dir, subdir), path)
278 #print(link)286 #print(link)
279 #link = link + '/%s'%bname287 #link = link + '/%s'%bname
280 #print(link)288 #print(link)
281 symlink_dir=os.path.dirname(link)289 symlink_dir = os.path.dirname(link)
282 if not os.path.exists(symlink_dir):290 if not os.path.exists(symlink_dir):
283 # If the symlink directory does not exist create it291 # If the symlink directory does not exist create it
284 os.makedirs(symlink_dir)292 os.makedirs(symlink_dir)
@@ -287,7 +295,7 @@
287 try:295 try:
288 os.symlink(filename, link)296 os.symlink(filename, link)
289 except:297 except:
290 raise AppArmorException(_('Could not create %s symlink to %s.')%(link, filename))298 raise AppArmorException(_('Could not create %s symlink to %s.') % (link, filename))
291299
292def head(file):300def head(file):
293 """Returns the first/head line of the file"""301 """Returns the first/head line of the file"""
@@ -300,7 +308,7 @@
300 pass308 pass
301 return first309 return first
302 else:310 else:
303 raise AppArmorException(_('Unable to read first line from %s: File Not Found') %file)311 raise AppArmorException(_('Unable to read first line from %s: File Not Found') % file)
304312
305def get_output(params):313def get_output(params):
306 """Returns the return code output by running the program with the args given in the list"""314 """Returns the return code output by running the program with the args given in the list"""
@@ -314,7 +322,7 @@
314 # Get the output of the program322 # Get the output of the program
315 output = subprocess.check_output(params)323 output = subprocess.check_output(params)
316 except OSError as e:324 except OSError as e:
317 raise AppArmorException(_("Unable to fork: %s\n\t%s") %(program, str(e)))325 raise AppArmorException(_("Unable to fork: %s\n\t%s") % (program, str(e)))
318 # If exit-codes besides 0326 # If exit-codes besides 0
319 except subprocess.CalledProcessError as e:327 except subprocess.CalledProcessError as e:
320 output = e.output328 output = e.output
@@ -419,7 +427,7 @@
419427
420 created.append(localfile)428 created.append(localfile)
421 changed.append(localfile)429 changed.append(localfile)
422 430
423 debug_logger.debug("Profile for %s:\n\t%s" % (localfile, local_profile.__str__()))431 debug_logger.debug("Profile for %s:\n\t%s" % (localfile, local_profile.__str__()))
424 return {localfile: local_profile}432 return {localfile: local_profile}
425433
@@ -434,9 +442,9 @@
434 #prof_unload(local_prof)442 #prof_unload(local_prof)
435443
436def confirm_and_abort():444def confirm_and_abort():
437 ans = UI_YesNo(_('Are you sure you want to abandon this set of profile changes and exit?'), 'n')445 ans = aaui.UI_YesNo(_('Are you sure you want to abandon this set of profile changes and exit?'), 'n')
438 if ans == 'y':446 if ans == 'y':
439 UI_Info(_('Abandoning all changes.'))447 aaui.UI_Info(_('Abandoning all changes.'))
440 shutdown_yast()448 shutdown_yast()
441 for prof in created:449 for prof in created:
442 delete_profile(prof)450 delete_profile(prof)
@@ -449,13 +457,13 @@
449 local_profiles = []457 local_profiles = []
450 profile_hash = hasher()458 profile_hash = hasher()
451 if repo_is_enabled():459 if repo_is_enabled():
452 UI_BusyStart(_('Connecting to repository...'))460 aaui.UI_BusyStart(_('Connecting to repository...'))
453 status_ok, ret = fetch_profiles_by_name(repo_url, distro, prof_name)461 status_ok, ret = fetch_profiles_by_name(repo_url, distro, prof_name)
454 UI_BusyStop()462 aaui.UI_BusyStop()
455 if status_ok:463 if status_ok:
456 profile_hash = ret464 profile_hash = ret
457 else:465 else:
458 UI_Important(_('WARNING: Error fetching profiles from the repository'))466 aaui.UI_Important(_('WARNING: Error fetching profiles from the repository'))
459 inactive_profile = get_inactive_profile(prof_name)467 inactive_profile = get_inactive_profile(prof_name)
460 if inactive_profile:468 if inactive_profile:
461 uname = 'Inactive local profile for %s' % prof_name469 uname = 'Inactive local profile for %s' % prof_name
@@ -493,13 +501,12 @@
493501
494 ans = ''502 ans = ''
495 while 'CMD_USE_PROFILE' not in ans and 'CMD_CREATE_PROFILE' not in ans:503 while 'CMD_USE_PROFILE' not in ans and 'CMD_CREATE_PROFILE' not in ans:
496 ans, arg = UI_PromptUser(q)504 ans, arg = aaui.UI_PromptUser(q)
497 p = profile_hash[options[arg]]505 p = profile_hash[options[arg]]
498 q['selected'] = options.index(options[arg])506 q['selected'] = options.index(options[arg])
499 if ans == 'CMD_VIEW_PROFILE':507 if ans == 'CMD_VIEW_PROFILE':
500 if UI_mode == 'yast':508 if aaui.UI_mode == 'yast':
501 SendDataToYast({509 SendDataToYast({'type': 'dialogue-view-profile',
502 'type': 'dialogue-view-profile',
503 'user': options[arg],510 'user': options[arg],
504 'profile': p['profile'],511 'profile': p['profile'],
505 'profile_type': p['profile_type']512 'profile_type': p['profile_type']
@@ -530,7 +537,7 @@
530 if complain:537 if complain:
531 fname = get_profile_filename(pname)538 fname = get_profile_filename(pname)
532 set_profile_flags(profile_dir + fname, 'complain')539 set_profile_flags(profile_dir + fname, 'complain')
533 UI_Info(_('Setting %s to complain mode.') % pname)540 aaui.UI_Info(_('Setting %s to complain mode.') % pname)
534 except Exception as e:541 except Exception as e:
535 sys.stderr.write(_("Error activating profiles: %s") % e)542 sys.stderr.write(_("Error activating profiles: %s") % e)
536543
@@ -585,7 +592,7 @@
585 if profile == program:592 if profile == program:
586 return flags593 return flags
587594
588 raise AppArmorException(_('%s contains no profile')%filename)595 raise AppArmorException(_('%s contains no profile') % filename)
589596
590def change_profile_flags(filename, program, flag, set_flag):597def change_profile_flags(filename, program, flag, set_flag):
591 old_flags = get_profile_flags(filename, program)598 old_flags = get_profile_flags(filename, program)
@@ -595,7 +602,7 @@
595 # Flags maybe white-space and/or , separated602 # Flags maybe white-space and/or , separated
596 old_flags = old_flags.split(',')603 old_flags = old_flags.split(',')
597604
598 if type(old_flags) == type([]):605 if not isinstance(old_flags, str):
599 for i in old_flags:606 for i in old_flags:
600 newflags += i.split()607 newflags += i.split()
601 else:608 else:
@@ -619,7 +626,7 @@
619 regex_hat_flag = re.compile('^([a-z]*)\s+([A-Z]*)\s*(#.*)?$')626 regex_hat_flag = re.compile('^([a-z]*)\s+([A-Z]*)\s*(#.*)?$')
620 if os.path.isfile(prof_filename):627 if os.path.isfile(prof_filename):
621 with open_file_read(prof_filename) as f_in:628 with open_file_read(prof_filename) as f_in:
622 temp_file = tempfile.NamedTemporaryFile('w', prefix=prof_filename , suffix='~', delete=False, dir=profile_dir)629 temp_file = tempfile.NamedTemporaryFile('w', prefix=prof_filename, suffix='~', delete=False, dir=profile_dir)
623 shutil.copymode(prof_filename, temp_file.name)630 shutil.copymode(prof_filename, temp_file.name)
624 with open_file_write(temp_file.name) as f_out:631 with open_file_write(temp_file.name) as f_out:
625 for line in f_in:632 for line in f_in:
@@ -679,7 +686,7 @@
679 if not status_ok:686 if not status_ok:
680 if not ret:687 if not ret:
681 ret = 'UNKNOWN ERROR'688 ret = 'UNKNOWN ERROR'
682 UI_Important(_('WARNING: Error synchronizing profiles with the repository:\n%s\n') % ret)689 aaui.UI_Important(_('WARNING: Error synchronizing profiles with the repository:\n%s\n') % ret)
683 else:690 else:
684 users_repo_profiles = ret691 users_repo_profiles = ret
685 serialize_opts['NO_FLAGS'] = True692 serialize_opts['NO_FLAGS'] = True
@@ -717,7 +724,7 @@
717 else:724 else:
718 if not ret:725 if not ret:
719 ret = 'UNKNOWN ERROR'726 ret = 'UNKNOWN ERROR'
720 UI_Important(_('WARNING: Error synchronizing profiles with the repository\n%s') % ret)727 aaui.UI_Important(_('WARNING: Error synchronizing profiles with the repository\n%s') % ret)
721 continue728 continue
722 if p_repo != p_local:729 if p_repo != p_local:
723 changed_profiles.append(prof)730 changed_profiles.append(prof)
@@ -743,7 +750,7 @@
743def submit_created_profiles(new_profiles):750def submit_created_profiles(new_profiles):
744 #url = cfg['repository']['url']751 #url = cfg['repository']['url']
745 if new_profiles:752 if new_profiles:
746 if UI_mode == 'yast':753 if aaui.UI_mode == 'yast':
747 title = 'New Profiles'754 title = 'New Profiles'
748 message = 'Please select the newly created profiles that you would like to store in the repository'755 message = 'Please select the newly created profiles that you would like to store in the repository'
749 yast_select_and_upload_profiles(title, message, new_profiles)756 yast_select_and_upload_profiles(title, message, new_profiles)
@@ -755,7 +762,7 @@
755def submit_changed_profiles(changed_profiles):762def submit_changed_profiles(changed_profiles):
756 #url = cfg['repository']['url']763 #url = cfg['repository']['url']
757 if changed_profiles:764 if changed_profiles:
758 if UI_mode == 'yast':765 if aaui.UI_mode == 'yast':
759 title = 'Changed Profiles'766 title = 'Changed Profiles'
760 message = 'Please select which of the changed profiles would you like to upload to the repository'767 message = 'Please select which of the changed profiles would you like to upload to the repository'
761 yast_select_and_upload_profiles(title, message, changed_profiles)768 yast_select_and_upload_profiles(title, message, changed_profiles)
@@ -770,8 +777,7 @@
770 profs = profiles_up[:]777 profs = profiles_up[:]
771 for p in profs:778 for p in profs:
772 profile_changes[p[0]] = get_profile_diff(p[2], p[1])779 profile_changes[p[0]] = get_profile_diff(p[2], p[1])
773 SendDataToYast({780 SendDataToYast({'type': 'dialog-select-profiles',
774 'type': 'dialog-select-profiles',
775 'title': title,781 'title': title,
776 'explanation': message,782 'explanation': message,
777 'default_select': 'false',783 'default_select': 'false',
@@ -806,8 +812,8 @@
806 else:812 else:
807 if not ret:813 if not ret:
808 ret = 'UNKNOWN ERROR'814 ret = 'UNKNOWN ERROR'
809 UI_Important(_('WARNING: An error occurred while uploading the profile %s\n%s') % (p, ret))815 aaui.UI_Important(_('WARNING: An error occurred while uploading the profile %s\n%s') % (p, ret))
810 UI_Info(_('Uploaded changes to repository.'))816 aaui.UI_Info(_('Uploaded changes to repository.'))
811 if yarg.get('NEVER_ASK_AGAIN'):817 if yarg.get('NEVER_ASK_AGAIN'):
812 unselected_profiles = []818 unselected_profiles = []
813 for p in profs:819 for p in profs:
@@ -833,13 +839,13 @@
833 q['selected'] = 0839 q['selected'] = 0
834 ans = ''840 ans = ''
835 while 'CMD_UPLOAD_CHANGES' not in ans and 'CMD_ASK_NEVER' not in ans and 'CMD_ASK_LATER' not in ans:841 while 'CMD_UPLOAD_CHANGES' not in ans and 'CMD_ASK_NEVER' not in ans and 'CMD_ASK_LATER' not in ans:
836 ans, arg = UI_PromptUser(q)842 ans, arg = aaui.UI_PromptUser(q)
837 if ans == 'CMD_VIEW_CHANGES':843 if ans == 'CMD_VIEW_CHANGES':
838 display_changes(profs[arg][2], profs[arg][1])844 display_changes(profs[arg][2], profs[arg][1])
839 if ans == 'CMD_NEVER_ASK':845 if ans == 'CMD_NEVER_ASK':
840 set_profiles_local_only([i[0] for i in profs])846 set_profiles_local_only([i[0] for i in profs])
841 elif ans == 'CMD_UPLOAD_CHANGES':847 elif ans == 'CMD_UPLOAD_CHANGES':
842 changelog = UI_GetString(_('Changelog Entry: '), '')848 changelog = aaui.UI_GetString(_('Changelog Entry: '), '')
843 user, passw = get_repo_user_pass()849 user, passw = get_repo_user_pass()
844 if user and passw:850 if user and passw:
845 for p_data in profs:851 for p_data in profs:
@@ -847,19 +853,19 @@
847 prof_string = p_data[1]853 prof_string = p_data[1]
848 status_ok, ret = upload_profile(url, user, passw,854 status_ok, ret = upload_profile(url, user, passw,
849 cfg['repository']['distro'],855 cfg['repository']['distro'],
850 prof, prof_string, changelog )856 prof, prof_string, changelog)
851 if status_ok:857 if status_ok:
852 newprof = ret858 newprof = ret
853 newid = newprof['id']859 newid = newprof['id']
854 set_repo_info(aa[prof][prof], url, user, newid)860 set_repo_info(aa[prof][prof], url, user, newid)
855 write_profile_ui_feedback(prof)861 write_profile_ui_feedback(prof)
856 UI_Info('Uploaded %s to repository' % prof)862 aaui.UI_Info('Uploaded %s to repository' % prof)
857 else:863 else:
858 if not ret:864 if not ret:
859 ret = 'UNKNOWN ERROR'865 ret = 'UNKNOWN ERROR'
860 UI_Important(_('WARNING: An error occurred while uploading the profile %s\n%s') % (prof, ret))866 aaui.UI_Important(_('WARNING: An error occurred while uploading the profile %s\n%s') % (prof, ret))
861 else:867 else:
862 UI_Important(_('Repository Error\nRegistration or Signin was unsuccessful. User login\ninformation is required to upload profiles to the repository.\nThese changes could not be sent.'))868 aaui.UI_Important(_('Repository Error\nRegistration or Signin was unsuccessful. User login\ninformation is required to upload profiles to the repository.\nThese changes could not be sent.'))
863869
864def set_profiles_local_only(profs):870def set_profiles_local_only(profs):
865 for p in profs:871 for p in profs:
@@ -886,7 +892,7 @@
886 ret_list.append('CMD_EXEC_IX_OFF')892 ret_list.append('CMD_EXEC_IX_OFF')
887 if 'u' in options:893 if 'u' in options:
888 ret_list.append('CMD_ux')894 ret_list.append('CMD_ux')
889 895
890 else:896 else:
891 if 'i' in options:897 if 'i' in options:
892 ret_list.append('CMD_ix')898 ret_list.append('CMD_ix')
@@ -985,7 +991,7 @@
985991
986 seen_events += 1992 seen_events += 1
987993
988 ans = UI_PromptUser(q)994 ans = aaui.UI_PromptUser(q)
989995
990 transitions[context] = ans996 transitions[context] = ans
991997
@@ -1043,7 +1049,7 @@
1043 else:1049 else:
1044 do_execute = True1050 do_execute = True
10451051
1046 if mode & AA_MAY_LINK:1052 if mode & apparmor.aamode.AA_MAY_LINK:
1047 regex_link = re.compile('^from (.+) to (.+)$')1053 regex_link = re.compile('^from (.+) to (.+)$')
1048 match = regex_link.search(detail)1054 match = regex_link.search(detail)
1049 if match:1055 if match:
@@ -1090,7 +1096,7 @@
1090 combinedaudit = set()1096 combinedaudit = set()
1091 ## Check return Value Consistency1097 ## Check return Value Consistency
1092 # Check if path matches any existing regexps in profile1098 # Check if path matches any existing regexps in profile
1093 cm, am , m = rematchfrag(aa[profile][hat], 'allow', exec_target)1099 cm, am, m = rematchfrag(aa[profile][hat], 'allow', exec_target)
1094 if cm:1100 if cm:
1095 combinedmode |= cm1101 combinedmode |= cm
1096 if am:1102 if am:
@@ -1202,7 +1208,7 @@
1202 default = None1208 default = None
1203 if 'p' in options and os.path.exists(get_profile_filename(exec_target)):1209 if 'p' in options and os.path.exists(get_profile_filename(exec_target)):
1204 default = 'CMD_px'1210 default = 'CMD_px'
1205 sys.stdout.write(_('Target profile exists: %s\n') %get_profile_filename(exec_target))1211 sys.stdout.write(_('Target profile exists: %s\n') % get_profile_filename(exec_target))
1206 elif 'i' in options:1212 elif 'i' in options:
1207 default = 'CMD_ix'1213 default = 'CMD_ix'
1208 elif 'c' in options:1214 elif 'c' in options:
@@ -1241,7 +1247,7 @@
12411247
1242 ans = ''1248 ans = ''
1243 while not regex_options.search(ans):1249 while not regex_options.search(ans):
1244 ans = UI_PromptUser(q)[0].strip()1250 ans = aaui.UI_PromptUser(q)[0].strip()
1245 if ans.startswith('CMD_EXEC_IX_'):1251 if ans.startswith('CMD_EXEC_IX_'):
1246 exec_toggle = not exec_toggle1252 exec_toggle = not exec_toggle
1247 q['functions'] = []1253 q['functions'] = []
@@ -1252,7 +1258,7 @@
1252 arg = exec_target1258 arg = exec_target
1253 ynans = 'n'1259 ynans = 'n'
1254 if profile == hat:1260 if profile == hat:
1255 ynans = UI_YesNo(_('Are you specifying a transition to a local profile?'), 'n')1261 ynans = aaui.UI_YesNo(_('Are you specifying a transition to a local profile?'), 'n')
1256 if ynans == 'y':1262 if ynans == 'y':
1257 if ans == 'CMD_nx':1263 if ans == 'CMD_nx':
1258 ans = 'CMD_cx'1264 ans = 'CMD_cx'
@@ -1264,7 +1270,7 @@
1264 else:1270 else:
1265 ans = 'CMD_pix'1271 ans = 'CMD_pix'
12661272
1267 to_name = UI_GetString(_('Enter profile name to transition to: '), arg)1273 to_name = aaui.UI_GetString(_('Enter profile name to transition to: '), arg)
12681274
1269 regex_optmode = re.compile('CMD_(px|cx|nx|pix|cix|nix)')1275 regex_optmode = re.compile('CMD_(px|cx|nx|pix|cix|nix)')
1270 if ans == 'CMD_ix':1276 if ans == 'CMD_ix':
@@ -1277,18 +1283,18 @@
1277 if parent_uses_ld_xxx:1283 if parent_uses_ld_xxx:
1278 px_msg = _("Should AppArmor sanitise the environment when\nswitching profiles?\n\nSanitising environment is more secure,\nbut this application appears to be using LD_PRELOAD\nor LD_LIBRARY_PATH and sanitising the environment\ncould cause functionality problems.")1284 px_msg = _("Should AppArmor sanitise the environment when\nswitching profiles?\n\nSanitising environment is more secure,\nbut this application appears to be using LD_PRELOAD\nor LD_LIBRARY_PATH and sanitising the environment\ncould cause functionality problems.")
12791285
1280 ynans = UI_YesNo(px_msg, px_default)1286 ynans = aaui.UI_YesNo(px_msg, px_default)
1281 if ynans == 'y':1287 if ynans == 'y':
1282 # Disable the unsafe mode1288 # Disable the unsafe mode
1283 exec_mode = exec_mode - (AA_EXEC_UNSAFE | AA_OTHER(AA_EXEC_UNSAFE))1289 exec_mode = exec_mode - (apparmor.aamode.AA_EXEC_UNSAFE | AA_OTHER(apparmor.aamode.AA_EXEC_UNSAFE))
1284 elif ans == 'CMD_ux':1290 elif ans == 'CMD_ux':
1285 exec_mode = str_to_mode('ux')1291 exec_mode = str_to_mode('ux')
1286 ynans = UI_YesNo(_("Launching processes in an unconfined state is a very\ndangerous operation and can cause serious security holes.\n\nAre you absolutely certain you wish to remove all\nAppArmor protection when executing %s ?") % exec_target, 'n')1292 ynans = aaui.UI_YesNo(_("Launching processes in an unconfined state is a very\ndangerous operation and can cause serious security holes.\n\nAre you absolutely certain you wish to remove all\nAppArmor protection when executing %s ?") % exec_target, 'n')
1287 if ynans == 'y':1293 if ynans == 'y':
1288 ynans = UI_YesNo(_("Should AppArmor sanitise the environment when\nrunning this program unconfined?\n\nNot sanitising the environment when unconfining\na program opens up significant security holes\nand should be avoided if at all possible."), 'y')1294 ynans = aaui.UI_YesNo(_("Should AppArmor sanitise the environment when\nrunning this program unconfined?\n\nNot sanitising the environment when unconfining\na program opens up significant security holes\nand should be avoided if at all possible."), 'y')
1289 if ynans == 'y':1295 if ynans == 'y':
1290 # Disable the unsafe mode1296 # Disable the unsafe mode
1291 exec_mode = exec_mode - (AA_EXEC_UNSAFE | AA_OTHER(AA_EXEC_UNSAFE))1297 exec_mode = exec_mode - (apparmor.aamode.AA_EXEC_UNSAFE | AA_OTHER(apparmor.aamode.AA_EXEC_UNSAFE))
1292 else:1298 else:
1293 ans = 'INVALID'1299 ans = 'INVALID'
1294 transitions[context_new] = ans1300 transitions[context_new] = ans
@@ -1345,7 +1351,7 @@
13451351
1346 if ans == 'CMD_ix':1352 if ans == 'CMD_ix':
1347 if hat:1353 if hat:
1348 profile_changes[pid] = '%s//%s' %(profile, hat)1354 profile_changes[pid] = '%s//%s' % (profile, hat)
1349 else:1355 else:
1350 profile_changes[pid] = '%s//' % profile1356 profile_changes[pid] = '%s//' % profile
1351 elif re.search('^CMD_(px|nx|pix|nix)', ans):1357 elif re.search('^CMD_(px|nx|pix|nix)', ans):
@@ -1361,7 +1367,7 @@
1361 if not os.path.exists(get_profile_filename(exec_target)):1367 if not os.path.exists(get_profile_filename(exec_target)):
1362 ynans = 'y'1368 ynans = 'y'
1363 if exec_mode & str_to_mode('i'):1369 if exec_mode & str_to_mode('i'):
1364 ynans = UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') %exec_target, 'n')1370 ynans = aaui.UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n')
1365 if ynans == 'y':1371 if ynans == 'y':
1366 helpers[exec_target] = 'enforce'1372 helpers[exec_target] = 'enforce'
1367 if to_name:1373 if to_name:
@@ -1379,7 +1385,7 @@
1379 if not aa[profile].get(exec_target, False):1385 if not aa[profile].get(exec_target, False):
1380 ynans = 'y'1386 ynans = 'y'
1381 if exec_mode & str_to_mode('i'):1387 if exec_mode & str_to_mode('i'):
1382 ynans = UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n')1388 ynans = aaui.UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n')
1383 if ynans == 'y':1389 if ynans == 'y':
1384 hat = exec_target1390 hat = exec_target
1385 aa[profile][hat]['declared'] = False1391 aa[profile][hat]['declared'] = False
@@ -1488,9 +1494,9 @@
1488 for aamode in sorted(log_dict.keys()):1494 for aamode in sorted(log_dict.keys()):
1489 # Describe the type of changes1495 # Describe the type of changes
1490 if aamode == 'PERMITTING':1496 if aamode == 'PERMITTING':
1491 UI_Info(_('Complain-mode changes:'))1497 aaui.UI_Info(_('Complain-mode changes:'))
1492 elif aamode == 'REJECTING':1498 elif aamode == 'REJECTING':
1493 UI_Info(_('Enforce-mode changes:'))1499 aaui.UI_Info(_('Enforce-mode changes:'))
1494 else:1500 else:
1495 # This is so wrong!1501 # This is so wrong!
1496 fatal_error(_('Invalid mode found: %s') % aamode)1502 fatal_error(_('Invalid mode found: %s') % aamode)
@@ -1520,7 +1526,7 @@
1520 q = hasher()1526 q = hasher()
15211527
1522 if newincludes:1528 if newincludes:
1523 options += list(map(lambda inc: '#include <%s>' %inc, sorted(set(newincludes))))1529 options += list(map(lambda inc: '#include <%s>' % inc, sorted(set(newincludes))))
15241530
1525 if options:1531 if options:
1526 options.append('capability %s' % capability)1532 options.append('capability %s' % capability)
@@ -1546,7 +1552,7 @@
15461552
1547 done = False1553 done = False
1548 while not done:1554 while not done:
1549 ans, selected = UI_PromptUser(q)1555 ans, selected = aaui.UI_PromptUser(q)
1550 # Ignore the log entry1556 # Ignore the log entry
1551 if ans == 'CMD_IGNORE_ENTRY':1557 if ans == 'CMD_IGNORE_ENTRY':
1552 done = True1558 done = True
@@ -1574,27 +1580,27 @@
1574 match = re_match_include(selection)1580 match = re_match_include(selection)
1575 if match:1581 if match:
1576 deleted = False1582 deleted = False
1577 inc = match #.groups()[0]1583 inc = match # .groups()[0]
1578 deleted = delete_duplicates(aa[profile][hat], inc)1584 deleted = delete_duplicates(aa[profile][hat], inc)
1579 aa[profile][hat]['include'][inc] = True1585 aa[profile][hat]['include'][inc] = True
15801586
1581 UI_Info(_('Adding %s to profile.') % selection)1587 aaui.UI_Info(_('Adding %s to profile.') % selection)
1582 if deleted:1588 if deleted:
1583 UI_Info(_('Deleted %s previous matching profile entries.') % deleted)1589 aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
15841590
1585 aa[profile][hat]['allow']['capability'][capability]['set'] = True1591 aa[profile][hat]['allow']['capability'][capability]['set'] = True
1586 aa[profile][hat]['allow']['capability'][capability]['audit'] = audit_toggle1592 aa[profile][hat]['allow']['capability'][capability]['audit'] = audit_toggle
15871593
1588 changed[profile] = True1594 changed[profile] = True
15891595
1590 UI_Info(_('Adding capability %s to profile.') % capability)1596 aaui.UI_Info(_('Adding capability %s to profile.') % capability)
1591 done = True1597 done = True
15921598
1593 elif ans == 'CMD_DENY':1599 elif ans == 'CMD_DENY':
1594 aa[profile][hat]['deny']['capability'][capability]['set'] = True1600 aa[profile][hat]['deny']['capability'][capability]['set'] = True
1595 changed[profile] = True1601 changed[profile] = True
15961602
1597 UI_Info(_('Denying capability %s to profile.') % capability)1603 aaui.UI_Info(_('Denying capability %s to profile.') % capability)
1598 done = True1604 done = True
1599 else:1605 else:
1600 done = False1606 done = False
@@ -1632,7 +1638,7 @@
1632 if cam:1638 if cam:
1633 deny_audit |= cam1639 deny_audit |= cam
16341640
1635 if deny_mode & AA_MAY_EXEC:1641 if deny_mode & apparmor.aamode.AA_MAY_EXEC:
1636 deny_mode |= apparmor.aamode.ALL_AA_EXEC_TYPE1642 deny_mode |= apparmor.aamode.ALL_AA_EXEC_TYPE
16371643
1638 # Mask off the denied modes1644 # Mask off the denied modes
@@ -1641,10 +1647,10 @@
1641 # If we get an exec request from some kindof event that generates 'PERMITTING X'1647 # If we get an exec request from some kindof event that generates 'PERMITTING X'
1642 # check if its already in allow_mode1648 # check if its already in allow_mode
1643 # if not add ix permission1649 # if not add ix permission
1644 if mode & AA_MAY_EXEC:1650 if mode & apparmor.aamode.AA_MAY_EXEC:
1645 # Remove all type access permission1651 # Remove all type access permission
1646 mode = mode - apparmor.aamode.ALL_AA_EXEC_TYPE1652 mode = mode - apparmor.aamode.ALL_AA_EXEC_TYPE
1647 if not allow_mode & AA_MAY_EXEC:1653 if not allow_mode & apparmor.aamode.AA_MAY_EXEC:
1648 mode |= str_to_mode('ix')1654 mode |= str_to_mode('ix')
16491655
1650 # m is not implied by ix1656 # m is not implied by ix
@@ -1678,7 +1684,7 @@
1678 if aa[profile][hat][incname]:1684 if aa[profile][hat][incname]:
1679 continue1685 continue
1680 if incname.startswith(profile_dir):1686 if incname.startswith(profile_dir):
1681 incname = incname.replace(profile_dir+'/', '', 1)1687 incname = incname.replace(profile_dir + '/', '', 1)
16821688
1683 include_valid = valid_include('', incname)1689 include_valid = valid_include('', incname)
16841690
@@ -1725,7 +1731,7 @@
1725 owner_toggle = cfg['settings']['default_owner_prompt']1731 owner_toggle = cfg['settings']['default_owner_prompt']
1726 done = False1732 done = False
1727 while not done:1733 while not done:
1728 q = hasher()1734 q = hasher()
1729 q['headers'] = [_('Profile'), combine_name(profile, hat),1735 q['headers'] = [_('Profile'), combine_name(profile, hat),
1730 _('Path'), path]1736 _('Path'), path]
17311737
@@ -1789,7 +1795,7 @@
17891795
1790 seen_events += 11796 seen_events += 1
17911797
1792 ans, selected = UI_PromptUser(q)1798 ans, selected = aaui.UI_PromptUser(q)
17931799
1794 if ans == 'CMD_IGNORE_ENTRY':1800 if ans == 'CMD_IGNORE_ENTRY':
1795 done = True1801 done = True
@@ -1806,16 +1812,16 @@
1806 elif ans == 'CMD_ALLOW':1812 elif ans == 'CMD_ALLOW':
1807 path = options[selected]1813 path = options[selected]
1808 done = True1814 done = True
1809 match = re_match_include(path) #.search('^#include\s+<(.+)>$', path)1815 match = re_match_include(path) # .search('^#include\s+<(.+)>$', path)
1810 if match:1816 if match:
1811 inc = match #.groups()[0]1817 inc = match # .groups()[0]
1812 deleted = 01818 deleted = 0
1813 deleted = delete_duplicates(aa[profile][hat], inc)1819 deleted = delete_duplicates(aa[profile][hat], inc)
1814 aa[profile][hat]['include'][inc] = True1820 aa[profile][hat]['include'][inc] = True
1815 changed[profile] = True1821 changed[profile] = True
1816 UI_Info(_('Adding %s to profile.') % path)1822 aaui.UI_Info(_('Adding %s to profile.') % path)
1817 if deleted:1823 if deleted:
1818 UI_Info(_('Deleted %s previous matching profile entries.') % deleted)1824 aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
18191825
1820 else:1826 else:
1821 if aa[profile][hat]['allow']['path'][path].get('mode', False):1827 if aa[profile][hat]['allow']['path'][path].get('mode', False):
@@ -1845,7 +1851,7 @@
18451851
1846 tmpmode = set()1852 tmpmode = set()
1847 if audit_toggle == 1:1853 if audit_toggle == 1:
1848 tmpmode = mode- allow_mode1854 tmpmode = mode - allow_mode
1849 elif audit_toggle == 2:1855 elif audit_toggle == 2:
1850 tmpmode = mode1856 tmpmode = mode
18511857
@@ -1853,9 +1859,9 @@
18531859
1854 changed[profile] = True1860 changed[profile] = True
18551861
1856 UI_Info(_('Adding %s %s to profile') % (path, mode_to_str_user(mode)))1862 aaui.UI_Info(_('Adding %s %s to profile') % (path, mode_to_str_user(mode)))
1857 if deleted:1863 if deleted:
1858 UI_Info(_('Deleted %s previous matching profile entries.') % deleted)1864 aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
18591865
1860 elif ans == 'CMD_DENY':1866 elif ans == 'CMD_DENY':
1861 path = options[selected].strip()1867 path = options[selected].strip()
@@ -1871,11 +1877,11 @@
1871 elif ans == 'CMD_NEW':1877 elif ans == 'CMD_NEW':
1872 arg = options[selected]1878 arg = options[selected]
1873 if not re_match_include(arg):1879 if not re_match_include(arg):
1874 ans = UI_GetString(_('Enter new path: '), arg)1880 ans = aaui.UI_GetString(_('Enter new path: '), arg)
1875 if ans:1881 if ans:
1876 if not matchliteral(ans, path):1882 if not matchliteral(ans, path):
1877 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)1883 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)
1878 key = UI_YesNo(ynprompt, 'n')1884 key = aaui.UI_YesNo(ynprompt, 'n')
1879 if key == 'n':1885 if key == 'n':
1880 continue1886 continue
18811887
@@ -1919,7 +1925,7 @@
1919 newincludes = match_net_includes(aa[profile][hat], family, sock_type)1925 newincludes = match_net_includes(aa[profile][hat], family, sock_type)
1920 q = hasher()1926 q = hasher()
1921 if newincludes:1927 if newincludes:
1922 options += list(map(lambda s: '#include <%s>'%s, sorted(set(newincludes))))1928 options += list(map(lambda s: '#include <%s>' % s, sorted(set(newincludes))))
1923 if options:1929 if options:
1924 options.append('network %s %s' % (family, sock_type))1930 options.append('network %s %s' % (family, sock_type))
1925 q['options'] = options1931 q['options'] = options
@@ -1941,7 +1947,7 @@
19411947
1942 done = False1948 done = False
1943 while not done:1949 while not done:
1944 ans, selected = UI_PromptUser(q)1950 ans, selected = aaui.UI_PromptUser(q)
1945 if ans == 'CMD_IGNORE_ENTRY':1951 if ans == 'CMD_IGNORE_ENTRY':
1946 done = True1952 done = True
1947 break1953 break
@@ -1963,18 +1969,18 @@
1963 elif ans == 'CMD_ALLOW':1969 elif ans == 'CMD_ALLOW':
1964 selection = options[selected]1970 selection = options[selected]
1965 done = True1971 done = True
1966 if re_match_include(selection): #re.search('#include\s+<.+>$', selection):1972 if re_match_include(selection): # re.search('#include\s+<.+>$', selection):
1967 inc = re_match_include(selection) #re.search('#include\s+<(.+)>$', selection).groups()[0]1973 inc = re_match_include(selection) # re.search('#include\s+<(.+)>$', selection).groups()[0]
1968 deleted = 01974 deleted = 0
1969 deleted = delete_duplicates(aa[profile][hat], inc)1975 deleted = delete_duplicates(aa[profile][hat], inc)
19701976
1971 aa[profile][hat]['include'][inc] = True1977 aa[profile][hat]['include'][inc] = True
19721978
1973 changed[profile] = True1979 changed[profile] = True
19741980
1975 UI_Info(_('Adding %s to profile') % selection)1981 aaui.UI_Info(_('Adding %s to profile') % selection)
1976 if deleted:1982 if deleted:
1977 UI_Info(_('Deleted %s previous matching profile entries.') % deleted)1983 aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
19781984
1979 else:1985 else:
1980 aa[profile][hat]['allow']['netdomain']['audit'][family][sock_type] = audit_toggle1986 aa[profile][hat]['allow']['netdomain']['audit'][family][sock_type] = audit_toggle
@@ -1982,13 +1988,13 @@
19821988
1983 changed[profile] = True1989 changed[profile] = True
19841990
1985 UI_Info(_('Adding network access %s %s to profile.') % (family, sock_type))1991 aaui.UI_Info(_('Adding network access %s %s to profile.') % (family, sock_type))
19861992
1987 elif ans == 'CMD_DENY':1993 elif ans == 'CMD_DENY':
1988 done = True1994 done = True
1989 aa[profile][hat]['deny']['netdomain']['rule'][family][sock_type] = True1995 aa[profile][hat]['deny']['netdomain']['rule'][family][sock_type] = True
1990 changed[profile] = True1996 changed[profile] = True
1991 UI_Info(_('Denying network access %s %s to profile') % (family, sock_type))1997 aaui.UI_Info(_('Denying network access %s %s to profile') % (family, sock_type))
19921998
1993 else:1999 else:
1994 done = False2000 done = False
@@ -1998,13 +2004,13 @@
1998 if newpath[-1] == '/':2004 if newpath[-1] == '/':
1999 if newpath[-4:] == '/**/' or newpath[-3:] == '/*/':2005 if newpath[-4:] == '/**/' or newpath[-3:] == '/*/':
2000 # /foo/**/ and /foo/*/ => /**/2006 # /foo/**/ and /foo/*/ => /**/
2001 newpath = re.sub('/[^/]+/\*{1,2}/$', '/**/', newpath) #re.sub('/[^/]+/\*{1,2}$/', '/\*\*/', newpath)2007 newpath = re.sub('/[^/]+/\*{1,2}/$', '/**/', newpath) # re.sub('/[^/]+/\*{1,2}$/', '/\*\*/', newpath)
2002 elif re.search('/[^/]+\*\*[^/]*/$', newpath):2008 elif re.search('/[^/]+\*\*[^/]*/$', newpath):
2003 # /foo**/ and /foo**bar/ => /**/2009 # /foo**/ and /foo**bar/ => /**/
2004 newpath = re.sub('/[^/]+\*\*[^/]*/$', '/**/', newpath)2010 newpath = re.sub('/[^/]+\*\*[^/]*/$', '/**/', newpath)
2005 elif re.search('/\*\*[^/]+/$', newpath):2011 elif re.search('/\*\*[^/]+/$', newpath):
2006 # /**bar/ => /**/2012 # /**bar/ => /**/
2007 newpath = re.sub('/\*\*[^/]+/$', '/**/', newpath)2013 newpath = re.sub('/\*\*[^/]+/$', '/**/', newpath)
2008 else:2014 else:
2009 newpath = re.sub('/[^/]+/$', '/*/', newpath)2015 newpath = re.sub('/[^/]+/$', '/*/', newpath)
2010 else:2016 else:
@@ -2016,7 +2022,7 @@
2016 newpath = re.sub('/[^/]*\*\*[^/]+$', '/**', newpath)2022 newpath = re.sub('/[^/]*\*\*[^/]+$', '/**', newpath)
2017 elif re.search('/[^/]+\*\*$', newpath):2023 elif re.search('/[^/]+\*\*$', newpath):
2018 # /foo** => /**2024 # /foo** => /**
2019 newpath = re.sub('/[^/]+\*\*$', '/**', newpath)2025 newpath = re.sub('/[^/]+\*\*$', '/**', newpath)
2020 else:2026 else:
2021 newpath = re.sub('/[^/]+$', '/*', newpath)2027 newpath = re.sub('/[^/]+$', '/*', newpath)
2022 return newpath2028 return newpath
@@ -2027,19 +2033,19 @@
2027 match = re.search('/\*{1,2}(\.[^/]+)$', newpath)2033 match = re.search('/\*{1,2}(\.[^/]+)$', newpath)
2028 if match:2034 if match:
2029 # /foo/**.ext and /foo/*.ext => /**.ext2035 # /foo/**.ext and /foo/*.ext => /**.ext
2030 newpath = re.sub('/[^/]+/\*{1,2}\.[^/]+$', '/**'+match.groups()[0], newpath)2036 newpath = re.sub('/[^/]+/\*{1,2}\.[^/]+$', '/**' + match.groups()[0], newpath)
2031 elif re.search('/[^/]+\*\*[^/]*\.[^/]+$', newpath):2037 elif re.search('/[^/]+\*\*[^/]*\.[^/]+$', newpath):
2032 # /foo**.ext and /foo**bar.ext => /**.ext2038 # /foo**.ext and /foo**bar.ext => /**.ext
2033 match = re.search('/[^/]+\*\*[^/]*(\.[^/]+)$', newpath)2039 match = re.search('/[^/]+\*\*[^/]*(\.[^/]+)$', newpath)
2034 newpath = re.sub('/[^/]+\*\*[^/]*\.[^/]+$', '/**'+match.groups()[0], newpath)2040 newpath = re.sub('/[^/]+\*\*[^/]*\.[^/]+$', '/**' + match.groups()[0], newpath)
2035 elif re.search('/\*\*[^/]+\.[^/]+$', newpath):2041 elif re.search('/\*\*[^/]+\.[^/]+$', newpath):
2036 # /**foo.ext => /**.ext2042 # /**foo.ext => /**.ext
2037 match = re.search('/\*\*[^/]+(\.[^/]+)$', newpath)2043 match = re.search('/\*\*[^/]+(\.[^/]+)$', newpath)
2038 newpath = re.sub('/\*\*[^/]+\.[^/]+$', '/**'+match.groups()[0], newpath)2044 newpath = re.sub('/\*\*[^/]+\.[^/]+$', '/**' + match.groups()[0], newpath)
2039 else:2045 else:
2040 match = re.search('(\.[^/]+)$', newpath)2046 match = re.search('(\.[^/]+)$', newpath)
2041 if match:2047 if match:
2042 newpath = re.sub('/[^/]+(\.[^/]+)$', '/*'+match.groups()[0], newpath)2048 newpath = re.sub('/[^/]+(\.[^/]+)$', '/*' + match.groups()[0], newpath)
2043 return newpath2049 return newpath
20442050
2045def delete_net_duplicates(netrules, incnetrules):2051def delete_net_duplicates(netrules, incnetrules):
@@ -2081,7 +2087,7 @@
2081def delete_path_duplicates(profile, incname, allow):2087def delete_path_duplicates(profile, incname, allow):
2082 deleted = []2088 deleted = []
2083 for entry in profile[allow]['path'].keys():2089 for entry in profile[allow]['path'].keys():
2084 if entry == '#include <%s>'%incname:2090 if entry == '#include <%s>' % incname:
2085 continue2091 continue
2086 cm, am, m = match_include_to_path(incname, allow, entry)2092 cm, am, m = match_include_to_path(incname, allow, entry)
2087 if cm and mode_contains(cm, profile[allow]['path'][entry]['mode']) and mode_contains(am, profile[allow]['path'][entry]['audit']):2093 if cm and mode_contains(cm, profile[allow]['path'][entry]['mode']) and mode_contains(am, profile[allow]['path'][entry]['audit']):
@@ -2201,10 +2207,10 @@
2201 skip = hasher()2207 skip = hasher()
2202# filelist = hasher()2208# filelist = hasher()
22032209
2204 UI_Info(_('Reading log entries from %s.') %filename)2210 aaui.UI_Info(_('Reading log entries from %s.') % filename)
22052211
2206 if not passno:2212 if not passno:
2207 UI_Info(_('Updating AppArmor profiles in %s.') %profile_dir)2213 aaui.UI_Info(_('Updating AppArmor profiles in %s.') % profile_dir)
2208 read_profiles()2214 read_profiles()
22092215
2210 if not sev_db:2216 if not sev_db:
@@ -2231,7 +2237,7 @@
22312237
2232 ask_the_questions()2238 ask_the_questions()
22332239
2234 if UI_mode == 'yast':2240 if aaui.UI_mode == 'yast':
2235 # To-Do2241 # To-Do
2236 pass2242 pass
22372243
@@ -2263,7 +2269,7 @@
22632269
2264 if changed_list:2270 if changed_list:
22652271
2266 if UI_mode == 'yast':2272 if aaui.UI_mode == 'yast':
2267 # To-Do2273 # To-Do
2268 selected_profiles = []2274 selected_profiles = []
2269 profile_changes = dict()2275 profile_changes = dict()
@@ -2273,8 +2279,7 @@
2273 profile_changes[prof] = get_profile_diff(oldprofile, newprofile)2279 profile_changes[prof] = get_profile_diff(oldprofile, newprofile)
2274 explanation = _('Select which profile changes you would like to save to the\nlocal profile set.')2280 explanation = _('Select which profile changes you would like to save to the\nlocal profile set.')
2275 title = _('Local profile changes')2281 title = _('Local profile changes')
2276 SendDataToYast({2282 SendDataToYast({'type': 'dialog-select-profiles',
2277 'type': 'dialog-select-profiles',
2278 'title': title,2283 'title': title,
2279 'explanation': explanation,2284 'explanation': explanation,
2280 'dialog_select': 'true',2285 'dialog_select': 'true',
@@ -2299,13 +2304,13 @@
2299 q['default'] = 'CMD_VIEW_CHANGES'2304 q['default'] = 'CMD_VIEW_CHANGES'
2300 q['options'] = changed2305 q['options'] = changed
2301 q['selected'] = 02306 q['selected'] = 0
2302 p =None2307 p = None
2303 ans = ''2308 ans = ''
2304 arg = None2309 arg = None
2305 while ans != 'CMD_SAVE_CHANGES':2310 while ans != 'CMD_SAVE_CHANGES':
2306 if not changed:2311 if not changed:
2307 return2312 return
2308 ans, arg = UI_PromptUser(q)2313 ans, arg = aaui.UI_PromptUser(q)
2309 if ans == 'CMD_SAVE_SELECTED':2314 if ans == 'CMD_SAVE_SELECTED':
2310 profile_name = list(changed.keys())[arg]2315 profile_name = list(changed.keys())[arg]
2311 write_profile_ui_feedback(profile_name)2316 write_profile_ui_feedback(profile_name)
@@ -2350,7 +2355,7 @@
23502355
2351 difftemp = tempfile.NamedTemporaryFile('w', delete=False)2356 difftemp = tempfile.NamedTemporaryFile('w', delete=False)
23522357
2353 subprocess.call('diff -u -p %s %s > %s' %(oldtemp.name, newtemp.name, difftemp.name), shell=True)2358 subprocess.call('diff -u -p %s %s > %s' % (oldtemp.name, newtemp.name, difftemp.name), shell=True)
23542359
2355 oldtemp.close()2360 oldtemp.close()
2356 newtemp.close()2361 newtemp.close()
@@ -2369,19 +2374,19 @@
2369 return ''.join(diff)2374 return ''.join(diff)
23702375
2371def display_changes(oldprofile, newprofile):2376def display_changes(oldprofile, newprofile):
2372 if UI_mode == 'yast':2377 if aaui.UI_mode == 'yast':
2373 UI_LongMessage(_('Profile Changes'), get_profile_diff(oldprofile, newprofile))2378 aaui.UI_LongMessage(_('Profile Changes'), get_profile_diff(oldprofile, newprofile))
2374 else:2379 else:
2375 difftemp = generate_diff(oldprofile, newprofile)2380 difftemp = generate_diff(oldprofile, newprofile)
2376 subprocess.call('less %s' %difftemp.name, shell=True)2381 subprocess.call('less %s' % difftemp.name, shell=True)
2377 difftemp.delete = True2382 difftemp.delete = True
2378 difftemp.close()2383 difftemp.close()
23792384
2380def display_changes_with_comments(oldprofile, newprofile):2385def display_changes_with_comments(oldprofile, newprofile):
2381 """Compare the new profile with the existing profile inclusive of all the comments"""2386 """Compare the new profile with the existing profile inclusive of all the comments"""
2382 if not os.path.exists(oldprofile):2387 if not os.path.exists(oldprofile):
2383 raise AppArmorException(_("Can't find existing profile %s to compare changes.") %oldprofile)2388 raise AppArmorException(_("Can't find existing profile %s to compare changes.") % oldprofile)
2384 if UI_mode == 'yast':2389 if aaui.UI_mode == 'yast':
2385 #To-Do2390 #To-Do
2386 pass2391 pass
2387 else:2392 else:
@@ -2391,10 +2396,10 @@
23912396
2392 difftemp = tempfile.NamedTemporaryFile('w')2397 difftemp = tempfile.NamedTemporaryFile('w')
23932398
2394 subprocess.call('diff -u -p %s %s > %s' %(oldprofile, newtemp.name, difftemp.name), shell=True)2399 subprocess.call('diff -u -p %s %s > %s' % (oldprofile, newtemp.name, difftemp.name), shell=True)
23952400
2396 newtemp.close()2401 newtemp.close()
2397 subprocess.call('less %s' %difftemp.name, shell=True)2402 subprocess.call('less %s' % difftemp.name, shell=True)
2398 difftemp.close()2403 difftemp.close()
23992404
2400def set_process(pid, profile):2405def set_process(pid, profile):
@@ -2497,8 +2502,8 @@
2497def is_skippable_file(path):2502def is_skippable_file(path):
2498 """Returns True if filename matches something to be skipped"""2503 """Returns True if filename matches something to be skipped"""
2499 if (re.search('(^|/)\.[^/]*$', path) or re.search('\.rpm(save|new)$', path)2504 if (re.search('(^|/)\.[^/]*$', path) or re.search('\.rpm(save|new)$', path)
2500 or re.search('\.dpkg-(old|new)$', path) or re.search('\.swp$', path)2505 or re.search('\.dpkg-(old|new)$', path) or re.search('\.swp$', path)
2501 or path[-1] == '~' or path == 'README'):2506 or path[-1] == '~' or path == 'README'):
2502 return True2507 return True
25032508
2504def is_skippable_dir(path):2509def is_skippable_dir(path):
@@ -2517,7 +2522,7 @@
2517def read_profiles():2522def read_profiles():
2518 try:2523 try:
2519 os.listdir(profile_dir)2524 os.listdir(profile_dir)
2520 except :2525 except:
2521 fatal_error(_("Can't read AppArmor profiles in %s") % profile_dir)2526 fatal_error(_("Can't read AppArmor profiles in %s") % profile_dir)
25222527
2523 for file in os.listdir(profile_dir):2528 for file in os.listdir(profile_dir):
@@ -2532,7 +2537,7 @@
2532 return None2537 return None
2533 try:2538 try:
2534 os.listdir(profile_dir)2539 os.listdir(profile_dir)
2535 except :2540 except:
2536 fatal_error(_("Can't read AppArmor profiles in %s") % extra_profile_dir)2541 fatal_error(_("Can't read AppArmor profiles in %s") % extra_profile_dir)
25372542
2538 for file in os.listdir(profile_dir):2543 for file in os.listdir(profile_dir):
@@ -2548,7 +2553,7 @@
2548 with open_file_read(file) as f_in:2553 with open_file_read(file) as f_in:
2549 data = f_in.readlines()2554 data = f_in.readlines()
2550 except IOError:2555 except IOError:
2551 debug_logger.debug("read_profile: can't read %s - skipping" %file)2556 debug_logger.debug("read_profile: can't read %s - skipping" % file)
2552 return None2557 return None
25532558
2554 profile_data = parse_profile_data(data, file, 0)2559 profile_data = parse_profile_data(data, file, 0)
@@ -2609,13 +2614,13 @@
2609 if profile:2614 if profile:
2610 #print(profile, hat)2615 #print(profile, hat)
2611 if profile != hat or not matches[3]:2616 if profile != hat or not matches[3]:
2612 raise AppArmorException(_('%s profile in %s contains syntax errors in line: %s.') % (profile, file, lineno+1))2617 raise AppArmorException(_('%s profile in %s contains syntax errors in line: %s.') % (profile, file, lineno + 1))
2613 # Keep track of the start of a profile2618 # Keep track of the start of a profile
2614 if profile and profile == hat and matches[3]:2619 if profile and profile == hat and matches[3]:
2615 # local profile2620 # local profile
2616 hat = matches[3]2621 hat = matches[3]
2617 in_contained_hat = True2622 in_contained_hat = True
2618 profile_data[profile][hat]['profile'] = True2623 profile_data[profile][hat]['profile'] = True
2619 else:2624 else:
2620 if matches[1]:2625 if matches[1]:
2621 profile = matches[1]2626 profile = matches[1]
@@ -2661,7 +2666,7 @@
2661 elif RE_PROFILE_END.search(line):2666 elif RE_PROFILE_END.search(line):
2662 # If profile ends and we're not in one2667 # If profile ends and we're not in one
2663 if not profile:2668 if not profile:
2664 raise AppArmorException(_('Syntax Error: Unexpected End of Profile reached in file: %s line: %s') % (file, lineno+1))2669 raise AppArmorException(_('Syntax Error: Unexpected End of Profile reached in file: %s line: %s') % (file, lineno + 1))
26652670
2666 if in_contained_hat:2671 if in_contained_hat:
2667 hat = profile2672 hat = profile
@@ -2676,7 +2681,7 @@
2676 matches = RE_PROFILE_CAP.search(line).groups()2681 matches = RE_PROFILE_CAP.search(line).groups()
26772682
2678 if not profile:2683 if not profile:
2679 raise AppArmorException(_('Syntax Error: Unexpected capability entry found in file: %s line: %s') % (file, lineno+1))2684 raise AppArmorException(_('Syntax Error: Unexpected capability entry found in file: %s line: %s') % (file, lineno + 1))
26802685
2681 audit = False2686 audit = False
2682 if matches[0]:2687 if matches[0]:
@@ -2695,7 +2700,7 @@
2695 matches = RE_PROFILE_LINK.search(line).groups()2700 matches = RE_PROFILE_LINK.search(line).groups()
26962701
2697 if not profile:2702 if not profile:
2698 raise AppArmorException(_('Syntax Error: Unexpected link entry found in file: %s line: %s') % (file, lineno+1))2703 raise AppArmorException(_('Syntax Error: Unexpected link entry found in file: %s line: %s') % (file, lineno + 1))
26992704
2700 audit = False2705 audit = False
2701 if matches[0]:2706 if matches[0]:
@@ -2709,13 +2714,13 @@
2709 link = strip_quotes(matches[6])2714 link = strip_quotes(matches[6])
2710 value = strip_quotes(matches[7])2715 value = strip_quotes(matches[7])
2711 profile_data[profile][hat][allow]['link'][link]['to'] = value2716 profile_data[profile][hat][allow]['link'][link]['to'] = value
2712 profile_data[profile][hat][allow]['link'][link]['mode'] = profile_data[profile][hat][allow]['link'][link].get('mode', set()) | AA_MAY_LINK2717 profile_data[profile][hat][allow]['link'][link]['mode'] = profile_data[profile][hat][allow]['link'][link].get('mode', set()) | apparmor.aamode.AA_MAY_LINK
27132718
2714 if subset:2719 if subset:
2715 profile_data[profile][hat][allow]['link'][link]['mode'] |= AA_LINK_SUBSET2720 profile_data[profile][hat][allow]['link'][link]['mode'] |= apparmor.aamode.AA_LINK_SUBSET
27162721
2717 if audit:2722 if audit:
2718 profile_data[profile][hat][allow]['link'][link]['audit'] = profile_data[profile][hat][allow]['link'][link].get('audit', set()) | AA_LINK_SUBSET2723 profile_data[profile][hat][allow]['link'][link]['audit'] = profile_data[profile][hat][allow]['link'][link].get('audit', set()) | apparmor.aamode.AA_LINK_SUBSET
2719 else:2724 else:
2720 profile_data[profile][hat][allow]['link'][link]['audit'] = set()2725 profile_data[profile][hat][allow]['link'][link]['audit'] = set()
27212726
@@ -2723,7 +2728,7 @@
2723 matches = RE_PROFILE_CHANGE_PROFILE.search(line).groups()2728 matches = RE_PROFILE_CHANGE_PROFILE.search(line).groups()
27242729
2725 if not profile:2730 if not profile:
2726 raise AppArmorException(_('Syntax Error: Unexpected change profile entry found in file: %s line: %s') % (file, lineno+1))2731 raise AppArmorException(_('Syntax Error: Unexpected change profile entry found in file: %s line: %s') % (file, lineno + 1))
27272732
2728 cp = strip_quotes(matches[0])2733 cp = strip_quotes(matches[0])
2729 profile_data[profile][hat]['changes_profile'][cp] = True2734 profile_data[profile][hat]['changes_profile'][cp] = True
@@ -2745,7 +2750,7 @@
2745 matches = RE_PROFILE_RLIMIT.search(line).groups()2750 matches = RE_PROFILE_RLIMIT.search(line).groups()
27462751
2747 if not profile:2752 if not profile:
2748 raise AppArmorException(_('Syntax Error: Unexpected rlimit entry found in file: %s line: %s') % (file, lineno+1))2753 raise AppArmorException(_('Syntax Error: Unexpected rlimit entry found in file: %s line: %s') % (file, lineno + 1))
27492754
2750 from_name = matches[0]2755 from_name = matches[0]
2751 to_name = matches[2]2756 to_name = matches[2]
@@ -2756,7 +2761,7 @@
2756 matches = RE_PROFILE_BOOLEAN.search(line)2761 matches = RE_PROFILE_BOOLEAN.search(line)
27572762
2758 if not profile:2763 if not profile:
2759 raise AppArmorException(_('Syntax Error: Unexpected boolean definition found in file: %s line: %s') % (file, lineno+1))2764 raise AppArmorException(_('Syntax Error: Unexpected boolean definition found in file: %s line: %s') % (file, lineno + 1))
27602765
2761 bool_var = matches[0]2766 bool_var = matches[0]
2762 value = matches[1]2767 value = matches[1]
@@ -2796,7 +2801,7 @@
2796 matches = RE_PROFILE_PATH_ENTRY.search(line).groups()2801 matches = RE_PROFILE_PATH_ENTRY.search(line).groups()
27972802
2798 if not profile:2803 if not profile:
2799 raise AppArmorException(_('Syntax Error: Unexpected path entry found in file: %s line: %s') % (file, lineno+1))2804 raise AppArmorException(_('Syntax Error: Unexpected path entry found in file: %s line: %s') % (file, lineno + 1))
28002805
2801 audit = False2806 audit = False
2802 if matches[0]:2807 if matches[0]:
@@ -2820,10 +2825,10 @@
2820 try:2825 try:
2821 re.compile(p_re)2826 re.compile(p_re)
2822 except:2827 except:
2823 raise AppArmorException(_('Syntax Error: Invalid Regex %s in file: %s line: %s') % (path, file, lineno+1))2828 raise AppArmorException(_('Syntax Error: Invalid Regex %s in file: %s line: %s') % (path, file, lineno + 1))
28242829
2825 if not validate_profile_mode(mode, allow, nt_name):2830 if not validate_profile_mode(mode, allow, nt_name):
2826 raise AppArmorException(_('Invalid mode %s in file: %s line: %s') % (mode, file, lineno+1))2831 raise AppArmorException(_('Invalid mode %s in file: %s line: %s') % (mode, file, lineno + 1))
28272832
2828 tmpmode = set()2833 tmpmode = set()
2829 if user:2834 if user:
@@ -2847,7 +2852,6 @@
2847 if include_name.startswith('local/'):2852 if include_name.startswith('local/'):
2848 profile_data[profile][hat]['localinclude'][include_name] = True2853 profile_data[profile][hat]['localinclude'][include_name] = True
28492854
2850
2851 if profile:2855 if profile:
2852 profile_data[profile][hat]['include'][include_name] = True2856 profile_data[profile][hat]['include'][include_name] = True
2853 else:2857 else:
@@ -2862,7 +2866,7 @@
2862 continue2866 continue
2863 if os.path.isfile(profile_dir + '/' + include_name + '/' + path):2867 if os.path.isfile(profile_dir + '/' + include_name + '/' + path):
2864 file_name = include_name + '/' + path2868 file_name = include_name + '/' + path
2865 file_name = file_name.replace(profile_dir+'/', '')2869 file_name = file_name.replace(profile_dir + '/', '')
2866 if not include.get(file_name, False):2870 if not include.get(file_name, False):
2867 load_include(file_name)2871 load_include(file_name)
2868 else:2872 else:
@@ -2873,7 +2877,7 @@
2873 matches = RE_PROFILE_NETWORK.search(line).groups()2877 matches = RE_PROFILE_NETWORK.search(line).groups()
28742878
2875 if not profile:2879 if not profile:
2876 raise AppArmorException(_('Syntax Error: Unexpected network entry found in file: %s line: %s') % (file, lineno+1))2880 raise AppArmorException(_('Syntax Error: Unexpected network entry found in file: %s line: %s') % (file, lineno + 1))
28772881
2878 audit = False2882 audit = False
2879 if matches[0]:2883 if matches[0]:
@@ -2889,7 +2893,7 @@
2889 ##Simply ignore any type subrules if family has True (seperately for allow and deny)2893 ##Simply ignore any type subrules if family has True (seperately for allow and deny)
2890 ##This will lead to those type specific rules being lost when written2894 ##This will lead to those type specific rules being lost when written
2891 #if type(profile_data[profile][hat][allow]['netdomain']['rule'].get(fam, False)) == dict:2895 #if type(profile_data[profile][hat][allow]['netdomain']['rule'].get(fam, False)) == dict:
2892 profile_data[profile][hat][allow]['netdomain']['rule'][fam][typ] = 12896 profile_data[profile][hat][allow]['netdomain']['rule'][fam][typ] = 1
2893 profile_data[profile][hat][allow]['netdomain']['audit'][fam][typ] = audit2897 profile_data[profile][hat][allow]['netdomain']['audit'][fam][typ] = audit
2894 elif RE_NETWORK_FAMILY.search(network):2898 elif RE_NETWORK_FAMILY.search(network):
2895 fam = RE_NETWORK_FAMILY.search(network).groups()[0]2899 fam = RE_NETWORK_FAMILY.search(network).groups()[0]
@@ -2897,13 +2901,13 @@
2897 profile_data[profile][hat][allow]['netdomain']['audit'][fam] = audit2901 profile_data[profile][hat][allow]['netdomain']['audit'][fam] = audit
2898 else:2902 else:
2899 profile_data[profile][hat][allow]['netdomain']['rule']['all'] = True2903 profile_data[profile][hat][allow]['netdomain']['rule']['all'] = True
2900 profile_data[profile][hat][allow]['netdomain']['audit']['all'] = audit # True2904 profile_data[profile][hat][allow]['netdomain']['audit']['all'] = audit # True
29012905
2902 elif RE_PROFILE_CHANGE_HAT.search(line):2906 elif RE_PROFILE_CHANGE_HAT.search(line):
2903 matches = RE_PROFILE_CHANGE_HAT.search(line).groups()2907 matches = RE_PROFILE_CHANGE_HAT.search(line).groups()
29042908
2905 if not profile:2909 if not profile:
2906 raise AppArmorException(_('Syntax Error: Unexpected change hat declaration found in file: %s line: %s') % (file, lineno+1))2910 raise AppArmorException(_('Syntax Error: Unexpected change hat declaration found in file: %s line: %s') % (file, lineno + 1))
29072911
2908 hat = matches[0]2912 hat = matches[0]
2909 hat = strip_quotes(hat)2913 hat = strip_quotes(hat)
@@ -2915,7 +2919,7 @@
2915 # An embedded hat syntax definition starts2919 # An embedded hat syntax definition starts
2916 matches = RE_PROFILE_HAT_DEF.search(line).groups()2920 matches = RE_PROFILE_HAT_DEF.search(line).groups()
2917 if not profile:2921 if not profile:
2918 raise AppArmorException(_('Syntax Error: Unexpected hat definition found in file: %s line: %s') % (file, lineno+1))2922 raise AppArmorException(_('Syntax Error: Unexpected hat definition found in file: %s line: %s') % (file, lineno + 1))
29192923
2920 in_contained_hat = True2924 in_contained_hat = True
2921 hat = matches[0]2925 hat = matches[0]
@@ -2931,7 +2935,7 @@
2931 profile_data[profile][hat]['initial_comment'] = initial_comment2935 profile_data[profile][hat]['initial_comment'] = initial_comment
2932 initial_comment = ''2936 initial_comment = ''
2933 if filelist[file]['profiles'][profile].get(hat, False):2937 if filelist[file]['profiles'][profile].get(hat, False):
2934 raise AppArmorException(_('Error: Multiple definitions for hat %s in profile %s.') %(hat, profile))2938 raise AppArmorException(_('Error: Multiple definitions for hat %s in profile %s.') % (hat, profile))
2935 filelist[file]['profiles'][profile][hat] = True2939 filelist[file]['profiles'][profile][hat] = True
29362940
2937 elif line[0] == '#':2941 elif line[0] == '#':
@@ -2951,7 +2955,7 @@
2951 initial_comment = ' '.join(line) + '\n'2955 initial_comment = ' '.join(line) + '\n'
29522956
2953 else:2957 else:
2954 raise AppArmorException(_('Syntax Error: Unknown line found in file: %s line: %s') % (file, lineno+1))2958 raise AppArmorException(_('Syntax Error: Unknown line found in file: %s line: %s') % (file, lineno + 1))
29552959
2956 # Below is not required I'd say2960 # Below is not required I'd say
2957 if not do_include:2961 if not do_include:
@@ -2995,18 +2999,18 @@
2995 var[list_var] = set(vlist)2999 var[list_var] = set(vlist)
2996 else:3000 else:
2997 #print('Ignored: New definition for variable for:',list_var,'=', value, 'operation was:',var_operation,'old value=', var[list_var])3001 #print('Ignored: New definition for variable for:',list_var,'=', value, 'operation was:',var_operation,'old value=', var[list_var])
2998 raise AppArmorException(_('An existing variable redefined: %s') %list_var)3002 raise AppArmorException(_('An existing variable redefined: %s') % list_var)
2999 elif var_operation == '+=':3003 elif var_operation == '+=':
3000 if var.get(list_var, False):3004 if var.get(list_var, False):
3001 var[list_var] = set(var[list_var] + vlist)3005 var[list_var] = set(var[list_var] + vlist)
3002 else:3006 else:
3003 raise AppArmorException(_('Values added to a non-existing variable: %s') %list_var)3007 raise AppArmorException(_('Values added to a non-existing variable: %s') % list_var)
3004 else:3008 else:
3005 raise AppArmorException(_('Unknown variable operation: %s') %var_operation)3009 raise AppArmorException(_('Unknown variable operation: %s') % var_operation)
30063010
30073011
3008def strip_quotes(data):3012def strip_quotes(data):
3009 if data[0]+data[-1] == '""':3013 if data[0] + data[-1] == '""':
3010 return data[1:-1]3014 return data[1:-1]
3011 else:3015 else:
3012 return data3016 return data
@@ -3029,7 +3033,7 @@
3029 data = []3033 data = []
3030 name = quote_if_needed(name)3034 name = quote_if_needed(name)
30313035
3032 if (not embedded_hat and re.search('^[^/]|^"[^/]', name)) or (embedded_hat and re.search('^[^^]' ,name)):3036 if (not embedded_hat and re.search('^[^/]|^"[^/]', name)) or (embedded_hat and re.search('^[^^]', name)):
3033 name = 'profile %s' % name3037 name = 'profile %s' % name
30343038
3035 if write_flags and prof_data['flags']:3039 if write_flags and prof_data['flags']:
@@ -3047,7 +3051,7 @@
3047 if ref.get(name, False):3051 if ref.get(name, False):
3048 for key in sorted(ref[name].keys()):3052 for key in sorted(ref[name].keys()):
3049 qkey = quote_if_needed(key)3053 qkey = quote_if_needed(key)
3050 data.append('%s%s%s%s%s' %(pre, allow, prefix, qkey, tail))3054 data.append('%s%s%s%s%s' % (pre, allow, prefix, qkey, tail))
3051 if ref[name].keys():3055 if ref[name].keys():
3052 data.append('')3056 data.append('')
30533057
@@ -3077,8 +3081,8 @@
30773081
3078 if ref.get(name, False):3082 if ref.get(name, False):
3079 for key in sorted(ref[name].keys()):3083 for key in sorted(ref[name].keys()):
3080 value = fn(ref[name][key])#eval('%s(%s)' % (fn, ref[name][key]))3084 value = fn(ref[name][key]) # eval('%s(%s)' % (fn, ref[name][key]))
3081 data.append('%s%s%s%s%s%s' %(pre, allow, prefix, key, sep, value))3085 data.append('%s%s%s%s%s%s' % (pre, allow, prefix, key, sep, value))
3082 if ref[name].keys():3086 if ref[name].keys():
3083 data.append('')3087 data.append('')
30843088
@@ -3116,7 +3120,7 @@
3116 if prof_data[allow]['capability'][cap].get('audit', False):3120 if prof_data[allow]['capability'][cap].get('audit', False):
3117 audit = 'audit '3121 audit = 'audit '
3118 if prof_data[allow]['capability'][cap].get('set', False):3122 if prof_data[allow]['capability'][cap].get('set', False):
3119 data.append('%s%s%scapability %s,' %(pre, audit, allowstr, cap))3123 data.append('%s%s%scapability %s,' % (pre, audit, allowstr, cap))
3120 data.append('')3124 data.append('')
31213125
3122 return data3126 return data
@@ -3136,10 +3140,10 @@
3136 if prof_data[allow]['netdomain'].get('rule', False) == 'all':3140 if prof_data[allow]['netdomain'].get('rule', False) == 'all':
3137 if prof_data[allow]['netdomain']['audit'].get('all', False):3141 if prof_data[allow]['netdomain']['audit'].get('all', False):
3138 audit = 'audit '3142 audit = 'audit '
3139 data.append('%s%snetwork,' %(pre, audit))3143 data.append('%s%snetwork,' % (pre, audit))
3140 else:3144 else:
3141 for fam in sorted(prof_data[allow]['netdomain']['rule'].keys()):3145 for fam in sorted(prof_data[allow]['netdomain']['rule'].keys()):
3142 if prof_data[allow]['netdomain']['rule'][fam] == True:3146 if prof_data[allow]['netdomain']['rule'][fam] is True:
3143 if prof_data[allow]['netdomain']['audit'][fam]:3147 if prof_data[allow]['netdomain']['audit'][fam]:
3144 audit = 'audit'3148 audit = 'audit'
3145 data.append('%s%s%snetwork %s' % (pre, audit, allowstr, fam))3149 data.append('%s%s%snetwork %s' % (pre, audit, allowstr, fam))
@@ -3147,7 +3151,7 @@
3147 for typ in sorted(prof_data[allow]['netdomain']['rule'][fam].keys()):3151 for typ in sorted(prof_data[allow]['netdomain']['rule'][fam].keys()):
3148 if prof_data[allow]['netdomain']['audit'][fam].get(typ, False):3152 if prof_data[allow]['netdomain']['audit'][fam].get(typ, False):
3149 audit = 'audit'3153 audit = 'audit'
3150 data.append('%s%s%snetwork %s %s,' % (pre, audit, allowstr,fam, typ))3154 data.append('%s%s%snetwork %s %s,' % (pre, audit, allowstr, fam, typ))
3151 if prof_data[allow].get('netdomain', False):3155 if prof_data[allow].get('netdomain', False):
3152 data.append('')3156 data.append('')
31533157
@@ -3167,14 +3171,14 @@
3167 for path in sorted(prof_data[allow]['link'].keys()):3171 for path in sorted(prof_data[allow]['link'].keys()):
3168 to_name = prof_data[allow]['link'][path]['to']3172 to_name = prof_data[allow]['link'][path]['to']
3169 subset = ''3173 subset = ''
3170 if prof_data[allow]['link'][path]['mode'] & AA_LINK_SUBSET:3174 if prof_data[allow]['link'][path]['mode'] & apparmor.aamode.AA_LINK_SUBSET:
3171 subset = 'subset'3175 subset = 'subset'
3172 audit = ''3176 audit = ''
3173 if prof_data[allow]['link'][path].get('audit', False):3177 if prof_data[allow]['link'][path].get('audit', False):
3174 audit = 'audit '3178 audit = 'audit '
3175 path = quote_if_needed(path)3179 path = quote_if_needed(path)
3176 to_name = quote_if_needed(to_name)3180 to_name = quote_if_needed(to_name)
3177 data.append('%s%s%slink %s%s -> %s,' %(pre, audit, allowstr, subset, path, to_name))3181 data.append('%s%s%slink %s%s -> %s,' % (pre, audit, allowstr, subset, path, to_name))
3178 data.append('')3182 data.append('')
31793183
3180 return data3184 return data
@@ -3226,13 +3230,13 @@
3226 if tmpmode & tmpaudit:3230 if tmpmode & tmpaudit:
3227 modestr = mode_to_str(tmpmode & tmpaudit)3231 modestr = mode_to_str(tmpmode & tmpaudit)
3228 path = quote_if_needed(path)3232 path = quote_if_needed(path)
3229 data.append('%saudit %s%s%s %s%s,' %(pre, allowstr, ownerstr, path, modestr, tail))3233 data.append('%saudit %s%s%s %s%s,' % (pre, allowstr, ownerstr, path, modestr, tail))
3230 tmpmode = tmpmode - tmpaudit3234 tmpmode = tmpmode - tmpaudit
32313235
3232 if tmpmode:3236 if tmpmode:
3233 modestr = mode_to_str(tmpmode)3237 modestr = mode_to_str(tmpmode)
3234 path = quote_if_needed(path)3238 path = quote_if_needed(path)
3235 data.append('%s%s%s%s %s%s,' %(pre, allowstr, ownerstr, path, modestr, tail))3239 data.append('%s%s%s%s %s%s,' % (pre, allowstr, ownerstr, path, modestr, tail))
32363240
3237 data.append('')3241 data.append('')
3238 return data3242 return data
@@ -3268,13 +3272,13 @@
3268 name = nhat3272 name = nhat
3269 inhat = True3273 inhat = True
3270 data += write_header(profile_data[name], depth, wname, False, write_flags)3274 data += write_header(profile_data[name], depth, wname, False, write_flags)
3271 data += write_rules(profile_data[name], depth+1)3275 data += write_rules(profile_data[name], depth + 1)
32723276
3273 pre2 = ' ' * (depth+1)3277 pre2 = ' ' * (depth + 1)
3274 # External hat declarations3278 # External hat declarations
3275 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):3279 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):
3276 if profile_data[hat].get('declared', False):3280 if profile_data[hat].get('declared', False):
3277 data.append('%s^%s,' %(pre2, hat))3281 data.append('%s^%s,' % (pre2, hat))
32783282
3279 if not inhat:3283 if not inhat:
3280 # Embedded hats3284 # Embedded hats
@@ -3282,21 +3286,21 @@
3282 if not profile_data[hat]['external'] and not profile_data[hat]['declared']:3286 if not profile_data[hat]['external'] and not profile_data[hat]['declared']:
3283 data.append('')3287 data.append('')
3284 if profile_data[hat]['profile']:3288 if profile_data[hat]['profile']:
3285 data += list(map(str, write_header(profile_data[hat], depth+1, hat, True, write_flags)))3289 data += list(map(str, write_header(profile_data[hat], depth + 1, hat, True, write_flags)))
3286 else:3290 else:
3287 data += list(map(str, write_header(profile_data[hat], depth+1, '^'+hat, True, write_flags)))3291 data += list(map(str, write_header(profile_data[hat], depth + 1, '^' + hat, True, write_flags)))
32883292
3289 data += list(map(str, write_rules(profile_data[hat], depth+2)))3293 data += list(map(str, write_rules(profile_data[hat], depth + 2)))
32903294
3291 data.append('%s}' %pre2)3295 data.append('%s}' % pre2)
32923296
3293 data.append('%s}' %pre)3297 data.append('%s}' % pre)
32943298
3295 # External hats3299 # External hats
3296 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):3300 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):
3297 if name == nhat and profile_data[hat].get('external', False):3301 if name == nhat and profile_data[hat].get('external', False):
3298 data.append('')3302 data.append('')
3299 data += list(map(lambda x: ' %s' %x, write_piece(profile_data, depth-1, name, nhat, write_flags)))3303 data += list(map(lambda x: ' %s' % x, write_piece(profile_data, depth - 1, name, nhat, write_flags)))
3300 data.append(' }')3304 data.append(' }')
33013305
3302 return data3306 return data
@@ -3305,21 +3309,23 @@
3305 string = ''3309 string = ''
3306 include_metadata = False3310 include_metadata = False
3307 include_flags = True3311 include_flags = True
3308 data= []3312 data = []
33093313
3310 if options:# and type(options) == dict:3314 if options: # and type(options) == dict:
3311 if options.get('METADATA', False):3315 if options.get('METADATA', False):
3312 include_metadata = True3316 include_metadata = True
3313 if options.get('NO_FLAGS', False):3317 if options.get('NO_FLAGS', False):
3314 include_flags = False3318 include_flags = False
33153319
3316 if include_metadata:3320 if include_metadata:
3317 string = '# Last Modified: %s\n' %time.asctime()3321 string = '# Last Modified: %s\n' % time.asctime()
33183322
3319 if (profile_data[name].get('repo', False) and profile_data[name]['repo']['url']3323 if (profile_data[name].get('repo', False) and
3320 and profile_data[name]['repo']['user'] and profile_data[name]['repo']['id']):3324 profile_data[name]['repo']['url'] and
3325 profile_data[name]['repo']['user'] and
3326 profile_data[name]['repo']['id']):
3321 repo = profile_data[name]['repo']3327 repo = profile_data[name]['repo']
3322 string += '# REPOSITORY: %s %s %s\n' %(repo['url'], repo['user'], repo['id'])3328 string += '# REPOSITORY: %s %s %s\n' % (repo['url'], repo['user'], repo['id'])
3323 elif profile_data[name]['repo']['neversubmit']:3329 elif profile_data[name]['repo']['neversubmit']:
3324 string += '# REPOSITORY: NEVERSUBMIT\n'3330 string += '# REPOSITORY: NEVERSUBMIT\n'
33253331
@@ -3351,7 +3357,7 @@
33513357
3352 string += '\n'.join(data)3358 string += '\n'.join(data)
33533359
3354 return string+'\n'3360 return string + '\n'
33553361
3356def serialize_profile_from_old_profile(profile_data, name, options):3362def serialize_profile_from_old_profile(profile_data, name, options):
3357 data = []3363 data = []
@@ -3363,28 +3369,29 @@
3363 write_filelist = deepcopy(filelist[prof_filename])3369 write_filelist = deepcopy(filelist[prof_filename])
3364 write_prof_data = deepcopy(profile_data)3370 write_prof_data = deepcopy(profile_data)
33653371
3366 if options:# and type(options) == dict:3372 if options: # and type(options) == dict:
3367 if options.get('METADATA', False):3373 if options.get('METADATA', False):
3368 include_metadata = True3374 include_metadata = True
3369 if options.get('NO_FLAGS', False):3375 if options.get('NO_FLAGS', False):
3370 include_flags = False3376 include_flags = False
33713377
3372 if include_metadata:3378 if include_metadata:
3373 string = '# Last Modified: %s\n' %time.asctime()3379 string = '# Last Modified: %s\n' % time.asctime()
33743380
3375 if (profile_data[name].get('repo', False) and profile_data[name]['repo']['url']3381 if (profile_data[name].get('repo', False) and
3376 and profile_data[name]['repo']['user'] and profile_data[name]['repo']['id']):3382 profile_data[name]['repo']['url'] and
3383 profile_data[name]['repo']['user'] and
3384 profile_data[name]['repo']['id']):
3377 repo = profile_data[name]['repo']3385 repo = profile_data[name]['repo']
3378 string += '# REPOSITORY: %s %s %s\n' %(repo['url'], repo['user'], repo['id'])3386 string += '# REPOSITORY: %s %s %s\n' % (repo['url'], repo['user'], repo['id'])
3379 elif profile_data[name]['repo']['neversubmit']:3387 elif profile_data[name]['repo']['neversubmit']:
3380 string += '# REPOSITORY: NEVERSUBMIT\n'3388 string += '# REPOSITORY: NEVERSUBMIT\n'
33813389
3382
3383 if not os.path.isfile(prof_filename):3390 if not os.path.isfile(prof_filename):
3384 raise AppArmorException(_("Can't find existing profile to modify"))3391 raise AppArmorException(_("Can't find existing profile to modify"))
3385 3392
3386 profiles_list = filelist[prof_filename].keys()3393 profiles_list = filelist[prof_filename].keys()
3387 3394
3388 with open_file_read(prof_filename) as f_in:3395 with open_file_read(prof_filename) as f_in:
3389 profile = None3396 profile = None
3390 hat = None3397 hat = None
@@ -3399,8 +3406,7 @@
3399 'change_profile': write_change_profile,3406 'change_profile': write_change_profile,
3400 }3407 }
3401 prof_correct = True3408 prof_correct = True
3402 segments = {3409 segments = {'alias': False,
3403 'alias': False,
3404 'lvar': False,3410 'lvar': False,
3405 'include': False,3411 'include': False,
3406 'rlimit': False,3412 'rlimit': False,
@@ -3410,7 +3416,7 @@
3410 'path': False,3416 'path': False,
3411 'change_profile': False,3417 'change_profile': False,
3412 'include_local_started': False,3418 'include_local_started': False,
3413 }3419 }
3414 #data.append('reading prof')3420 #data.append('reading prof')
3415 for line in f_in:3421 for line in f_in:
3416 correct = True3422 correct = True
@@ -3446,7 +3452,7 @@
3446 if not write_prof_data[hat]['name'] == profile:3452 if not write_prof_data[hat]['name'] == profile:
3447 correct = False3453 correct = False
34483454
3449 if not write_filelist['profiles'][profile][hat] == True:3455 if not write_filelist['profiles'][profile][hat] is True:
3450 correct = False3456 correct = False
34513457
3452 if not write_prof_data[hat]['flags'] == flags:3458 if not write_prof_data[hat]['flags'] == flags:
@@ -3462,7 +3468,7 @@
3462 else:3468 else:
3463 if write_prof_data[hat]['name'] == profile:3469 if write_prof_data[hat]['name'] == profile:
3464 depth = len(line) - len(line.lstrip())3470 depth = len(line) - len(line.lstrip())
3465 data += write_header(write_prof_data[name], int(depth/2), name, False, include_flags)3471 data += write_header(write_prof_data[name], int(depth / 2), name, False, include_flags)
34663472
3467 elif RE_PROFILE_END.search(line):3473 elif RE_PROFILE_END.search(line):
3468 # DUMP REMAINDER OF PROFILE3474 # DUMP REMAINDER OF PROFILE
@@ -3471,11 +3477,12 @@
3471 if True in segments.values():3477 if True in segments.values():
3472 for segs in list(filter(lambda x: segments[x], segments.keys())):3478 for segs in list(filter(lambda x: segments[x], segments.keys())):
34733479
3474 data += write_methods[segs](write_prof_data[name], int(depth/2))3480 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3475 segments[segs] = False3481 segments[segs] = False
3476 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3482 if write_prof_data[name]['allow'].get(segs, False):
3477 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3483 write_prof_data[name]['allow'].pop(segs)
34783484 if write_prof_data[name]['deny'].get(segs, False):
3485 write_prof_data[name]['deny'].pop(segs)
34793486
3480 data += write_alias(write_prof_data[name], depth)3487 data += write_alias(write_prof_data[name], depth)
3481 data += write_list_vars(write_prof_data[name], depth)3488 data += write_list_vars(write_prof_data[name], depth)
@@ -3494,25 +3501,25 @@
34943501
3495 if not in_contained_hat:3502 if not in_contained_hat:
3496 # Embedded hats3503 # Embedded hats
3497 depth = int((len(line) - len(line.lstrip()))/2)3504 depth = int((len(line) - len(line.lstrip())) / 2)
3498 pre2 = ' ' * (depth+1)3505 pre2 = ' ' * (depth + 1)
3499 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):3506 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):
3500 if not profile_data[hat]['external'] and not profile_data[hat]['declared']:3507 if not profile_data[hat]['external'] and not profile_data[hat]['declared']:
3501 data.append('')3508 data.append('')
3502 if profile_data[hat]['profile']:3509 if profile_data[hat]['profile']:
3503 data += list(map(str, write_header(profile_data[hat], depth+1, hat, True, include_flags)))3510 data += list(map(str, write_header(profile_data[hat], depth + 1, hat, True, include_flags)))
3504 else:3511 else:
3505 data += list(map(str, write_header(profile_data[hat], depth+1, '^'+hat, True, include_flags)))3512 data += list(map(str, write_header(profile_data[hat], depth + 1, '^' + hat, True, include_flags)))
35063513
3507 data += list(map(str, write_rules(profile_data[hat], depth+2)))3514 data += list(map(str, write_rules(profile_data[hat], depth + 2)))
35083515
3509 data.append('%s}' %pre2)3516 data.append('%s}' % pre2)
35103517
3511 # External hats3518 # External hats
3512 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):3519 for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):
3513 if profile_data[hat].get('external', False):3520 if profile_data[hat].get('external', False):
3514 data.append('')3521 data.append('')
3515 data += list(map(lambda x: ' %s' %x, write_piece(profile_data, depth-1, name, name, include_flags)))3522 data += list(map(lambda x: ' %s' % x, write_piece(profile_data, depth - 1, name, name, include_flags)))
3516 data.append(' }')3523 data.append(' }')
35173524
3518 if in_contained_hat:3525 if in_contained_hat:
@@ -3522,7 +3529,6 @@
3522 else:3529 else:
3523 profile = None3530 profile = None
35243531
3525
3526 elif RE_PROFILE_CAP.search(line):3532 elif RE_PROFILE_CAP.search(line):
3527 matches = RE_PROFILE_CAP.search(line).groups()3533 matches = RE_PROFILE_CAP.search(line).groups()
3528 audit = False3534 audit = False
@@ -3544,10 +3550,12 @@
3544 if not segments['capability'] and True in segments.values():3550 if not segments['capability'] and True in segments.values():
3545 for segs in list(filter(lambda x: segments[x], segments.keys())):3551 for segs in list(filter(lambda x: segments[x], segments.keys())):
3546 depth = len(line) - len(line.lstrip())3552 depth = len(line) - len(line.lstrip())
3547 data += write_methods[segs](write_prof_data[name], int(depth/2))3553 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3548 segments[segs] = False3554 segments[segs] = False
3549 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3555 if write_prof_data[name]['allow'].get(segs, False):
3550 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3556 write_prof_data[name]['allow'].pop(segs)
3557 if write_prof_data[name]['deny'].get(segs, False):
3558 write_prof_data[name]['deny'].pop(segs)
3551 segments['capability'] = True3559 segments['capability'] = True
3552 write_prof_data[hat][allow]['capability'].pop(capability)3560 write_prof_data[hat][allow]['capability'].pop(capability)
3553 data.append(line)3561 data.append(line)
@@ -3572,21 +3580,23 @@
3572 value = strip_quotes(matches[7])3580 value = strip_quotes(matches[7])
3573 if not write_prof_data[hat][allow]['link'][link]['to'] == value:3581 if not write_prof_data[hat][allow]['link'][link]['to'] == value:
3574 correct = False3582 correct = False
3575 if not write_prof_data[hat][allow]['link'][link]['mode'] & AA_MAY_LINK:3583 if not write_prof_data[hat][allow]['link'][link]['mode'] & apparmor.aamode.AA_MAY_LINK:
3576 correct = False3584 correct = False
3577 if subset and not write_prof_data[hat][allow]['link'][link]['mode'] & AA_LINK_SUBSET:3585 if subset and not write_prof_data[hat][allow]['link'][link]['mode'] & apparmor.aamode.AA_LINK_SUBSET:
3578 correct = False3586 correct = False
3579 if audit and not write_prof_data[hat][allow]['link'][link]['audit'] & AA_LINK_SUBSET:3587 if audit and not write_prof_data[hat][allow]['link'][link]['audit'] & apparmor.aamode.AA_LINK_SUBSET:
3580 correct = False3588 correct = False
35813589
3582 if correct:3590 if correct:
3583 if not segments['link'] and True in segments.values():3591 if not segments['link'] and True in segments.values():
3584 for segs in list(filter(lambda x: segments[x], segments.keys())):3592 for segs in list(filter(lambda x: segments[x], segments.keys())):
3585 depth = len(line) - len(line.lstrip())3593 depth = len(line) - len(line.lstrip())
3586 data += write_methods[segs](write_prof_data[name], int(depth/2))3594 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3587 segments[segs] = False3595 segments[segs] = False
3588 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3596 if write_prof_data[name]['allow'].get(segs, False):
3589 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3597 write_prof_data[name]['allow'].pop(segs)
3598 if write_prof_data[name]['deny'].get(segs, False):
3599 write_prof_data[name]['deny'].pop(segs)
3590 segments['link'] = True3600 segments['link'] = True
3591 write_prof_data[hat][allow]['link'].pop(link)3601 write_prof_data[hat][allow]['link'].pop(link)
3592 data.append(line)3602 data.append(line)
@@ -3598,17 +3608,19 @@
3598 matches = RE_PROFILE_CHANGE_PROFILE.search(line).groups()3608 matches = RE_PROFILE_CHANGE_PROFILE.search(line).groups()
3599 cp = strip_quotes(matches[0])3609 cp = strip_quotes(matches[0])
36003610
3601 if not write_prof_data[hat]['changes_profile'][cp] == True:3611 if not write_prof_data[hat]['changes_profile'][cp] is True:
3602 correct = False3612 correct = False
36033613
3604 if correct:3614 if correct:
3605 if not segments['change_profile'] and True in segments.values():3615 if not segments['change_profile'] and True in segments.values():
3606 for segs in list(filter(lambda x: segments[x], segments.keys())):3616 for segs in list(filter(lambda x: segments[x], segments.keys())):
3607 depth = len(line) - len(line.lstrip())3617 depth = len(line) - len(line.lstrip())
3608 data += write_methods[segs](write_prof_data[name], int(depth/2))3618 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3609 segments[segs] = False3619 segments[segs] = False
3610 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3620 if write_prof_data[name]['allow'].get(segs, False):
3611 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3621 write_prof_data[name]['allow'].pop(segs)
3622 if write_prof_data[name]['deny'].get(segs, False):
3623 write_prof_data[name]['deny'].pop(segs)
3612 segments['change_profile'] = True3624 segments['change_profile'] = True
3613 write_prof_data[hat]['change_profile'].pop(cp)3625 write_prof_data[hat]['change_profile'].pop(cp)
3614 data.append(line)3626 data.append(line)
@@ -3633,10 +3645,12 @@
3633 if not segments['alias'] and True in segments.values():3645 if not segments['alias'] and True in segments.values():
3634 for segs in list(filter(lambda x: segments[x], segments.keys())):3646 for segs in list(filter(lambda x: segments[x], segments.keys())):
3635 depth = len(line) - len(line.lstrip())3647 depth = len(line) - len(line.lstrip())
3636 data += write_methods[segs](write_prof_data[name], int(depth/2))3648 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3637 segments[segs] = False3649 segments[segs] = False
3638 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3650 if write_prof_data[name]['allow'].get(segs, False):
3639 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3651 write_prof_data[name]['allow'].pop(segs)
3652 if write_prof_data[name]['deny'].get(segs, False):
3653 write_prof_data[name]['deny'].pop(segs)
3640 segments['alias'] = True3654 segments['alias'] = True
3641 if profile:3655 if profile:
3642 write_prof_data[hat]['alias'].pop(from_name)3656 write_prof_data[hat]['alias'].pop(from_name)
@@ -3660,10 +3674,12 @@
3660 if not segments['rlimit'] and True in segments.values():3674 if not segments['rlimit'] and True in segments.values():
3661 for segs in list(filter(lambda x: segments[x], segments.keys())):3675 for segs in list(filter(lambda x: segments[x], segments.keys())):
3662 depth = len(line) - len(line.lstrip())3676 depth = len(line) - len(line.lstrip())
3663 data += write_methods[segs](write_prof_data[name], int(depth/2))3677 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3664 segments[segs] = False3678 segments[segs] = False
3665 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3679 if write_prof_data[name]['allow'].get(segs, False):
3666 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3680 write_prof_data[name]['allow'].pop(segs)
3681 if write_prof_data[name]['deny'].get(segs, False):
3682 write_prof_data[name]['deny'].pop(segs)
3667 segments['rlimit'] = True3683 segments['rlimit'] = True
3668 write_prof_data[hat]['rlimit'].pop(from_name)3684 write_prof_data[hat]['rlimit'].pop(from_name)
3669 data.append(line)3685 data.append(line)
@@ -3683,10 +3699,12 @@
3683 if not segments['lvar'] and True in segments.values():3699 if not segments['lvar'] and True in segments.values():
3684 for segs in list(filter(lambda x: segments[x], segments.keys())):3700 for segs in list(filter(lambda x: segments[x], segments.keys())):
3685 depth = len(line) - len(line.lstrip())3701 depth = len(line) - len(line.lstrip())
3686 data += write_methods[segs](write_prof_data[name], int(depth/2))3702 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3687 segments[segs] = False3703 segments[segs] = False
3688 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3704 if write_prof_data[name]['allow'].get(segs, False):
3689 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3705 write_prof_data[name]['allow'].pop(segs)
3706 if write_prof_data[name]['deny'].get(segs, False):
3707 write_prof_data[name]['deny'].pop(segs)
3690 segments['lvar'] = True3708 segments['lvar'] = True
3691 write_prof_data[hat]['lvar'].pop(bool_var)3709 write_prof_data[hat]['lvar'].pop(bool_var)
3692 data.append(line)3710 data.append(line)
@@ -3712,10 +3730,12 @@
3712 if not segments['lvar'] and True in segments.values():3730 if not segments['lvar'] and True in segments.values():
3713 for segs in list(filter(lambda x: segments[x], segments.keys())):3731 for segs in list(filter(lambda x: segments[x], segments.keys())):
3714 depth = len(line) - len(line.lstrip())3732 depth = len(line) - len(line.lstrip())
3715 data += write_methods[segs](write_prof_data[name], int(depth/2))3733 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3716 segments[segs] = False3734 segments[segs] = False
3717 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3735 if write_prof_data[name]['allow'].get(segs, False):
3718 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3736 write_prof_data[name]['allow'].pop(segs)
3737 if write_prof_data[name]['deny'].get(segs, False):
3738 write_prof_data[name]['deny'].pop(segs)
3719 segments['lvar'] = True3739 segments['lvar'] = True
3720 if profile:3740 if profile:
3721 write_prof_data[hat]['lvar'].pop(list_var)3741 write_prof_data[hat]['lvar'].pop(list_var)
@@ -3747,7 +3767,7 @@
37473767
3748 tmpmode = set()3768 tmpmode = set()
3749 if user:3769 if user:
3750 tmpmode = str_to_mode('%s::' %mode)3770 tmpmode = str_to_mode('%s::' % mode)
3751 else:3771 else:
3752 tmpmode = str_to_mode(mode)3772 tmpmode = str_to_mode(mode)
37533773
@@ -3764,10 +3784,12 @@
3764 if not segments['path'] and True in segments.values():3784 if not segments['path'] and True in segments.values():
3765 for segs in list(filter(lambda x: segments[x], segments.keys())):3785 for segs in list(filter(lambda x: segments[x], segments.keys())):
3766 depth = len(line) - len(line.lstrip())3786 depth = len(line) - len(line.lstrip())
3767 data += write_methods[segs](write_prof_data[name], int(depth/2))3787 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3768 segments[segs] = False3788 segments[segs] = False
3769 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3789 if write_prof_data[name]['allow'].get(segs, False):
3770 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3790 write_prof_data[name]['allow'].pop(segs)
3791 if write_prof_data[name]['deny'].get(segs, False):
3792 write_prof_data[name]['deny'].pop(segs)
3771 segments['path'] = True3793 segments['path'] = True
3772 write_prof_data[hat][allow]['path'].pop(path)3794 write_prof_data[hat][allow]['path'].pop(path)
3773 data.append(line)3795 data.append(line)
@@ -3782,10 +3804,12 @@
3782 if not segments['include'] and True in segments.values():3804 if not segments['include'] and True in segments.values():
3783 for segs in list(filter(lambda x: segments[x], segments.keys())):3805 for segs in list(filter(lambda x: segments[x], segments.keys())):
3784 depth = len(line) - len(line.lstrip())3806 depth = len(line) - len(line.lstrip())
3785 data += write_methods[segs](write_prof_data[name], int(depth/2))3807 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3786 segments[segs] = False3808 segments[segs] = False
3787 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3809 if write_prof_data[name]['allow'].get(segs, False):
3788 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3810 write_prof_data[name]['allow'].pop(segs)
3811 if write_prof_data[name]['deny'].get(segs, False):
3812 write_prof_data[name]['deny'].pop(segs)
3789 segments['include'] = True3813 segments['include'] = True
3790 write_prof_data[hat]['include'].pop(include_name)3814 write_prof_data[hat]['include'].pop(include_name)
3791 data.append(line)3815 data.append(line)
@@ -3833,16 +3857,18 @@
3833 if not segments['netdomain'] and True in segments.values():3857 if not segments['netdomain'] and True in segments.values():
3834 for segs in list(filter(lambda x: segments[x], segments.keys())):3858 for segs in list(filter(lambda x: segments[x], segments.keys())):
3835 depth = len(line) - len(line.lstrip())3859 depth = len(line) - len(line.lstrip())
3836 data += write_methods[segs](write_prof_data[name], int(depth/2))3860 data += write_methods[segs](write_prof_data[name], int(depth / 2))
3837 segments[segs] = False3861 segments[segs] = False
3838 if write_prof_data[name]['allow'].get(segs, False): write_prof_data[name]['allow'].pop(segs)3862 if write_prof_data[name]['allow'].get(segs, False):
3839 if write_prof_data[name]['deny'].get(segs, False): write_prof_data[name]['deny'].pop(segs)3863 write_prof_data[name]['allow'].pop(segs)
3864 if write_prof_data[name]['deny'].get(segs, False):
3865 write_prof_data[name]['deny'].pop(segs)
3840 segments['netdomain'] = True3866 segments['netdomain'] = True
38413867
3842 elif RE_PROFILE_CHANGE_HAT.search(line):3868 elif RE_PROFILE_CHANGE_HAT.search(line):
3843 matches = RE_PROFILE_CHANGE_HAT.search(line).groups()3869 matches = RE_PROFILE_CHANGE_HAT.search(line).groups()
3844 hat = matches[0]3870 hat = matches[0]
3845 hat = strip_quotes(hat)3871 hat = strip_quotes(hat)
3846 if not write_prof_data[hat]['declared']:3872 if not write_prof_data[hat]['declared']:
3847 correct = False3873 correct = False
3848 if correct:3874 if correct:
@@ -3858,7 +3884,7 @@
3858 flags = matches[3]3884 flags = matches[3]
3859 if not write_prof_data[hat]['flags'] == flags:3885 if not write_prof_data[hat]['flags'] == flags:
3860 correct = False3886 correct = False
3861 if not write_prof_data[hat]['declared'] == False:3887 if not write_prof_data[hat]['declared'] is False:
3862 correct = False3888 correct = False
3863 if not write_filelist['profile'][profile][hat]:3889 if not write_filelist['profile'][profile][hat]:
3864 correct = False3890 correct = False
@@ -3883,10 +3909,10 @@
38833909
3884 string += '\n'.join(data)3910 string += '\n'.join(data)
38853911
3886 return string+'\n'3912 return string + '\n'
38873913
3888def write_profile_ui_feedback(profile):3914def write_profile_ui_feedback(profile):
3889 UI_Info(_('Writing updated profile for %s.') %profile)3915 aaui.UI_Info(_('Writing updated profile for %s.') % profile)
3890 write_profile(profile)3916 write_profile(profile)
38913917
3892def write_profile(profile):3918def write_profile(profile):
@@ -3896,7 +3922,7 @@
3896 else:3922 else:
3897 prof_filename = get_profile_filename(profile)3923 prof_filename = get_profile_filename(profile)
38983924
3899 newprof = tempfile.NamedTemporaryFile('w', suffix='~' ,delete=False, dir=profile_dir)3925 newprof = tempfile.NamedTemporaryFile('w', suffix='~', delete=False, dir=profile_dir)
3900 if os.path.exists(prof_filename):3926 if os.path.exists(prof_filename):
3901 shutil.copymode(prof_filename, newprof.name)3927 shutil.copymode(prof_filename, newprof.name)
3902 else:3928 else:
@@ -3917,7 +3943,7 @@
3917 original_aa[profile] = deepcopy(aa[profile])3943 original_aa[profile] = deepcopy(aa[profile])
39183944
3919def matchliteral(aa_regexp, literal):3945def matchliteral(aa_regexp, literal):
3920 p_regexp = '^'+convert_regexp(aa_regexp)+'$'3946 p_regexp = '^' + convert_regexp(aa_regexp) + '$'
3921 match = False3947 match = False
3922 try:3948 try:
3923 match = re.search(p_regexp, literal)3949 match = re.search(p_regexp, literal)
@@ -3932,19 +3958,19 @@
3932 m = []3958 m = []
39333959
3934 cm, am, m = rematchfrag(profile, 'deny', exec_target)3960 cm, am, m = rematchfrag(profile, 'deny', exec_target)
3935 if cm & AA_MAY_EXEC:3961 if cm & apparmor.aamode.AA_MAY_EXEC:
3936 return -13962 return -1
39373963
3938 cm, am, m = match_prof_incs_to_path(profile, 'deny', exec_target)3964 cm, am, m = match_prof_incs_to_path(profile, 'deny', exec_target)
3939 if cm & AA_MAY_EXEC:3965 if cm & apparmor.aamode.AA_MAY_EXEC:
3940 return -13966 return -1
39413967
3942 cm, am, m = rematchfrag(profile, 'allow', exec_target)3968 cm, am, m = rematchfrag(profile, 'allow', exec_target)
3943 if cm & AA_MAY_EXEC:3969 if cm & apparmor.aamode.AA_MAY_EXEC:
3944 return 13970 return 1
39453971
3946 cm, am, m = match_prof_incs_to_path(profile, 'allow', exec_target)3972 cm, am, m = match_prof_incs_to_path(profile, 'allow', exec_target)
3947 if cm & AA_MAY_EXEC:3973 if cm & apparmor.aamode.AA_MAY_EXEC:
3948 return 13974 return 1
39493975
3950 return 03976 return 0
@@ -3986,11 +4012,11 @@
3986 net_family_sock = False4012 net_family_sock = False
3987 if netrules['rule'].get('all', False):4013 if netrules['rule'].get('all', False):
3988 all_net = True4014 all_net = True
3989 if netrules['rule'].get(family, False) == True:4015 if netrules['rule'].get(family, False) is True:
3990 all_net_family = True4016 all_net_family = True
3991 if (netrules['rule'].get(family, False) and4017 if (netrules['rule'].get(family, False) and
3992 type(netrules['rule'][family]) == dict and4018 type(netrules['rule'][family]) == dict and
3993 netrules['rule'][family][sock_type]):4019 netrules['rule'][family][sock_type]):
3994 net_family_sock = True4020 net_family_sock = True
39954021
3996 if all_net or all_net_family or net_family_sock:4022 if all_net or all_net_family or net_family_sock:
@@ -4004,7 +4030,7 @@
40044030
4005 prof_filename = get_profile_filename(bin_path)4031 prof_filename = get_profile_filename(bin_path)
40064032
4007 subprocess.call("cat '%s' | %s -I%s -r >/dev/null 2>&1" %(prof_filename, parser ,profile_dir), shell=True)4033 subprocess.call("cat '%s' | %s -I%s -r >/dev/null 2>&1" % (prof_filename, parser, profile_dir), shell=True)
40084034
4009def reload(bin_path):4035def reload(bin_path):
4010 bin_path = find_executable(bin_path)4036 bin_path = find_executable(bin_path)
@@ -4020,7 +4046,7 @@
4020 with open_file_read(filename) as f_in:4046 with open_file_read(filename) as f_in:
4021 data = f_in.readlines()4047 data = f_in.readlines()
4022 else:4048 else:
4023 raise AppArmorException(_('File Not Found: %s') %filename)4049 raise AppArmorException(_('File Not Found: %s') % filename)
4024 return data4050 return data
40254051
4026def load_include(incname):4052def load_include(incname):
@@ -4029,7 +4055,7 @@
4029 return 04055 return 0
4030 while load_includeslist:4056 while load_includeslist:
4031 incfile = load_includeslist.pop(0)4057 incfile = load_includeslist.pop(0)
4032 if os.path.isfile(profile_dir+'/'+incfile):4058 if os.path.isfile(profile_dir + '/' + incfile):
4033 data = get_include_data(incfile)4059 data = get_include_data(incfile)
4034 incdata = parse_profile_data(data, incfile, True)4060 incdata = parse_profile_data(data, incfile, True)
4035 #print(incdata)4061 #print(incdata)
@@ -4040,8 +4066,8 @@
4040 incdata[incname] = hasher()4066 incdata[incname] = hasher()
4041 attach_profile_data(include, incdata)4067 attach_profile_data(include, incdata)
4042 #If the include is a directory means include all subfiles4068 #If the include is a directory means include all subfiles
4043 elif os.path.isdir(profile_dir+'/'+incfile):4069 elif os.path.isdir(profile_dir + '/' + incfile):
4044 load_includeslist += list(map(lambda x: incfile+'/'+x, os.listdir(profile_dir+'/'+incfile)))4070 load_includeslist += list(map(lambda x: incfile + '/' + x, os.listdir(profile_dir + '/' + incfile)))
40454071
4046 return 04072 return 0
40474073
@@ -4069,7 +4095,7 @@
4069 while includelist:4095 while includelist:
4070 incfile = str(includelist.pop(0))4096 incfile = str(includelist.pop(0))
4071 ret = load_include(incfile)4097 ret = load_include(incfile)
4072 if not include.get(incfile,{}):4098 if not include.get(incfile, {}):
4073 continue4099 continue
4074 cm, am, m = rematchfrag(include[incfile].get(incfile, {}), allow, path)4100 cm, am, m = rematchfrag(include[incfile].get(incfile, {}), allow, path)
4075 #print(incfile, cm, am, m)4101 #print(incfile, cm, am, m)
@@ -4111,7 +4137,7 @@
4111 includelist = [incname]4137 includelist = [incname]
4112 while includelist:4138 while includelist:
4113 inc = includelist.pop(0)4139 inc = includelist.pop(0)
4114 cm, am , m = rematchfrag(include[inc][inc], 'allow', path)4140 cm, am, m = rematchfrag(include[inc][inc], 'allow', path)
4115 if cm:4141 if cm:
4116 combinedmode |= cm4142 combinedmode |= cm
4117 combinedaudit |= am4143 combinedaudit |= am
@@ -4129,12 +4155,12 @@
4129def check_qualifiers(program):4155def check_qualifiers(program):
4130 if cfg['qualifiers'].get(program, False):4156 if cfg['qualifiers'].get(program, False):
4131 if cfg['qualifiers'][program] != 'p':4157 if cfg['qualifiers'][program] != 'p':
4132 fatal_error(_("%s is currently marked as a program that should not have its own\nprofile. Usually, programs are marked this way if creating a profile for \nthem is likely to break the rest of the system. If you know what you\'re\ndoing and are certain you want to create a profile for this program, edit\nthe corresponding entry in the [qualifiers] section in /etc/apparmor/logprof.conf.") %program)4158 fatal_error(_("%s is currently marked as a program that should not have its own\nprofile. Usually, programs are marked this way if creating a profile for \nthem is likely to break the rest of the system. If you know what you\'re\ndoing and are certain you want to create a profile for this program, edit\nthe corresponding entry in the [qualifiers] section in /etc/apparmor/logprof.conf.") % program)
4133 return False4159 return False
41344160
4135def get_subdirectories(current_dir):4161def get_subdirectories(current_dir):
4136 """Returns a list of all directories directly inside given directory"""4162 """Returns a list of all directories directly inside given directory"""
4137 if sys.version_info < (3,0):4163 if sys.version_info < (3, 0):
4138 return os.walk(current_dir).next()[1]4164 return os.walk(current_dir).next()[1]
4139 else:4165 else:
4140 return os.walk(current_dir).__next__()[1]4166 return os.walk(current_dir).__next__()[1]
@@ -4152,7 +4178,7 @@
4152 continue4178 continue
4153 else:4179 else:
4154 fi = dirpath + '/' + fi4180 fi = dirpath + '/' + fi
4155 fi = fi.replace(profile_dir+'/', '', 1)4181 fi = fi.replace(profile_dir + '/', '', 1)
4156 load_include(fi)4182 load_include(fi)
41574183
4158def glob_common(path):4184def glob_common(path):
@@ -4178,7 +4204,7 @@
4178 if name1 == name2:4204 if name1 == name2:
4179 return name14205 return name1
4180 else:4206 else:
4181 return '%s^%s' %(name1, name2)4207 return '%s^%s' % (name1, name2)
41824208
4183def split_name(name):4209def split_name(name):
4184 names = name.split('^')4210 names = name.split('^')
@@ -4187,7 +4213,7 @@
4187 else:4213 else:
4188 return names[0], names[1]4214 return names[0], names[1]
4189def commonprefix(new, old):4215def commonprefix(new, old):
4190 match=re.search(r'^([^\0]*)[^\0]*(\0\1[^\0]*)*$', '\0'.join([new, old]))4216 match = re.search(r'^([^\0]*)[^\0]*(\0\1[^\0]*)*$', '\0'.join([new, old]))
4191 if match:4217 if match:
4192 return match.groups()[0]4218 return match.groups()[0]
4193 return match4219 return match
@@ -4234,7 +4260,7 @@
42344260
4235profile_dir = conf.find_first_dir(cfg['settings']['profiledir']) or '/etc/apparmor.d'4261profile_dir = conf.find_first_dir(cfg['settings']['profiledir']) or '/etc/apparmor.d'
4236if not os.path.isdir(profile_dir):4262if not os.path.isdir(profile_dir):
4237 raise AppArmorException('Can\'t find AppArmor profiles' )4263 raise AppArmorException('Can\'t find AppArmor profiles')
42384264
4239extra_profile_dir = conf.find_first_dir(cfg['settings']['inactive_profiledir']) or '/etc/apparmor/profiles/extras/'4265extra_profile_dir = conf.find_first_dir(cfg['settings']['inactive_profiledir']) or '/etc/apparmor/profiles/extras/'
42404266
42414267
=== modified file 'apparmor/aamode.py'
--- apparmor/aamode.py 2013-12-29 09:42:30 +0000
+++ apparmor/aamode.py 2014-02-12 00:39:55 +0000
@@ -16,7 +16,7 @@
16def AA_OTHER(mode):16def AA_OTHER(mode):
17 other = set()17 other = set()
18 for i in mode:18 for i in mode:
19 other.add('::%s'%i)19 other.add('::%s' % i)
20 return other20 return other
2121
22def AA_OTHER_REMOVE(mode):22def AA_OTHER_REMOVE(mode):
@@ -57,14 +57,14 @@
57 'm': AA_EXEC_MMAP, 'M': AA_EXEC_MMAP,57 'm': AA_EXEC_MMAP, 'M': AA_EXEC_MMAP,
58 'i': AA_EXEC_INHERIT, 'I': AA_EXEC_INHERIT,58 'i': AA_EXEC_INHERIT, 'I': AA_EXEC_INHERIT,
59 'u': AA_EXEC_UNCONFINED | AA_EXEC_UNSAFE, # Unconfined + Unsafe59 'u': AA_EXEC_UNCONFINED | AA_EXEC_UNSAFE, # Unconfined + Unsafe
60 'U': AA_EXEC_UNCONFINED,60 'U': AA_EXEC_UNCONFINED,
61 'p': AA_EXEC_PROFILE | AA_EXEC_UNSAFE, # Profile + unsafe61 'p': AA_EXEC_PROFILE | AA_EXEC_UNSAFE, # Profile + unsafe
62 'P': AA_EXEC_PROFILE,62 'P': AA_EXEC_PROFILE,
63 'c': AA_EXEC_CHILD | AA_EXEC_UNSAFE, # Child + Unsafe63 'c': AA_EXEC_CHILD | AA_EXEC_UNSAFE, # Child + Unsafe
64 'C': AA_EXEC_CHILD,64 'C': AA_EXEC_CHILD,
65 'n': AA_EXEC_NT | AA_EXEC_UNSAFE,65 'n': AA_EXEC_NT | AA_EXEC_UNSAFE,
66 'N': AA_EXEC_NT66 'N': AA_EXEC_NT
67 }67 }
6868
69LOG_MODE_RE = re.compile('(r|w|l|m|k|a|x|ix|ux|px|cx|nx|pix|cix|Ix|Ux|Px|PUx|Cx|Nx|Pix|Cix)')69LOG_MODE_RE = re.compile('(r|w|l|m|k|a|x|ix|ux|px|cx|nx|pix|cix|Ix|Ux|Px|PUx|Cx|Nx|Pix|Cix)')
70MODE_MAP_RE = re.compile('(r|w|l|m|k|a|x|i|u|p|c|n|I|U|P|C|N)')70MODE_MAP_RE = re.compile('(r|w|l|m|k|a|x|i|u|p|c|n|I|U|P|C|N)')
7171
=== modified file 'apparmor/common.py'
--- apparmor/common.py 2014-02-01 01:34:08 +0000
+++ apparmor/common.py 2014-02-12 00:39:55 +0000
@@ -11,7 +11,6 @@
11from __future__ import print_function11from __future__ import print_function
12import codecs12import codecs
13import collections13import collections
14import gettext
15import glob14import glob
16import logging15import logging
17import os16import os
@@ -23,6 +22,7 @@
2322
24DEBUGGING = False23DEBUGGING = False
2524
25
26#26#
27# Utility classes27# Utility classes
28#28#
@@ -110,7 +110,7 @@
110 debug("%s (relative)" % (m))110 debug("%s (relative)" % (m))
111 return False111 return False
112112
113 if '"' in path: # We double quote elsewhere113 if '"' in path: # We double quote elsewhere
114 return False114 return False
115115
116 try:116 try:
@@ -166,13 +166,6 @@
166 # Creates a dictionary for any depth and returns empty dictionary otherwise166 # Creates a dictionary for any depth and returns empty dictionary otherwise
167 return collections.defaultdict(hasher)167 return collections.defaultdict(hasher)
168168
169def init_translations(domain='apparmor-utils'):
170 """Installs the translations for the given domain, defaults to apparmor-utils domain"""
171 #Setup Translation
172 gettext.translation(domain, fallback=True)
173 gettext.install(domain)
174
175
176def convert_regexp(regexp):169def convert_regexp(regexp):
177 regex_paren = re.compile('^(.*){([^}]*)}(.*)$')170 regex_paren = re.compile('^(.*){([^}]*)}(.*)$')
178 regexp = regexp.strip()171 regexp = regexp.strip()
@@ -182,8 +175,8 @@
182 match = regex_paren.search(new_reg).groups()175 match = regex_paren.search(new_reg).groups()
183 prev = match[0]176 prev = match[0]
184 after = match[2]177 after = match[2]
185 p1 = match[1].replace(',','|')178 p1 = match[1].replace(',', '|')
186 new_reg = prev+'('+p1+')'+after179 new_reg = prev + '(' + p1 + ')' + after
187180
188 new_reg = new_reg.replace('?', '[^/\000]')181 new_reg = new_reg.replace('?', '[^/\000]')
189182
@@ -198,7 +191,7 @@
198 if regexp[0] != '^':191 if regexp[0] != '^':
199 new_reg = '^' + new_reg192 new_reg = '^' + new_reg
200 if regexp[-1] != '$':193 if regexp[-1] != '$':
201 new_reg = new_reg + '$'194 new_reg = new_reg + '$'
202 return new_reg195 return new_reg
203196
204def user_perm(prof_dir):197def user_perm(prof_dir):
@@ -221,7 +214,7 @@
221 self.debugging = False214 self.debugging = False
222 if self.debugging not in range(0, 4):215 if self.debugging not in range(0, 4):
223 sys.stdout.write('Environment Variable: LOGPROF_DEBUG contains invalid value: %s'216 sys.stdout.write('Environment Variable: LOGPROF_DEBUG contains invalid value: %s'
224 %os.getenv('LOGPROF_DEBUG'))217 % os.getenv('LOGPROF_DEBUG'))
225 if self.debugging == 0: # debugging disabled, don't need to setup logging218 if self.debugging == 0: # debugging disabled, don't need to setup logging
226 return219 return
227 if self.debugging == 1:220 if self.debugging == 1:
@@ -230,22 +223,21 @@
230 self.debug_level = logging.INFO223 self.debug_level = logging.INFO
231 elif self.debugging == 3:224 elif self.debugging == 3:
232 self.debug_level = logging.DEBUG225 self.debug_level = logging.DEBUG
233 226
234 try:227 try:
235 logging.basicConfig(filename=self.logfile, level=self.debug_level,228 logging.basicConfig(filename=self.logfile, level=self.debug_level,
236 format='%(asctime)s - %(name)s - %(message)s\n')229 format='%(asctime)s - %(name)s - %(message)s\n')
237 except OSError:230 except OSError:
238 # Unable to open the default logfile, so create a temporary logfile and tell use about it231 # Unable to open the default logfile, so create a temporary logfile and tell use about it
239 import tempfile232 import tempfile
240 templog = tempfile.NamedTemporaryFile('w', prefix='apparmor', suffix='.log' ,delete=False)233 templog = tempfile.NamedTemporaryFile('w', prefix='apparmor', suffix='.log', delete=False)
241 sys.stdout.write("\nCould not open: %s\nLogging to: %s\n"%(self.logfile, templog.name))234 sys.stdout.write("\nCould not open: %s\nLogging to: %s\n" % (self.logfile, templog.name))
242 235
243 logging.basicConfig(filename=templog.name, level=self.debug_level,236 logging.basicConfig(filename=templog.name, level=self.debug_level,
244 format='%(asctime)s - %(name)s - %(message)s\n')237 format='%(asctime)s - %(name)s - %(message)s\n')
245 238
246 self.logger = logging.getLogger(module_name)239 self.logger = logging.getLogger(module_name)
247240
248
249 def error(self, message):241 def error(self, message):
250 if self.debugging:242 if self.debugging:
251 self.logger.error(message)243 self.logger.error(message)
252244
=== modified file 'apparmor/config.py'
--- apparmor/config.py 2013-12-29 09:42:30 +0000
+++ apparmor/config.py 2014-02-12 00:39:55 +0000
@@ -20,6 +20,7 @@
20import tempfile20import tempfile
21if sys.version_info < (3, 0):21if sys.version_info < (3, 0):
22 import ConfigParser as configparser22 import ConfigParser as configparser
23
23 # Class to provide the object[section][option] behavior in Python224 # Class to provide the object[section][option] behavior in Python2
24 class configparser_py2(configparser.ConfigParser):25 class configparser_py2(configparser.ConfigParser):
25 def __getitem__(self, section):26 def __getitem__(self, section):
@@ -34,7 +35,7 @@
34 import configparser35 import configparser
3536
3637
37from apparmor.common import AppArmorException, open_file_read#, warn, msg,38from apparmor.common import AppArmorException, open_file_read # , warn, msg,
3839
3940
40# CFG = None41# CFG = None
@@ -110,7 +111,6 @@
110 # Replace the target config file with the temporary file111 # Replace the target config file with the temporary file
111 os.rename(config_file.name, filepath)112 os.rename(config_file.name, filepath)
112113
113
114 def find_first_file(self, file_list):114 def find_first_file(self, file_list):
115 """Returns name of first matching file None otherwise"""115 """Returns name of first matching file None otherwise"""
116 filename = None116 filename = None
@@ -164,7 +164,7 @@
164 option, value = result[0].split('=')164 option, value = result[0].split('=')
165 if '#' in line:165 if '#' in line:
166 comment = value.split('#', 1)[1]166 comment = value.split('#', 1)[1]
167 comment = '#'+comment167 comment = '#' + comment
168 else:168 else:
169 comment = ''169 comment = ''
170 # If option exists in the new config file170 # If option exists in the new config file
@@ -172,7 +172,7 @@
172 # If value is different172 # If value is different
173 if value != config[''][option]:173 if value != config[''][option]:
174 value_new = config[''][option]174 value_new = config[''][option]
175 if value_new != None:175 if value_new is not None:
176 # Update value176 # Update value
177 if '"' in line:177 if '"' in line:
178 value_new = '"' + value_new + '"'178 value_new = '"' + value_new + '"'
@@ -190,7 +190,7 @@
190 # If option exists in the new config file190 # If option exists in the new config file
191 if option in options:191 if option in options:
192 # If its no longer option type192 # If its no longer option type
193 if config[''][option] != None:193 if config[''][option] is not None:
194 value = config[''][option]194 value = config[''][option]
195 line = option + '=' + value + '\n'195 line = option + '=' + value + '\n'
196 f_out.write(line)196 f_out.write(line)
@@ -204,7 +204,7 @@
204 for option in options:204 for option in options:
205 value = config[''][option]205 value = config[''][option]
206 # option type entry206 # option type entry
207 if value == None:207 if value is None:
208 line = option + '\n'208 line = option + '\n'
209 # option=value type entry209 # option=value type entry
210 else:210 else:
@@ -273,7 +273,7 @@
273 if section in sections:273 if section in sections:
274 sections.remove(section)274 sections.remove(section)
275 for section in sections:275 for section in sections:
276 f_out.write('\n['+section+']\n')276 f_out.write('\n[%s]\n' % section)
277 options = config.options(section)277 options = config.options(section)
278 for option in options:278 for option in options:
279 line = ' ' + option + ' = ' + config[section][option] + '\n'279 line = ' ' + option + ' = ' + config[section][option] + '\n'
280280
=== modified file 'apparmor/logparser.py'
--- apparmor/logparser.py 2013-09-28 15:13:06 +0000
+++ apparmor/logparser.py 2014-02-12 00:39:55 +0000
@@ -11,16 +11,22 @@
11# GNU General Public License for more details.11# GNU General Public License for more details.
12#12#
13# ----------------------------------------------------------------------13# ----------------------------------------------------------------------
14import gettext
14import os15import os
15import re16import re
16import sys17import sys
17import time18import time
18import LibAppArmor19import LibAppArmor
19from apparmor.common import (AppArmorException, error, debug, msg,20from apparmor.common import (AppArmorException, error, debug,
20 open_file_read, valid_path,21 open_file_read, valid_path, hasher,
21 hasher, open_file_write, convert_regexp, DebugLogger)22 open_file_write, convert_regexp,
2223 DebugLogger)
23from apparmor.aamode import *24
25from apparmor.aamode import validate_log_mode, log_str_to_mode, hide_log_mode, AA_MAY_EXEC
26
27# setup module translations
28from apparmor.translations import init_translation
29_ = init_translation()
2430
25class ReadLog:31class ReadLog:
26 RE_LOG_v2_6_syslog = re.compile('kernel:\s+(\[[\d\.\s]+\]\s+)?type=\d+\s+audit\([\d\.\:]+\):\s+apparmor=')32 RE_LOG_v2_6_syslog = re.compile('kernel:\s+(\[[\d\.\s]+\]\s+)?type=\d+\s+audit\([\d\.\:]+\):\s+apparmor=')
@@ -31,9 +37,8 @@
31 PROFILE_MODE_NT_RE = re.compile('r|w|l|m|k|a|x|ix|ux|px|cx|pix|cix|Ux|Px|PUx|Cx|Pix|Cix')37 PROFILE_MODE_NT_RE = re.compile('r|w|l|m|k|a|x|ix|ux|px|cx|pix|cix|Ux|Px|PUx|Cx|Pix|Cix')
32 PROFILE_MODE_DENY_RE = re.compile('r|w|l|m|k|a|x')38 PROFILE_MODE_DENY_RE = re.compile('r|w|l|m|k|a|x')
33 # Used by netdomain to identify the operation types39 # Used by netdomain to identify the operation types
34 OPERATION_TYPES = {40 # New socket names
35 # New socket names41 OPERATION_TYPES = {'create': 'net',
36 'create': 'net',
37 'post_create': 'net',42 'post_create': 'net',
38 'bind': 'net',43 'bind': 'net',
39 'connect': 'net',44 'connect': 'net',
@@ -47,6 +52,7 @@
47 'setsockopt': 'net',52 'setsockopt': 'net',
48 'sock_shutdown': 'net'53 'sock_shutdown': 'net'
49 }54 }
55
50 def __init__(self, pid, filename, existing_profiles, profile_dir, log):56 def __init__(self, pid, filename, existing_profiles, profile_dir, log):
51 self.filename = filename57 self.filename = filename
52 self.profile_dir = profile_dir58 self.profile_dir = profile_dir
@@ -96,7 +102,7 @@
96 msg = msg.strip()102 msg = msg.strip()
97 self.debug_logger.info('parse_event: %s' % msg)103 self.debug_logger.info('parse_event: %s' % msg)
98 #print(repr(msg))104 #print(repr(msg))
99 if sys.version_info < (3,0):105 if sys.version_info < (3, 0):
100 # parse_record fails with u'foo' style strings hence typecasting to string106 # parse_record fails with u'foo' style strings hence typecasting to string
101 msg = str(msg)107 msg = str(msg)
102 event = LibAppArmor.parse_record(msg)108 event = LibAppArmor.parse_record(msg)
@@ -152,8 +158,7 @@
152158
153 if ev['aamode']:159 if ev['aamode']:
154 # Convert aamode values to their counter-parts160 # Convert aamode values to their counter-parts
155 mode_convertor = {161 mode_convertor = {0: 'UNKNOWN',
156 0: 'UNKNOWN',
157 1: 'ERROR',162 1: 'ERROR',
158 2: 'AUDITING',163 2: 'AUDITING',
159 3: 'PERMITTING',164 3: 'PERMITTING',
@@ -254,30 +259,30 @@
254 if e['operation'] == 'exec':259 if e['operation'] == 'exec':
255 if e.get('info', False) and e['info'] == 'mandatory profile missing':260 if e.get('info', False) and e['info'] == 'mandatory profile missing':
256 self.add_to_tree(e['pid'], e['parent'], 'exec',261 self.add_to_tree(e['pid'], e['parent'], 'exec',
257 [profile, hat, aamode, 'PERMITTING', e['denied_mask'], e['name'], e['name2']])262 [profile, hat, aamode, 'PERMITTING', e['denied_mask'], e['name'], e['name2']])
258 elif e.get('name2', False) and '\\null-/' in e['name2']:263 elif e.get('name2', False) and '\\null-/' in e['name2']:
259 self.add_to_tree(e['pid'], e['parent'], 'exec',264 self.add_to_tree(e['pid'], e['parent'], 'exec',
260 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])265 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])
261 elif e.get('name', False):266 elif e.get('name', False):
262 self.add_to_tree(e['pid'], e['parent'], 'exec',267 self.add_to_tree(e['pid'], e['parent'], 'exec',
263 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])268 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])
264 else:269 else:
265 self.debug_logger.debug('add_event_to_tree: dropped exec event in %s' % e['profile'])270 self.debug_logger.debug('add_event_to_tree: dropped exec event in %s' % e['profile'])
266271
267 elif 'file_' in e['operation']:272 elif 'file_' in e['operation']:
268 self.add_to_tree(e['pid'], e['parent'], 'path',273 self.add_to_tree(e['pid'], e['parent'], 'path',
269 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])274 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])
270 elif e['operation'] in ['open', 'truncate', 'mkdir', 'mknod', 'rename_src',275 elif e['operation'] in ['open', 'truncate', 'mkdir', 'mknod', 'rename_src',
271 'rename_dest', 'unlink', 'rmdir', 'symlink_create', 'link']:276 'rename_dest', 'unlink', 'rmdir', 'symlink_create', 'link']:
272 #print(e['operation'], e['name'])277 #print(e['operation'], e['name'])
273 self.add_to_tree(e['pid'], e['parent'], 'path',278 self.add_to_tree(e['pid'], e['parent'], 'path',
274 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])279 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])
275 elif e['operation'] == 'capable':280 elif e['operation'] == 'capable':
276 self.add_to_tree(e['pid'], e['parent'], 'capability',281 self.add_to_tree(e['pid'], e['parent'], 'capability',
277 [profile, hat, prog, aamode, e['name'], ''])282 [profile, hat, prog, aamode, e['name'], ''])
278 elif e['operation'] == 'setattr' or 'xattr' in e['operation']:283 elif e['operation'] == 'setattr' or 'xattr' in e['operation']:
279 self.add_to_tree(e['pid'], e['parent'], 'path',284 self.add_to_tree(e['pid'], e['parent'], 'path',
280 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])285 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])
281 elif 'inode_' in e['operation']:286 elif 'inode_' in e['operation']:
282 is_domain_change = False287 is_domain_change = False
283 if e['operation'] == 'inode_permission' and (e['denied_mask'] & AA_MAY_EXEC) and aamode == 'PERMITTING':288 if e['operation'] == 'inode_permission' and (e['denied_mask'] & AA_MAY_EXEC) and aamode == 'PERMITTING':
@@ -290,17 +295,17 @@
290295
291 if is_domain_change:296 if is_domain_change:
292 self.add_to_tree(e['pid'], e['parent'], 'exec',297 self.add_to_tree(e['pid'], e['parent'], 'exec',
293 [profile, hat, prog, aamode, e['denied_mask'], e['name'], e['name2']])298 [profile, hat, prog, aamode, e['denied_mask'], e['name'], e['name2']])
294 else:299 else:
295 self.add_to_tree(e['pid'], e['parent'], 'path',300 self.add_to_tree(e['pid'], e['parent'], 'path',
296 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])301 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])
297302
298 elif e['operation'] == 'sysctl':303 elif e['operation'] == 'sysctl':
299 self.add_to_tree(e['pid'], e['parent'], 'path',304 self.add_to_tree(e['pid'], e['parent'], 'path',
300 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])305 [profile, hat, prog, aamode, e['denied_mask'], e['name'], ''])
301306
302 elif e['operation'] == 'clone':307 elif e['operation'] == 'clone':
303 parent , child = e['pid'], e['task']308 parent, child = e['pid'], e['task']
304 if not parent:309 if not parent:
305 parent = 'null-complain-profile'310 parent = 'null-complain-profile'
306 if not hat:311 if not hat:
@@ -321,10 +326,10 @@
321326
322 elif self.op_type(e['operation']) == 'net':327 elif self.op_type(e['operation']) == 'net':
323 self.add_to_tree(e['pid'], e['parent'], 'netdomain',328 self.add_to_tree(e['pid'], e['parent'], 'netdomain',
324 [profile, hat, prog, aamode, e['family'], e['sock_type'], e['protocol']])329 [profile, hat, prog, aamode, e['family'], e['sock_type'], e['protocol']])
325 elif e['operation'] == 'change_hat':330 elif e['operation'] == 'change_hat':
326 self.add_to_tree(e['pid'], e['parent'], 'unknown_hat',331 self.add_to_tree(e['pid'], e['parent'], 'unknown_hat',
327 [profile, hat, aamode, hat])332 [profile, hat, aamode, hat])
328 else:333 else:
329 self.debug_logger.debug('UNHANDLED: %s' % e)334 self.debug_logger.debug('UNHANDLED: %s' % e)
330335
@@ -351,7 +356,7 @@
351 if self.logmark in line:356 if self.logmark in line:
352 seenmark = True357 seenmark = True
353358
354 self.debug_logger.debug('read_log: seenmark = %s' %seenmark)359 self.debug_logger.debug('read_log: seenmark = %s' % seenmark)
355 if not seenmark:360 if not seenmark:
356 continue361 continue
357362
@@ -382,7 +387,6 @@
382 return True387 return True
383 return False388 return False
384389
385
386 def get_profile_filename(self, profile):390 def get_profile_filename(self, profile):
387 """Returns the full profile name"""391 """Returns the full profile name"""
388 if profile.startswith('/'):392 if profile.startswith('/'):
@@ -392,4 +396,4 @@
392 profile = "profile_" + profile396 profile = "profile_" + profile
393 profile = profile.replace('/', '.')397 profile = profile.replace('/', '.')
394 full_profilename = self.profile_dir + '/' + profile398 full_profilename = self.profile_dir + '/' + profile
395 return full_profilename
396\ No newline at end of file399\ No newline at end of file
400 return full_profilename
397401
=== modified file 'apparmor/severity.py'
--- apparmor/severity.py 2014-02-01 00:44:05 +0000
+++ apparmor/severity.py 2014-02-12 00:39:55 +0000
@@ -14,7 +14,7 @@
14from __future__ import with_statement14from __future__ import with_statement
15import os15import os
16import re16import re
17from apparmor.common import AppArmorException, open_file_read, warn, convert_regexp #, msg, error, debug17from apparmor.common import AppArmorException, open_file_read, warn, convert_regexp # , msg, error, debug
1818
19class Severity(object):19class Severity(object):
20 def __init__(self, dbname=None, default_rank=10):20 def __init__(self, dbname=None, default_rank=10):
@@ -31,10 +31,10 @@
31 if not dbname:31 if not dbname:
32 return None32 return None
3333
34 with open_file_read(dbname) as database:#open(dbname, 'r')34 with open_file_read(dbname) as database: # open(dbname, 'r')
35 for lineno, line in enumerate(database, start=1):35 for lineno, line in enumerate(database, start=1):
36 line = line.strip() # or only rstrip and lstrip?36 line = line.strip() # or only rstrip and lstrip?
37 if line == '' or line.startswith('#') :37 if line == '' or line.startswith('#'):
38 continue38 continue
39 if line.startswith('/'):39 if line.startswith('/'):
40 try:40 try:
@@ -43,7 +43,7 @@
43 except ValueError:43 except ValueError:
44 raise AppArmorException("Insufficient values for permissions in file: %s\n\t[Line %s]: %s" % (dbname, lineno, line))44 raise AppArmorException("Insufficient values for permissions in file: %s\n\t[Line %s]: %s" % (dbname, lineno, line))
45 else:45 else:
46 if read not in range(0, 11) or write not in range(0,11) or execute not in range(0,11):46 if read not in range(0, 11) or write not in range(0, 11) or execute not in range(0, 11):
47 raise AppArmorException("Inappropriate values for permissions in file: %s\n\t[Line %s]: %s" % (dbname, lineno, line))47 raise AppArmorException("Inappropriate values for permissions in file: %s\n\t[Line %s]: %s" % (dbname, lineno, line))
48 path = path.lstrip('/')48 path = path.lstrip('/')
49 if '*' not in path:49 if '*' not in path:
@@ -67,7 +67,7 @@
67 except ValueError as e:67 except ValueError as e:
68 error_message = 'No severity value present in file: %s\n\t[Line %s]: %s' % (dbname, lineno, line)68 error_message = 'No severity value present in file: %s\n\t[Line %s]: %s' % (dbname, lineno, line)
69 #error(error_message)69 #error(error_message)
70 raise AppArmorException(error_message) # from None70 raise AppArmorException(error_message) # from None
71 else:71 else:
72 if severity not in range(0, 11):72 if severity not in range(0, 11):
73 raise AppArmorException("Inappropriate severity value present in file: %s\n\t[Line %s]: %s" % (dbname, lineno, line))73 raise AppArmorException("Inappropriate severity value present in file: %s\n\t[Line %s]: %s" % (dbname, lineno, line))
@@ -83,7 +83,6 @@
83 warn("unknown capability: %s" % resource)83 warn("unknown capability: %s" % resource)
84 return self.severity['DEFAULT_RANK']84 return self.severity['DEFAULT_RANK']
8585
86
87 def check_subtree(self, tree, mode, sev, segments):86 def check_subtree(self, tree, mode, sev, segments):
88 """Returns the max severity from the regex tree"""87 """Returns the max severity from the regex tree"""
89 if len(segments) == 0:88 if len(segments) == 0:
@@ -91,21 +90,21 @@
91 else:90 else:
92 first = segments[0]91 first = segments[0]
93 rest = segments[1:]92 rest = segments[1:]
94 path = '/'.join([first]+rest)93 path = '/'.join([first] + rest)
95 # Check if we have a matching directory tree to descend into94 # Check if we have a matching directory tree to descend into
96 if tree.get(first, False):95 if tree.get(first, False):
97 sev = self.check_subtree(tree[first], mode, sev, rest)96 sev = self.check_subtree(tree[first], mode, sev, rest)
98 # If severity still not found, match against globs97 # If severity still not found, match against globs
99 if sev == None:98 if sev is None:
100 # Match against all globs at this directory level99 # Match against all globs at this directory level
101 for chunk in tree.keys():100 for chunk in tree.keys():
102 if '*' in chunk:101 if '*' in chunk:
103 # Match rest of the path102 # Match rest of the path
104 if re.search("^"+chunk, path):103 if re.search("^" + chunk, path):
105 # Find max rank104 # Find max rank
106 if "AA_RANK" in tree[chunk].keys():105 if "AA_RANK" in tree[chunk].keys():
107 for m in mode:106 for m in mode:
108 if sev == None or tree[chunk]["AA_RANK"].get(m, -1) > sev:107 if sev is None or tree[chunk]["AA_RANK"].get(m, -1) > sev:
109 sev = tree[chunk]["AA_RANK"].get(m, None)108 sev = tree[chunk]["AA_RANK"].get(m, None)
110 return sev109 return sev
111110
@@ -118,12 +117,12 @@
118 if resource in self.severity['FILES'].keys():117 if resource in self.severity['FILES'].keys():
119 # Find max value among the given modes118 # Find max value among the given modes
120 for m in mode:119 for m in mode:
121 if sev == None or self.severity['FILES'][resource].get(m, -1) > sev:120 if sev is None or self.severity['FILES'][resource].get(m, -1) > sev:
122 sev = self.severity['FILES'][resource].get(m, None)121 sev = self.severity['FILES'][resource].get(m, None)
123 else:122 else:
124 # Search regex tree for matching glob123 # Search regex tree for matching glob
125 sev = self.check_subtree(self.severity['REGEXPS'], mode, sev, pieces)124 sev = self.check_subtree(self.severity['REGEXPS'], mode, sev, pieces)
126 if sev == None:125 if sev is None:
127 # Return default rank if severity cannot be found126 # Return default rank if severity cannot be found
128 return self.severity['DEFAULT_RANK']127 return self.severity['DEFAULT_RANK']
129 else:128 else:
@@ -146,13 +145,13 @@
146 rank = None145 rank = None
147 if '@' in resource:146 if '@' in resource:
148 variable = regex_variable.search(resource).groups()[0]147 variable = regex_variable.search(resource).groups()[0]
149 variable = '@{'+variable+'}'148 variable = '@{%s}' % variable
150 #variables = regex_variable.findall(resource)149 #variables = regex_variable.findall(resource)
151 for replacement in self.severity['VARIABLES'][variable]:150 for replacement in self.severity['VARIABLES'][variable]:
152 resource_replaced = self.variable_replace(variable, replacement, resource)151 resource_replaced = self.variable_replace(variable, replacement, resource)
153 rank_new = self.handle_variable_rank(resource_replaced, mode)152 rank_new = self.handle_variable_rank(resource_replaced, mode)
154 #rank_new = self.handle_variable_rank(resource.replace('@{'+variable+'}', replacement), mode)153 #rank_new = self.handle_variable_rank(resource.replace('@{'+variable+'}', replacement), mode)
155 if rank == None or rank_new > rank:154 if rank is None or rank_new > rank:
156 rank = rank_new155 rank = rank_new
157 return rank156 return rank
158 else:157 else:
@@ -163,13 +162,13 @@
163 leading = False162 leading = False
164 trailing = False163 trailing = False
165 # Check for leading or trailing / that may need to be collapsed164 # Check for leading or trailing / that may need to be collapsed
166 if resource.find("/"+variable) != -1 and resource.find("//"+variable) == -1: # find that a single / exists before variable or not165 if resource.find("/" + variable) != -1 and resource.find("//" + variable) == -1: # find that a single / exists before variable or not
167 leading = True166 leading = True
168 if resource.find(variable+"/") != -1 and resource.find(variable+"//") == -1:167 if resource.find(variable + "/") != -1 and resource.find(variable + "//") == -1:
169 trailing = True168 trailing = True
170 if replacement[0] == '/' and replacement[:2] != '//' and leading: # finds if the replacement has leading / or not169 if replacement[0] == '/' and replacement[:2] != '//' and leading: # finds if the replacement has leading / or not
171 replacement = replacement[1:]170 replacement = replacement[1:]
172 if replacement[-1] == '/' and replacement[-2:] !='//' and trailing:171 if replacement[-1] == '/' and replacement[-2:] != '//' and trailing:
173 replacement = replacement[:-1]172 replacement = replacement[:-1]
174 return resource.replace(variable, replacement)173 return resource.replace(variable, replacement)
175174
176175
=== modified file 'apparmor/tools.py'
--- apparmor/tools.py 2014-02-01 01:34:08 +0000
+++ apparmor/tools.py 2014-02-12 00:39:55 +0000
@@ -11,12 +11,17 @@
11# GNU General Public License for more details.11# GNU General Public License for more details.
12#12#
13# ----------------------------------------------------------------------13# ----------------------------------------------------------------------
14import gettext
14import os15import os
15import sys16import sys
1617
17import apparmor.aa as apparmor18import apparmor.aa as apparmor
18from apparmor.common import user_perm19from apparmor.common import user_perm
1920
21# setup module translations
22from apparmor.translations import init_translation
23_ = init_translation()
24
20class aa_tools:25class aa_tools:
21 def __init__(self, tool_name, args):26 def __init__(self, tool_name, args):
22 self.name = tool_name27 self.name = tool_name
@@ -24,12 +29,12 @@
24 self.profiling = args.program29 self.profiling = args.program
25 self.check_profile_dir()30 self.check_profile_dir()
26 self.silent = None31 self.silent = None
27 32
28 if tool_name in ['audit', 'complain']:33 if tool_name in ['audit', 'complain']:
29 self.remove = args.remove34 self.remove = args.remove
30 elif tool_name == 'disable':35 elif tool_name == 'disable':
31 self.revert = args.revert36 self.revert = args.revert
32 self.disabledir = apparmor.profile_dir+'/disable'37 self.disabledir = apparmor.profile_dir + '/disable'
33 self.check_disable_dir()38 self.check_disable_dir()
34 elif tool_name == 'autodep':39 elif tool_name == 'autodep':
35 self.force = args.force40 self.force = args.force
@@ -41,14 +46,14 @@
41 if self.profiledir:46 if self.profiledir:
42 apparmor.profile_dir = apparmor.get_full_path(self.profiledir)47 apparmor.profile_dir = apparmor.get_full_path(self.profiledir)
43 if not os.path.isdir(apparmor.profile_dir):48 if not os.path.isdir(apparmor.profile_dir):
44 raise apparmor.AppArmorException("%s is not a directory." %self.profiledir)49 raise apparmor.AppArmorException("%s is not a directory." % self.profiledir)
4550
46 if not user_perm(apparmor.profile_dir):51 if not user_perm(apparmor.profile_dir):
47 raise apparmor.AppArmorException("Cannot write to profile directory: %s" %(apparmor.profile_dir))52 raise apparmor.AppArmorException("Cannot write to profile directory: %s" % (apparmor.profile_dir))
4853
49 def check_disable_dir(self):54 def check_disable_dir(self):
50 if not os.path.isdir(self.disabledir):55 if not os.path.isdir(self.disabledir):
51 raise apparmor.AppArmorException("Can't find AppArmor disable directory %s" %self.disabledir)56 raise apparmor.AppArmorException("Can't find AppArmor disable directory %s" % self.disabledir)
5257
53 def act(self):58 def act(self):
54 for p in self.profiling:59 for p in self.profiling:
@@ -72,12 +77,12 @@
72 if program and not program.startswith('/'):77 if program and not program.startswith('/'):
73 program = apparmor.UI_GetString(_('The given program cannot be found, please try with the fully qualified path name of the program: '), '')78 program = apparmor.UI_GetString(_('The given program cannot be found, please try with the fully qualified path name of the program: '), '')
74 else:79 else:
75 apparmor.UI_Info(_("%s does not exist, please double-check the path.")%p)80 apparmor.UI_Info(_("%s does not exist, please double-check the path.") % p)
76 sys.exit(1)81 sys.exit(1)
7782
78 if self.name == 'autodep' and program and os.path.exists(program):83 if self.name == 'autodep' and program and os.path.exists(program):
79 self.use_autodep(program)84 self.use_autodep(program)
80 85
81 elif program and apparmor.profile_exists(program):86 elif program and apparmor.profile_exists(program):
82 if self.name == 'cleanprof':87 if self.name == 'cleanprof':
83 self.clean_profile(program, p)88 self.clean_profile(program, p)
@@ -86,21 +91,21 @@
86 filename = apparmor.get_profile_filename(program)91 filename = apparmor.get_profile_filename(program)
8792
88 if not os.path.isfile(filename) or apparmor.is_skippable_file(filename):93 if not os.path.isfile(filename) or apparmor.is_skippable_file(filename):
89 apparmor.UI_Info(_('Profile for %s not found, skipping')%p)94 apparmor.UI_Info(_('Profile for %s not found, skipping') % p)
9095
91 elif self.name == 'disable':96 elif self.name == 'disable':
92 if not self.revert:97 if not self.revert:
93 apparmor.UI_Info(_('Disabling %s.')%program)98 apparmor.UI_Info(_('Disabling %s.') % program)
94 self.disable_profile(filename)99 self.disable_profile(filename)
95 else:100 else:
96 apparmor.UI_Info(_('Enabling %s.')%program)101 apparmor.UI_Info(_('Enabling %s.') % program)
97 self.enable_profile(filename)102 self.enable_profile(filename)
98103
99 elif self.name == 'audit':104 elif self.name == 'audit':
100 if not self.remove:105 if not self.remove:
101 apparmor.UI_Info(_('Setting %s to audit mode.')%program)106 apparmor.UI_Info(_('Setting %s to audit mode.') % program)
102 else:107 else:
103 apparmor.UI_Info(_('Removing audit mode from %s.')%program)108 apparmor.UI_Info(_('Removing audit mode from %s.') % program)
104 apparmor.change_profile_flags(filename, program, 'audit', not self.remove)109 apparmor.change_profile_flags(filename, program, 'audit', not self.remove)
105110
106 elif self.name == 'complain':111 elif self.name == 'complain':
@@ -111,9 +116,9 @@
111 #apparmor.set_profile_flags(filename, self.name)116 #apparmor.set_profile_flags(filename, self.name)
112 else:117 else:
113 # One simply does not walk in here!118 # One simply does not walk in here!
114 raise apparmor.AppArmorException('Unknown tool: %s'%self.name)119 raise apparmor.AppArmorException('Unknown tool: %s' % self.name)
115120
116 cmd_info = apparmor.cmd([apparmor.parser, filename, '-I%s'%apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])121 cmd_info = apparmor.cmd([apparmor.parser, filename, '-I%s' % apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])
117 #cmd_info = apparmor.cmd(['cat', filename, '|', apparmor.parser, '-I%s'%apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])122 #cmd_info = apparmor.cmd(['cat', filename, '|', apparmor.parser, '-I%s'%apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])
118123
119 if cmd_info[0] != 0:124 if cmd_info[0] != 0:
@@ -121,9 +126,9 @@
121126
122 else:127 else:
123 if '/' not in p:128 if '/' not in p:
124 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))129 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))
125 else:130 else:
126 apparmor.UI_Info(_("%s does not exist, please double-check the path.")%p)131 apparmor.UI_Info(_("%s does not exist, please double-check the path.") % p)
127 sys.exit(1)132 sys.exit(1)
128133
129 def clean_profile(self, program, p):134 def clean_profile(self, program, p):
@@ -140,12 +145,12 @@
140 q = apparmor.hasher()145 q = apparmor.hasher()
141 q['title'] = 'Changed Local Profiles'146 q['title'] = 'Changed Local Profiles'
142 q['headers'] = []147 q['headers'] = []
143 q['explanation'] = _('The local profile for %s in file %s was changed. Would you like to save it?') %(program, filename)148 q['explanation'] = _('The local profile for %s in file %s was changed. Would you like to save it?') % (program, filename)
144 q['functions'] = ['CMD_SAVE_CHANGES', 'CMD_VIEW_CHANGES', 'CMD_ABORT']149 q['functions'] = ['CMD_SAVE_CHANGES', 'CMD_VIEW_CHANGES', 'CMD_ABORT']
145 q['default'] = 'CMD_VIEW_CHANGES'150 q['default'] = 'CMD_VIEW_CHANGES'
146 q['options'] = []151 q['options'] = []
147 q['selected'] = 0152 q['selected'] = 0
148 p =None153 p = None
149 ans = ''154 ans = ''
150 arg = None155 arg = None
151 while ans != 'CMD_SAVE_CHANGES':156 while ans != 'CMD_SAVE_CHANGES':
@@ -161,13 +166,13 @@
161 apparmor.write_profile_ui_feedback(program)166 apparmor.write_profile_ui_feedback(program)
162 apparmor.reload_base(program)167 apparmor.reload_base(program)
163 else:168 else:
164 raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.')%p)169 raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.') % p)
165170
166 def use_autodep(self, program):171 def use_autodep(self, program):
167 apparmor.check_qualifiers(program)172 apparmor.check_qualifiers(program)
168173
169 if os.path.exists(apparmor.get_profile_filename(program) and not self.force):174 if os.path.exists(apparmor.get_profile_filename(program) and not self.force):
170 apparmor.UI_Info('Profile for %s already exists - skipping.'%program)175 apparmor.UI_Info('Profile for %s already exists - skipping.' % program)
171 else:176 else:
172 apparmor.autodep(program)177 apparmor.autodep(program)
173 if self.aa_mountpoint:178 if self.aa_mountpoint:
@@ -177,4 +182,4 @@
177 apparmor.delete_symlink('disable', filename)182 apparmor.delete_symlink('disable', filename)
178183
179 def disable_profile(self, filename):184 def disable_profile(self, filename):
180 apparmor.create_symlink('disable', filename)
181\ No newline at end of file185\ No newline at end of file
186 apparmor.create_symlink('disable', filename)
182187
=== modified file 'apparmor/ui.py'
--- apparmor/ui.py 2014-02-01 00:44:05 +0000
+++ apparmor/ui.py 2014-02-12 00:39:55 +0000
@@ -11,12 +11,16 @@
11# GNU General Public License for more details.11# GNU General Public License for more details.
12#12#
13# ----------------------------------------------------------------------13# ----------------------------------------------------------------------
14import gettext
14import sys15import sys
15import os
16import re16import re
17from apparmor.yasti import yastLog, SendDataToYast, GetDataFromYast17from apparmor.yasti import yastLog, SendDataToYast, GetDataFromYast
1818
19from apparmor.common import readkey, AppArmorException, DebugLogger, msg19from apparmor.common import readkey, AppArmorException, DebugLogger
20
21# setup module translations
22from apparmor.translations import init_translation
23_ = init_translation()
2024
21# Set up UI logger for separate messages from UI module25# Set up UI logger for separate messages from UI module
22debug_logger = DebugLogger('UI')26debug_logger = DebugLogger('UI')
@@ -48,14 +52,13 @@
48 if UI_mode == 'text':52 if UI_mode == 'text':
49 sys.stdout.write('\n' + text + '\n')53 sys.stdout.write('\n' + text + '\n')
50 else:54 else:
51 SendDataToYast({55 SendDataToYast({'type': 'dialog-error',
52 'type': 'dialog-error',
53 'message': text56 'message': text
54 })57 })
55 path, yarg = GetDataFromYast()58 path, yarg = GetDataFromYast()
5659
57def get_translated_hotkey(translated, cmsg=''):60def get_translated_hotkey(translated, cmsg=''):
58 msg = 'PromptUser: '+_('Invalid hotkey for')61 msg = 'PromptUser: ' + _('Invalid hotkey for')
5962
60 # Originally (\S) was used but with translations it would not work :(63 # Originally (\S) was used but with translations it would not work :(
61 if re.search('\((\S+)\)', translated, re.LOCALE):64 if re.search('\((\S+)\)', translated, re.LOCALE):
@@ -64,10 +67,10 @@
64 if cmsg:67 if cmsg:
65 raise AppArmorException(cmsg)68 raise AppArmorException(cmsg)
66 else:69 else:
67 raise AppArmorException('%s %s' %(msg, translated))70 raise AppArmorException('%s %s' % (msg, translated))
6871
69def UI_YesNo(text, default):72def UI_YesNo(text, default):
70 debug_logger.debug('UI_YesNo: %s: %s %s' %(UI_mode, text, default))73 debug_logger.debug('UI_YesNo: %s: %s %s' % (UI_mode, text, default))
71 default = default.lower()74 default = default.lower()
72 ans = None75 ans = None
73 if UI_mode == 'text':76 if UI_mode == 'text':
@@ -101,10 +104,9 @@
101 ans = default104 ans = default
102105
103 else:106 else:
104 SendDataToYast({107 SendDataToYast({'type': 'dialog-yesno',
105 'type': 'dialog-yesno',108 'question': text
106 'question': text109 })
107 })
108 ypath, yarg = GetDataFromYast()110 ypath, yarg = GetDataFromYast()
109 ans = yarg['answer']111 ans = yarg['answer']
110 if not ans:112 if not ans:
@@ -142,7 +144,7 @@
142 elif ans == nokey:144 elif ans == nokey:
143 ans = 'n'145 ans = 'n'
144 elif ans == cancelkey:146 elif ans == cancelkey:
145 ans= 'c'147 ans = 'c'
146 elif ans == 'left':148 elif ans == 'left':
147 if default == 'n':149 if default == 'n':
148 default = 'y'150 default = 'y'
@@ -156,8 +158,7 @@
156 else:158 else:
157 ans = default159 ans = default
158 else:160 else:
159 SendDataToYast({161 SendDataToYast({'type': 'dialog-yesnocancel',
160 'type': 'dialog-yesnocancel',
161 'question': text162 'question': text
162 })163 })
163 ypath, yarg = GetDataFromYast()164 ypath, yarg = GetDataFromYast()
@@ -173,8 +174,7 @@
173 sys.stdout.write('\n' + text)174 sys.stdout.write('\n' + text)
174 string = sys.stdin.readline()175 string = sys.stdin.readline()
175 else:176 else:
176 SendDataToYast({177 SendDataToYast({'type': 'dialog-getstring',
177 'type': 'dialog-getstring',
178 'label': text,178 'label': text,
179 'default': default179 'default': default
180 })180 })
@@ -201,8 +201,7 @@
201 if UI_mode == 'text':201 if UI_mode == 'text':
202 UI_Info(message)202 UI_Info(message)
203 else:203 else:
204 SendDataToYast({204 SendDataToYast({'type': 'dialog-busy-start',
205 'type': 'dialog-busy-start',
206 'message': message205 'message': message
207 })206 })
208 ypath, yarg = GetDataFromYast()207 ypath, yarg = GetDataFromYast()
@@ -213,8 +212,7 @@
213 SendDataToYast({'type': 'dialog-busy-stop'})212 SendDataToYast({'type': 'dialog-busy-stop'})
214 ypath, yarg = GetDataFromYast()213 ypath, yarg = GetDataFromYast()
215214
216CMDS = {215CMDS = {'CMD_ALLOW': _('(A)llow'),
217 'CMD_ALLOW': _('(A)llow'),
218 'CMD_OTHER': _('(M)ore'),216 'CMD_OTHER': _('(M)ore'),
219 'CMD_AUDIT_NEW': _('Audi(t)'),217 'CMD_AUDIT_NEW': _('Audi(t)'),
220 'CMD_AUDIT_OFF': _('Audi(t) off'),218 'CMD_AUDIT_OFF': _('Audi(t) off'),
@@ -307,16 +305,14 @@
307 sys.exit(0)305 sys.exit(0)
308306
309def UI_ShortMessage(title, message):307def UI_ShortMessage(title, message):
310 SendDataToYast({308 SendDataToYast({'type': 'short-dialog-message',
311 'type': 'short-dialog-message',
312 'headline': title,309 'headline': title,
313 'message': message310 'message': message
314 })311 })
315 ypath, yarg = GetDataFromYast()312 ypath, yarg = GetDataFromYast()
316313
317def UI_LongMessage(title, message):314def UI_LongMessage(title, message):
318 SendDataToYast({315 SendDataToYast({'type': 'long-dialog-message',
319 'type': 'long-dialog-message',
320 'headline': title,316 'headline': title,
321 'message': message317 'message': message
322 })318 })
@@ -356,7 +352,7 @@
356 keys[key] = cmd352 keys[key] = cmd
357353
358 if default and default == cmd:354 if default and default == cmd:
359 menutext = '[%s]' %menutext355 menutext = '[%s]' % menutext
360356
361 menu_items.append(menutext)357 menu_items.append(menutext)
362358
@@ -392,14 +388,14 @@
392388
393 prompt = '\n'389 prompt = '\n'
394 if title:390 if title:
395 prompt += '= %s =\n\n' %title391 prompt += '= %s =\n\n' % title
396392
397 if headers:393 if headers:
398 header_copy = headers[:]394 header_copy = headers[:]
399 while header_copy:395 while header_copy:
400 header = header_copy.pop(0)396 header = header_copy.pop(0)
401 value = header_copy.pop(0)397 value = header_copy.pop(0)
402 prompt += formatstr %(header+':', value)398 prompt += formatstr % (header + ':', value)
403 prompt += '\n'399 prompt += '\n'
404400
405 if explanation:401 if explanation:
@@ -411,12 +407,12 @@
411 format_option = ' [%s - %s]'407 format_option = ' [%s - %s]'
412 else:408 else:
413 format_option = ' %s - %s '409 format_option = ' %s - %s '
414 prompt += format_option %(index+1, option)410 prompt += format_option % (index + 1, option)
415 prompt += '\n'411 prompt += '\n'
416412
417 prompt += ' / '.join(menu_items)413 prompt += ' / '.join(menu_items)
418414
419 sys.stdout.write(prompt+'\n')415 sys.stdout.write(prompt + '\n')
420416
421 ans = getkey().lower()417 ans = getkey().lower()
422418
@@ -427,7 +423,7 @@
427 ans = 'XXXINVALIDXXX'423 ans = 'XXXINVALIDXXX'
428424
429 elif ans == 'down':425 elif ans == 'down':
430 if options and selected < len(options)-1:426 if options and selected < len(options) - 1:
431 selected += 1427 selected += 1
432 ans = 'XXXINVALIDXXX'428 ans = 'XXXINVALIDXXX'
433429
@@ -446,7 +442,7 @@
446 ans = 'XXXINVALIDXXX'442 ans = 'XXXINVALIDXXX'
447443
448 if keys.get(ans, False) == 'CMD_HELP':444 if keys.get(ans, False) == 'CMD_HELP':
449 sys.stdout.write('\n%s\n' %helptext)445 sys.stdout.write('\n%s\n' % helptext)
450 ans = 'again'446 ans = 'again'
451447
452 if keys.get(ans, False):448 if keys.get(ans, False):
453449
=== removed file 'apparmor/writeprofile.py'
=== modified file 'apparmor/yasti.py'
--- apparmor/yasti.py 2013-09-28 15:13:06 +0000
+++ apparmor/yasti.py 2014-02-12 00:39:55 +0000
@@ -101,4 +101,3 @@
101 else:101 else:
102 ret += argref102 ret += argref
103 return ret103 return ret
104

Subscribers

People subscribed via source and target branches