2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 18:17:09 +00:00

Remove Python 2 support.

This commit is contained in:
Mark Grassi 2022-06-28 21:08:50 -04:00
parent 43f419458e
commit df97cf89bd
37 changed files with 146 additions and 319 deletions

View File

@ -1,6 +1 @@
import sys from LibAppArmor.LibAppArmor import *
if sys.version_info[0] >= 3:
from LibAppArmor.LibAppArmor import *
else:
from .LibAppArmor import *

View File

@ -17,7 +17,6 @@
from argparse import ArgumentParser from argparse import ArgumentParser
import os import os
import platform
import shutil import shutil
import time import time
import tempfile import tempfile
@ -147,9 +146,6 @@ class AAParserCachingCommon(testlib.AATestTemplate):
class AAParserBasicCachingTests(AAParserCachingCommon): class AAParserBasicCachingTests(AAParserCachingCommon):
def setUp(self):
super(AAParserBasicCachingTests, self).setUp()
def test_no_cache_by_default(self): def test_no_cache_by_default(self):
'''test profiles are not cached by default''' '''test profiles are not cached by default'''
@ -201,7 +197,7 @@ class AAParserAltCacheBasicTests(AAParserBasicCachingTests):
'''Same tests as above, but with an alternate cache location specified on the command line''' '''Same tests as above, but with an alternate cache location specified on the command line'''
def setUp(self): def setUp(self):
super(AAParserAltCacheBasicTests, self).setUp() super().setUp()
alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir) alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
os.chmod(alt_cache_loc, 0o755) os.chmod(alt_cache_loc, 0o755)
@ -213,14 +209,14 @@ class AAParserAltCacheBasicTests(AAParserBasicCachingTests):
def tearDown(self): def tearDown(self):
if len(os.listdir(self.unused_cache_loc)) > 0: if len(os.listdir(self.unused_cache_loc)) > 0:
self.fail('original cache dir \'%s\' not empty' % self.unused_cache_loc) self.fail('original cache dir \'%s\' not empty' % self.unused_cache_loc)
super(AAParserAltCacheBasicTests, self).tearDown() super().tearDown()
class AAParserCreateCacheBasicTestsCacheExists(AAParserBasicCachingTests): class AAParserCreateCacheBasicTestsCacheExists(AAParserBasicCachingTests):
'''Same tests as above, but with create cache option on the command line and the cache already exists''' '''Same tests as above, but with create cache option on the command line and the cache already exists'''
def setUp(self): def setUp(self):
super(AAParserCreateCacheBasicTestsCacheExists, self).setUp() super().setUp()
self.cmd_prefix.append('--create-cache-dir') self.cmd_prefix.append('--create-cache-dir')
@ -228,7 +224,7 @@ class AAParserCreateCacheBasicTestsCacheNotExist(AAParserBasicCachingTests):
'''Same tests as above, but with create cache option on the command line and cache dir removed''' '''Same tests as above, but with create cache option on the command line and cache dir removed'''
def setUp(self): def setUp(self):
super(AAParserCreateCacheBasicTestsCacheNotExist, self).setUp() super().setUp()
shutil.rmtree(self.cache_dir) shutil.rmtree(self.cache_dir)
self.cmd_prefix.append('--create-cache-dir') self.cmd_prefix.append('--create-cache-dir')
@ -238,7 +234,7 @@ class AAParserCreateCacheAltCacheTestsCacheNotExist(AAParserBasicCachingTests):
alt cache specified, and cache dir removed''' alt cache specified, and cache dir removed'''
def setUp(self): def setUp(self):
super(AAParserCreateCacheAltCacheTestsCacheNotExist, self).setUp() super().setUp()
shutil.rmtree(self.cache_dir) shutil.rmtree(self.cache_dir)
self.cmd_prefix.append('--create-cache-dir') self.cmd_prefix.append('--create-cache-dir')
@ -246,7 +242,7 @@ class AAParserCreateCacheAltCacheTestsCacheNotExist(AAParserBasicCachingTests):
class AAParserCachingTests(AAParserCachingCommon): class AAParserCachingTests(AAParserCachingCommon):
def setUp(self): def setUp(self):
super(AAParserCachingTests, self).setUp() super().setUp()
r = testlib.filesystem_time_resolution() r = testlib.filesystem_time_resolution()
self.mtime_res = r[1] self.mtime_res = r[1]
@ -258,24 +254,10 @@ class AAParserCachingTests(AAParserCachingCommon):
self.run_cmd_check(cmd) self.run_cmd_check(cmd)
self.assert_path_exists(self.cache_file) self.assert_path_exists(self.cache_file)
def _assertTimeStampEquals(self, time1, time2):
'''Compare two timestamps to ensure equality'''
# python 3.2 and earlier don't support writing timestamps with
# nanosecond resolution, only microsecond. When comparing
# timestamps in such an environment, loosen the equality bounds
# to compensate
# Reference: https://bugs.python.org/issue12904
(major, minor, _) = platform.python_version_tuple()
if (int(major) < 3) or ((int(major) == 3) and (int(minor) <= 2)):
self.assertAlmostEquals(time1, time2, places=5)
else:
self.assertEqual(time1, time2)
def _set_mtime(self, path, mtime): def _set_mtime(self, path, mtime):
atime = os.stat(path).st_atime atime = os.stat(path).st_atime
os.utime(path, (atime, mtime)) os.utime(path, (atime, mtime))
self._assertTimeStampEquals(os.stat(path).st_mtime, mtime) self.assertEqual(os.stat(path).st_mtime, mtime)
def test_cache_loaded_when_exists(self): def test_cache_loaded_when_exists(self):
'''test cache is loaded when it exists, is newer than profile, and features match''' '''test cache is loaded when it exists, is newer than profile, and features match'''
@ -458,7 +440,7 @@ class AAParserCachingTests(AAParserCachingCommon):
stat = os.stat(self.cache_file) stat = os.stat(self.cache_file)
self.assertNotEqual(orig_stat.st_ino, stat.st_ino) self.assertNotEqual(orig_stat.st_ino, stat.st_ino)
self._assertTimeStampEquals(profile_mtime, stat.st_mtime) self.assertEqual(profile_mtime, stat.st_mtime)
def test_abstraction_newer_rewrites_cache(self): def test_abstraction_newer_rewrites_cache(self):
'''test cache is rewritten if abstraction is newer''' '''test cache is rewritten if abstraction is newer'''
@ -475,7 +457,7 @@ class AAParserCachingTests(AAParserCachingCommon):
stat = os.stat(self.cache_file) stat = os.stat(self.cache_file)
self.assertNotEqual(orig_stat.st_ino, stat.st_ino) self.assertNotEqual(orig_stat.st_ino, stat.st_ino)
self._assertTimeStampEquals(abstraction_mtime, stat.st_mtime) self.assertEqual(abstraction_mtime, stat.st_mtime)
def test_parser_newer_uses_cache(self): def test_parser_newer_uses_cache(self):
'''test cache is not skipped if parser is newer''' '''test cache is not skipped if parser is newer'''
@ -521,7 +503,7 @@ class AAParserAltCacheTests(AAParserCachingTests):
check_orig_cache = True check_orig_cache = True
def setUp(self): def setUp(self):
super(AAParserAltCacheTests, self).setUp() super().setUp()
alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir) alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
os.chmod(alt_cache_loc, 0o755) os.chmod(alt_cache_loc, 0o755)
@ -534,7 +516,7 @@ class AAParserAltCacheTests(AAParserCachingTests):
def tearDown(self): def tearDown(self):
if self.check_orig_cache and len(os.listdir(self.orig_cache_dir)) > 0: if self.check_orig_cache and len(os.listdir(self.orig_cache_dir)) > 0:
self.fail('original cache dir \'%s\' not empty' % self.orig_cache_dir) self.fail('original cache dir \'%s\' not empty' % self.orig_cache_dir)
super(AAParserAltCacheTests, self).tearDown() super().tearDown()
def test_cache_purge_leaves_original_cache_alone(self): def test_cache_purge_leaves_original_cache_alone(self):
'''test cache purging only touches alt cache''' '''test cache purging only touches alt cache'''

View File

@ -13,7 +13,7 @@
# TODO # TODO
# - finish adding suppressions for valgrind false positives # - finish adding suppressions for valgrind false positives
from argparse import ArgumentParser # requires python 2.7 or newer from argparse import ArgumentParser
import os import os
import sys import sys
import tempfile import tempfile

View File

@ -13,7 +13,6 @@
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# No old version logs, only 2.6 + supported # No old version logs, only 2.6 + supported
from __future__ import division, with_statement
import os import os
import re import re
import shutil import shutil
@ -23,6 +22,7 @@ import time
import traceback import traceback
import atexit import atexit
import tempfile import tempfile
from shutil import which
import apparmor.config import apparmor.config
import apparmor.logparser import apparmor.logparser
@ -33,7 +33,7 @@ from copy import deepcopy
from apparmor.aare import AARE from apparmor.aare import AARE
from apparmor.common import (AppArmorException, AppArmorBug, cmd, is_skippable_file, open_file_read, valid_path, hasher, from apparmor.common import (AppArmorException, AppArmorBug, cmd, is_skippable_file, open_file_read, valid_path, hasher,
combine_profname, split_name, type_is_str, open_file_write, DebugLogger) combine_profname, split_name, open_file_write, DebugLogger)
import apparmor.ui as aaui import apparmor.ui as aaui
@ -176,18 +176,6 @@ def check_for_apparmor(filesystem='/proc/filesystems', mounts='/proc/mounts'):
break break
return aa_mountpoint return aa_mountpoint
def which(file):
"""Returns the executable fullpath for the file, None otherwise"""
if sys.version_info >= (3, 3):
return shutil.which(file)
env_dirs = os.getenv('PATH').split(':')
for env_dir in env_dirs:
env_path = os.path.join(env_dir, file)
# Test if the path is executable or not
if os.access(env_path, os.X_OK):
return env_path
return None
def get_full_path(original_path): def get_full_path(original_path):
"""Return the full path after resolving any symlinks""" """Return the full path after resolving any symlinks"""
path = original_path path = original_path
@ -626,7 +614,7 @@ def change_profile_flags(prof_filename, program, flag, set_flag):
found = False found = False
depth = -1 depth = -1
if not flag or (type_is_str(flag) and flag.strip() == ''): if not flag or (type(flag) is str and flag.strip() == ''):
raise AppArmorBug('New flag for %s is empty' % prof_filename) raise AppArmorBug('New flag for %s is empty' % prof_filename)
with open_file_read(prof_filename) as f_in: with open_file_read(prof_filename) as f_in:
@ -1529,28 +1517,28 @@ def save_profiles(is_mergeprof=False):
ans, arg = q.promptUser() ans, arg = q.promptUser()
q.selected = arg # remember selection q.selected = arg # remember selection
which = options[arg] which_ = options[arg]
if ans == 'CMD_SAVE_SELECTED': if ans == 'CMD_SAVE_SELECTED':
write_profile_ui_feedback(which) write_profile_ui_feedback(which_)
reload_base(which) reload_base(which_)
q.selected = 0 # saving the selected profile removes it from the list, therefore reset selection q.selected = 0 # saving the selected profile removes it from the list, therefore reset selection
elif ans == 'CMD_VIEW_CHANGES': elif ans == 'CMD_VIEW_CHANGES':
oldprofile = None oldprofile = None
if aa[which][which].get('filename', False): if aa[which_][which_].get('filename', False):
oldprofile = aa[which][which]['filename'] oldprofile = aa[which_][which_]['filename']
else: else:
oldprofile = get_profile_filename_from_attachment(which, True) oldprofile = get_profile_filename_from_attachment(which_, True)
serialize_options = {'METADATA': True} serialize_options = {'METADATA': True}
newprofile = serialize_profile(split_to_merged(aa), which, serialize_options) newprofile = serialize_profile(split_to_merged(aa), which_, serialize_options)
aaui.UI_Changes(oldprofile, newprofile, comments=True) aaui.UI_Changes(oldprofile, newprofile, comments=True)
elif ans == 'CMD_VIEW_CHANGES_CLEAN': elif ans == 'CMD_VIEW_CHANGES_CLEAN':
oldprofile = serialize_profile(split_to_merged(original_aa), which, {}) oldprofile = serialize_profile(split_to_merged(original_aa), which_, {})
newprofile = serialize_profile(split_to_merged(aa), which, {}) newprofile = serialize_profile(split_to_merged(aa), which_, {})
aaui.UI_Changes(oldprofile, newprofile) aaui.UI_Changes(oldprofile, newprofile)
@ -2385,10 +2373,7 @@ def check_qualifiers(program):
def get_subdirectories(current_dir): def get_subdirectories(current_dir):
"""Returns a list of all directories directly inside given directory""" """Returns a list of all directories directly inside given directory"""
if sys.version_info < (3, 0): return next(os.walk(current_dir))[1]
return os.walk(current_dir).next()[1]
else:
return os.walk(current_dir).__next__()[1]
def loadincludes(): def loadincludes():
loadincludes_dir('tunables', True) loadincludes_dir('tunables', True)

View File

@ -14,9 +14,9 @@
import re import re
from apparmor.common import convert_regexp, type_is_str, AppArmorBug, AppArmorException from apparmor.common import convert_regexp, AppArmorBug, AppArmorException
class AARE(object): class AARE:
'''AARE (AppArmor Regular Expression) wrapper class''' '''AARE (AppArmor Regular Expression) wrapper class'''
def __init__(self, regex, is_path, log_event=None): def __init__(self, regex, is_path, log_event=None):
@ -68,7 +68,7 @@ class AARE(object):
expression = expression.regex expression = expression.regex
else: else:
return self.is_equal(expression) # better safe than sorry return self.is_equal(expression) # better safe than sorry
elif not type_is_str(expression): elif type(expression) is not str:
raise AppArmorBug('AARE.match() called with unknown object: %s' % str(expression)) raise AppArmorBug('AARE.match() called with unknown object: %s' % str(expression))
if self._regex_compiled is None: if self._regex_compiled is None:
@ -81,7 +81,7 @@ class AARE(object):
if type(expression) == AARE: if type(expression) == AARE:
return self.regex == expression.regex return self.regex == expression.regex
elif type_is_str(expression): elif type(expression) is str:
return self.regex == expression return self.regex == expression
else: else:
raise AppArmorBug('AARE.is_equal() called with unknown object: %s' % str(expression)) raise AppArmorBug('AARE.is_equal() called with unknown object: %s' % str(expression))

View File

@ -14,7 +14,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
import apparmor.aa as apparmor import apparmor.aa as apparmor
class Prof(object): class Prof:
def __init__(self, filename): def __init__(self, filename):
apparmor.init_aa() apparmor.init_aa()
self.aa = apparmor.aa self.aa = apparmor.aa
@ -22,7 +22,7 @@ class Prof(object):
self.include = apparmor.include self.include = apparmor.include
self.filename = filename self.filename = filename
class CleanProf(object): class CleanProf:
def __init__(self, same_file, profile, other): def __init__(self, same_file, profile, other):
#If same_file we're basically comparing the file against itself to check superfluous rules #If same_file we're basically comparing the file against itself to check superfluous rules
self.same_file = same_file self.same_file = same_file

View File

@ -9,7 +9,6 @@
# #
# ------------------------------------------------------------------ # ------------------------------------------------------------------
from __future__ import print_function
import codecs import codecs
import collections import collections
import glob import glob
@ -118,10 +117,7 @@ def cmd(command):
except OSError as ex: except OSError as ex:
return [127, str(ex)] return [127, str(ex)]
if sys.version_info[0] >= 3: out = sp.communicate()[0].decode('ascii', 'ignore')
out = sp.communicate()[0].decode('ascii', 'ignore')
else:
out = sp.communicate()[0]
return [sp.returncode, out] return [sp.returncode, out]
@ -134,10 +130,7 @@ def cmd_pipe(command1, command2):
except OSError as ex: except OSError as ex:
return [127, str(ex)] return [127, str(ex)]
if sys.version_info[0] >= 3: out = sp2.communicate()[0].decode('ascii', 'ignore')
out = sp2.communicate()[0].decode('ascii', 'ignore')
else:
out = sp2.communicate()[0]
return [sp2.returncode, out] return [sp2.returncode, out]
@ -202,14 +195,7 @@ def open_file_anymode(mode, path, encoding='UTF-8'):
# This avoids a crash when reading a logfile with special characters that # This avoids a crash when reading a logfile with special characters that
# are not utf8-encoded (for example a latin1 "ö"), and also avoids crashes # are not utf8-encoded (for example a latin1 "ö"), and also avoids crashes
# at several other places we don't know yet ;-) # at several other places we don't know yet ;-)
errorhandling = 'surrogateescape' return codecs.open(path, mode, encoding, errors='surrogateescape')
if sys.version_info[0] < 3:
errorhandling = 'replace'
orig = codecs.open(path, mode, encoding, errors=errorhandling)
return orig
def readkey(): def readkey():
'''Returns the pressed key''' '''Returns the pressed key'''
@ -268,15 +254,6 @@ def user_perm(prof_dir):
return False return False
return True return True
if sys.version_info[0] > 2:
unicode = str # python 3 dropped the unicode type. To keep type_is_str() simple (and pyflakes3 happy), re-create it as alias of str.
def type_is_str(var):
''' returns True if the given variable is a str (or unicode string when using python 2)'''
if type(var) in (str, unicode): # python 2 sometimes uses the 'unicode' type
return True
else:
return False
def split_name(full_profile): def split_name(full_profile):
if '//' in full_profile: if '//' in full_profile:
@ -301,7 +278,7 @@ def combine_profname(name_parts):
return '//'.join(name_parts) return '//'.join(name_parts)
class DebugLogger(object): class DebugLogger:
'''Unified debug facility. Logs to file or stderr. '''Unified debug facility. Logs to file or stderr.
Does not log anything by default. Will only log if environment variable Does not log anything by default. Will only log if environment variable

View File

@ -11,29 +11,12 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from __future__ import with_statement
import os import os
import shlex import shlex
import shutil import shutil
import stat import stat
import sys
import tempfile import tempfile
if sys.version_info < (3, 0): from configparser import ConfigParser
import ConfigParser as configparser
# Class to provide the object[section][option] behavior in Python2
class configparser_py2(configparser.ConfigParser):
def __getitem__(self, section):
section_val = self.items(section)
section_options = dict()
for option, value in section_val:
section_options[option] = value
return section_options
else:
import configparser
from apparmor.common import AppArmorException, open_file_read # , warn, msg, from apparmor.common import AppArmorException, open_file_read # , warn, msg,
@ -41,7 +24,7 @@ from apparmor.common import AppArmorException, open_file_read # , warn, msg,
# CFG = None # CFG = None
# REPO_CFG = None # REPO_CFG = None
# SHELL_FILES = ['easyprof.conf', 'notify.conf', 'parser.conf'] # SHELL_FILES = ['easyprof.conf', 'notify.conf', 'parser.conf']
class Config(object): class Config:
def __init__(self, conf_type, conf_dir='/etc/apparmor'): def __init__(self, conf_type, conf_dir='/etc/apparmor'):
self.CONF_DIR = conf_dir self.CONF_DIR = conf_dir
# The type of config file that'll be read and/or written # The type of config file that'll be read and/or written
@ -55,7 +38,7 @@ class Config(object):
if self.conf_type == 'shell': if self.conf_type == 'shell':
config = {'': dict()} config = {'': dict()}
elif self.conf_type == 'ini': elif self.conf_type == 'ini':
config = configparser.ConfigParser() config = ConfigParser()
return config return config
def read_config(self, filename): def read_config(self, filename):
@ -65,21 +48,10 @@ class Config(object):
if self.conf_type == 'shell': if self.conf_type == 'shell':
config = self.read_shell(filepath) config = self.read_shell(filepath)
elif self.conf_type == 'ini': elif self.conf_type == 'ini':
if sys.version_info > (3, 0): config = ConfigParser()
config = configparser.ConfigParser()
else:
config = configparser_py2()
# Set the option form to string -prevents forced conversion to lowercase # Set the option form to string -prevents forced conversion to lowercase
config.optionxform = str config.optionxform = str
if sys.version_info > (3, 0): config.read(filepath)
config.read(filepath)
else:
try:
config.read(filepath)
except configparser.ParsingError:
tmp_filepath = py2_parser(filepath)
config.read(tmp_filepath.name)
##config.__get__()
return config return config
def write_config(self, filename, config): def write_config(self, filename, config):
@ -275,18 +247,3 @@ class Config(object):
for option in options: for option in options:
line = ' ' + option + ' = ' + config[section][option] + '\n' line = ' ' + option + ' = ' + config[section][option] + '\n'
f_out.write(line) f_out.write(line)
def py2_parser(filename):
"""Returns the de-dented ini file from the new format ini"""
tmp = tempfile.NamedTemporaryFile('rw')
if os.path.exists(filename):
with open(tmp.name, 'w') as f_out, open_file_read(filename) as f_in:
for line in f_in:
# The ini format allows for multi-line entries, with the subsequent
# entries being indented deeper hence simple lstrip() is not appropriate
if line[:2] == ' ':
line = line[2:]
elif line[0] == '\t':
line = line[1:]
f_out.write(line)
return tmp

View File

@ -8,8 +8,6 @@
# #
# ------------------------------------------------------------------ # ------------------------------------------------------------------
from __future__ import with_statement
import codecs import codecs
import copy import copy
import glob import glob
@ -21,8 +19,8 @@ import shutil
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
from shutil import which
from apparmor.aa import which
from apparmor.common import AppArmorException from apparmor.common import AppArmorException

View File

@ -8,8 +8,6 @@
# #
# ------------------------------------------------------------------ # ------------------------------------------------------------------
from __future__ import print_function # needed in py2 for print('...', file=sys.stderr)
import cgitb import cgitb
import os import os
import sys import sys

View File

@ -79,9 +79,6 @@ class ReadLog:
"""Parse the event from log into key value pairs""" """Parse the event from log into key value pairs"""
msg = msg.strip() msg = msg.strip()
self.debug_logger.info('parse_event: %s' % msg) self.debug_logger.info('parse_event: %s' % msg)
if sys.version_info < (3, 0):
# parse_record fails with u'foo' style strings hence typecasting to string
msg = str(msg)
event = LibAppArmor.parse_record(msg) event = LibAppArmor.parse_record(msg)
ev = dict() ev = dict()
ev['resource'] = event.info ev['resource'] = event.info
@ -288,8 +285,7 @@ class ReadLog:
except AppArmorException as e: except AppArmorException as e:
ex_msg = ('%(msg)s\n\nThis error was caused by the log line:\n%(logline)s' % ex_msg = ('%(msg)s\n\nThis error was caused by the log line:\n%(logline)s' %
{'msg': e.value, 'logline': line}) {'msg': e.value, 'logline': line})
# when py3 only: Drop the original AppArmorException by passing None as the parent exception raise AppArmorBug(ex_msg) from None
raise AppArmorBug(ex_msg) # py3-only: from None
self.LOG.close() self.LOG.close()
self.logmark = '' self.logmark = ''

View File

@ -14,7 +14,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule.abi import AbiRule, AbiRuleset from apparmor.rule.abi import AbiRule, AbiRuleset
from apparmor.rule.capability import CapabilityRule, CapabilityRuleset from apparmor.rule.capability import CapabilityRule, CapabilityRuleset
@ -108,14 +108,14 @@ class ProfileStorage:
# allow writing str or None to some keys # allow writing str or None to some keys
elif key in ('flags', 'filename'): elif key in ('flags', 'filename'):
if type_is_str(value) or value is None: if type(value) is str or value is None:
self.data[key] = value self.data[key] = value
else: else:
raise AppArmorBug('Attempt to change type of "%s" from %s to %s, value %s' % (key, type(self.data[key]), type(value), value)) raise AppArmorBug('Attempt to change type of "%s" from %s to %s, value %s' % (key, type(self.data[key]), type(value), value))
# allow writing str values # allow writing str values
elif type_is_str(self.data[key]): elif type(self.data[key]) is str:
if type_is_str(value): if type(value) is str:
self.data[key] = value self.data[key] = value
else: else:
raise AppArmorBug('Attempt to change type of "%s" from %s to %s, value %s' % (key, type(self.data[key]), type(value), value)) raise AppArmorBug('Attempt to change type of "%s" from %s to %s, value %s' % (key, type(self.data[key]), type(value), value))
@ -268,10 +268,10 @@ def split_flags(flags):
def add_or_remove_flag(flags, flags_to_change, set_flag): def add_or_remove_flag(flags, flags_to_change, set_flag):
'''add (if set_flag == True) or remove the given flags_to_change to flags''' '''add (if set_flag == True) or remove the given flags_to_change to flags'''
if type_is_str(flags) or flags is None: if type(flags) is str or flags is None:
flags = split_flags(flags) flags = split_flags(flags)
if type_is_str(flags_to_change) or flags_to_change is None: if type(flags_to_change) is str or flags_to_change is None:
flags_to_change = split_flags(flags_to_change) flags_to_change = split_flags(flags_to_change)
if set_flag: if set_flag:

View File

@ -13,15 +13,17 @@
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from abc import abstractmethod
from apparmor.aare import AARE from apparmor.aare import AARE
from apparmor.common import AppArmorBug, type_is_str from apparmor.common import AppArmorBug
# setup module translations # setup module translations
from apparmor.translations import init_translation from apparmor.translations import init_translation
_ = init_translation() _ = init_translation()
class BaseRule(object): class BaseRule:
'''Base class to handle and store a single rule''' '''Base class to handle and store a single rule'''
# type specific rules should inherit from this class. # type specific rules should inherit from this class.
@ -76,7 +78,7 @@ class BaseRule(object):
if rulepart == self.ALL: if rulepart == self.ALL:
return None, True return None, True
elif type_is_str(rulepart): elif type(rulepart) is str:
if len(rulepart.strip()) == 0: if len(rulepart.strip()) == 0:
raise AppArmorBug('Passed empty %(partname)s to %(classname)s: %(rulepart)s' % raise AppArmorBug('Passed empty %(partname)s to %(classname)s: %(rulepart)s' %
{'partname': partname, 'classname': self.__class__.__name__, 'rulepart': str(rulepart)}) {'partname': partname, 'classname': self.__class__.__name__, 'rulepart': str(rulepart)})
@ -104,8 +106,8 @@ class BaseRule(object):
else: else:
return False return False
# @abstractmethod FIXME - uncomment when python3 only
@classmethod @classmethod
@abstractmethod
def _match(cls, raw_rule): def _match(cls, raw_rule):
'''parse raw_rule and return regex match object''' '''parse raw_rule and return regex match object'''
raise NotImplementedError("'%s' needs to implement _match(), but didn't" % (str(cls))) raise NotImplementedError("'%s' needs to implement _match(), but didn't" % (str(cls)))
@ -117,14 +119,14 @@ class BaseRule(object):
rule.raw_rule = raw_rule.strip() rule.raw_rule = raw_rule.strip()
return rule return rule
# @abstractmethod FIXME - uncomment when python3 only
@classmethod @classmethod
@abstractmethod
def _parse(cls, raw_rule): def _parse(cls, raw_rule):
'''returns a Rule object created from parsing the raw rule. '''returns a Rule object created from parsing the raw rule.
required to be implemented by subclasses; raise exception if not''' required to be implemented by subclasses; raise exception if not'''
raise NotImplementedError("'%s' needs to implement _parse(), but didn't" % (str(cls))) raise NotImplementedError("'%s' needs to implement _parse(), but didn't" % (str(cls)))
# @abstractmethod FIXME - uncomment when python3 only @abstractmethod
def get_clean(self, depth=0): def get_clean(self, depth=0):
'''return clean rule (with default formatting, and leading whitespace as specified in the depth parameter)''' '''return clean rule (with default formatting, and leading whitespace as specified in the depth parameter)'''
raise NotImplementedError("'%s' needs to implement get_clean(), but didn't" % (str(self.__class__))) raise NotImplementedError("'%s' needs to implement get_clean(), but didn't" % (str(self.__class__)))
@ -157,7 +159,7 @@ class BaseRule(object):
# still here? -> then the common part is covered, check rule-specific things now # still here? -> then the common part is covered, check rule-specific things now
return self.is_covered_localvars(other_rule) return self.is_covered_localvars(other_rule)
# @abstractmethod FIXME - uncomment when python3 only @abstractmethod
def is_covered_localvars(self, other_rule): def is_covered_localvars(self, other_rule):
'''check if the rule-specific parts of other_rule is covered by this rule object''' '''check if the rule-specific parts of other_rule is covered by this rule object'''
raise NotImplementedError("'%s' needs to implement is_covered_localvars(), but didn't" % (str(self))) raise NotImplementedError("'%s' needs to implement is_covered_localvars(), but didn't" % (str(self)))
@ -238,7 +240,7 @@ class BaseRule(object):
# still here? -> then it is equal # still here? -> then it is equal
return True return True
# @abstractmethod FIXME - uncomment when python3 only @abstractmethod
def is_equal_localvars(self, other_rule, strict): def is_equal_localvars(self, other_rule, strict):
'''compare if rule-specific variables are equal''' '''compare if rule-specific variables are equal'''
raise NotImplementedError("'%s' needs to implement is_equal_localvars(), but didn't" % (str(self))) raise NotImplementedError("'%s' needs to implement is_equal_localvars(), but didn't" % (str(self)))
@ -273,24 +275,24 @@ class BaseRule(object):
return headers return headers
# @abstractmethod FIXME - uncomment when python3 only @abstractmethod
def logprof_header_localvars(self): def logprof_header_localvars(self):
'''return the headers (human-readable version of the rule) to display in aa-logprof for this rule object '''return the headers (human-readable version of the rule) to display in aa-logprof for this rule object
returns {'label1': 'value1', 'label2': 'value2'} ''' returns {'label1': 'value1', 'label2': 'value2'} '''
raise NotImplementedError("'%s' needs to implement logprof_header(), but didn't" % (str(self))) raise NotImplementedError("'%s' needs to implement logprof_header(), but didn't" % (str(self)))
# @abstractmethod FIXME - uncomment when python3 only @abstractmethod
def edit_header(self): def edit_header(self):
'''return the prompt for, and the path to edit when using '(N)ew' ''' '''return the prompt for, and the path to edit when using '(N)ew' '''
raise NotImplementedError("'%s' needs to implement edit_header(), but didn't" % (str(self))) raise NotImplementedError("'%s' needs to implement edit_header(), but didn't" % (str(self)))
# @abstractmethod FIXME - uncomment when python3 only @abstractmethod
def validate_edit(self, newpath): def validate_edit(self, newpath):
'''validate the new path. '''validate the new path.
Returns True if it covers the previous path, False if it doesn't.''' Returns True if it covers the previous path, False if it doesn't.'''
raise NotImplementedError("'%s' needs to implement validate_edit(), but didn't" % (str(self))) raise NotImplementedError("'%s' needs to implement validate_edit(), but didn't" % (str(self)))
# @abstractmethod FIXME - uncomment when python3 only @abstractmethod
def store_edit(self, newpath): def store_edit(self, newpath):
'''store the changed path. '''store the changed path.
This is done even if the new path doesn't match the original one.''' This is done even if the new path doesn't match the original one.'''
@ -314,7 +316,7 @@ class BaseRule(object):
return '%s%s' % (auditstr, allowstr) return '%s%s' % (auditstr, allowstr)
class BaseRuleset(object): class BaseRuleset:
'''Base class to handle and store a collection of rules''' '''Base class to handle and store a collection of rules'''
# decides if the (G)lob and Glob w/ (E)xt options are displayed # decides if the (G)lob and Glob w/ (E)xt options are displayed
@ -499,7 +501,7 @@ def check_and_split_list(lst, allowed_keywords, all_obj, classname, keyword_name
if lst == all_obj: if lst == all_obj:
return None, True, None return None, True, None
elif type_is_str(lst): elif type(lst) is str:
result_list = {lst} result_list = {lst}
elif type(lst) in (list, tuple, set) and (len(lst) > 0 or allow_empty_list): elif type(lst) in (list, tuple, set) and (len(lst) > 0 or allow_empty_list):
result_list = set(lst) result_list = set(lst)

View File

@ -30,10 +30,9 @@ class AbiRule(IncludeRule):
def __init__(self, path, ifexists, ismagic, audit=False, deny=False, allow_keyword=False, def __init__(self, path, ifexists, ismagic, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(AbiRule, self).__init__(path, ifexists, ismagic, super().__init__(path, ifexists, ismagic,
audit=audit, deny=deny, allow_keyword=allow_keyword, audit=audit, deny=deny, allow_keyword=allow_keyword,
comment=comment, comment=comment, log_event=log_event)
log_event=log_event)
# abi doesn't support 'if exists' # abi doesn't support 'if exists'
if ifexists: if ifexists:

View File

@ -13,7 +13,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from apparmor.regex import RE_PROFILE_ALIAS, strip_quotes from apparmor.regex import RE_PROFILE_ALIAS, strip_quotes
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed
# setup module translations # setup module translations
@ -29,10 +29,8 @@ class AliasRule(BaseRule):
def __init__(self, orig_path, target, audit=False, deny=False, allow_keyword=False, def __init__(self, orig_path, target, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(AliasRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
# aliass don't support audit or deny # aliass don't support audit or deny
if audit: if audit:
@ -40,14 +38,14 @@ class AliasRule(BaseRule):
if deny: if deny:
raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__)
if not type_is_str(orig_path): if type(orig_path) is not str:
raise AppArmorBug('Passed unknown type for orig_path to %s: %s' % (self.__class__.__name__, orig_path)) raise AppArmorBug('Passed unknown type for orig_path to %s: %s' % (self.__class__.__name__, orig_path))
if not orig_path: if not orig_path:
raise AppArmorException('Passed empty orig_path to %s: %s' % (self.__class__.__name__, orig_path)) raise AppArmorException('Passed empty orig_path to %s: %s' % (self.__class__.__name__, orig_path))
if not orig_path.startswith('/'): if not orig_path.startswith('/'):
raise AppArmorException("Alias path doesn't start with '/'") raise AppArmorException("Alias path doesn't start with '/'")
if not type_is_str(target): if type(target) is not str:
raise AppArmorBug('Passed unknown type for target to %s: %s' % (self.__class__.__name__, target)) raise AppArmorBug('Passed unknown type for target to %s: %s' % (self.__class__.__name__, target))
if not target: if not target:
raise AppArmorException('Passed empty target to %s: %s' % (self.__class__.__name__, target)) raise AppArmorException('Passed empty target to %s: %s' % (self.__class__.__name__, target))

View File

@ -14,7 +14,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from apparmor.regex import RE_PROFILE_BOOLEAN from apparmor.regex import RE_PROFILE_BOOLEAN
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, parse_comment from apparmor.rule import BaseRule, BaseRuleset, parse_comment
# setup module translations # setup module translations
@ -30,10 +30,8 @@ class BooleanRule(BaseRule):
def __init__(self, varname, value, audit=False, deny=False, allow_keyword=False, def __init__(self, varname, value, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(BooleanRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
# boolean variables don't support audit or deny # boolean variables don't support audit or deny
if audit: if audit:
@ -41,12 +39,12 @@ class BooleanRule(BaseRule):
if deny: if deny:
raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__)
if not type_is_str(varname): if type(varname) is not str:
raise AppArmorBug('Passed unknown type for boolean variable to %s: %s' % (self.__class__.__name__, varname)) raise AppArmorBug('Passed unknown type for boolean variable to %s: %s' % (self.__class__.__name__, varname))
if not varname.startswith('$'): if not varname.startswith('$'):
raise AppArmorException("Passed invalid boolean to %s (doesn't start with '$'): %s" % (self.__class__.__name__, varname)) raise AppArmorException("Passed invalid boolean to %s (doesn't start with '$'): %s" % (self.__class__.__name__, varname))
if not type_is_str(value): if type(value) is not str:
raise AppArmorBug('Passed unknown type for value to %s: %s' % (self.__class__.__name__, value)) raise AppArmorBug('Passed unknown type for value to %s: %s' % (self.__class__.__name__, value))
if not value: if not value:
raise AppArmorException('Passed empty value to %s: %s' % (self.__class__.__name__, value)) raise AppArmorException('Passed empty value to %s: %s' % (self.__class__.__name__, value))
@ -131,4 +129,4 @@ class BooleanRuleset(BaseRuleset):
if rule.varname == knownrule.varname: if rule.varname == knownrule.varname:
raise AppArmorException(_('Redefining existing variable %(variable)s: %(value)s') % { 'variable': rule.varname, 'value': rule.value }) raise AppArmorException(_('Redefining existing variable %(variable)s: %(value)s') % { 'variable': rule.varname, 'value': rule.value })
super(BooleanRuleset, self).add(rule, cleanup) super().add(rule, cleanup)

View File

@ -16,7 +16,7 @@
import re import re
from apparmor.regex import RE_PROFILE_CAP from apparmor.regex import RE_PROFILE_CAP
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, logprof_value_or_all, parse_modifiers from apparmor.rule import BaseRule, BaseRuleset, logprof_value_or_all, parse_modifiers
# setup module translations # setup module translations
@ -29,7 +29,7 @@ class CapabilityRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field CapabilityRule.ALL # should reference the class field CapabilityRule.ALL
class __CapabilityAll(object): class __CapabilityAll:
pass pass
ALL = __CapabilityAll ALL = __CapabilityAll
@ -39,10 +39,8 @@ class CapabilityRule(BaseRule):
def __init__(self, cap_list, audit=False, deny=False, allow_keyword=False, def __init__(self, cap_list, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(CapabilityRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
# Because we support having multiple caps in one rule, # Because we support having multiple caps in one rule,
# initializer needs to accept a list of caps. # initializer needs to accept a list of caps.
self.all_caps = False self.all_caps = False
@ -50,7 +48,7 @@ class CapabilityRule(BaseRule):
self.all_caps = True self.all_caps = True
self.capability = set() self.capability = set()
else: else:
if type_is_str(cap_list): if type(cap_list) is str:
self.capability = {cap_list} self.capability = {cap_list}
elif type(cap_list) == list and len(cap_list) > 0: elif type(cap_list) == list and len(cap_list) > 0:
self.capability = set(cap_list) self.capability = set(cap_list)

View File

@ -14,7 +14,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from apparmor.regex import RE_PROFILE_CHANGE_PROFILE, strip_quotes from apparmor.regex import RE_PROFILE_CHANGE_PROFILE, strip_quotes
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, logprof_value_or_all, quote_if_needed from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, logprof_value_or_all, quote_if_needed
# setup module translations # setup module translations
@ -27,7 +27,7 @@ class ChangeProfileRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field ChangeProfileRule.ALL # should reference the class field ChangeProfileRule.ALL
class __ChangeProfileAll(object): class __ChangeProfileAll:
pass pass
ALL = __ChangeProfileAll ALL = __ChangeProfileAll
@ -43,10 +43,8 @@ class ChangeProfileRule(BaseRule):
CHANGE_PROFILE RULE = 'change_profile' [ [ EXEC MODE ] EXEC COND ] [ -> PROGRAMCHILD ] CHANGE_PROFILE RULE = 'change_profile' [ [ EXEC MODE ] EXEC COND ] [ -> PROGRAMCHILD ]
''' '''
super(ChangeProfileRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
if execmode: if execmode:
if execmode != 'safe' and execmode != 'unsafe': if execmode != 'safe' and execmode != 'unsafe':
@ -59,7 +57,7 @@ class ChangeProfileRule(BaseRule):
self.all_execconds = False self.all_execconds = False
if execcond == ChangeProfileRule.ALL: if execcond == ChangeProfileRule.ALL:
self.all_execconds = True self.all_execconds = True
elif type_is_str(execcond): elif type(execcond) is str:
if not execcond.strip(): if not execcond.strip():
raise AppArmorBug('Empty exec condition in change_profile rule') raise AppArmorBug('Empty exec condition in change_profile rule')
elif execcond.startswith('/') or execcond.startswith('@'): elif execcond.startswith('/') or execcond.startswith('@'):
@ -73,7 +71,7 @@ class ChangeProfileRule(BaseRule):
self.all_targetprofiles = False self.all_targetprofiles = False
if targetprofile == ChangeProfileRule.ALL: if targetprofile == ChangeProfileRule.ALL:
self.all_targetprofiles = True self.all_targetprofiles = True
elif type_is_str(targetprofile): elif type(targetprofile) is str:
if targetprofile.strip(): if targetprofile.strip():
self.targetprofile = targetprofile self.targetprofile = targetprofile
else: else:

View File

@ -68,7 +68,7 @@ class DbusRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field DbusRule.ALL # should reference the class field DbusRule.ALL
class __DbusAll(object): class __DbusAll:
pass pass
ALL = __DbusAll ALL = __DbusAll
@ -78,10 +78,8 @@ class DbusRule(BaseRule):
def __init__(self, access, bus, path, name, interface, member, peername, peerlabel, def __init__(self, access, bus, path, name, interface, member, peername, peerlabel,
audit=False, deny=False, allow_keyword=False, comment='', log_event=None): audit=False, deny=False, allow_keyword=False, comment='', log_event=None):
super(DbusRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, DbusRule.ALL, 'DbusRule', 'access') self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, DbusRule.ALL, 'DbusRule', 'access')
if unknown_items: if unknown_items:

View File

@ -14,7 +14,7 @@
from apparmor.aare import AARE from apparmor.aare import AARE
from apparmor.regex import RE_PROFILE_FILE_ENTRY, strip_quotes from apparmor.regex import RE_PROFILE_FILE_ENTRY, strip_quotes
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, check_and_split_list, logprof_value_or_all, parse_modifiers, quote_if_needed from apparmor.rule import BaseRule, BaseRuleset, check_and_split_list, logprof_value_or_all, parse_modifiers, quote_if_needed
# setup module translations # setup module translations
@ -34,9 +34,9 @@ class FileRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field FileRule.ALL # should reference the class field FileRule.ALL
class __FileAll(object): class __FileAll:
pass pass
class __FileAnyExec(object): class __FileAnyExec:
pass pass
ALL = __FileAll ALL = __FileAll
@ -58,8 +58,8 @@ class FileRule(BaseRule):
- leading_perms: bool - leading_perms: bool
''' '''
super(FileRule, self).__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
comment=comment, log_event=log_event) comment=comment, log_event=log_event)
# rulepart partperms is_path log_event # rulepart partperms is_path log_event
self.path, self.all_paths = self._aare_or_all(path, 'path', True, log_event) self.path, self.all_paths = self._aare_or_all(path, 'path', True, log_event)
@ -69,7 +69,7 @@ class FileRule(BaseRule):
self.can_glob_ext = not self.all_paths self.can_glob_ext = not self.all_paths
self.can_edit = not self.all_paths self.can_edit = not self.all_paths
if type_is_str(perms): if type(perms) is str:
perms, tmp_exec_perms = split_perms(perms, deny) perms, tmp_exec_perms = split_perms(perms, deny)
if tmp_exec_perms: if tmp_exec_perms:
raise AppArmorBug('perms must not contain exec perms') raise AppArmorBug('perms must not contain exec perms')
@ -96,7 +96,7 @@ class FileRule(BaseRule):
raise AppArmorBug("link rules can't have execute permissions") raise AppArmorBug("link rules can't have execute permissions")
elif exec_perms == self.ANY_EXEC: elif exec_perms == self.ANY_EXEC:
self.exec_perms = exec_perms self.exec_perms = exec_perms
elif type_is_str(exec_perms): elif type(exec_perms) is str:
if deny: if deny:
if exec_perms != 'x': if exec_perms != 'x':
raise AppArmorException(_("file deny rules only allow to use 'x' as execute mode, but not %s" % exec_perms)) raise AppArmorException(_("file deny rules only allow to use 'x' as execute mode, but not %s" % exec_perms))

View File

@ -13,7 +13,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from apparmor.regex import RE_INCLUDE, re_match_include_parse from apparmor.regex import RE_INCLUDE, re_match_include_parse
from apparmor.common import AppArmorBug, AppArmorException, is_skippable_file, type_is_str from apparmor.common import AppArmorBug, AppArmorException, is_skippable_file
from apparmor.rule import BaseRule, BaseRuleset, parse_comment from apparmor.rule import BaseRule, BaseRuleset, parse_comment
import os import os
@ -30,10 +30,8 @@ class IncludeRule(BaseRule):
def __init__(self, path, ifexists, ismagic, audit=False, deny=False, allow_keyword=False, def __init__(self, path, ifexists, ismagic, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(IncludeRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
# include doesn't support audit or deny # include doesn't support audit or deny
if audit: if audit:
@ -45,7 +43,7 @@ class IncludeRule(BaseRule):
raise AppArmorBug('Passed unknown type for ifexists to %s: %s' % (self.__class__.__name__, ifexists)) raise AppArmorBug('Passed unknown type for ifexists to %s: %s' % (self.__class__.__name__, ifexists))
if type(ismagic) is not bool: if type(ismagic) is not bool:
raise AppArmorBug('Passed unknown type for ismagic to %s: %s' % (self.__class__.__name__, ismagic)) raise AppArmorBug('Passed unknown type for ismagic to %s: %s' % (self.__class__.__name__, ismagic))
if not type_is_str(path): if type(path) is not str:
raise AppArmorBug('Passed unknown type for path to %s: %s' % (self.__class__.__name__, path)) raise AppArmorBug('Passed unknown type for path to %s: %s' % (self.__class__.__name__, path))
if not path: if not path:
raise AppArmorBug('Passed empty path to %s: %s' % (self.__class__.__name__, path)) raise AppArmorBug('Passed empty path to %s: %s' % (self.__class__.__name__, path))

View File

@ -16,7 +16,7 @@
import re import re
from apparmor.regex import RE_PROFILE_NETWORK from apparmor.regex import RE_PROFILE_NETWORK
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, logprof_value_or_all, parse_modifiers from apparmor.rule import BaseRule, BaseRuleset, logprof_value_or_all, parse_modifiers
# setup module translations # setup module translations
@ -49,7 +49,7 @@ class NetworkRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field NetworkRule.ALL # should reference the class field NetworkRule.ALL
class __NetworkAll(object): class __NetworkAll:
pass pass
ALL = __NetworkAll ALL = __NetworkAll
@ -59,16 +59,14 @@ class NetworkRule(BaseRule):
def __init__(self, domain, type_or_protocol, audit=False, deny=False, allow_keyword=False, def __init__(self, domain, type_or_protocol, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(NetworkRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
self.domain = None self.domain = None
self.all_domains = False self.all_domains = False
if domain == NetworkRule.ALL: if domain == NetworkRule.ALL:
self.all_domains = True self.all_domains = True
elif type_is_str(domain): elif type(domain) is str:
if domain in network_domain_keywords: if domain in network_domain_keywords:
self.domain = domain self.domain = domain
else: else:
@ -80,7 +78,7 @@ class NetworkRule(BaseRule):
self.all_type_or_protocols = False self.all_type_or_protocols = False
if type_or_protocol == NetworkRule.ALL: if type_or_protocol == NetworkRule.ALL:
self.all_type_or_protocols = True self.all_type_or_protocols = True
elif type_is_str(type_or_protocol): elif type(type_or_protocol) is str:
if type_or_protocol in network_protocol_keywords: if type_or_protocol in network_protocol_keywords:
self.type_or_protocol = type_or_protocol self.type_or_protocol = type_or_protocol
elif type_or_protocol in network_type_keywords: elif type_or_protocol in network_type_keywords:

View File

@ -45,7 +45,7 @@ class PtraceRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field PtraceRule.ALL # should reference the class field PtraceRule.ALL
class __PtraceAll(object): class __PtraceAll:
pass pass
ALL = __PtraceAll ALL = __PtraceAll
@ -55,10 +55,8 @@ class PtraceRule(BaseRule):
def __init__(self, access, peer, audit=False, deny=False, allow_keyword=False, def __init__(self, access, peer, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(PtraceRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, PtraceRule.ALL, 'PtraceRule', 'access') self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, PtraceRule.ALL, 'PtraceRule', 'access')
if unknown_items: if unknown_items:

View File

@ -16,7 +16,7 @@
import re import re
from apparmor.regex import RE_PROFILE_RLIMIT, strip_quotes from apparmor.regex import RE_PROFILE_RLIMIT, strip_quotes
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed
# setup module translations # setup module translations
@ -41,7 +41,7 @@ class RlimitRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field RlimitRule.ALL # should reference the class field RlimitRule.ALL
class __RlimitAll(object): class __RlimitAll:
pass pass
ALL = __RlimitAll ALL = __RlimitAll
@ -51,15 +51,13 @@ class RlimitRule(BaseRule):
def __init__(self, rlimit, value, audit=False, deny=False, allow_keyword=False, def __init__(self, rlimit, value, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(RlimitRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
if audit or deny or allow_keyword: if audit or deny or allow_keyword:
raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.') raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.')
if type_is_str(rlimit): if type(rlimit) is str:
if rlimit in rlimit_all: if rlimit in rlimit_all:
self.rlimit = rlimit self.rlimit = rlimit
else: else:
@ -72,7 +70,7 @@ class RlimitRule(BaseRule):
self.all_values = False self.all_values = False
if value == RlimitRule.ALL: if value == RlimitRule.ALL:
self.all_values = True self.all_values = True
elif type_is_str(value): elif type(value) is str:
if not value.strip(): if not value.strip():
raise AppArmorBug('Empty value in rlimit rule') raise AppArmorBug('Empty value in rlimit rule')

View File

@ -66,7 +66,7 @@ class SignalRule(BaseRule):
# Nothing external should reference this class, all external users # Nothing external should reference this class, all external users
# should reference the class field SignalRule.ALL # should reference the class field SignalRule.ALL
class __SignalAll(object): class __SignalAll:
pass pass
ALL = __SignalAll ALL = __SignalAll
@ -76,10 +76,8 @@ class SignalRule(BaseRule):
def __init__(self, access, signal, peer, audit=False, deny=False, allow_keyword=False, def __init__(self, access, signal, peer, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(SignalRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, SignalRule.ALL, 'SignalRule', 'access') self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, SignalRule.ALL, 'SignalRule', 'access')
if unknown_items: if unknown_items:

View File

@ -14,7 +14,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from apparmor.regex import RE_PROFILE_VARIABLE, strip_quotes from apparmor.regex import RE_PROFILE_VARIABLE, strip_quotes
from apparmor.common import AppArmorBug, AppArmorException, type_is_str from apparmor.common import AppArmorBug, AppArmorException
from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed
import re import re
@ -32,10 +32,8 @@ class VariableRule(BaseRule):
def __init__(self, varname, mode, values, audit=False, deny=False, allow_keyword=False, def __init__(self, varname, mode, values, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None): comment='', log_event=None):
super(VariableRule, self).__init__(audit=audit, deny=deny, super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
allow_keyword=allow_keyword, comment=comment, log_event=log_event)
comment=comment,
log_event=log_event)
# variables don't support audit or deny # variables don't support audit or deny
if audit: if audit:
@ -43,14 +41,14 @@ class VariableRule(BaseRule):
if deny: if deny:
raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__)
if not type_is_str(varname): if type(varname) is not str:
raise AppArmorBug('Passed unknown type for varname to %s: %s' % (self.__class__.__name__, varname)) raise AppArmorBug('Passed unknown type for varname to %s: %s' % (self.__class__.__name__, varname))
if not varname.startswith('@{'): if not varname.startswith('@{'):
raise AppArmorException("Passed invalid varname to %s (doesn't start with '@{'): %s" % (self.__class__.__name__, varname)) raise AppArmorException("Passed invalid varname to %s (doesn't start with '@{'): %s" % (self.__class__.__name__, varname))
if not varname.endswith('}'): if not varname.endswith('}'):
raise AppArmorException("Passed invalid varname to %s (doesn't end with '}'): %s" % (self.__class__.__name__, varname)) raise AppArmorException("Passed invalid varname to %s (doesn't end with '}'): %s" % (self.__class__.__name__, varname))
if not type_is_str(mode): if type(mode) is not str:
raise AppArmorBug('Passed unknown type for variable assignment mode to %s: %s' % (self.__class__.__name__, mode)) raise AppArmorBug('Passed unknown type for variable assignment mode to %s: %s' % (self.__class__.__name__, mode))
if mode not in ('=', '+='): if mode not in ('=', '+='):
raise AppArmorBug('Passed unknown variable assignment mode to %s: %s' % (self.__class__.__name__, mode)) raise AppArmorBug('Passed unknown variable assignment mode to %s: %s' % (self.__class__.__name__, mode))
@ -151,7 +149,7 @@ class VariableRuleset(BaseRuleset):
if rule.varname == knownrule.varname: if rule.varname == knownrule.varname:
raise AppArmorException(_('Redefining existing variable %(variable)s: %(value)s') % { 'variable': rule.varname, 'value': rule.values }) raise AppArmorException(_('Redefining existing variable %(variable)s: %(value)s') % { 'variable': rule.varname, 'value': rule.values })
super(VariableRuleset, self).add(rule, cleanup) super().add(rule, cleanup)
def get_merged_variables(self): def get_merged_variables(self):
''' Get merged variables of this VariableRuleset. ''' Get merged variables of this VariableRuleset.

View File

@ -8,7 +8,7 @@
# #
# ------------------------------------------------------------------ # ------------------------------------------------------------------
class _Raw_Rule(object): class _Raw_Rule:
audit = False audit = False
deny = False deny = False

View File

@ -9,7 +9,6 @@
# ------------------------------------------------------------------ # ------------------------------------------------------------------
from apparmor.common import AppArmorException, debug, error, msg, cmd from apparmor.common import AppArmorException, debug, error, msg, cmd
from apparmor.aa import which
import apparmor.easyprof import apparmor.easyprof
import optparse import optparse
import os import os
@ -20,6 +19,7 @@ import socket
import sys import sys
import tempfile import tempfile
import time import time
from shutil import which
def check_requirements(binary): def check_requirements(binary):
'''Verify necessary software is installed''' '''Verify necessary software is installed'''
@ -129,10 +129,7 @@ def aa_exec(command, opt, environ={}, verify_rules=[]):
debug("\n%s" % policy) debug("\n%s" % policy)
with tempfile.NamedTemporaryFile(prefix='%s-' % policy_name) as tmp: with tempfile.NamedTemporaryFile(prefix='%s-' % policy_name) as tmp:
if sys.version_info[0] >= 3: tmp.write(bytes(policy, 'utf-8'))
tmp.write(bytes(policy, 'utf-8'))
else:
tmp.write(policy)
debug("using '%s' template" % opt.template) debug("using '%s' template" % opt.template)
# TODO: get rid of this # TODO: get rid of this
@ -543,10 +540,7 @@ EndSection
tmp, xorg_conf = tempfile.mkstemp(prefix='aa-sandbox-xorg.conf-') tmp, xorg_conf = tempfile.mkstemp(prefix='aa-sandbox-xorg.conf-')
self.tempfiles.append(xorg_conf) self.tempfiles.append(xorg_conf)
if sys.version_info[0] >= 3: os.write(tmp, bytes(conf, 'utf-8'))
os.write(tmp, bytes(conf, 'utf-8'))
else:
os.write(tmp, conf)
os.close(tmp) os.close(tmp)
xvfb_args.append('--xvfb=Xorg') xvfb_args.append('--xvfb=Xorg')

View File

@ -11,11 +11,10 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
from __future__ import with_statement
import re import re
from apparmor.common import AppArmorException, open_file_read, warn, convert_regexp # , msg, error, debug from apparmor.common import AppArmorException, open_file_read, warn, convert_regexp # , msg, error, debug
class Severity(object): class Severity:
def __init__(self, dbname=None, default_rank=10): def __init__(self, dbname=None, default_rank=10):
"""Initialises the class object""" """Initialises the class object"""
self.PROF_DIR = '/etc/apparmor.d' # The profile directory self.PROF_DIR = '/etc/apparmor.d' # The profile directory

View File

@ -14,6 +14,7 @@
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
import os import os
import sys import sys
from shutil import which
import apparmor.aa as apparmor import apparmor.aa as apparmor
import apparmor.ui as aaui import apparmor.ui as aaui
@ -61,9 +62,9 @@ class aa_tools:
program = fq_path program = fq_path
profile = apparmor.get_profile_filename_from_attachment(fq_path, True) profile = apparmor.get_profile_filename_from_attachment(fq_path, True)
else: else:
which = apparmor.which(p) which_ = which(p)
if which is not None: if which_ is not None:
program = apparmor.get_full_path(which) program = apparmor.get_full_path(which_)
profile = apparmor.get_profile_filename_from_attachment(program, True) profile = apparmor.get_profile_filename_from_attachment(program, True)
elif os.path.exists(os.path.join(apparmor.profile_dir, p)): elif os.path.exists(os.path.join(apparmor.profile_dir, p)):
program = None program = None

View File

@ -31,10 +31,6 @@ _ = init_translation()
# Set up UI logger for separate messages from UI module # Set up UI logger for separate messages from UI module
debug_logger = DebugLogger('UI') debug_logger = DebugLogger('UI')
# If Python3, wrap input in raw_input so make check passes
if 'raw_input' not in dir(__builtins__):
raw_input = input
ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'} ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'}
UI_mode = 'text' UI_mode = 'text'
@ -70,7 +66,7 @@ def set_text_mode():
# reads the response on command line for json and verifies the response # reads the response on command line for json and verifies the response
# for the dialog type # for the dialog type
def json_response(dialog_type): def json_response(dialog_type):
string = raw_input('\n') string = input('\n')
rh = json.loads(string.strip()) rh = json.loads(string.strip())
if rh["dialog"] != dialog_type: if rh["dialog"] != dialog_type:
raise AppArmorException('Expected response %s got %s.' % (dialog_type, string)) raise AppArmorException('Expected response %s got %s.' % (dialog_type, string))
@ -222,7 +218,7 @@ def UI_GetString(text, default):
else: # text mode else: # text mode
readline.set_startup_hook(lambda: readline.insert_text(default)) readline.set_startup_hook(lambda: readline.insert_text(default))
try: try:
string = raw_input('\n' + text) string = input('\n' + text)
except EOFError: except EOFError:
string = '' string = ''
finally: finally:
@ -362,7 +358,7 @@ CMDS = {'CMD_ALLOW': _('(A)llow'),
} }
class PromptQuestion(object): class PromptQuestion:
title = None title = None
headers = None headers = None
explanation = None explanation = None

View File

@ -26,11 +26,11 @@ import os
import shutil import shutil
import sys import sys
class Install(_install, object): class Install(_install):
'''Override setuptools to install the files where we want them.''' '''Override setuptools to install the files where we want them.'''
def run(self): def run(self):
# Now byte-compile everything # Now byte-compile everything
super(Install, self).run() super().run()
prefix = self.prefix prefix = self.prefix
if self.root != None: if self.root != None:

View File

@ -58,7 +58,7 @@ class InterceptingOptionParser(optparse.OptionParser):
raise InterceptedError(error_message=msg) raise InterceptedError(error_message=msg)
class Manifest(object): class Manifest:
def __init__(self, profile_name): def __init__(self, profile_name):
self.security = dict() self.security = dict()
self.security['profiles'] = dict() self.security['profiles'] = dict()

View File

@ -15,7 +15,6 @@ from common_test import read_file, write_file
import os import os
import shutil import shutil
import sys
import apparmor.aa # needed to set global vars in some tests import apparmor.aa # needed to set global vars in some tests
from apparmor.aa import (check_for_apparmor, get_output, get_reqs, get_interpreter_and_abstraction, create_new_profile, from apparmor.aa import (check_for_apparmor, get_output, get_reqs, get_interpreter_and_abstraction, create_new_profile,
@ -99,14 +98,7 @@ class AATest_get_reqs(AATest):
) )
def _run_test(self, params, expected): def _run_test(self, params, expected):
# for some reason, setting the ldd config option does not get
# honored in python2.7
# XXX KILL when python 2.7 is dropped XXX
if sys.version_info[0] < 3:
print("Skipping on python < 3.x")
return
apparmor.aa.cfg['settings']['ldd'] = './fake_ldd' apparmor.aa.cfg['settings']['ldd'] = './fake_ldd'
self.assertEqual(get_reqs(params), expected) self.assertEqual(get_reqs(params), expected)
class AaTest_create_new_profile(AATest): class AaTest_create_new_profile(AATest):
@ -118,12 +110,6 @@ class AaTest_create_new_profile(AATest):
) )
def _run_test(self, params, expected): def _run_test(self, params, expected):
apparmor.aa.cfg['settings']['ldd'] = './fake_ldd' apparmor.aa.cfg['settings']['ldd'] = './fake_ldd'
# for some reason, setting the ldd config option does not get
# honored in python2.7
# XXX KILL when python 2.7 is dropped XXX
if sys.version_info[0] < 3:
print("Skipping on python < 3.x")
return
self.createTmpdir() self.createTmpdir()

View File

@ -13,19 +13,7 @@ import unittest
from common_test import AATest, setup_all_loops from common_test import AATest, setup_all_loops
from apparmor.common import AppArmorBug from apparmor.common import AppArmorBug
from apparmor.common import type_is_str, split_name, combine_profname from apparmor.common import split_name, combine_profname
class TestIs_str_type(AATest):
tests = (
('foo', True),
(u'foo', True),
(42, False),
(True, False),
([], False),
)
def _run_test(self, params, expected):
self.assertEqual(type_is_str(params), expected)
class AaTest_split_name(AATest): class AaTest_split_name(AATest):
tests = ( tests = (

View File

@ -14,16 +14,13 @@
import os import os
import shutil import shutil
import subprocess import subprocess
import sys
import unittest import unittest
from common_test import AATest, setup_all_loops, setup_aa from common_test import AATest, setup_all_loops, setup_aa
import apparmor.aa as apparmor import apparmor.aa as apparmor
from common_test import read_file from common_test import read_file
python_interpreter = 'python' python_interpreter = 'python3'
if sys.version_info >= (3, 0):
python_interpreter = 'python3'
class MinitoolsTest(AATest): class MinitoolsTest(AATest):

View File

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/python3
# #
# Copyright (C) 2012 Canonical Ltd. # Copyright (C) 2012 Canonical Ltd.
# #
@ -9,7 +9,6 @@
# Written by Steve Beattie <steve@nxnw.org>, based on work by # Written by Steve Beattie <steve@nxnw.org>, based on work by
# Christian Boltz <apparmor@cboltz.de> # Christian Boltz <apparmor@cboltz.de>
from __future__ import with_statement
import re import re
import subprocess import subprocess
import sys import sys