#!/usr/bin/env python3 # Copyright 2015-2016, Tresys Technology, LLC # # SPDX-License-Identifier: GPL-2.0-only # import setools import argparse import sys import logging import signal import warnings from itertools import chain from contextlib import suppress signal.signal(signal.SIGPIPE, signal.SIG_DFL) parser = argparse.ArgumentParser( description="SELinux policy semantic difference tool.", epilog="If no differences are selected, all differences will be printed.") parser.add_argument("POLICY1", help="Path to the first SELinux policy to diff.", nargs=1) parser.add_argument("POLICY2", help="Path to the second SELinux policy to diff.", nargs=1) parser.add_argument("--version", action="version", version=setools.__version__) parser.add_argument("--stats", action="store_true", help="Display only statistics.") 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.") comp = parser.add_argument_group("component differences") comp.add_argument("--common", action="store_true", help="Print common differences") comp.add_argument("-c", "--class", action="store_true", help="Print class differences", dest="class_") comp.add_argument("-t", "--type", action="store_true", help="Print type differences", dest="type_") comp.add_argument("-a", "--attribute", action="store_true", help="Print type attribute differences") comp.add_argument("-r", "--role", action="store_true", help="Print role differences") comp.add_argument("-u", "--user", action="store_true", help="Print user differences") comp.add_argument("-b", "--bool", action="store_true", help="Print Boolean differences", dest="bool_") comp.add_argument("--sensitivity", action="store_true", help="Print MLS sensitivity differences") comp.add_argument("--category", action="store_true", help="Print MLS category differences") comp.add_argument("--level", action="store_true", help="Print MLS level definition differences") terule = parser.add_argument_group("type enforcement rule differences") terule.add_argument("-A", action="store_true", help="Print allow and allowxperm rule differences") terule.add_argument("--allow", action="store_true", help="Print allow rule differences") # terule.add_argument("--neverallow", action="store_true", help="Print neverallow rule differences") terule.add_argument("--auditallow", action="store_true", help="Print auditallow rule differences") terule.add_argument("--dontaudit", action="store_true", help="Print dontaudit rule differences") terule.add_argument("--allowxperm", action="store_true", help="Print allowxperm rule differences") # terule.add_argument("--neverallowxperm", action="store_true", # help="Print neverallowxperm rule differences") terule.add_argument("--auditallowxperm", action="store_true", help="Print auditallowxperm rule differences") terule.add_argument("--dontauditxperm", action="store_true", help="Print dontauditxperm rule differences") terule.add_argument("-T", "--type_trans", action="store_true", help="Print type_transition rule differences") terule.add_argument("--type_change", action="store_true", help="Print type_change rule differences") terule.add_argument("--type_member", action="store_true", help="Print type_member rule differences") rbacrule = parser.add_argument_group("RBAC rule differences") rbacrule.add_argument("--role_allow", action="store_true", help="Print role allow rule differences") rbacrule.add_argument("--role_trans", action="store_true", help="Print role_transition rule differences") mlsrule = parser.add_argument_group("MLS rule differences") mlsrule.add_argument("--range_trans", action="store_true", help="Print range_transition rule differences") constrain = parser.add_argument_group("Constraint differences") constrain.add_argument("--constrain", action="store_true", help="Print constrain differences") constrain.add_argument("--mlsconstrain", action="store_true", help="Print mlsconstrain differences") constrain.add_argument("--validatetrans", action="store_true", help="Print validatetrans differences") constrain.add_argument("--mlsvalidatetrans", action="store_true", help="Print mlsvalidatetrans differences") labeling = parser.add_argument_group("labeling statement differences") labeling.add_argument("--ibendportcon", action="store_true", help="Print ibendportcon differences") labeling.add_argument("--ibpkeycon", action="store_true", help="Print ibkeycon differences") labeling.add_argument("--initialsid", action="store_true", help="Print initial SID differences") labeling.add_argument("--fs_use", action="store_true", help="Print fs_use_* differences") labeling.add_argument("--genfscon", action="store_true", help="Print genfscon differences") labeling.add_argument("--netifcon", action="store_true", help="Print netifcon differences") labeling.add_argument("--nodecon", action="store_true", help="Print nodecon differences") labeling.add_argument("--portcon", action="store_true", help="Print portcon differences") other = parser.add_argument_group("other differences") other.add_argument("--default", action="store_true", help="Print default_* differences") other.add_argument("--property", action="store_true", help="Print policy property differences (handle_unknown, version, MLS)") other.add_argument("--polcap", action="store_true", help="Print policy capability differences") other.add_argument("--typebounds", action="store_true", help="Print typebounds differences") args = parser.parse_args() # neverallow and neverallowxperm options are disabled args.neverallow = False args.neverallowxperm = False if args.A: args.allow = True args.allowxperm = True all_differences = not any((args.class_, args.common, args.type_, args.attribute, args.role, args.user, args.bool_, args.sensitivity, args.category, args.level, args.allow, args.neverallow, args.auditallow, args.dontaudit, args.type_trans, args.type_change, args.type_member, args.role_allow, args.role_trans, args.range_trans, args.initialsid, args.genfscon, args.netifcon, args.nodecon, args.portcon, args.fs_use, args.polcap, args.property, args.default, args.constrain, args.mlsconstrain, args.validatetrans, args.mlsvalidatetrans, args.typebounds, args.allowxperm, args.neverallowxperm, args.auditallowxperm, args.dontauditxperm, args.ibendportcon, args.ibpkeycon)) 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: p1 = setools.SELinuxPolicy(args.POLICY1[0]) p2 = setools.SELinuxPolicy(args.POLICY2[0]) diff = setools.PolicyDifference(p1, p2) perms: list[str] if all_differences or args.property: if diff.modified_properties or args.property: print(f"Policy Properties ({len(diff.modified_properties)} Modified)") if not args.stats: for prop in sorted(diff.modified_properties): print(f" * {prop.property} +{prop.added} -{prop.removed}") print() del diff.modified_properties if all_differences or args.polcap: if diff.added_polcaps or diff.removed_polcaps or args.polcap: na = len(diff.added_polcaps) nr = len(diff.removed_polcaps) print(f"Policy Capabilities ({na} Added, {nr} Removed)") if diff.added_polcaps and not args.stats: print(f" Added Policy Capabilities: {na}") for cap in sorted(diff.added_polcaps): print(f" + {cap}") if diff.removed_polcaps and not args.stats: print(f" Removed Policy Capabilities: {nr}") for cap in sorted(diff.removed_polcaps): print(f" - {cap}") print() del diff.added_polcaps del diff.removed_polcaps if all_differences or args.common: if diff.added_commons or diff.removed_commons or diff.modified_commons or args.common: na = len(diff.added_commons) nr = len(diff.removed_commons) nm = len(diff.modified_commons) print(f"Commons ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_commons and not args.stats: print(f" Added Commons: {na}") for c in sorted(diff.added_commons): print(f" + {c}") if diff.removed_commons and not args.stats: print(f" Removed Commons: {nr}") for c in sorted(diff.removed_commons): print(f" - {c}") if diff.modified_commons and not args.stats: print(f" Modified Commons: {nm}") for com in sorted(diff.modified_commons): change = [] if com.added_perms: change.append(f"{len(com.added_perms)} Added permissions") if com.removed_perms: change.append(f"{len(com.removed_perms)} Removed permissions") print(f" * {com.common.name} ({', '.join(change)})") for p in sorted(com.added_perms): print(f" + {p}") for p in sorted(com.removed_perms): print(f" - {p}") print() del diff.added_commons del diff.removed_commons del diff.modified_commons if all_differences or args.class_: if diff.added_classes or diff.removed_classes or diff.modified_classes or args.class_: na = len(diff.added_classes) nr = len(diff.removed_classes) nm = len(diff.modified_classes) print(f"Classes ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_classes and not args.stats: print(f" Added Classes: {na}") for cls in sorted(diff.added_classes): print(f" + {cls}") if diff.removed_classes and not args.stats: print(f" Removed Classes: {nr}") for cls in sorted(diff.removed_classes): print(f" - {cls}") if diff.modified_classes and not args.stats: print(f" Modified Classes: {nm}") for mcls in sorted(diff.modified_classes): change = [] if mcls.added_perms: change.append(f"{len(mcls.added_perms)} Added permissions") if mcls.removed_perms: change.append(f"{len(mcls.removed_perms)} Removed permissions") print(f" * {mcls.class_.name} ({', '.join(change)})") for p in sorted(mcls.added_perms): print(f" + {p}") for p in sorted(mcls.removed_perms): print(f" - {p}") print() del diff.added_classes del diff.removed_classes del diff.modified_classes if all_differences or args.default: if diff.added_defaults or diff.removed_defaults or diff.modified_defaults or args.default: na = len(diff.added_defaults) nr = len(diff.removed_defaults) nm = len(diff.modified_defaults) print(f"Defaults ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_defaults and not args.stats: print(f" Added Defaults: {na}") for dflt in sorted(diff.added_defaults): print(f" + {dflt}") if diff.removed_defaults and not args.stats: print(f" Removed Defaults: {nr}") for dflt in sorted(diff.removed_defaults): print(f" - {dflt}") if diff.modified_defaults and not args.stats: print(f" Modified Defaults: {nm}") for mdflt in sorted(diff.modified_defaults): line = f" * {mdflt.rule.ruletype} {mdflt.rule.tclass} " if mdflt.removed_default: line += f"+{mdflt.added_default} -{mdflt.removed_default}" else: line += mdflt.rule.default.name if mdflt.removed_default_range: line += f" +{mdflt.added_default_range} -{mdflt.removed_default_range};" else: try: line += f" {mdflt.rule.default_range};" # type: ignore except AttributeError: line += ";" print(line) print() del diff.added_defaults del diff.removed_defaults del diff.modified_defaults if all_differences or args.bool_: if diff.added_booleans or diff.removed_booleans or \ diff.modified_booleans or args.bool_: na = len(diff.added_booleans) nr = len(diff.removed_booleans) nm = len(diff.modified_booleans) print(f"Booleans ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_booleans and not args.stats: print(f" Added Booleans: {na}") for a in sorted(diff.added_booleans): print(f" + {a}") if diff.removed_booleans and not args.stats: print(f" Removed Booleans: {nr}") for a in sorted(diff.removed_booleans): print(f" - {a}") if diff.modified_booleans and not args.stats: print(f" Modified Booleans: {nm}") for bool_ in sorted(diff.modified_booleans): print(f" * {bool_.boolean.name} (Modified default state)") print(f" + {bool_.added_state}") print(f" - {bool_.removed_state}") print() del diff.added_booleans del diff.removed_booleans del diff.modified_booleans if all_differences or args.role: if diff.added_roles or diff.removed_roles or diff.modified_roles or args.role: na = len(diff.added_roles) nr = len(diff.removed_roles) nm = len(diff.modified_roles) print(f"Roles ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_roles and not args.stats: print(f" Added Roles: {na}") for role in sorted(diff.added_roles): print(f" + {role}") if diff.removed_roles and not args.stats: print(f" Removed Roles: {nr}") for role in sorted(diff.removed_roles): print(f" - {role}") if diff.modified_roles and not args.stats: print(f" Modified Roles: {nm}") for mrole in sorted(diff.modified_roles): change = [] if mrole.added_types: change.append(f"{len(mrole.added_types)} Added types") if mrole.removed_types: change.append(f"{len(mrole.removed_types)} Removed types") print(f" * {mrole.role.name} ({', '.join(change)})") for type_ in sorted(mrole.added_types): print(f" + {type_}") for type_ in sorted(mrole.removed_types): print(f" - {type_}") print() del diff.added_roles del diff.removed_roles del diff.modified_roles if all_differences or args.type_: if diff.added_types or diff.removed_types or diff.modified_types or args.type_: na = len(diff.added_types) nr = len(diff.removed_types) nm = len(diff.modified_types) print(f"Types ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_types and not args.stats: print(f" Added Types: {na}") for type_ in sorted(diff.added_types): print(f" + {type_}") if diff.removed_types and not args.stats: print(f" Removed Types: {nr}") for type_ in sorted(diff.removed_types): print(f" - {type_}") if diff.modified_types and not args.stats: print(f" Modified Types: {nm}") for mtype in sorted(diff.modified_types): change = [] if mtype.added_attributes: change.append(f"{len(mtype.added_attributes)} Added attributes") if mtype.removed_attributes: change.append(f"{len(mtype.removed_attributes)} Removed attributes") if mtype.added_aliases: change.append(f"{len(mtype.added_aliases)} Added aliases") if mtype.removed_aliases: change.append(f"{len(mtype.removed_aliases)} Removed aliases") if mtype.modified_permissive: if mtype.permissive: change.append("Removed permissive") else: change.append("Added permissive") print(f" * {mtype.type_.name} ({','.join(change)})") if mtype.added_attributes or mtype.removed_attributes: print(" Attributes:") for attr in sorted(mtype.added_attributes): print(f" + {attr}") for attr in sorted(mtype.removed_attributes): print(f" - {attr}") if mtype.added_aliases or mtype.removed_aliases: print(" Aliases:") for alias in sorted(mtype.added_aliases): print(f" + {alias}") for alias in sorted(mtype.removed_aliases): print(f" - {alias}") print() del diff.added_types del diff.removed_types del diff.modified_types if all_differences or args.typebounds: if diff.added_typebounds or diff.removed_typebounds or diff.modified_typebounds \ or args.typebounds: na = len(diff.added_typebounds) nr = len(diff.removed_typebounds) nm = len(diff.modified_typebounds) print(f"Typebounds ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_typebounds and not args.stats: print(f" Added Typebounds: {na}") for tb in sorted(diff.added_typebounds): print(f" + {tb}") if diff.removed_typebounds and not args.stats: print(f" Removed Typebounds: {nr}") for tb in sorted(diff.removed_typebounds): print(f" - {tb}") if diff.modified_typebounds and not args.stats: print(f" Modified Typebounds: {nm}") for mtb in sorted(diff.modified_typebounds): print( f" * {mtb.rule.ruletype} +{mtb.added_bound} -{mtb.removed_bound} " f"{mtb.rule.child};") print() del diff.added_typebounds del diff.removed_typebounds if all_differences or args.attribute: if diff.added_type_attributes or diff.removed_type_attributes or \ diff.modified_type_attributes or args.attribute: na = len(diff.added_type_attributes) nr = len(diff.removed_type_attributes) nm = len(diff.modified_type_attributes) print(f"Type Attributes ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_type_attributes and not args.stats: print(f" Added Type Attributes: {na}") for attr in sorted(diff.added_type_attributes): print(f" + {attr}") if diff.removed_type_attributes and not args.stats: print(f" Removed Type Attributes: {nr}") for attr in sorted(diff.removed_type_attributes): print(f" - {attr}") if diff.modified_type_attributes and not args.stats: print(f" Modified Type Attributes: {nm}") for mattr in sorted(diff.modified_type_attributes): change = [] if mattr.added_types: change.append(f"{len(mattr.added_types)} Added types") if mattr.removed_types: change.append(f"{len(mattr.removed_types)} Removed types") print(f" * {mattr.attr.name} ({', '.join(change)})") for type_ in sorted(mattr.added_types): print(f" + {type_}") for type_ in sorted(mattr.removed_types): print(f" - {type_}") print() del diff.added_type_attributes del diff.removed_type_attributes del diff.modified_type_attributes if all_differences or args.user: if diff.added_users or diff.removed_users or diff.modified_users or args.user: na = len(diff.added_users) nr = len(diff.removed_users) nm = len(diff.modified_users) print(f"Users ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_users and not args.stats: print(f" Added Users: {na}") for user in sorted(diff.added_users): print(f" + {user}") if diff.removed_users and not args.stats: print(f" Removed Users: {nr}") for user in sorted(diff.removed_users): print(f" - {user}") if diff.modified_users and not args.stats: print(f" Modified Users: {nm}") for muser in sorted(diff.modified_users): change = [] if muser.added_roles: change.append(f"{len(muser.added_roles)} Added roles") if muser.removed_roles: change.append(f"{len(muser.removed_roles)} Removed roles") if muser.removed_level: change.append("Modified default level") if muser.removed_range: change.append("Modified range") print(f" * {muser.user.name} ({', '.join(change)})") if muser.added_roles or muser.removed_roles: print(" Roles:") for role in sorted(muser.added_roles): print(f" + {role}") for role in sorted(muser.removed_roles): print(f" - {role}") if muser.removed_level: print(" Default level:") print(f" + {muser.added_level}") print(f" - {muser.removed_level}") if muser.removed_range: print(" Range:") print(f" + {muser.added_range}") print(f" - {muser.removed_range}") print() del diff.added_users del diff.removed_users del diff.modified_users if all_differences or args.category: if diff.added_categories or diff.removed_categories or diff.modified_categories \ or args.category: na = len(diff.added_categories) nr = len(diff.removed_categories) nm = len(diff.modified_categories) print(f"Categories ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_categories and not args.stats: print(f" Added Categories: {na}") for cat in sorted(diff.added_categories): print(f" + {cat}") if diff.removed_categories and not args.stats: print(f" Removed Categories: {nr}") for cat in sorted(diff.removed_categories): print(f" - {cat}") if diff.modified_categories and not args.stats: print(f" Modified Categories: {nm}") for mcat in sorted(diff.modified_categories): change = [] if mcat.added_aliases: change.append(f"{len(mcat.added_aliases)} Added Aliases") if mcat.removed_aliases: change.append(f"{len(mcat.removed_aliases)} Removed Aliases") print(f" * {mcat.category.name} ({', '.join(change)})") print(" Aliases:") for alias in sorted(mcat.added_aliases): print(f" + {alias}") for alias in sorted(mcat.removed_aliases): print(f" - {alias}") print() del diff.added_categories del diff.removed_categories del diff.modified_categories if all_differences or args.sensitivity: if diff.added_sensitivities or diff.removed_sensitivities or diff.modified_sensitivities \ or args.sensitivity: na = len(diff.added_sensitivities) nr = len(diff.removed_sensitivities) nm = len(diff.modified_sensitivities) print(f"Sensitivities ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_sensitivities and not args.stats: print(f" Added Sensitivities: {na}") for sens in sorted(diff.added_sensitivities): print(f" + {sens}") if diff.removed_sensitivities and not args.stats: print(f" Removed Sensitivities: {nr}") for sens in sorted(diff.removed_sensitivities): print(f" - {sens}") if diff.modified_sensitivities and not args.stats: print(f" Modified Sensitivities: {nm}") for msens in sorted(diff.modified_sensitivities): change = [] if msens.added_aliases: change.append(f"{len(msens.added_aliases)} Added Aliases") if msens.removed_aliases: change.append(f"{len(msens.removed_aliases)} Removed Aliases") print(f" * {msens.sensitivity.name} ({', '.join(change)})") print(" Aliases:") for alias in sorted(msens.added_aliases): print(f" + {alias}") for alias in sorted(msens.removed_aliases): print(f" - {alias}") print() del diff.added_sensitivities del diff.removed_sensitivities del diff.modified_sensitivities if all_differences or args.level: if diff.added_levels or diff.removed_levels or \ diff.modified_levels or args.level: na = len(diff.added_levels) nr = len(diff.removed_levels) nm = len(diff.modified_levels) print(f"Levels ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_levels and not args.stats: print(f" Added Levels: {na}") for level in sorted(diff.added_levels): print(f" + {level}") if diff.removed_levels and not args.stats: print(f" Removed Levels: {len(diff.removed_levels)}") for level in sorted(diff.removed_levels): print(f" - {level}") if diff.modified_levels and not args.stats: print(f" Modified Levels: {len(diff.modified_levels)}") for mlevel in sorted(diff.modified_levels): change = [] if mlevel.added_categories: change.append(f"{len(mlevel.added_categories)} Added Categories") if mlevel.removed_categories: change.append(f"{len(mlevel.removed_categories)} Removed Categories") print(f" * level {mlevel.level.sensitivity} ({', '.join(change)})") for cat in sorted(mlevel.added_categories): print(f" + {cat}") for cat in sorted(mlevel.removed_categories): print(f" - {cat}") print() del diff.added_levels del diff.removed_levels del diff.modified_levels if all_differences or args.allow: if diff.added_allows or diff.removed_allows or diff.modified_allows or args.allow: na = len(diff.added_allows) nr = len(diff.removed_allows) nm = len(diff.modified_allows) print(f"Allow Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_allows and not args.stats: print(f" Added Allow Rules: {na}") for avr in sorted(diff.added_allows): print(f" + {avr}") if diff.removed_allows and not args.stats: print(f" Removed Allow Rules: {nr}") for avr in sorted(diff.removed_allows): print(f" - {avr}") if diff.modified_allows and not args.stats: print(f" Modified Allow Rules: {nm}") for mavr in sorted(diff.modified_allows): perm_str = " ".join(chain((p for p in mavr.matched_perms), (f"+{p}" for p in mavr.added_perms), (f"-{p}" for p in mavr.removed_perms))) rule_string = f"{mavr.rule.ruletype} {mavr.rule.source} " \ f"{mavr.rule.target}:{mavr.rule.tclass} {{ {perm_str} }};" with suppress(AttributeError): rule_string += f" [ {mavr.rule.conditional} ]" print(f" * {rule_string}") print() del diff.added_allows del diff.removed_allows del diff.modified_allows if all_differences or args.allowxperm: if diff.added_allowxperms or diff.removed_allowxperms or diff.modified_allowxperms \ or args.allowxperm: na = len(diff.added_allowxperms) nr = len(diff.removed_allowxperms) nm = len(diff.modified_allowxperms) print(f"Allowxperm Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_allowxperms and not args.stats: print(f" Added Allowxperm Rules: {na}") for avxr in sorted(diff.added_allowxperms): print(f" + {avxr}") if diff.removed_allowxperms and not args.stats: print(f" Removed Allowxperm Rules: {nr}") for avxr in sorted(diff.removed_allowxperms): print(f" - {avxr}") if diff.modified_allowxperms and not args.stats: print(f" Modified Allowxperm Rules: {nm}") for mavxr in sorted(diff.modified_allowxperms): # Process the string representation of the sets # so hex representation and ranges are preserved. # Check if the perm sets have contents, otherwise # split on empty string will be an empty string. # Add brackets to added and removed permissions # in case there is a range of permissions. perms = [] if mavxr.matched_perms: for p in str(mavxr.matched_perms).split(" "): perms.append(p) if mavxr.added_perms: for p in str(mavxr.added_perms).split(" "): if '-' in p: perms.append(f"+[{p}]") else: perms.append(f"+{p}") if mavxr.removed_perms: for p in str(mavxr.removed_perms).split(" "): if '-' in p: perms.append(f"-[{p}]") else: perms.append(f"-{p}") print(f" * {mavxr.rule.ruletype} {mavxr.rule.source} " f"{mavxr.rule.target}:{mavxr.rule.tclass} {mavxr.rule.xperm_type} " f"{{ {' '.join(perms)} }};") print() del diff.added_allowxperms del diff.removed_allowxperms del diff.modified_allowxperms if all_differences or args.neverallow: if diff.added_neverallows or diff.removed_neverallows or diff.modified_neverallows or \ args.neverallow: na = len(diff.added_neverallows) nr = len(diff.removed_neverallows) nm = len(diff.modified_neverallows) print(f"Neverallow Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_neverallows and not args.stats: print(f" Added Neverallow Rules: {na}") for avr in sorted(diff.added_neverallows): print(f" + {avr}") if diff.removed_neverallows and not args.stats: print(f" Removed Neverallow Rules: {nr}") for avr in sorted(diff.removed_neverallows): print(f" - {avr}") if diff.modified_neverallows and not args.stats: print(f" Modified Neverallow Rules: {nm}") for mavr in sorted(diff.modified_neverallows): perm_str = " ".join(chain((p for p in mavr.matched_perms), ("+" + p for p in mavr.added_perms), ("-" + p for p in mavr.removed_perms))) rule_string = f"{mavr.rule.ruletype} {mavr.rule.source} " \ f"{mavr.rule.target}:{mavr.rule.tclass} {{ {perm_str} }};" with suppress(AttributeError): rule_string += f" [ {mavr.rule.conditional} ]" print(f" * {rule_string}") print() del diff.added_neverallows del diff.removed_neverallows del diff.modified_neverallows if all_differences or args.neverallowxperm: if diff.added_neverallowxperms or diff.removed_neverallowxperms or \ diff.modified_neverallowxperms or args.neverallowxperm: na = len(diff.added_neverallowxperms) nr = len(diff.removed_neverallowxperms) nm = len(diff.modified_neverallowxperms) print(f"Neverallowxperm Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_neverallowxperms and not args.stats: print(f" Added Neverallowxperm Rules: {na}") for avxr in sorted(diff.added_neverallowxperms): print(f" + {avxr}") if diff.removed_neverallowxperms and not args.stats: print(f" Removed Neverallowxperm Rules: {nr}") for avxr in sorted(diff.removed_neverallowxperms): print(f" - {avxr}") if diff.modified_neverallowxperms and not args.stats: print(f" Modified Neverallowxperm Rules: {nm}") for mavxr in sorted(diff.modified_neverallowxperms): # Process the string representation of the sets # so hex representation and ranges are preserved. # Check if the perm sets have contents, otherwise # split on empty string will be an empty string. # Add brackets to added and removed permissions # in case there is a range of permissions. perms = [] if mavxr.matched_perms: for p in str(mavxr.matched_perms).split(" "): perms.append(p) if mavxr.added_perms: for p in str(mavxr.added_perms).split(" "): if '-' in p: perms.append(f"+[{p}]") else: perms.append(f"+{p}") if mavxr.removed_perms: for p in str(mavxr.removed_perms).split(" "): if '-' in p: perms.append(f"-[{p}]") else: perms.append(f"-{p}") print(f" * {mavxr.rule.ruletype} {mavxr.rule.source} " f"{mavxr.rule.target}:{mavxr.rule.tclass} " f"{mavxr.rule.xperm_type} {{ {' '.join(perms)} }};") print() del diff.added_neverallowxperms del diff.removed_neverallowxperms del diff.modified_neverallowxperms if all_differences or args.auditallow: if diff.added_auditallows or diff.removed_auditallows or diff.modified_auditallows or \ args.auditallow: na = len(diff.added_auditallows) nr = len(diff.removed_auditallows) nm = len(diff.modified_auditallows) print(f"Auditallow Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_auditallows and not args.stats: print(f" Added Auditallow Rules: {na}") for avr in sorted(diff.added_auditallows): print(f" + {avr}") if diff.removed_auditallows and not args.stats: print(f" Removed Auditallow Rules: {nr}") for avr in sorted(diff.removed_auditallows): print(f" - {avr}") if diff.modified_auditallows and not args.stats: print(f" Modified Auditallow Rules: {nm}") for mavr in sorted(diff.modified_auditallows): perm_str = " ".join(chain((p for p in mavr.matched_perms), ("+" + p for p in mavr.added_perms), ("-" + p for p in mavr.removed_perms))) rule_string = f"{mavr.rule.ruletype} {mavr.rule.source} " \ f"{mavr.rule.target}:{mavr.rule.tclass} {{ {perm_str} }};" with suppress(AttributeError): rule_string += f" [ {mavr.rule.conditional} ]" print(f" * {rule_string}") print() del diff.added_auditallows del diff.removed_auditallows del diff.modified_auditallows if all_differences or args.auditallowxperm: if diff.added_auditallowxperms or diff.removed_auditallowxperms or \ diff.modified_auditallowxperms or args.auditallowxperm: na = len(diff.added_auditallowxperms) nr = len(diff.removed_auditallowxperms) nm = len(diff.modified_auditallowxperms) print(f"Auditallowxperm Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_auditallowxperms and not args.stats: print(f" Added Auditallowxperm Rules: {na}") for avxr in sorted(diff.added_auditallowxperms): print(f" + {avxr}") if diff.removed_auditallowxperms and not args.stats: print(f" Removed Auditallowxperm Rules: {nr}") for avxr in sorted(diff.removed_auditallowxperms): print(f" - {avxr}") if diff.modified_auditallowxperms and not args.stats: print(f" Modified Auditallowxperm Rules: {nm}") for mavxr in sorted(diff.modified_auditallowxperms): # Process the string representation of the sets # so hex representation and ranges are preserved. # Check if the perm sets have contents, otherwise # split on empty string will be an empty string. # Add brackets to added and removed permissions # in case there is a range of permissions. perms = [] if mavxr.matched_perms: for p in str(mavxr.matched_perms).split(" "): perms.append(p) if mavxr.added_perms: for p in str(mavxr.added_perms).split(" "): if '-' in p: perms.append(f"+[{p}]") else: perms.append(f"+{p}") if mavxr.removed_perms: for p in str(mavxr.removed_perms).split(" "): if '-' in p: perms.append(f"-[{p}]") else: perms.append(f"-{p}") print(f" * {mavxr.rule.ruletype} {mavxr.rule.source} " f"{mavxr.rule.target}:{mavxr.rule.tclass} " f"{mavxr.rule.xperm_type} {{ {' '.join(perms)} }};") print() del diff.added_auditallowxperms del diff.removed_auditallowxperms del diff.modified_auditallowxperms if all_differences or args.dontaudit: if diff.added_dontaudits or diff.removed_dontaudits or diff.modified_dontaudits or \ args.dontaudit: na = len(diff.added_dontaudits) nr = len(diff.removed_dontaudits) nm = len(diff.modified_dontaudits) print(f"Dontaudit Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_dontaudits and not args.stats: print(f" Added Dontaudit Rules: {na}") for avr in sorted(diff.added_dontaudits): print(f" + {avr}") if diff.removed_dontaudits and not args.stats: print(f" Removed Dontaudit Rules: {nr}") for avr in sorted(diff.removed_dontaudits): print(f" - {avr}") if diff.modified_dontaudits and not args.stats: print(f" Modified Dontaudit Rules: {nm}") for mavr in sorted(diff.modified_dontaudits): perm_str = " ".join(chain((p for p in mavr.matched_perms), ("+" + p for p in mavr.added_perms), ("-" + p for p in mavr.removed_perms))) rule_string = f"{mavr.rule.ruletype} {mavr.rule.source} " \ f"{mavr.rule.target}:{mavr.rule.tclass} {{ {perm_str} }};" with suppress(AttributeError): rule_string += f" [ {mavr.rule.conditional} ]" print(f" * {rule_string}") print() del diff.added_dontaudits del diff.removed_dontaudits del diff.modified_dontaudits if all_differences or args.dontauditxperm: if diff.added_dontauditxperms or diff.removed_dontauditxperms or \ diff.modified_dontauditxperms or args.dontauditxperm: na = len(diff.added_dontauditxperms) nr = len(diff.removed_dontauditxperms) nm = len(diff.modified_dontauditxperms) print(f"Dontauditxperm Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_dontauditxperms and not args.stats: print(f" Added Dontauditxperm Rules: {na}") for avxr in sorted(diff.added_dontauditxperms): print(f" + {avxr}") if diff.removed_dontauditxperms and not args.stats: print(f" Removed Dontauditxperm Rules: {nr}") for avxr in sorted(diff.removed_dontauditxperms): print(f" - {avxr}") if diff.modified_dontauditxperms and not args.stats: print(f" Modified Dontauditxperm Rules: {nm}") for mavxr in sorted(diff.modified_dontauditxperms): # Process the string representation of the sets # so hex representation and ranges are preserved. # Check if the perm sets have contents, otherwise # split on empty string will be an empty string. # Add brackets to added and removed permissions # in case there is a range of permissions. perms = [] if mavxr.matched_perms: for p in str(mavxr.matched_perms).split(" "): perms.append(p) if mavxr.added_perms: for p in str(mavxr.added_perms).split(" "): if '-' in p: perms.append(f"+[{p}]") else: perms.append(f"+{p}") if mavxr.removed_perms: for p in str(mavxr.removed_perms).split(" "): if '-' in p: perms.append(f"-[{p}]") else: perms.append(f"-{p}") print(f" * {mavxr.rule.ruletype} {mavxr.rule.source} " f"{mavxr.rule.target}:{mavxr.rule.tclass} " f"{mavxr.rule.xperm_type} {{ {' '.join(perms)} }};") print() del diff.added_dontauditxperms del diff.removed_dontauditxperms del diff.modified_dontauditxperms if all_differences or args.type_trans: if diff.added_type_transitions or diff.removed_type_transitions or \ diff.modified_type_transitions or args.type_trans: na = len(diff.added_type_transitions) nr = len(diff.removed_type_transitions) nm = len(diff.modified_type_transitions) print(f"Type_transition Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_type_transitions and not args.stats: print(f" Added Type_transition Rules: {na}") for ter in sorted(diff.added_type_transitions): print(f" + {ter}") if diff.removed_type_transitions and not args.stats: print(f" Removed Type_transition Rules: {nr}") for ter in sorted(diff.removed_type_transitions): print(f" - {ter}") if diff.modified_type_transitions and not args.stats: print(f" Modified Type_transition Rules: {nm}") for mter in sorted(diff.modified_type_transitions): rule_string = \ f"{mter.rule.ruletype} {mter.rule.source} " \ f"{mter.rule.target}:{mter.rule.tclass} " \ f"+{mter.added_default} -{mter.removed_default}" with suppress(AttributeError): rule_string += f" {mter.rule.filename}" rule_string += ";" with suppress(AttributeError): rule_string += f" [ {mter.rule.conditional} ]" print(f" * {rule_string}") print() del diff.added_type_transitions del diff.removed_type_transitions del diff.modified_type_transitions if all_differences or args.type_change: if diff.added_type_changes or diff.removed_type_changes or \ diff.modified_type_changes or args.type_change: na = len(diff.added_type_changes) nr = len(diff.removed_type_changes) nm = len(diff.modified_type_changes) print(f"Type_change Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_type_changes and not args.stats: print(f" Added Type_change Rules: {na}") for ter in sorted(diff.added_type_changes): print(f" + {ter}") if diff.removed_type_changes and not args.stats: print(f" Removed Type_change Rules: {nr}") for ter in sorted(diff.removed_type_changes): print(f" - {ter}") if diff.modified_type_changes and not args.stats: print(f" Modified Type_change Rules: {nm}") for mter in sorted(diff.modified_type_changes): rule_string = \ f"{mter.rule.ruletype} {mter.rule.source} " \ f"{mter.rule.target}:{mter.rule.tclass} " \ f"+{mter.added_default} -{mter.removed_default};" with suppress(AttributeError): rule_string += f" [ {mter.rule.conditional} ]" print(f" * {rule_string}") print() del diff.added_type_changes del diff.removed_type_changes del diff.modified_type_changes if all_differences or args.type_member: if diff.added_type_members or diff.removed_type_members or \ diff.modified_type_members or args.type_member: na = len(diff.added_type_members) nr = len(diff.removed_type_members) nm = len(diff.modified_type_members) print(f"Type_member Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_type_members and not args.stats: print(f" Added Type_member Rules: {na}") for ter in sorted(diff.added_type_members): print(f" + {ter}") if diff.removed_type_members and not args.stats: print(f" Removed Type_member Rules: {nr}") for ter in sorted(diff.removed_type_members): print(f" - {ter}") if diff.modified_type_members and not args.stats: print(f" Modified Type_member Rules: {nm}") for mter in sorted(diff.modified_type_members): rule_string = \ f"{mter.rule.ruletype} {mter.rule.source} " \ f"{mter.rule.target}:{mter.rule.tclass} " \ f"+{mter.added_default} -{mter.removed_default};" with suppress(AttributeError): rule_string += f" [ {mter.rule.conditional} ]" print(f" * {rule_string}") print() del diff.added_type_members del diff.removed_type_members del diff.modified_type_members if all_differences or args.role_allow: if diff.added_role_allows or diff.removed_role_allows or args.role_allow: na = len(diff.added_role_allows) nr = len(diff.removed_role_allows) print(f"Role allow Rules ({na} Added, {nr} Removed)") if diff.added_role_allows and not args.stats: print(f" Added Role Allow Rules: {na}") for ra in sorted(diff.added_role_allows): print(f" + {ra}") if diff.removed_role_allows and not args.stats: print(f" Removed Role Allow Rules: {nr}") for ra in sorted(diff.removed_role_allows): print(f" - {ra}") print() del diff.added_role_allows del diff.removed_role_allows if all_differences or args.role_trans: if diff.added_role_transitions or diff.removed_role_transitions or \ diff.modified_role_transitions or args.role_trans: na = len(diff.added_role_transitions) nr = len(diff.removed_role_transitions) nm = len(diff.modified_role_transitions) print(f"Role_transition Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_role_transitions and not args.stats: print(f" Added Role_transition Rules: {na}") for rotr in sorted(diff.added_role_transitions): print(f" + {rotr}") if diff.removed_role_transitions and not args.stats: print(f" Removed Role_transition Rules: {nr}") for rotr in sorted(diff.removed_role_transitions): print(f" - {rotr}") if diff.modified_role_transitions and not args.stats: print(f" Modified Role_transition Rules: {nm}") for mrotr in sorted(diff.modified_role_transitions): rule_string = \ f"{mrotr.rule.ruletype} {mrotr.rule.source} " \ f"{mrotr.rule.target}:{mrotr.rule.tclass} " \ f"+{mrotr.added_default} -{mrotr.removed_default};" print(f" * {rule_string}") print() del diff.added_role_transitions del diff.removed_role_transitions del diff.modified_role_transitions if all_differences or args.range_trans: if diff.added_range_transitions or diff.removed_range_transitions or \ diff.modified_range_transitions or args.range_trans: na = len(diff.added_range_transitions) nr = len(diff.removed_range_transitions) nm = len(diff.modified_range_transitions) print(f"Range_transition Rules ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_range_transitions and not args.stats: print(f" Added Range_transition Rules: {na}") for ratr in sorted(diff.added_range_transitions): print(f" + {ratr}") if diff.removed_range_transitions and not args.stats: print(f" Removed Range_transition Rules: {nr}") for ratr in sorted(diff.removed_range_transitions): print(f" - {ratr}") if diff.modified_range_transitions and not args.stats: print(f" Modified Range_transition Rules: {nm}") for mratr in sorted(diff.modified_range_transitions): # added brackets around range change for clarity since ranges # can have '-' and spaces. rule_string = \ f"{mratr.rule.ruletype} {mratr.rule.source} " \ f"{mratr.rule.target}:{mratr.rule.tclass} " \ f"+[{mratr.added_default}] -[{mratr.removed_default}];" print(f" * {rule_string}") print() del diff.added_range_transitions del diff.removed_range_transitions del diff.modified_range_transitions if all_differences or args.constrain: if diff.added_constrains or diff.removed_constrains or args.constrain: na = len(diff.added_constrains) nr = len(diff.removed_constrains) print(f"Constraints ({na} Added, {nr} Removed)") if diff.added_constrains and not args.stats: print(f" Added Constraints: {na}") for constraint in sorted(diff.added_constrains): print(f" + {constraint}") if diff.removed_constrains and not args.stats: print(f" Removed Constraints: {nr}") for constraint in sorted(diff.removed_constrains): print(f" - {constraint}") print() del diff.added_constrains del diff.removed_constrains if all_differences or args.mlsconstrain: if diff.added_mlsconstrains or diff.removed_mlsconstrains or args.mlsconstrain: na = len(diff.added_mlsconstrains) nr = len(diff.removed_mlsconstrains) print(f"MLS Constraints ({na} Added, {nr} Removed)") if diff.added_mlsconstrains and not args.stats: print(f" Added MLS Constraints: {na}") for constraint in sorted(diff.added_mlsconstrains): print(f" + {constraint}") if diff.removed_mlsconstrains and not args.stats: print(f" Removed MLS Constraints: {nr}") for constraint in sorted(diff.removed_mlsconstrains): print(f" - {constraint}") print() del diff.added_mlsconstrains del diff.removed_mlsconstrains if all_differences or args.validatetrans: if diff.added_validatetrans or diff.removed_validatetrans or args.validatetrans: na = len(diff.added_validatetrans) nr = len(diff.removed_validatetrans) print(f"Validatetrans ({na} Added, {nr} Removed)") if diff.added_validatetrans and not args.stats: print(f" Added Validatetrans: {na}") for validatetrans in sorted(diff.added_validatetrans): print(f" + {validatetrans}") if diff.removed_validatetrans and not args.stats: print(f" Removed Validatetrans: {nr}") for validatetrans in sorted(diff.removed_validatetrans): print(f" - {validatetrans}") print() del diff.added_validatetrans del diff.removed_validatetrans if all_differences or args.mlsvalidatetrans: if diff.added_mlsvalidatetrans or diff.removed_mlsvalidatetrans or args.mlsvalidatetrans: na = len(diff.added_mlsvalidatetrans) nr = len(diff.removed_mlsvalidatetrans) print(f"MLS Validatetrans ({na} Added, {nr} Removed)") if diff.added_mlsvalidatetrans and not args.stats: print(f" Added MLS Validatetrans: {na}") for validatetrans in sorted(diff.added_mlsvalidatetrans): print(f" + {validatetrans}") if diff.removed_mlsvalidatetrans and not args.stats: print(f" Removed MLS Validatetrans: {nr}") for validatetrans in sorted(diff.removed_mlsvalidatetrans): print(f" - {validatetrans}") print() del diff.added_mlsvalidatetrans del diff.removed_mlsvalidatetrans if all_differences or args.initialsid: if diff.added_initialsids or diff.removed_initialsids or diff.modified_initialsids \ or args.initialsid: na = len(diff.added_initialsids) nr = len(diff.removed_initialsids) nm = len(diff.modified_initialsids) print(f"Initial SIDs ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_initialsids and not args.stats: print(f" Added Initial SIDs: {na}") for isid in sorted(diff.added_initialsids): print(f" + {isid.statement()}") if diff.removed_initialsids and not args.stats: print(f" Removed Initial SIDs: {nr}") for isid in sorted(diff.removed_initialsids): print(f" - {isid.statement()}") if diff.modified_initialsids and not args.stats: print(f" Modified Initial SIDs: {nm}") for misid in sorted(diff.modified_initialsids): print(f" * sid {misid.isid.name} +[{misid.added_context}] " f"-[{misid.removed_context}];") print() del diff.added_initialsids del diff.removed_initialsids del diff.modified_initialsids if all_differences or args.ibendportcon: if diff.added_ibendportcons or diff.removed_ibendportcons or diff.modified_ibendportcons \ or args.ibendportcon: na = len(diff.added_ibendportcons) nr = len(diff.removed_ibendportcons) nm = len(diff.modified_ibendportcons) print(f"Ibendportcons ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_ibendportcons and not args.stats: print(f" Added Ibendportcons: {na}") for ibp in sorted(diff.added_ibendportcons): print(f" + {ibp}") if diff.removed_ibendportcons and not args.stats: print(f" Removed Ibendportcons: {nr}") for ibp in sorted(diff.removed_ibendportcons): print(f" - {ibp}") if diff.modified_ibendportcons and not args.stats: print(f" Modified Ibendportcons: {nm}") for mibp in sorted(diff.modified_ibendportcons): print(f" * ibendportcon {mibp.rule.name} {mibp.rule.port} " f"+[{mibp.added_context}] -[{mibp.removed_context}]") print() del diff.added_ibendportcons del diff.removed_ibendportcons del diff.modified_ibendportcons if all_differences or args.ibpkeycon: if diff.added_ibpkeycons or diff.removed_ibpkeycons or diff.modified_ibpkeycons \ or args.ibpkeycon: na = len(diff.added_ibpkeycons) nr = len(diff.removed_ibpkeycons) nm = len(diff.modified_ibpkeycons) print(f"Ibpkeycons ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_ibpkeycons and not args.stats: print(f" Added Ibpkeycons: {na}") for ibpk in sorted(diff.added_ibpkeycons): print(f" + {ibpk}") if diff.removed_ibpkeycons and not args.stats: print(f" Removed Ibpkeycons: {nr}") for ibpk in sorted(diff.removed_ibpkeycons): print(f" - {ibpk}") if diff.modified_ibpkeycons and not args.stats: print(f" Modified Ibpkeycons: {nm}") for mibpk in sorted(diff.modified_ibpkeycons): if mibpk.rule.pkeys.low == mibpk.rule.pkeys.high: print(f" * ibpkeycon {mibpk.rule.subnet_prefix} " f"{mibpk.rule.pkeys.low:#x} +[{mibpk.added_context}] " f"-[{mibpk.removed_context}]") else: print(f" * ibpkeycon {mibpk.rule.subnet_prefix} " f"{mibpk.rule.pkeys.low:#x}-{mibpk.rule.pkeys.high:#x} " f"+[{mibpk.added_context}] -[{mibpk.removed_context}]") print() del diff.added_ibpkeycons del diff.removed_ibpkeycons del diff.modified_ibpkeycons if all_differences or args.fs_use: if diff.added_fs_uses or diff.removed_fs_uses or diff.modified_fs_uses \ or args.fs_use: na = len(diff.added_fs_uses) nr = len(diff.removed_fs_uses) nm = len(diff.modified_fs_uses) print(f"Fs_use ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_fs_uses and not args.stats: print(f" Added Fs_use: {na}") for fsu in sorted(diff.added_fs_uses): print(f" + {fsu}") if diff.removed_fs_uses and not args.stats: print(f" Removed Fs_use: {nr}") for fsu in sorted(diff.removed_fs_uses): print(f" - {fsu}") if diff.modified_fs_uses and not args.stats: print(f" Modified Fs_use: {nm}") for mfsu in sorted(diff.modified_fs_uses): print(f" * {mfsu.rule.ruletype} {mfsu.rule.fs} " f"+[{mfsu.added_context}] -[{mfsu.removed_context}];") print() del diff.added_fs_uses del diff.removed_fs_uses del diff.modified_fs_uses if all_differences or args.genfscon: if diff.added_genfscons or diff.removed_genfscons or diff.modified_genfscons \ or args.genfscon: na = len(diff.added_genfscons) nr = len(diff.removed_genfscons) nm = len(diff.modified_genfscons) print(f"Genfscons ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_genfscons and not args.stats: print(f" Added Genfscons: {na}") for genfs in sorted(diff.added_genfscons): print(f" + {genfs}") if diff.removed_genfscons and not args.stats: print(f" Removed Genfscons: {nr}") for genfs in sorted(diff.removed_genfscons): print(f" - {genfs}") if diff.modified_genfscons and not args.stats: print(f" Modified Genfscons: {nm}") for mgenfs in sorted(diff.modified_genfscons): print(f" * genfscon {mgenfs.rule.fs} {mgenfs.rule.path} " f"{mgenfs.rule.filetype} +[{mgenfs.added_context}] " f"-[{mgenfs.removed_context}];") print() del diff.added_genfscons del diff.removed_genfscons del diff.modified_genfscons if all_differences or args.netifcon: if diff.added_netifcons or diff.removed_netifcons or \ diff.modified_netifcons or args.netifcon: na = len(diff.added_netifcons) nr = len(diff.removed_netifcons) nm = len(diff.modified_netifcons) print(f"Netifcons ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_netifcons and not args.stats: print(f" Added Netifcons: {na}") for netif in sorted(diff.added_netifcons): print(f" + {netif}") if diff.removed_netifcons and not args.stats: print(f" Removed Netifcons: {nr}") for netif in sorted(diff.removed_netifcons): print(f" - {netif}") if diff.modified_netifcons and not args.stats: print(f" Modified Netifcons: {nm}") for mnetif in sorted(diff.modified_netifcons): # This output is different than other statements because # it becomes difficult to read if this was condensed # into a single line, especially if both contexts # are modified. change = [] if mnetif.removed_context: change.append("Modified Context") if mnetif.removed_packet: change.append("Modified Packet Context") print(f" * netif {mnetif.rule.netif} ({', '.join(change)})") if mnetif.removed_context: print(" Context:") print(f" + {mnetif.added_context}") print(f" - {mnetif.removed_context}") if mnetif.removed_packet: print(" Packet Context:") print(f" + {mnetif.added_packet}") print(f" - {mnetif.removed_packet}") print() del diff.added_netifcons del diff.removed_netifcons del diff.modified_netifcons if all_differences or args.nodecon: if diff.added_nodecons or diff.removed_nodecons or diff.modified_nodecons \ or args.nodecon: na = len(diff.added_nodecons) nr = len(diff.removed_nodecons) nm = len(diff.modified_nodecons) print(f"Nodecons ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_nodecons and not args.stats: print(f" Added Nodecons: {na}") for node in sorted(diff.added_nodecons): print(f" + {node}") if diff.removed_nodecons and not args.stats: print(f" Removed Nodecons: {nr}") for node in sorted(diff.removed_nodecons): print(f" - {node}") if diff.modified_nodecons and not args.stats: print(f" Modified Nodecons: {nm}") for mnode in sorted(diff.modified_nodecons): print(f" * nodecon {mnode.rule.network.with_netmask.replace('/', ' ')} " f"+[{mnode.added_context}] -[{mnode.removed_context}];") print() del diff.added_nodecons del diff.removed_nodecons del diff.modified_nodecons if all_differences or args.portcon: if diff.added_portcons or diff.removed_portcons or diff.modified_portcons \ or args.portcon: na = len(diff.added_portcons) nr = len(diff.removed_portcons) nm = len(diff.modified_portcons) print(f"Portcons ({na} Added, {nr} Removed, {nm} Modified)") if diff.added_portcons and not args.stats: print(f" Added Portcons: {na}") for port in sorted(diff.added_portcons): print(f" + {port}") if diff.removed_portcons and not args.stats: print(f" Removed Portcons: {nr}") for port in sorted(diff.removed_portcons): print(f" - {port}") if diff.modified_portcons and not args.stats: print(f" Modified Portcons: {nm}") for mport in sorted(diff.modified_portcons): low, high = mport.rule.ports.low, mport.rule.ports.high if low == high: print(f" * portcon {mport.rule.protocol} {low} " f"+[{mport.added_context}] -[{mport.removed_context}];") else: print(f" * portcon {mport.rule.protocol} {low}-{high} " f"+[{mport.added_context}] -[{mport.removed_context}];") print() del diff.added_portcons del diff.removed_portcons del diff.modified_portcons except AssertionError: # Always provide a traceback for assertion errors raise except Exception as err: if args.debug: raise else: print(err) sys.exit(1)