Home | History | Annotate | Download | only in bin
      1 #!/usr/bin/env 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 
     20 from __future__ import print_function
     21 import setools
     22 import argparse
     23 import sys
     24 import logging
     25 
     26 
     27 def expand_attr(attr):
     28     """Render type and role attributes."""
     29     items = "\n\t".join(sorted(str(i) for i in attr.expand()))
     30     contents = items if items else "<empty attribute>"
     31     return "{0}\n\t{1}".format(attr.statement(), contents)
     32 
     33 parser = argparse.ArgumentParser(
     34     description="SELinux policy information tool.")
     35 parser.add_argument("--version", action="version", version=setools.__version__)
     36 parser.add_argument("policy", help="Path to the SELinux policy to query.", nargs="?")
     37 parser.add_argument("-x", "--expand", action="store_true",
     38                     help="Print additional information about the specified components.")
     39 parser.add_argument("--flat",  help="Print without item count nor indentation.",
     40                     dest="flat", default=False, action="store_true")
     41 parser.add_argument("-v", "--verbose", action="store_true",
     42                     help="Print extra informational messages")
     43 parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
     44 
     45 queries = parser.add_argument_group("Component Queries")
     46 queries.add_argument("-a", "--attribute",  help="Print type attributes.", dest="typeattrquery",
     47                      nargs='?', const=True, metavar="ATTR")
     48 queries.add_argument("-b", "--bool", help="Print Booleans.", dest="boolquery",
     49                      nargs='?', const=True, metavar="BOOL")
     50 queries.add_argument("-c", "--class", help="Print object classes.", dest="classquery",
     51                      nargs='?', const=True, metavar="CLASS")
     52 queries.add_argument("-r", "--role", help="Print roles.", dest="rolequery",
     53                      nargs='?', const=True, metavar="ROLE")
     54 queries.add_argument("-t", "--type", help="Print types.", dest="typequery",
     55                      nargs='?', const=True, metavar="TYPE")
     56 queries.add_argument("-u", "--user", help="Print users.", dest="userquery",
     57                      nargs='?', const=True, metavar="USER")
     58 queries.add_argument("--category", help="Print MLS categories.", dest="mlscatsquery",
     59                      nargs='?', const=True, metavar="CAT")
     60 queries.add_argument("--common", help="Print common permission set.", dest="commonquery",
     61                      nargs='?', const=True, metavar="COMMON")
     62 queries.add_argument("--constrain", help="Print constraints.", dest="constraintquery",
     63                      nargs='?', const=True, metavar="CLASS")
     64 queries.add_argument("--default", help="Print default_* rules.", dest="defaultquery",
     65                      nargs='?', const=True, metavar="CLASS")
     66 queries.add_argument("--fs_use", help="Print fs_use statements.", dest="fsusequery",
     67                      nargs='?', const=True, metavar="FS_TYPE")
     68 queries.add_argument("--genfscon", help="Print genfscon statements.", dest="genfsconquery",
     69                      nargs='?', const=True, metavar="FS_TYPE")
     70 queries.add_argument("--initialsid", help="Print initial SIDs (contexts).", dest="initialsidquery",
     71                      nargs='?', const=True, metavar="NAME")
     72 queries.add_argument("--netifcon", help="Print netifcon statements.", dest="netifconquery",
     73                      nargs='?', const=True, metavar="DEVICE")
     74 queries.add_argument("--nodecon", help="Print nodecon statements.", dest="nodeconquery",
     75                      nargs='?', const=True, metavar="ADDR")
     76 queries.add_argument("--permissive", help="Print permissive types.", dest="permissivequery",
     77                      nargs='?', const=True, metavar="TYPE")
     78 queries.add_argument("--polcap", help="Print policy capabilities.", dest="polcapquery",
     79                      nargs='?', const=True, metavar="NAME")
     80 queries.add_argument("--portcon", help="Print portcon statements.", dest="portconquery",
     81                      nargs='?', const=True, metavar="PORTNUM[-PORTNUM]")
     82 queries.add_argument("--sensitivity", help="Print MLS sensitivities.", dest="mlssensquery",
     83                      nargs='?', const=True, metavar="SENS")
     84 queries.add_argument("--typebounds", help="Print typebounds statements.", dest="typeboundsquery",
     85                      nargs='?', const=True, metavar="BOUND_TYPE")
     86 queries.add_argument("--validatetrans", help="Print validatetrans.", dest="validatetransquery",
     87                      nargs='?', const=True, metavar="CLASS")
     88 queries.add_argument("--all", help="Print all of the above.  On a Xen policy, the Xen components "
     89                      "will also be printed", dest="all", default=False, action="store_true")
     90 
     91 xen = parser.add_argument_group("Xen Component Queries")
     92 xen.add_argument("--ioportcon", help="Print all ioportcon statements.", dest="ioportconquery",
     93                  default=False, action="store_true")
     94 xen.add_argument("--iomemcon", help="Print all iomemcon statements.", dest="iomemconquery",
     95                  default=False, action="store_true")
     96 xen.add_argument("--pcidevicecon", help="Print all pcidevicecon statements.",
     97                  dest="pcideviceconquery", default=False, action="store_true")
     98 xen.add_argument("--pirqcon", help="Print all pirqcon statements.", dest="pirqconquery",
     99                  default=False, action="store_true")
    100 xen.add_argument("--devicetreecon", help="Print all devicetreecon statements.",
    101                  dest="devicetreeconquery", default=False, action="store_true")
    102 
    103 
    104 args = parser.parse_args()
    105 
    106 if args.debug:
    107     logging.basicConfig(level=logging.DEBUG,
    108                         format='%(asctime)s|%(levelname)s|%(name)s|%(message)s')
    109 elif args.verbose:
    110     logging.basicConfig(level=logging.INFO, format='%(message)s')
    111 else:
    112     logging.basicConfig(level=logging.WARNING, format='%(message)s')
    113 
    114 try:
    115     p = setools.SELinuxPolicy(args.policy)
    116     components = []
    117 
    118     if args.boolquery or args.all:
    119         q = setools.BoolQuery(p)
    120         if isinstance(args.boolquery, str):
    121             q.name = args.boolquery
    122 
    123         components.append(("Booleans", q, lambda x: x.statement()))
    124 
    125     if args.mlscatsquery or args.all:
    126         q = setools.CategoryQuery(p)
    127         if isinstance(args.mlscatsquery, str):
    128             q.name = args.mlscatsquery
    129 
    130         components.append(("Categories", q, lambda x: x.statement()))
    131 
    132     if args.classquery or args.all:
    133         q = setools.ObjClassQuery(p)
    134         if isinstance(args.classquery, str):
    135             q.name = args.classquery
    136 
    137         components.append(("Classes", q, lambda x: x.statement()))
    138 
    139     if args.commonquery or args.all:
    140         q = setools.CommonQuery(p)
    141         if isinstance(args.commonquery, str):
    142             q.name = args.commonquery
    143 
    144         components.append(("Commons", q, lambda x: x.statement()))
    145 
    146     if args.constraintquery or args.all:
    147         q = setools.ConstraintQuery(p, ruletype=["constrain", "mlsconstrain"])
    148         if isinstance(args.constraintquery, str):
    149             q.tclass = [args.constraintquery]
    150 
    151         components.append(("Constraints", q, lambda x: x.statement()))
    152 
    153     if args.defaultquery or args.all:
    154         q = setools.DefaultQuery(p)
    155         if isinstance(args.defaultquery, str):
    156             q.tclass = [args.defaultquery]
    157 
    158         components.append(("Default rules", q, lambda x: x.statement()))
    159 
    160     if args.fsusequery or args.all:
    161         q = setools.FSUseQuery(p)
    162         if isinstance(args.fsusequery, str):
    163             q.fs = args.fsusequery
    164 
    165         components.append(("Fs_use", q, lambda x: x.statement()))
    166 
    167     if args.genfsconquery or args.all:
    168         q = setools.GenfsconQuery(p)
    169         if isinstance(args.genfsconquery, str):
    170             q.fs = args.genfsconquery
    171 
    172         components.append(("Genfscon", q, lambda x: x.statement()))
    173 
    174     if args.initialsidquery or args.all:
    175         q = setools.InitialSIDQuery(p)
    176         if isinstance(args.initialsidquery, str):
    177             q.name = args.initialsidquery
    178 
    179         components.append(("Initial SIDs", q, lambda x: x.statement()))
    180 
    181     if args.netifconquery or args.all:
    182         q = setools.NetifconQuery(p)
    183         if isinstance(args.netifconquery, str):
    184             q.name = args.netifconquery
    185 
    186         components.append(("Netifcon", q, lambda x: x.statement()))
    187 
    188     if args.nodeconquery or args.all:
    189         q = setools.NodeconQuery(p)
    190         if isinstance(args.nodeconquery, str):
    191             q.network = args.nodeconquery
    192 
    193         components.append(("Nodecon", q, lambda x: x.statement()))
    194 
    195     if args.permissivequery or args.all:
    196         q = setools.TypeQuery(p, permissive=True, match_permissive=True)
    197         if isinstance(args.permissivequery, str):
    198             q.name = args.permissivequery
    199 
    200         components.append(("Permissive Types", q, lambda x: x.statement()))
    201 
    202     if args.polcapquery or args.all:
    203         q = setools.PolCapQuery(p)
    204         if isinstance(args.polcapquery, str):
    205             q.name = args.polcapquery
    206 
    207         components.append(("Polcap", q, lambda x: x.statement()))
    208 
    209     if args.portconquery or args.all:
    210         q = setools.PortconQuery(p)
    211         if isinstance(args.portconquery, str):
    212             try:
    213                 ports = [int(i) for i in args.portconquery.split("-")]
    214             except ValueError:
    215                 parser.error("Enter a port number or range, e.g. 22 or 6000-6020")
    216 
    217             if len(ports) == 2:
    218                 q.ports = ports
    219             elif len(ports) == 1:
    220                 q.ports = (ports[0], ports[0])
    221             else:
    222                 parser.error("Enter a port number or range, e.g. 22 or 6000-6020")
    223 
    224         components.append(("Portcon", q, lambda x: x.statement()))
    225 
    226     if args.rolequery or args.all:
    227         q = setools.RoleQuery(p)
    228         if isinstance(args.rolequery, str):
    229             q.name = args.rolequery
    230 
    231         components.append(("Roles", q, lambda x: x.statement()))
    232 
    233     if args.mlssensquery or args.all:
    234         q = setools.SensitivityQuery(p)
    235         if isinstance(args.mlssensquery, str):
    236             q.name = args.mlssensquery
    237 
    238         components.append(("Sensitivities", q, lambda x: x.statement()))
    239 
    240     if args.typeboundsquery or args.all:
    241         q = setools.BoundsQuery(p, ruletype=["typebounds"])
    242         if isinstance(args.typeboundsquery, str):
    243             q.child = args.typeboundsquery
    244 
    245         components.append(("Typebounds", q, lambda x: x.statement()))
    246 
    247     if args.typequery or args.all:
    248         q = setools.TypeQuery(p)
    249         if isinstance(args.typequery, str):
    250             q.name = args.typequery
    251 
    252         components.append(("Types", q, lambda x: x.statement()))
    253 
    254     if args.typeattrquery or args.all:
    255         q = setools.TypeAttributeQuery(p)
    256         if isinstance(args.typeattrquery, str):
    257             q.name = args.typeattrquery
    258 
    259         components.append(("Type Attributes", q, expand_attr))
    260 
    261     if args.userquery or args.all:
    262         q = setools.UserQuery(p)
    263         if isinstance(args.userquery, str):
    264             q.name = args.userquery
    265 
    266         components.append(("Users", q, lambda x: x.statement()))
    267 
    268     if args.validatetransquery or args.all:
    269         q = setools.ConstraintQuery(p, ruletype=["validatetrans", "mlsvalidatetrans"])
    270         if isinstance(args.validatetransquery, str):
    271             q.tclass = [args.validatetransquery]
    272 
    273         components.append(("Validatetrans", q, lambda x: x.statement()))
    274 
    275     if p.target_platform == "xen":
    276         if args.ioportconquery or args.all:
    277             q = setools.IoportconQuery(p)
    278             components.append(("Ioportcon", q, lambda x: x.statement()))
    279 
    280         if args.iomemconquery or args.all:
    281             q = setools.IomemconQuery(p)
    282             components.append(("Iomemcon", q, lambda x: x.statement()))
    283 
    284         if args.pcideviceconquery or args.all:
    285             q = setools.PcideviceconQuery(p)
    286             components.append(("Pcidevicecon", q, lambda x: x.statement()))
    287 
    288         if args.pirqconquery or args.all:
    289             q = setools.PirqconQuery(p)
    290             components.append(("Pirqcon", q, lambda x: x.statement()))
    291 
    292         if args.devicetreeconquery or args.all:
    293             q = setools.DevicetreeconQuery(p)
    294             components.append(("Devicetreecon", q, lambda x: x.statement()))
    295 
    296     if (not components or args.all) and not args.flat:
    297         mls = "enabled" if p.mls else "disabled"
    298 
    299         print("Statistics for policy file: {0}".format(p))
    300         print("Policy Version:             {0} (MLS {1})".format(p.version, mls))
    301         print("Target Policy:              {0}".format(p.target_platform))
    302         print("Handle unknown classes:     {0}".format(p.handle_unknown))
    303         print("  Classes:         {0:7}    Permissions:     {1:7}".format(
    304             p.class_count, p.permission_count))
    305         print("  Sensitivities:   {0:7}    Categories:      {1:7}".format(
    306             p.level_count, p.category_count))
    307         print("  Types:           {0:7}    Attributes:      {1:7}".format(
    308             p.type_count, p.type_attribute_count))
    309         print("  Users:           {0:7}    Roles:           {1:7}".format(
    310             p.user_count, p.role_count))
    311         print("  Booleans:        {0:7}    Cond. Expr.:     {1:7}".format(
    312             p.boolean_count, p.conditional_count))
    313         print("  Allow:           {0:7}    Neverallow:      {1:7}".format(
    314             p.allow_count, p.neverallow_count))
    315         print("  Auditallow:      {0:7}    Dontaudit:       {1:7}".format(
    316             p.auditallow_count, p.dontaudit_count))
    317         print("  Type_trans:      {0:7}    Type_change:     {1:7}".format(
    318             p.type_transition_count, p.type_change_count))
    319         print("  Type_member:     {0:7}    Range_trans:     {1:7}".format(
    320             p.type_member_count, p.range_transition_count))
    321         print("  Role allow:      {0:7}    Role_trans:      {1:7}".format(
    322             p.role_allow_count, p.role_transition_count))
    323         print("  Constraints:     {0:7}    Validatetrans:   {1:7}".format(
    324             p.constraint_count, p.validatetrans_count))
    325         print("  MLS Constrain:   {0:7}    MLS Val. Tran:   {1:7}".format(
    326             p.mlsconstraint_count, p.mlsvalidatetrans_count))
    327         print("  Permissives:     {0:7}    Polcap:          {1:7}".format(
    328             p.permissives_count, p.polcap_count))
    329         print("  Defaults:        {0:7}    Typebounds:      {1:7}".format(
    330             p.default_count, p.typebounds_count))
    331 
    332         if p.target_platform == "selinux":
    333             print("  Allowxperm:      {0:7}    Neverallowxperm: {1:7}".format(
    334                 p.allowxperm_count, p.neverallowxperm_count))
    335             print("  Auditallowxperm: {0:7}    Dontauditxperm:  {1:7}".format(
    336                 p.auditallowxperm_count, p.dontauditxperm_count))
    337             print("  Initial SIDs:    {0:7}    Fs_use:          {1:7}".format(
    338                 p.initialsids_count, p.fs_use_count))
    339             print("  Genfscon:        {0:7}    Portcon:         {1:7}".format(
    340                 p.genfscon_count, p.portcon_count))
    341             print("  Netifcon:        {0:7}    Nodecon:         {1:7}".format(
    342                 p.netifcon_count, p.nodecon_count))
    343         elif p.target_platform == "xen":
    344             print("  Initial SIDs:    {0:7}    Devicetreecon    {1:7}".format(
    345                 p.initialsids_count, p.devicetreecon_count))
    346             print("  Iomemcon:        {0:7}    Ioportcon:       {1:7}".format(
    347                 p.iomemcon_count, p.ioportcon_count))
    348             print("  Pcidevicecon:    {0:7}    Pirqcon:         {1:7}".format(
    349                 p.pcidevicecon_count, p.pirqcon_count))
    350 
    351     for desc, component, expander in components:
    352         results = sorted(component.results())
    353         if not args.flat:
    354             print("\n{0}: {1}".format(desc, len(results)))
    355         for item in results:
    356             result = expander(item) if args.expand else item
    357             strfmt = "   {0}" if not args.flat else "{0}"
    358             print(strfmt.format(result))
    359 
    360 except Exception as err:
    361     if args.debug:
    362         logging.exception(str(err))
    363     else:
    364         print(err)
    365 
    366     sys.exit(1)
    367