#!/usr/bin/python # Copyright 2014, Tresys Technology, LLC # # This file is part of SETools. # # SETools is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # SETools 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. # # You should have received a copy of the GNU General Public License # along with SETools. If not, see . # from __future__ import print_function import libapol import argparse import sys 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=libapol.__version__) parser.add_argument( "policy", type=str, help="Path to the SELinux policy to search.") rtypes = parser.add_argument_group("TE Rule Types") rtypes.add_argument("-A", "--allow", action="append_const", const="allow", dest="tertypes", help="Search allow rules.") #rtypes.add_argument("--neverallow", action="append_const", const="neverallow", dest="tertypes", help="Search neverallow rules.") rtypes.add_argument("--auditallow", action="append_const", const="auditallow", dest="tertypes", help="Search auditallow rules.") rtypes.add_argument("--dontaudit", action="append_const", const="dontaudit", dest="tertypes", help="Search dontaudit rules.") rtypes.add_argument("-T", "--type_trans", action="append_const", const="type_transition", dest="tertypes", help="Search type_transition rules.") rtypes.add_argument("--type_change", action="append_const", const="type_change", dest="tertypes", help="Search type_change rules.") rtypes.add_argument("--type_member", action="append_const", const="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="allow", dest="rbacrtypes", help="Search role allow rules.") rbacrtypes.add_argument("--role_trans", action="append_const", const="role_transition", dest="rbacrtypes", help="Search role_transition rules.") mlsrtypes = parser.add_argument_group("MLS Rule Types") mlsrtypes.add_argument("--range_trans", action="append_const", const="range_transition", dest="mlsrtypes", help="Search range_transition rules.") expr = parser.add_argument_group("Expressions") expr.add_argument("-s", "--source", type=str, help="Source type/role of the TE/RBAC rule.", default="") expr.add_argument("-t", "--target", type=str, help="Target type/role of the TE/RBAC rule.", default="") expr.add_argument( "-c", "--class", help="Comma separated list of object classes", dest="tclass", default="") expr.add_argument( "-p", "--perms", help="Comma separated list of permissions.", metavar="PERMS", default="") expr.add_argument( "-D", "--default", help="Default type of the TE/RBAC rule.", default="") expr.add_argument("-b", "--bool", help="Conditional rules with the Boolean in the expression.", dest="boolname", metavar="BOOL", default="") opts = parser.add_argument_group("Search options") opts.add_argument("-e", action="store_true", help="Match permission set exactly instead of matching any listed permission.", dest="perms_equal") opts.add_argument("-ds", action="store_false", help="Match source attributes directly instead of matching member types/roles.", dest="source_indirect") opts.add_argument("-dt", action="store_false", help="Match target attributes directly instead of matching member types/roles.", dest="target_indirect") opts.add_argument("-rs", action="store_true", help="Use regular expression matching for the source type/role.", dest="source_regex") opts.add_argument("-rt", action="store_true", help="Use regular expression matching for the target type/role.", dest="target_regex") opts.add_argument("-rc", action="store_true", help="Use regular expression matching for the object class.", dest="tclass_regex") opts.add_argument("-rd", action="store_true", help="Use regular expression matching for the default type/role.", dest="default_regex") args = parser.parse_args() if not args.tertypes and not args.mlsrtypes and not args.rbacrtypes: parser.error("At least one rule type must be specified.") if (args.tertypes or args.mlsrtypes) and args.rbacrtypes: parser.error( "TE/MLS rule searches cannot be mixed with RBAC rule searches.") try: p = libapol.SELinuxPolicy(args.policy) except RuntimeError as err: print(err) sys.exit(-1) if args.tertypes: q = libapol.terulequery.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, default=args.default, default_regex=args.default_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: q.set_tclass(args.tclass) else: q.set_tclass(args.tclass.split(",")) if args.perms: q.set_perms(args.perms.split(",")) for r in sorted(q.results()): print(r) if args.rbacrtypes: q = libapol.rbacrulequery.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: q.set_tclass(args.tclass) else: q.set_tclass(args.tclass.split(",")) for r in sorted(q.results()): print(r) if args.mlsrtypes: q = libapol.mlsrulequery.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) # 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: q.set_tclass(args.tclass) else: q.set_tclass(args.tclass.split(",")) for r in sorted(q.results()): print(r)