1#!/usr/bin/python 2# Copyright 2014-2015, Tresys Technology, LLC 3# 4# This file is part of SETools. 5# 6# SETools is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 2 of the License, or 9# (at your option) any later version. 10# 11# SETools is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with SETools. If not, see <http://www.gnu.org/licenses/>. 18# 19 20from __future__ import print_function 21import setools 22import argparse 23import sys 24import logging 25 26parser = argparse.ArgumentParser( 27 description="SELinux policy rule search tool.", 28 epilog="TE/MLS rule searches cannot be mixed with RBAC rule searches.") 29parser.add_argument("--version", action="version", version=setools.__version__) 30parser.add_argument("policy", help="Path to the SELinux policy to search.", nargs="?") 31parser.add_argument("-v", "--verbose", action="store_true", 32 help="Print extra informational messages") 33parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.") 34 35rtypes = parser.add_argument_group("TE Rule Types") 36rtypes.add_argument("-A", "--allow", action="append_const", 37 const="allow", dest="tertypes", 38 help="Search allow rules.") 39rtypes.add_argument("--auditallow", action="append_const", 40 const="auditallow", dest="tertypes", 41 help="Search auditallow rules.") 42rtypes.add_argument("--dontaudit", action="append_const", 43 const="dontaudit", dest="tertypes", 44 help="Search dontaudit rules.") 45rtypes.add_argument("-T", "--type_trans", action="append_const", 46 const="type_transition", dest="tertypes", 47 help="Search type_transition rules.") 48rtypes.add_argument("--type_change", action="append_const", 49 const="type_change", dest="tertypes", 50 help="Search type_change rules.") 51rtypes.add_argument("--type_member", action="append_const", 52 const="type_member", dest="tertypes", 53 help="Search type_member rules.") 54 55rbacrtypes = parser.add_argument_group("RBAC Rule Types") 56rbacrtypes.add_argument("--role_allow", action="append_const", 57 const="allow", dest="rbacrtypes", 58 help="Search role allow rules.") 59rbacrtypes.add_argument("--role_trans", action="append_const", 60 const="role_transition", dest="rbacrtypes", 61 help="Search role_transition rules.") 62 63mlsrtypes = parser.add_argument_group("MLS Rule Types") 64mlsrtypes.add_argument("--range_trans", action="append_const", 65 const="range_transition", dest="mlsrtypes", 66 help="Search range_transition rules.") 67 68expr = parser.add_argument_group("Expressions") 69expr.add_argument("-s", "--source", 70 help="Source type/role of the TE/RBAC rule.") 71expr.add_argument("-t", "--target", 72 help="Target type/role of the TE/RBAC rule.") 73expr.add_argument("-c", "--class", dest="tclass", 74 help="Comma separated list of object classes") 75expr.add_argument("-p", "--perms", metavar="PERMS", 76 help="Comma separated list of permissions.") 77expr.add_argument("-D", "--default", 78 help="Default of the rule. (type/role/range transition rules)") 79expr.add_argument("-b", "--bool", dest="boolean", metavar="BOOL", 80 help="Comma separated list of Booleans in the conditional expression.") 81 82opts = parser.add_argument_group("Search options") 83opts.add_argument("-eb", action="store_true", dest="boolean_equal", 84 help="Match Boolean list exactly instead of matching any listed Boolean.") 85opts.add_argument("-ep", action="store_true", dest="perms_equal", 86 help="Match permission set exactly instead of matching any listed permission.") 87opts.add_argument("-ds", action="store_false", dest="source_indirect", 88 help="Match source attributes directly instead of matching member types/roles.") 89opts.add_argument("-dt", action="store_false", dest="target_indirect", 90 help="Match target attributes directly instead of matching member types/roles.") 91opts.add_argument("-rs", action="store_true", dest="source_regex", 92 help="Use regular expression matching for the source type/role.") 93opts.add_argument("-rt", action="store_true", dest="target_regex", 94 help="Use regular expression matching for the target type/role.") 95opts.add_argument("-rc", action="store_true", dest="tclass_regex", 96 help="Use regular expression matching for the object class.") 97opts.add_argument("-rd", action="store_true", dest="default_regex", 98 help="Use regular expression matching for the default type/role.") 99opts.add_argument("-rb", action="store_true", dest="boolean_regex", 100 help="Use regular expression matching for Booleans.") 101 102args = parser.parse_args() 103 104if not args.tertypes and not args.mlsrtypes and not args.rbacrtypes: 105 parser.error("At least one rule type must be specified.") 106 107if args.debug: 108 logging.basicConfig(level=logging.DEBUG, 109 format='%(asctime)s|%(levelname)s|%(name)s|%(message)s') 110elif args.verbose: 111 logging.basicConfig(level=logging.INFO, format='%(message)s') 112else: 113 logging.basicConfig(level=logging.WARNING, format='%(message)s') 114 115try: 116 p = setools.SELinuxPolicy(args.policy) 117 118 if args.tertypes: 119 q = setools.TERuleQuery(p, 120 ruletype=args.tertypes, 121 source=args.source, 122 source_indirect=args.source_indirect, 123 source_regex=args.source_regex, 124 target=args.target, 125 target_indirect=args.target_indirect, 126 target_regex=args.target_regex, 127 tclass_regex=args.tclass_regex, 128 perms_equal=args.perms_equal, 129 default=args.default, 130 default_regex=args.default_regex, 131 boolean_regex=args.boolean_regex, 132 boolean_equal=args.boolean_equal) 133 134 # these are broken out from the above statement to prevent making a list 135 # with an empty string in it (split on empty string) 136 if args.tclass: 137 if args.tclass_regex: 138 q.tclass = args.tclass 139 else: 140 q.tclass = args.tclass.split(",") 141 142 if args.perms: 143 q.perms = args.perms.split(",") 144 145 if args.boolean: 146 if args.boolean_regex: 147 q.boolean = args.boolean 148 else: 149 q.boolean = args.boolean.split(",") 150 151 for r in sorted(q.results()): 152 print(r) 153 154 if args.rbacrtypes: 155 q = setools.RBACRuleQuery(p, 156 ruletype=args.rbacrtypes, 157 source=args.source, 158 source_indirect=args.source_indirect, 159 source_regex=args.source_regex, 160 target=args.target, 161 target_indirect=args.target_indirect, 162 target_regex=args.target_regex, 163 default=args.default, 164 default_regex=args.default_regex, 165 tclass_regex=args.tclass_regex) 166 167 # these are broken out from the above statement to prevent making a list 168 # with an empty string in it (split on empty string) 169 if args.tclass: 170 if args.tclass_regex: 171 q.tclass = args.tclass 172 else: 173 q.tclass = args.tclass.split(",") 174 175 for r in sorted(q.results()): 176 print(r) 177 178 if args.mlsrtypes: 179 q = setools.MLSRuleQuery(p, 180 ruletype=args.mlsrtypes, 181 source=args.source, 182 source_regex=args.source_regex, 183 target=args.target, 184 target_regex=args.target_regex, 185 tclass_regex=args.tclass_regex, 186 default=args.default) 187 188 # these are broken out from the above statement to prevent making a list 189 # with an empty string in it (split on empty string) 190 if args.tclass: 191 if args.tclass_regex: 192 q.tclass = args.tclass 193 else: 194 q.tclass = args.tclass.split(",") 195 196 for r in sorted(q.results()): 197 print(r) 198 199except Exception as err: 200 if args.debug: 201 import traceback 202 traceback.print_exc() 203 else: 204 print(err) 205 206 sys.exit(-1) 207