示例#1
0
    def __setitem__(self, key, value):
        if key not in self.data:
            raise AppArmorBug('attempt to set unknown key %s' % key)

        # allow writing bool values
        if type(self.data[key]) == bool:
            if type(value) == bool:
                self.data[key] = value
            else:
                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 or None to some keys
        elif key in ('xattrs', 'flags', 'filename'):
            if type_is_str(value) or value is None:
                self.data[key] = value
            else:
                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
        elif type_is_str(self.data[key]):
            if type_is_str(value):
                self.data[key] = value
            else:
                raise AppArmorBug(
                    'Attempt to change type of "%s" from %s to %s, value %s' %
                    (key, type(self.data[key]), type(value), value))

        # don't allow overwriting of other types
        else:
            raise AppArmorBug('Attempt to overwrite "%s" with %s, type %s' %
                              (key, value, type(value)))
示例#2
0
    def __init__(self, rlimit, value, audit=False, deny=False, allow_keyword=False,
                 comment='', log_event=None):

        super(RlimitRule, self).__init__(audit=audit, deny=deny,
                                             allow_keyword=allow_keyword,
                                             comment=comment,
                                             log_event=log_event)

        if audit or deny or allow_keyword:
            raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.')

        if type_is_str(rlimit):
            if rlimit in rlimit_all:
                self.rlimit = rlimit
            else:
                raise AppArmorException('Unknown rlimit keyword in rlimit rule: %s' % rlimit)
        else:
            raise AppArmorBug('Passed unknown object to RlimitRule: %s' % str(rlimit))

        self.value = None
        self.value_as_int = None
        self.all_values = False
        if value == RlimitRule.ALL:
            self.all_values = True
        elif type_is_str(value):
            if not value.strip():
                raise AppArmorBug('Empty value in rlimit rule')

            elif rlimit in rlimit_size:
                if not RE_UNIT_SIZE.match(value):
                    raise AppArmorException('Invalid value or unit in rlimit %s %s rule' % (rlimit, value))
                self.value_as_int = self.size_to_int(value)

            elif rlimit in rlimit_number:
                if not RE_NUMBER.match(value):
                    raise AppArmorException('Invalid value in rlimit %s %s rule' % (rlimit, value))
                self.value_as_int = int(value)

            elif rlimit in rlimit_time:
                if not RE_NUMBER_UNIT.match(value):
                    raise AppArmorException('Invalid value in rlimit %s %s rule' % (rlimit, value))
                number, unit = split_unit(value)

                if rlimit == 'rttime':
                    self.value_as_int = self.time_to_int(value, 'us')
                else:
                    self.value_as_int = self.time_to_int(value, 'seconds')

            elif rlimit in rlimit_nice:
                if not RE_NICE.match(value):
                    raise AppArmorException('Invalid value or unit in rlimit %s %s rule' % (rlimit, value))
                self.value_as_int = 0 - int(value)  # lower numbers mean a higher limit for nice

            # still here? fine :-)
            self.value = value
        else:
            raise AppArmorBug('Passed unknown object to RlimitRule: %s' % str(value))
示例#3
0
    def __init__(self, rlimit, value, audit=False, deny=False, allow_keyword=False,
                 comment='', log_event=None):

        super(RlimitRule, self).__init__(audit=audit, deny=deny,
                                             allow_keyword=allow_keyword,
                                             comment=comment,
                                             log_event=log_event)

        if audit or deny or allow_keyword:
            raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.')

        if type_is_str(rlimit):
            if rlimit in rlimit_all:
                self.rlimit = rlimit
            else:
                raise AppArmorException('Unknown rlimit keyword in rlimit rule: %s' % rlimit)
        else:
            raise AppArmorBug('Passed unknown object to RlimitRule: %s' % str(rlimit))

        self.value = None
        self.value_as_int = None
        self.all_values = False
        if value == RlimitRule.ALL:
            self.all_values = True
        elif type_is_str(value):
            if not value.strip():
                raise AppArmorBug('Empty value in rlimit rule')

            elif rlimit in rlimit_size:
                if not RE_UNIT_SIZE.match(value):
                    raise AppArmorException('Invalid value or unit in rlimit %s %s rule' % (rlimit, value))
                self.value_as_int = self.size_to_int(value)

            elif rlimit in rlimit_number:
                if not RE_NUMBER.match(value):
                    raise AppArmorException('Invalid value in rlimit %s %s rule' % (rlimit, value))
                self.value_as_int = int(value)

            elif rlimit in rlimit_time:
                if not RE_NUMBER_UNIT.match(value):
                    raise AppArmorException('Invalid value in rlimit %s %s rule' % (rlimit, value))
                number, unit = split_unit(value)

                if rlimit == 'rttime':
                    self.value_as_int = self.time_to_int(value, 'us')
                else:
                    self.value_as_int = self.time_to_int(value, 'seconds')

            elif rlimit in rlimit_nice:  # pragma: no branch - "if rlimit in rlimit_all:" above avoids the need for an "else:" branch
                if not RE_NICE.match(value):
                    raise AppArmorException('Invalid value or unit in rlimit %s %s rule' % (rlimit, value))
                self.value_as_int = 0 - int(value)  # lower numbers mean a higher limit for nice

            # still here? fine :-)
            self.value = value
        else:
            raise AppArmorBug('Passed unknown object to RlimitRule: %s' % str(value))
示例#4
0
    def __init__(self,
                 varname,
                 mode,
                 values,
                 audit=False,
                 deny=False,
                 allow_keyword=False,
                 comment='',
                 log_event=None):

        super(VariableRule, self).__init__(audit=audit,
                                           deny=deny,
                                           allow_keyword=allow_keyword,
                                           comment=comment,
                                           log_event=log_event)

        # variables don't support audit or deny
        if audit:
            raise AppArmorBug('Attempt to initialize %s with audit flag' %
                              self.__class__.__name__)
        if deny:
            raise AppArmorBug('Attempt to initialize %s with deny flag' %
                              self.__class__.__name__)

        if not type_is_str(varname):
            raise AppArmorBug('Passed unknown type for varname to %s: %s' %
                              (self.__class__.__name__, varname))
        if not varname.startswith('@{'):
            raise AppArmorException(
                "Passed invalid varname to %s (doesn't start with '@{'): %s" %
                (self.__class__.__name__, varname))
        if not varname.endswith('}'):
            raise AppArmorException(
                "Passed invalid varname to %s (doesn't end with '}'): %s" %
                (self.__class__.__name__, varname))

        if not type_is_str(mode):
            raise AppArmorBug(
                'Passed unknown type for variable assignment mode to %s: %s' %
                (self.__class__.__name__, mode))
        if mode not in ['=', '+=']:
            raise AppArmorBug(
                'Passed unknown variable assignment mode to %s: %s' %
                (self.__class__.__name__, mode))

        if type(values) is not set:
            raise AppArmorBug('Passed unknown type for values to %s: %s' %
                              (self.__class__.__name__, values))
        if not values:
            raise AppArmorException('Passed empty list of values to %s: %s' %
                                    (self.__class__.__name__, values))

        self.varname = varname
        self.mode = mode
        self.values = values
    def __init__(self,
                 cap_list,
                 audit=False,
                 deny=False,
                 allow_keyword=False,
                 comment='',
                 log_event=None):

        super(CapabilityRule, self).__init__(audit=audit,
                                             deny=deny,
                                             allow_keyword=allow_keyword,
                                             comment=comment,
                                             log_event=log_event)
        # Because we support having multiple caps in one rule,
        # initializer needs to accept a list of caps.
        self.all_caps = False
        if cap_list == CapabilityRule.ALL:
            self.all_caps = True
            self.capability = set()
        else:
            if type_is_str(cap_list):
                self.capability = {cap_list}
            elif type(cap_list) == list and len(cap_list) > 0:
                self.capability = set(cap_list)
            else:
                raise AppArmorBug(
                    'Passed unknown object to CapabilityRule: %s' %
                    str(cap_list))
            # make sure none of the cap_list arguments are blank, in
            # case we decide to return one cap per output line
            for cap in self.capability:
                if len(cap.strip()) == 0:
                    raise AppArmorBug(
                        'Passed empty capability to CapabilityRule: %s' %
                        str(cap_list))
    def _aare_or_all(self, rulepart, partname, is_path, log_event):
        '''checks rulepart and returns
           - (AARE, False) if rulepart is a (non-empty) string
           - (None, True) if rulepart is all_obj (typically *Rule.ALL)
           - raises AppArmorBug if rulepart is an empty string or has a wrong type

           Parameters:
           - rulepart: the rule part to check (string or *Rule.ALL object)
           - partname: the name of the rulepart (for example 'peer', used for exception messages)
           - is_path (passed through to AARE)
           - log_event (passed through to AARE)
           '''

        if rulepart == self.ALL:
            return None, True
        elif type_is_str(rulepart):
            if len(rulepart.strip()) == 0:
                raise AppArmorBug(
                    'Passed empty %(partname)s to %(classname)s: %(rulepart)s'
                    % {
                        'partname': partname,
                        'classname': self.__class__.__name__,
                        'rulepart': str(rulepart)
                    })
            return AARE(rulepart, is_path=is_path, log_event=log_event), False
        else:
            raise AppArmorBug(
                'Passed unknown %(partname)s to %(classname)s: %(rulepart)s' %
                {
                    'partname': partname,
                    'classname': self.__class__.__name__,
                    'rulepart': str(rulepart)
                })
def check_and_split_list(lst, allowed_keywords, all_obj, classname,
                         keyword_name):
    '''check if lst is all_obj or contains only items listed in allowed_keywords'''

    if lst == all_obj:
        return None, True, None
    elif type_is_str(lst):
        result_list = {lst}
    elif (type(lst) == list or type(lst) == tuple) and len(lst) > 0:
        result_list = set(lst)
    else:
        raise AppArmorBug(
            'Passed unknown %(type)s object to %(classname)s: %(unknown_object)s'
            % {
                'type': type(lst),
                'classname': classname,
                'unknown_object': str(lst)
            })

    unknown_items = set()
    for item in result_list:
        if not item.strip():
            raise AppArmorBug(
                'Passed empty %(keyword_name)s to %(classname)s' % {
                    'keyword_name': keyword_name,
                    'classname': classname
                })
        if item not in allowed_keywords:
            unknown_items.add(item)

    return result_list, False, unknown_items
示例#8
0
    def __init__(self, cap_list, audit=False, deny=False, allow_keyword=False,
                 comment='', log_event=None):

        super(CapabilityRule, self).__init__(audit=audit, deny=deny,
                                             allow_keyword=allow_keyword,
                                             comment=comment,
                                             log_event=log_event)
        # Because we support having multiple caps in one rule,
        # initializer needs to accept a list of caps.
        self.all_caps = False
        if cap_list == CapabilityRule.ALL:
            self.all_caps = True
            self.capability = set()
        else:
            if type_is_str(cap_list):
                self.capability = {cap_list}
            elif type(cap_list) == list and len(cap_list) > 0:
                self.capability = set(cap_list)
            else:
                raise AppArmorBug('Passed unknown object to CapabilityRule: %s' % str(cap_list))
            # make sure none of the cap_list arguments are blank, in
            # case we decide to return one cap per output line
            for cap in self.capability:
                if len(cap.strip()) == 0:
                    raise AppArmorBug('Passed empty capability to CapabilityRule: %s' % str(cap_list))
示例#9
0
    def __init__(self,
                 domain,
                 type_or_protocol,
                 audit=False,
                 deny=False,
                 allow_keyword=False,
                 comment='',
                 log_event=None):

        super(NetworkRule, self).__init__(audit=audit,
                                          deny=deny,
                                          allow_keyword=allow_keyword,
                                          comment=comment,
                                          log_event=log_event)

        self.domain = None
        self.all_domains = False
        if domain == NetworkRule.ALL:
            self.all_domains = True
        elif type_is_str(domain):
            if domain in network_domain_keywords:
                self.domain = domain
            else:
                raise AppArmorBug('Passed unknown domain to NetworkRule: %s' %
                                  domain)
        else:
            raise AppArmorBug('Passed unknown object to NetworkRule: %s' %
                              str(domain))

        self.type_or_protocol = None
        self.all_type_or_protocols = False
        if type_or_protocol == NetworkRule.ALL:
            self.all_type_or_protocols = True
        elif type_is_str(type_or_protocol):
            if type_or_protocol in network_protocol_keywords:
                self.type_or_protocol = type_or_protocol
            elif type_or_protocol in network_type_keywords:
                self.type_or_protocol = type_or_protocol
            else:
                raise AppArmorBug(
                    'Passed unknown type_or_protocol to NetworkRule: %s' %
                    type_or_protocol)
        else:
            raise AppArmorBug('Passed unknown object to NetworkRule: %s' %
                              str(type_or_protocol))
示例#10
0
    def __init__(self, execmode, execcond, targetprofile, audit=False, deny=False, allow_keyword=False,
                 comment='', log_event=None):

        '''
            CHANGE_PROFILE RULE = 'change_profile' [ [ EXEC MODE ] EXEC COND ] [ -> PROGRAMCHILD ]
        '''

        super(ChangeProfileRule, self).__init__(audit=audit, deny=deny,
                                             allow_keyword=allow_keyword,
                                             comment=comment,
                                             log_event=log_event)

        if execmode:
            if execmode != 'safe' and execmode != 'unsafe':
                raise AppArmorBug('Unknown exec mode (%s) in change_profile rule' % execmode)
            elif not execcond or execcond == ChangeProfileRule.ALL:
                raise AppArmorException('Exec condition is required when unsafe or safe keywords are present')
        self.execmode = execmode

        self.execcond = None
        self.all_execconds = False
        if execcond == ChangeProfileRule.ALL:
            self.all_execconds = True
        elif type_is_str(execcond):
            if not execcond.strip():
                raise AppArmorBug('Empty exec condition in change_profile rule')
            elif execcond.startswith('/') or execcond.startswith('@'):
                self.execcond = execcond
            else:
                raise AppArmorException('Exec condition in change_profile rule does not start with /: %s' % str(execcond))
        else:
            raise AppArmorBug('Passed unknown object to ChangeProfileRule: %s' % str(execcond))

        self.targetprofile = None
        self.all_targetprofiles = False
        if targetprofile == ChangeProfileRule.ALL:
            self.all_targetprofiles = True
        elif type_is_str(targetprofile):
            if targetprofile.strip():
                self.targetprofile = targetprofile
            else:
                raise AppArmorBug('Empty target profile in change_profile rule')
        else:
            raise AppArmorBug('Passed unknown object to ChangeProfileRule: %s' % str(targetprofile))
示例#11
0
    def __init__(self,
                 orig_path,
                 target,
                 audit=False,
                 deny=False,
                 allow_keyword=False,
                 comment='',
                 log_event=None):

        super(AliasRule, self).__init__(audit=audit,
                                        deny=deny,
                                        allow_keyword=allow_keyword,
                                        comment=comment,
                                        log_event=log_event)

        # aliass don't support audit or deny
        if audit:
            raise AppArmorBug('Attempt to initialize %s with audit flag' %
                              self.__class__.__name__)
        if deny:
            raise AppArmorBug('Attempt to initialize %s with deny flag' %
                              self.__class__.__name__)

        if not type_is_str(orig_path):
            raise AppArmorBug('Passed unknown type for orig_path to %s: %s' %
                              (self.__class__.__name__, orig_path))
        if not orig_path:
            raise AppArmorException('Passed empty orig_path to %s: %s' %
                                    (self.__class__.__name__, orig_path))
        if not orig_path.startswith('/'):
            raise AppArmorException("Alias path doesn't start with '/'")

        if not type_is_str(target):
            raise AppArmorBug('Passed unknown type for target to %s: %s' %
                              (self.__class__.__name__, target))
        if not target:
            raise AppArmorException('Passed empty target to %s: %s' %
                                    (self.__class__.__name__, target))
        if not target.startswith('/'):
            raise AppArmorException("Alias target doesn't start with '/'")

        self.orig_path = orig_path
        self.target = target
示例#12
0
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'''

    if type_is_str(flags) or flags is None:
        flags = split_flags(flags)

    if type_is_str(flags_to_change) or flags_to_change is None:
        flags_to_change = split_flags(flags_to_change)

    if set_flag:
        for flag_to_change in flags_to_change:
            if flag_to_change not in flags:
                flags.append(flag_to_change)
    else:
        for flag_to_change in flags_to_change:
            if flag_to_change in flags:
                flags.remove(flag_to_change)

    return sorted(flags)
示例#13
0
    def is_equal(self, expression):
        '''check if the given expression is equal'''

        if type(expression) == AARE:
            return self.regex == expression.regex
        elif type_is_str(expression):
            return self.regex == expression
        else:
            raise AppArmorBug(
                'AARE.is_equal() called with unknown object: %s' %
                str(expression))
示例#14
0
    def __init__(self, execcond, targetprofile, audit=False, deny=False, allow_keyword=False,
                 comment='', log_event=None):

        '''
            CHANGE_PROFILE RULE = 'change_profile' [ EXEC COND ] [ -> PROGRAMCHILD ]
        '''

        super(ChangeProfileRule, self).__init__(audit=audit, deny=deny,
                                             allow_keyword=allow_keyword,
                                             comment=comment,
                                             log_event=log_event)

        self.execcond = None
        self.all_execconds = False
        if execcond == ChangeProfileRule.ALL:
            self.all_execconds = True
        elif type_is_str(execcond):
            if not execcond.strip():
                raise AppArmorBug('Empty exec condition in change_profile rule')
            elif execcond.startswith('/') or execcond.startswith('@'):
                self.execcond = execcond
            else:
                raise AppArmorException('Exec condition in change_profile rule does not start with /: %s' % str(execcond))
        else:
            raise AppArmorBug('Passed unknown object to ChangeProfileRule: %s' % str(execcond))

        self.targetprofile = None
        self.all_targetprofiles = False
        if targetprofile == ChangeProfileRule.ALL:
            self.all_targetprofiles = True
        elif type_is_str(targetprofile):
            if targetprofile.strip():
                self.targetprofile = targetprofile
            else:
                raise AppArmorBug('Empty target profile in change_profile rule')
        else:
            raise AppArmorBug('Passed unknown object to ChangeProfileRule: %s' % str(targetprofile))
示例#15
0
    def match(self, expression):
        '''check if the given expression (string or AARE) matches the regex'''

        if type(expression) == AARE:
            if expression.orig_regex:
                expression = expression.orig_regex
            else:
                return self.is_equal(expression)  # better safe than sorry
        elif not type_is_str(expression):
            raise AppArmorBug('AARE.match() called with unknown object: %s' %
                              str(expression))

        if self._regex_compiled is None:
            self._regex_compiled = re.compile(convert_regexp(self.regex))

        return bool(self._regex_compiled.match(expression))
示例#16
0
    def __init__(self,
                 path,
                 ifexists,
                 ismagic,
                 audit=False,
                 deny=False,
                 allow_keyword=False,
                 comment='',
                 log_event=None):

        super(IncludeRule, self).__init__(audit=audit,
                                          deny=deny,
                                          allow_keyword=allow_keyword,
                                          comment=comment,
                                          log_event=log_event)

        # include doesn't support audit or deny
        if audit:
            raise AppArmorBug('Attempt to initialize %s with audit flag' %
                              self.__class__.__name__)
        if deny:
            raise AppArmorBug('Attempt to initialize %s with deny flag' %
                              self.__class__.__name__)

        if type(ifexists) is not bool:
            raise AppArmorBug('Passed unknown type for ifexists to %s: %s' %
                              (self.__class__.__name__, ifexists))
        if type(ismagic) is not bool:
            raise AppArmorBug('Passed unknown type for ismagic to %s: %s' %
                              (self.__class__.__name__, ismagic))
        if not type_is_str(path):
            raise AppArmorBug('Passed unknown type for path to %s: %s' %
                              (self.__class__.__name__, path))
        if not path:
            raise AppArmorBug('Passed empty path to %s: %s' %
                              (self.__class__.__name__, path))

        self.path = path
        self.ifexists = ifexists
        self.ismagic = ismagic
示例#17
0
 def _run_test(self, params, expected):
     self.assertEqual(type_is_str(params), expected)
示例#18
0
文件: file.py 项目: youngker/apparmor
    def __init__(self,
                 path,
                 perms,
                 exec_perms,
                 target,
                 owner,
                 file_keyword=False,
                 leading_perms=False,
                 audit=False,
                 deny=False,
                 allow_keyword=False,
                 comment='',
                 log_event=None):
        '''Initialize FileRule

           Parameters:
           - path: string, AARE or FileRule.ALL
           - perms: string, set of chars or FileRule.ALL (must not contain exec mode)
           - exec_perms: None or string
           - target: string, AARE or FileRule.ALL
           - owner: bool
           - file_keyword: bool
           - leading_perms: bool
        '''

        super(FileRule, self).__init__(audit=audit,
                                       deny=deny,
                                       allow_keyword=allow_keyword,
                                       comment=comment,
                                       log_event=log_event)

        #                                                               rulepart        partperms       is_path log_event
        self.path, self.all_paths = self._aare_or_all(path, 'path', True,
                                                      log_event)
        self.target, self.all_targets, = self._aare_or_all(
            target, 'target', False, log_event)

        self.can_glob = not self.all_paths
        self.can_glob_ext = not self.all_paths
        self.can_edit = not self.all_paths

        if type_is_str(perms):
            perms, tmp_exec_perms = split_perms(perms, deny)
            if tmp_exec_perms:
                raise AppArmorBug('perms must not contain exec perms')
        elif perms == None:
            perms = set()

        if perms == {'subset'}:
            raise AppArmorBug('subset without link permissions given')
        elif perms in [{'link'}, {'link', 'subset'}]:
            self.perms = perms
            self.all_perms = False
        else:
            self.perms, self.all_perms, unknown_items = check_and_split_list(
                perms,
                file_permissions,
                FileRule.ALL,
                'FileRule',
                'permissions',
                allow_empty_list=True)
            if unknown_items:
                raise AppArmorBug('Passed unknown perms to FileRule: %s' %
                                  str(unknown_items))
            if self.perms and 'a' in self.perms and 'w' in self.perms:
                raise AppArmorException(
                    "Conflicting permissions found: 'a' and 'w'")

        self.original_perms = None  # might be set by aa-logprof / aa.py propose_file_rules()

        if exec_perms is None:
            self.exec_perms = None
        elif 'link' in self.perms:
            raise AppArmorBug("link rules can't have execute permissions")
        elif exec_perms == self.ANY_EXEC:
            self.exec_perms = exec_perms
        elif type_is_str(exec_perms):
            if deny:
                if exec_perms != 'x':
                    raise AppArmorException(
                        _("file deny rules only allow to use 'x' as execute mode, but not %s"
                          % exec_perms))
            else:
                if exec_perms == 'x':
                    raise AppArmorException(
                        _("Execute flag ('x') in file rule must specify the exec mode (ix, Px, Cx etc.)"
                          ))
                elif exec_perms not in allow_exec_transitions and exec_perms not in allow_exec_fallback_transitions:
                    raise AppArmorBug(
                        'Unknown execute mode specified in file rule: %s' %
                        exec_perms)
            self.exec_perms = exec_perms
        else:
            raise AppArmorBug('Passed unknown perms object to FileRule: %s' %
                              str(perms))

        if type(owner) is not bool:
            raise AppArmorBug('non-boolean value passed to owner flag')
        self.owner = owner
        self.can_owner = owner  # offer '(O)wner permissions on/off' buttons only if the rule has the owner flag

        if type(file_keyword) is not bool:
            raise AppArmorBug('non-boolean value passed to file keyword flag')
        self.file_keyword = file_keyword

        if type(leading_perms) is not bool:
            raise AppArmorBug(
                'non-boolean value passed to leading permissions flag')
        self.leading_perms = leading_perms

        # XXX subset

        # check for invalid combinations (bare 'file,' vs. path rule)
        #       if (self.all_paths and not self.all_perms) or (not self.all_paths and self.all_perms):
        #           raise AppArmorBug('all_paths and all_perms must be equal')
        # elif
        if self.all_paths and (self.exec_perms or self.target):
            raise AppArmorBug(
                'exec perms or target specified for bare file rule')
 def _run_test(self, params, expected):
     self.assertEqual(type_is_str(params), expected)