#!/usr/bin/env python3 # Copyright 2014-2015, Tresys Technology, LLC # # SPDX-License-Identifier: GPL-2.0-only # import setools import argparse import sys import logging import signal import warnings signal.signal(signal.SIGPIPE, signal.SIG_DFL) parser = argparse.ArgumentParser( description="SELinux policy rule search tool.", epilog="TE/MLS rule searches cannot be mixed with RBAC rule searches.") parser.add_argument("--version", action="version", version=setools.__version__) parser.add_argument("policy", help="Path to the SELinux policy to search.", nargs="?") parser.add_argument("-v", "--verbose", action="store_true", help="Print extra informational messages") parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.") rtypes = parser.add_argument_group("TE Rule Types") rtypes.add_argument("-A", action="store_true", help="Search allow and allowxperm rules.") rtypes.add_argument("--allow", action="append_const", const=setools.TERuletype.allow, dest="tertypes", help="Search allow rules.") rtypes.add_argument("--allowxperm", action="append_const", const=setools.TERuletype.allowxperm, dest="tertypes", help="Search allowxperm rules.") rtypes.add_argument("--auditallow", action="append_const", const=setools.TERuletype.auditallow, dest="tertypes", help="Search auditallow rules.") rtypes.add_argument("--auditallowxperm", action="append_const", const=setools.TERuletype.auditallowxperm, dest="tertypes", help="Search auditallowxperm rules.") rtypes.add_argument("--dontaudit", action="append_const", const=setools.TERuletype.dontaudit, dest="tertypes", help="Search dontaudit rules.") rtypes.add_argument("--dontauditxperm", action="append_const", const=setools.TERuletype.dontauditxperm, dest="tertypes", help="Search dontauditxperm rules.") # rtypes.add_argument("--neverallow", action="append_const", # const=setools.TERuletype.neverallow, dest="tertypes", # help="Search neverallow rules.") # rtypes.add_argument("--neverallowxperm", action="append_const", # const=setools.TERuletype.neverallowxperm, dest="tertypes", # help="Search neverallowxperm rules.") rtypes.add_argument("-T", "--type_transition", action="append_const", const=setools.TERuletype.type_transition, dest="tertypes", help="Search type_transition rules.") rtypes.add_argument("--type_change", action="append_const", const=setools.TERuletype.type_change, dest="tertypes", help="Search type_change rules.") rtypes.add_argument("--type_member", action="append_const", const=setools.TERuletype.type_member, dest="tertypes", help="Search type_member rules.") rbacrtypes = parser.add_argument_group("RBAC Rule Types") rbacrtypes.add_argument("--role_allow", action="append_const", const=setools.RBACRuletype.allow, dest="rbacrtypes", help="Search role allow rules.") rbacrtypes.add_argument("--role_transition", action="append_const", const=setools.RBACRuletype.role_transition, dest="rbacrtypes", help="Search role_transition rules.") mlsrtypes = parser.add_argument_group("MLS Rule Types") mlsrtypes.add_argument("--range_transition", action="append_const", const=setools.MLSRuletype.range_transition, dest="mlsrtypes", help="Search range_transition rules.") expr = parser.add_argument_group("Expressions") expr.add_argument("-s", "--source", help="Source type/role of the TE/RBAC rule.") expr.add_argument("-t", "--target", help="Target type/role of the TE/RBAC rule.") expr.add_argument("-c", "--class", dest="tclass", help="Comma separated list of object classes") expr.add_argument("-p", "--perms", metavar="PERMS", help="Comma separated list of permissions. (TE rule searches only.)") expr.add_argument("-x", "--xperms", metavar="XPERMS", help="Comma separated list of extended permissions. (TE rule searches only.)") expr.add_argument("-D", "--default", help="Default of the rule. (type/role/range transition rules)") expr.add_argument("-b", "--bool", dest="boolean", metavar="BOOL", help="Comma separated list of Booleans in the conditional expression. " "(TE rule searches only.)") opts = parser.add_argument_group("Search options") opts.add_argument("-eb", action="store_true", dest="boolean_equal", help="Match Boolean list exactly instead of matching any listed Boolean.") opts.add_argument("-ep", action="store_true", dest="perms_equal", help="Match permission set exactly instead of matching any listed permission.") opts.add_argument("-ex", action="store_true", dest="xperms_equal", help="Match extended permission set exactly instead of matching any listed " "permission.") opts.add_argument("-Sp", action="store_true", dest="perms_subset", help="Match rules where the listed permissions are a subset of the rule " "permissions.") opts.add_argument("-ds", action="store_false", dest="source_indirect", help="Match source attributes directly instead of matching member types/roles.") opts.add_argument("-dt", action="store_false", dest="target_indirect", help="Match target attributes directly instead of matching member types/roles.") opts.add_argument("-rs", action="store_true", dest="source_regex", help="Use regular expression matching for the source type/role.") opts.add_argument("-rt", action="store_true", dest="target_regex", help="Use regular expression matching for the target type/role.") opts.add_argument("-rc", action="store_true", dest="tclass_regex", help="Use regular expression matching for the object class.") opts.add_argument("-rd", action="store_true", dest="default_regex", help="Use regular expression matching for the default type/role.") opts.add_argument("-rb", action="store_true", dest="boolean_regex", help="Use regular expression matching for Booleans.") args = parser.parse_args() if args.A: try: args.tertypes.extend([setools.TERuletype.allow, setools.TERuletype.allowxperm]) except AttributeError: args.tertypes = [setools.TERuletype.allow, setools.TERuletype.allowxperm] if not any((args.tertypes, args.mlsrtypes, args.rbacrtypes)): parser.error("At least one rule type must be specified.") if any((args.perms, args.xperms, args.boolean)) and any((args.rbacrtypes, args.mlsrtypes)): parser.error("-p/--perms, -x/--xperms, and -b/--bool options are only supported " "with TE rule searches.") if args.debug: logging.basicConfig(level=logging.DEBUG, format='%(asctime)s|%(levelname)s|%(name)s|%(message)s') if not sys.warnoptions: warnings.simplefilter("default") elif args.verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not sys.warnoptions: warnings.simplefilter("default") else: logging.basicConfig(level=logging.WARNING, format='%(message)s') if not sys.warnoptions: warnings.simplefilter("ignore") try: p = setools.SELinuxPolicy(args.policy) if args.tertypes: terq = setools.TERuleQuery(p, ruletype=args.tertypes, source=args.source, source_indirect=args.source_indirect, source_regex=args.source_regex, target=args.target, target_indirect=args.target_indirect, target_regex=args.target_regex, tclass_regex=args.tclass_regex, perms_equal=args.perms_equal, perms_subset=args.perms_subset, xperms_equal=args.xperms_equal, default=args.default, default_regex=args.default_regex, boolean_regex=args.boolean_regex, boolean_equal=args.boolean_equal) # these are broken out from the above statement to prevent making a list # with an empty string in it (split on empty string) if args.tclass: if args.tclass_regex: terq.tclass = args.tclass else: terq.tclass = args.tclass.split(",") if args.perms: terq.perms = args.perms.split(",") if args.xperms: # https://github.com/python/mypy/issues/220 terq.xperms = setools.xperm_str_to_tuple_ranges(args.xperms) # type: ignore if args.boolean: if args.boolean_regex: terq.boolean = args.boolean else: if args.policy: terq.boolean = args.boolean.split(",") else: # try to find substitutions for old boolean names terq.boolean = map(setools.policyrep.lookup_boolean_name_sub, args.boolean.split(",")) for te_result in sorted(terq.results()): print(te_result) if args.rbacrtypes: rbacrq = setools.RBACRuleQuery(p, ruletype=args.rbacrtypes, source=args.source, source_indirect=args.source_indirect, source_regex=args.source_regex, target=args.target, target_indirect=args.target_indirect, target_regex=args.target_regex, default=args.default, default_regex=args.default_regex, tclass_regex=args.tclass_regex) # these are broken out from the above statement to prevent making a list # with an empty string in it (split on empty string) if args.tclass: if args.tclass_regex: rbacrq.tclass = args.tclass else: rbacrq.tclass = args.tclass.split(",") for rbac_result in sorted(rbacrq.results()): print(rbac_result) if args.mlsrtypes: mlsrq = setools.MLSRuleQuery(p, ruletype=args.mlsrtypes, source=args.source, source_indirect=args.source_indirect, source_regex=args.source_regex, target=args.target, target_indirect=args.target_indirect, target_regex=args.target_regex, tclass_regex=args.tclass_regex, default=args.default) # these are broken out from the above statement to prevent making a list # with an empty string in it (split on empty string) if args.tclass: if args.tclass_regex: mlsrq.tclass = args.tclass else: mlsrq.tclass = args.tclass.split(",") for mls_result in sorted(mlsrq.results()): print(mls_result) except AssertionError: # Always provide a traceback for assertion errors raise except Exception as err: if args.debug: raise else: print(err) sys.exit(1)