2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-23 02:27:12 +00:00
2025-08-13 12:31:52 -03:00

120 lines
4.4 KiB
Python

# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
# Copyright (C) 2020 Christian Boltz <apparmor@cboltz.de>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# ----------------------------------------------------------------------
from apparmor.common import AppArmorBug, AppArmorException
from apparmor.regex import RE_PROFILE_BOOLEAN
from apparmor.rule import BaseRule, BaseRuleset, parse_comment
from apparmor.translations import init_translation
_ = init_translation()
class BooleanRule(BaseRule):
"""Class to handle and store a single variable rule"""
rule_name = 'boolean'
_match_re = RE_PROFILE_BOOLEAN
def __init__(self, varname, value, audit=False, deny=False, allow_keyword=False,
comment='', log_event=None, priority=None):
super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword,
comment=comment, log_event=log_event, priority=priority)
# boolean variables don't support priority, allow keyword, audit or deny
self.ensure_modifiers_not_supported()
if not isinstance(varname, str):
raise AppArmorBug('Passed unknown type for boolean variable to %s: %s' % (self.__class__.__name__, varname))
if not varname.startswith('$'):
raise AppArmorException("Passed invalid boolean to %s (doesn't start with '$'): %s" % (self.__class__.__name__, varname))
if not isinstance(value, str):
raise AppArmorBug('Passed unknown type for value to %s: %s' % (self.__class__.__name__, value))
if not value:
raise AppArmorException('Passed empty value to %s: %s' % (self.__class__.__name__, value))
value = value.lower()
if value not in ('true', 'false'):
raise AppArmorException('Passed invalid value to %s: %s' % (self.__class__.__name__, value))
self.varname = varname
self.value = value == 'true'
@classmethod
def _create_instance(cls, raw_rule, matches):
"""parse raw_rule and return instance of this class"""
comment = parse_comment(matches)
varname = matches.group('varname')
value = matches.group('value')
return cls(varname, value,
audit=False, deny=False, allow_keyword=False, comment=comment, priority=None)
def get_clean(self, depth=0):
"""return rule (in clean/default formatting)"""
space = ' ' * depth
return '%s%s = %s' % (space, self.varname, str(self.value).lower())
def _is_covered_localvars(self, other_rule):
"""check if other_rule is covered by this rule object"""
if self.varname != other_rule.varname:
return False
if type(self.value) is not bool or type(other_rule.value) is not bool:
raise AppArmorBug(_('Invalid value for boolean variable'))
if self.value != other_rule.value:
return False
# still here? -> then it is covered
return True
def _is_equal_localvars(self, rule_obj, strict):
"""compare if rule-specific variables are equal"""
if self.varname != rule_obj.varname:
return False
if self.value != rule_obj.value:
return False
return True
def _logprof_header_localvars(self):
return _('Boolean Variable'), self.get_clean()
class BooleanRuleset(BaseRuleset):
"""Class to handle and store a collection of variable rules"""
def add(self, rule, cleanup=False):
"""Add boolean variable rule object
If the variable name is already known, raise an exception because re-defining a variable isn't allowed.
"""
for knownrule in self.rules:
if rule.varname == knownrule.varname:
raise AppArmorException(_('Redefining existing variable %(variable)s: %(value)s')
% {'variable': rule.varname, 'value': rule.value})
super().add(rule, cleanup)