1#!/usr/bin/env python 2# Copyright 2015-2016, 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 25from itertools import chain 26 27parser = argparse.ArgumentParser( 28 description="SELinux policy semantic difference tool.", 29 epilog="If no differences are selected, all differences will be printed.") 30parser.add_argument("POLICY1", help="Path to the first SELinux policy to diff.", nargs=1) 31parser.add_argument("POLICY2", help="Path to the second SELinux policy to diff.", nargs=1) 32parser.add_argument("--version", action="version", version=setools.__version__) 33parser.add_argument("--stats", action="store_true", help="Display only statistics.") 34parser.add_argument("-v", "--verbose", action="store_true", 35 help="Print extra informational messages") 36parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.") 37 38comp = parser.add_argument_group("component differences") 39comp.add_argument("--common", action="store_true", help="Print common differences") 40comp.add_argument("-c", "--class", action="store_true", help="Print class differences", 41 dest="class_") 42comp.add_argument("-t", "--type", action="store_true", help="Print type differences", 43 dest="type_") 44comp.add_argument("-a", "--attribute", action="store_true", help="Print type attribute differences") 45comp.add_argument("-r", "--role", action="store_true", help="Print role differences") 46comp.add_argument("-u", "--user", action="store_true", help="Print user differences") 47comp.add_argument("-b", "--bool", action="store_true", help="Print Boolean differences", 48 dest="bool_") 49comp.add_argument("--sensitivity", action="store_true", help="Print MLS sensitivity differences") 50comp.add_argument("--category", action="store_true", help="Print MLS category differences") 51comp.add_argument("--level", action="store_true", help="Print MLS level definition differences") 52 53terule = parser.add_argument_group("type enforcement rule differences") 54terule.add_argument("-A", action="store_true", help="Print allow and allowxperm rule differences") 55terule.add_argument("--allow", action="store_true", help="Print allow rule differences") 56terule.add_argument("--neverallow", action="store_true", help="Print neverallow rule differences") 57terule.add_argument("--auditallow", action="store_true", help="Print auditallow rule differences") 58terule.add_argument("--dontaudit", action="store_true", help="Print dontaudit rule differences") 59terule.add_argument("--allowxperm", action="store_true", help="Print allowxperm rule differences") 60terule.add_argument("--neverallowxperm", action="store_true", 61 help="Print neverallowxperm rule differences") 62terule.add_argument("--auditallowxperm", action="store_true", 63 help="Print auditallowxperm rule differences") 64terule.add_argument("--dontauditxperm", action="store_true", 65 help="Print dontauditxperm rule differences") 66terule.add_argument("-T", "--type_trans", action="store_true", 67 help="Print type_transition rule differences") 68terule.add_argument("--type_change", action="store_true", help="Print type_change rule differences") 69terule.add_argument("--type_member", action="store_true", 70 help="Print type_member rule differences") 71 72rbacrule = parser.add_argument_group("RBAC rule differences") 73rbacrule.add_argument("--role_allow", action="store_true", help="Print role allow rule differences") 74rbacrule.add_argument("--role_trans", action="store_true", 75 help="Print role_transition rule differences") 76 77mlsrule = parser.add_argument_group("MLS rule differences") 78mlsrule.add_argument("--range_trans", action="store_true", 79 help="Print range_transition rule differences") 80 81constrain = parser.add_argument_group("Constraint differences") 82constrain.add_argument("--constrain", action="store_true", help="Print constrain differences") 83constrain.add_argument("--mlsconstrain", action="store_true", help="Print mlsconstrain differences") 84constrain.add_argument("--validatetrans", action="store_true", 85 help="Print validatetrans differences") 86constrain.add_argument("--mlsvalidatetrans", action="store_true", 87 help="Print mlsvalidatetrans differences") 88 89labeling = parser.add_argument_group("labeling statement differences") 90labeling.add_argument("--initialsid", action="store_true", help="Print initial SID differences") 91labeling.add_argument("--fs_use", action="store_true", help="Print fs_use_* differences") 92labeling.add_argument("--genfscon", action="store_true", help="Print genfscon differences") 93labeling.add_argument("--netifcon", action="store_true", help="Print netifcon differences") 94labeling.add_argument("--nodecon", action="store_true", help="Print nodecon differences") 95labeling.add_argument("--portcon", action="store_true", help="Print portcon differences") 96 97other = parser.add_argument_group("other differences") 98other.add_argument("--default", action="store_true", help="Print default_* differences") 99other.add_argument("--property", action="store_true", 100 help="Print policy property differences (handle_unknown, version, MLS)") 101other.add_argument("--polcap", action="store_true", help="Print policy capability differences") 102other.add_argument("--typebounds", action="store_true", help="Print typebounds differences") 103 104args = parser.parse_args() 105 106if args.A: 107 args.allow = True 108 args.allowxperm = True 109 110all_differences = not any((args.class_, args.common, args.type_, args.attribute, args.role, 111 args.user, args.bool_, args.sensitivity, args.category, args.level, 112 args.allow, args.neverallow, args.auditallow, args.dontaudit, 113 args.type_trans, args.type_change, args.type_member, args.role_allow, 114 args.role_trans, args.range_trans, args.initialsid, args.genfscon, 115 args.netifcon, args.nodecon, args.portcon, args.fs_use, args.polcap, 116 args.property, args.default, args.constrain, args.mlsconstrain, 117 args.validatetrans, args.mlsvalidatetrans, args.typebounds, 118 args.allowxperm, args.neverallowxperm, args.auditallowxperm, 119 args.dontauditxperm)) 120 121if args.debug: 122 logging.basicConfig(level=logging.DEBUG, 123 format='%(asctime)s|%(levelname)s|%(name)s|%(message)s') 124elif args.verbose: 125 logging.basicConfig(level=logging.INFO, format='%(message)s') 126else: 127 logging.basicConfig(level=logging.WARNING, format='%(message)s') 128 129try: 130 p1 = setools.SELinuxPolicy(args.POLICY1[0]) 131 p2 = setools.SELinuxPolicy(args.POLICY2[0]) 132 diff = setools.PolicyDifference(p1, p2) 133 134 if all_differences or args.property: 135 print("Policy Properties ({0} Modified)".format(len(diff.modified_properties))) 136 137 if diff.modified_properties and not args.stats: 138 for name, added, removed in sorted(diff.modified_properties, key=lambda x: x.property): 139 print(" * {0} +{1} -{2}".format(name, added, removed)) 140 141 print() 142 143 if all_differences or args.common: 144 if diff.added_commons or diff.removed_commons or diff.modified_commons or args.common: 145 print("Commons ({0} Added, {1} Removed, {2} Modified)".format( 146 len(diff.added_commons), len(diff.removed_commons), len(diff.modified_commons))) 147 if diff.added_commons and not args.stats: 148 print(" Added Commons: {0}".format(len(diff.added_commons))) 149 for c in sorted(diff.added_commons): 150 print(" + {0}".format(c)) 151 if diff.removed_commons and not args.stats: 152 print(" Removed Commons: {0}".format(len(diff.removed_commons))) 153 for c in sorted(diff.removed_commons): 154 print(" - {0}".format(c)) 155 if diff.modified_commons and not args.stats: 156 print(" Modified Commons: {0}".format(len(diff.modified_commons))) 157 for name, mod in sorted(diff.modified_commons.items()): 158 change = [] 159 if mod.added_perms: 160 change.append("{0} Added permissions".format(len(mod.added_perms))) 161 if mod.removed_perms: 162 change.append("{0} Removed permissions".format(len(mod.removed_perms))) 163 164 print(" * {0} ({1})".format(name, ", ".join(change))) 165 for p in sorted(mod.added_perms): 166 print(" + {0}".format(p)) 167 for p in sorted(mod.removed_perms): 168 print(" - {0}".format(p)) 169 print() 170 171 if all_differences or args.class_: 172 if diff.added_classes or diff.removed_classes or diff.modified_classes or args.class_: 173 print("Classes ({0} Added, {1} Removed, {2} Modified)".format( 174 len(diff.added_classes), len(diff.removed_classes), len(diff.modified_classes))) 175 if diff.added_classes and not args.stats: 176 print(" Added Classes: {0}".format(len(diff.added_classes))) 177 for c in sorted(diff.added_classes): 178 print(" + {0}".format(c)) 179 if diff.removed_classes and not args.stats: 180 print(" Removed Classes: {0}".format(len(diff.removed_classes))) 181 for c in sorted(diff.removed_classes): 182 print(" - {0}".format(c)) 183 if diff.modified_classes and not args.stats: 184 print(" Modified Classes: {0}".format(len(diff.modified_classes))) 185 for name, mod in sorted(diff.modified_classes.items()): 186 change = [] 187 if mod.added_perms: 188 change.append("{0} Added permissions".format(len(mod.added_perms))) 189 if mod.removed_perms: 190 change.append("{0} Removed permissions".format(len(mod.removed_perms))) 191 192 print(" * {0} ({1})".format(name, ", ".join(change))) 193 for p in sorted(mod.added_perms): 194 print(" + {0}".format(p)) 195 for p in sorted(mod.removed_perms): 196 print(" - {0}".format(p)) 197 print() 198 199 if all_differences or args.bool_: 200 if diff.added_booleans or diff.removed_booleans or \ 201 diff.modified_booleans or args.bool_: 202 print("Booleans ({0} Added, {1} Removed, {2} Modified)".format( 203 len(diff.added_booleans), len(diff.removed_booleans), 204 len(diff.modified_booleans))) 205 if diff.added_booleans and not args.stats: 206 print(" Added Booleans: {0}".format(len(diff.added_booleans))) 207 for a in sorted(diff.added_booleans): 208 print(" + {0}".format(a)) 209 if diff.removed_booleans and not args.stats: 210 print(" Removed Booleans: {0}".format(len(diff.removed_booleans))) 211 for a in sorted(diff.removed_booleans): 212 print(" - {0}".format(a)) 213 if diff.modified_booleans and not args.stats: 214 print(" Modified Booleans: {0}".format(len(diff.modified_booleans))) 215 for name, mod in sorted(diff.modified_booleans.items()): 216 print(" * {0} (Modified default state)".format(name)) 217 print(" + {0}".format(mod.added_state)) 218 print(" - {0}".format(mod.removed_state)) 219 220 print() 221 222 if all_differences or args.role: 223 if diff.added_roles or diff.removed_roles or diff.modified_roles or args.role: 224 print("Roles ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_roles), 225 len(diff.removed_roles), 226 len(diff.modified_roles))) 227 if diff.added_roles and not args.stats: 228 print(" Added Roles: {0}".format(len(diff.added_roles))) 229 for r in sorted(diff.added_roles): 230 print(" + {0}".format(r)) 231 if diff.removed_roles and not args.stats: 232 print(" Removed Roles: {0}".format(len(diff.removed_roles))) 233 for r in sorted(diff.removed_roles): 234 print(" - {0}".format(r)) 235 if diff.modified_roles and not args.stats: 236 print(" Modified Roles: {0}".format(len(diff.modified_roles))) 237 for name, mod in sorted(diff.modified_roles.items()): 238 change = [] 239 if mod.added_types: 240 change.append("{0} Added types".format(len(mod.added_types))) 241 if mod.removed_types: 242 change.append("{0} Removed types".format(len(mod.removed_types))) 243 244 print(" * {0} ({1})".format(name, ", ".join(change))) 245 for t in sorted(mod.added_types): 246 print(" + {0}".format(t)) 247 for t in sorted(mod.removed_types): 248 print(" - {0}".format(t)) 249 print() 250 251 if all_differences or args.type_: 252 if diff.added_types or diff.removed_types or diff.modified_types or args.type_: 253 print("Types ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_types), 254 len(diff.removed_types), 255 len(diff.modified_types))) 256 if diff.added_types and not args.stats: 257 print(" Added Types: {0}".format(len(diff.added_types))) 258 for r in sorted(diff.added_types): 259 print(" + {0}".format(r)) 260 if diff.removed_types and not args.stats: 261 print(" Removed Types: {0}".format(len(diff.removed_types))) 262 for r in sorted(diff.removed_types): 263 print(" - {0}".format(r)) 264 if diff.modified_types and not args.stats: 265 print(" Modified Types: {0}".format(len(diff.modified_types))) 266 for name, mod in sorted(diff.modified_types.items()): 267 change = [] 268 if mod.added_attributes: 269 change.append("{0} Added attributes".format(len(mod.added_attributes))) 270 if mod.removed_attributes: 271 change.append("{0} Removed attributes".format(len(mod.removed_attributes))) 272 if mod.added_aliases: 273 change.append("{0} Added aliases".format(len(mod.added_aliases))) 274 if mod.removed_aliases: 275 change.append("{0} Removed aliases".format(len(mod.removed_aliases))) 276 if mod.modified_permissive: 277 if mod.permissive: 278 change.append("Removed permissive") 279 else: 280 change.append("Added permissive") 281 282 print(" * {0} ({1})".format(name, ", ".join(change))) 283 if mod.added_attributes or mod.removed_attributes: 284 print(" Attributes:") 285 for t in sorted(mod.added_attributes): 286 print(" + {0}".format(t)) 287 for t in sorted(mod.removed_attributes): 288 print(" - {0}".format(t)) 289 290 if mod.added_aliases or mod.removed_aliases: 291 print(" Aliases:") 292 for t in sorted(mod.added_aliases): 293 print(" + {0}".format(t)) 294 for t in sorted(mod.removed_aliases): 295 print(" - {0}".format(t)) 296 297 print() 298 299 if all_differences or args.attribute: 300 if diff.added_type_attributes or diff.removed_type_attributes or \ 301 diff.modified_type_attributes or args.attribute: 302 print("Type Attributes ({0} Added, {1} Removed, {2} Modified)".format( 303 len(diff.added_type_attributes), len(diff.removed_type_attributes), 304 len(diff.modified_type_attributes))) 305 if diff.added_type_attributes and not args.stats: 306 print(" Added Type Attributes: {0}".format(len(diff.added_type_attributes))) 307 for a in sorted(diff.added_type_attributes): 308 print(" + {0}".format(a)) 309 if diff.removed_type_attributes and not args.stats: 310 print(" Removed Type Attributes: {0}".format(len(diff.removed_type_attributes))) 311 for a in sorted(diff.removed_type_attributes): 312 print(" - {0}".format(a)) 313 if diff.modified_type_attributes and not args.stats: 314 print(" Modified Type Attributes: {0}".format(len(diff.modified_type_attributes))) 315 for name, mod in sorted(diff.modified_type_attributes.items()): 316 change = [] 317 if mod.added_types: 318 change.append("{0} Added types".format(len(mod.added_types))) 319 if mod.removed_types: 320 change.append("{0} Removed types".format(len(mod.removed_types))) 321 322 print(" * {0} ({1})".format(name, ", ".join(change))) 323 for t in sorted(mod.added_types): 324 print(" + {0}".format(t)) 325 for t in sorted(mod.removed_types): 326 print(" - {0}".format(t)) 327 print() 328 329 if all_differences or args.user: 330 if diff.added_users or diff.removed_users or diff.modified_users or args.user: 331 print("Users ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_users), 332 len(diff.removed_users), 333 len(diff.modified_users))) 334 if diff.added_users and not args.stats: 335 print(" Added Users: {0}".format(len(diff.added_users))) 336 for u in sorted(diff.added_users): 337 print(" + {0}".format(u)) 338 if diff.removed_users and not args.stats: 339 print(" Removed Users: {0}".format(len(diff.removed_users))) 340 for u in sorted(diff.removed_users): 341 print(" - {0}".format(u)) 342 if diff.modified_users and not args.stats: 343 print(" Modified Users: {0}".format(len(diff.modified_users))) 344 for name, mod in sorted(diff.modified_users.items()): 345 change = [] 346 if mod.added_roles: 347 change.append("{0} Added roles".format(len(mod.added_roles))) 348 if mod.removed_roles: 349 change.append("{0} Removed roles".format(len(mod.removed_roles))) 350 if mod.removed_level: 351 change.append("Modified default level") 352 if mod.removed_range: 353 change.append("Modified range") 354 355 print(" * {0} ({1})".format(name, ", ".join(change))) 356 if mod.added_roles or mod.removed_roles: 357 print(" Roles:") 358 for t in sorted(mod.added_roles): 359 print(" + {0}".format(t)) 360 for t in sorted(mod.removed_roles): 361 print(" - {0}".format(t)) 362 363 if mod.removed_level: 364 print(" Default level:") 365 print(" + {0}".format(mod.added_level)) 366 print(" - {0}".format(mod.removed_level)) 367 368 if mod.removed_range: 369 print(" Range:") 370 print(" + {0}".format(mod.added_range)) 371 print(" - {0}".format(mod.removed_range)) 372 print() 373 374 if all_differences or args.category: 375 if diff.added_categories or diff.removed_categories or diff.modified_categories \ 376 or args.category: 377 print("Categories ({0} Added, {1} Removed, {2} Modified)".format( 378 len(diff.added_categories), len(diff.removed_categories), 379 len(diff.modified_categories))) 380 if diff.added_categories and not args.stats: 381 print(" Added Categories: {0}".format(len(diff.added_categories))) 382 for c in sorted(diff.added_categories): 383 print(" + {0}".format(c)) 384 if diff.removed_categories and not args.stats: 385 print(" Removed Categories: {0}".format(len(diff.removed_categories))) 386 for c in sorted(diff.removed_categories): 387 print(" - {0}".format(c)) 388 if diff.modified_categories and not args.stats: 389 print(" Modified Categories: {0}".format(len(diff.modified_categories))) 390 for name, mod in sorted(diff.modified_categories.items()): 391 change = [] 392 if mod.added_aliases: 393 change.append("{0} Added Aliases".format(len(mod.added_aliases))) 394 if mod.removed_aliases: 395 change.append("{0} Removed Aliases".format(len(mod.removed_aliases))) 396 397 print(" * {0} ({1})".format(name, ", ".join(change))) 398 print(" Aliases:") 399 for a in sorted(mod.added_aliases): 400 print(" + {0}".format(a)) 401 for a in sorted(mod.removed_aliases): 402 print(" - {0}".format(a)) 403 404 print() 405 406 if all_differences or args.sensitivity: 407 if diff.added_sensitivities or diff.removed_sensitivities or diff.modified_sensitivities \ 408 or args.sensitivity: 409 print("Sensitivities ({0} Added, {1} Removed, {2} Modified)".format( 410 len(diff.added_sensitivities), len(diff.removed_sensitivities), 411 len(diff.modified_sensitivities))) 412 if diff.added_sensitivities and not args.stats: 413 print(" Added Sensitivites: {0}".format(len(diff.added_sensitivities))) 414 for s in sorted(diff.added_sensitivities): 415 print(" + {0}".format(s)) 416 if diff.removed_sensitivities and not args.stats: 417 print(" Removed Sensitivities: {0}".format(len(diff.removed_sensitivities))) 418 for s in sorted(diff.removed_sensitivities): 419 print(" - {0}".format(s)) 420 if diff.modified_sensitivities and not args.stats: 421 print(" Modified Sensitivities: {0}".format(len(diff.modified_sensitivities))) 422 for name, mod in sorted(diff.modified_sensitivities.items()): 423 change = [] 424 if mod.added_aliases: 425 change.append("{0} Added Aliases".format(len(mod.added_aliases))) 426 if mod.removed_aliases: 427 change.append("{0} Removed Aliases".format(len(mod.removed_aliases))) 428 429 print(" * {0} ({1})".format(name, ", ".join(change))) 430 print(" Aliases:") 431 for a in sorted(mod.added_aliases): 432 print(" + {0}".format(a)) 433 for a in sorted(mod.removed_aliases): 434 print(" - {0}".format(a)) 435 436 print() 437 438 if all_differences or args.level: 439 if diff.added_levels or diff.removed_levels or \ 440 diff.modified_levels or args.level: 441 print("Levels ({0} Added, {1} Removed, {2} Modified)".format( 442 len(diff.added_levels), len(diff.removed_levels), 443 len(diff.modified_levels))) 444 if diff.added_levels and not args.stats: 445 print(" Added Levels: {0}".format(len(diff.added_levels))) 446 for l in sorted(diff.added_levels): 447 print(" + {0}".format(l)) 448 if diff.removed_levels and not args.stats: 449 print(" Removed Levels: {0}".format(len(diff.removed_levels))) 450 for l in sorted(diff.removed_levels): 451 print(" - {0}".format(l)) 452 if diff.modified_levels and not args.stats: 453 print(" Modified Levels: {0}".format(len(diff.modified_levels))) 454 for level, added_categories, removed_categories, _ in sorted(diff.modified_levels, 455 key=lambda x: x.level): 456 change = [] 457 if added_categories: 458 change.append("{0} Added Categories".format(len(added_categories))) 459 if removed_categories: 460 change.append("{0} Removed Categories".format(len(removed_categories))) 461 462 print(" * {0} ({1})".format(level.sensitivity, ", ".join(change))) 463 for c in sorted(added_categories): 464 print(" + {0}".format(c)) 465 for c in sorted(removed_categories): 466 print(" - {0}".format(c)) 467 print() 468 469 if all_differences or args.allow: 470 if diff.added_allows or diff.removed_allows or diff.modified_allows or args.allow: 471 print("Allow Rules ({0} Added, {1} Removed, {2} Modified)".format( 472 len(diff.added_allows), len(diff.removed_allows), len(diff.modified_allows))) 473 474 if diff.added_allows and not args.stats: 475 print(" Added Allow Rules: {0}".format(len(diff.added_allows))) 476 for r in sorted(diff.added_allows): 477 print(" + {0}".format(r)) 478 479 if diff.removed_allows and not args.stats: 480 print(" Removed Allow Rules: {0}".format(len(diff.removed_allows))) 481 for r in sorted(diff.removed_allows): 482 print(" - {0}".format(r)) 483 484 if diff.modified_allows and not args.stats: 485 print(" Modified Allow Rules: {0}".format(len(diff.modified_allows))) 486 487 for rule, added_perms, removed_perms, matched_perms in sorted(diff.modified_allows, 488 key=lambda x: x.rule): 489 perms = " ".join(chain((p for p in matched_perms), 490 ("+" + p for p in added_perms), 491 ("-" + p for p in removed_perms))) 492 rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format( 493 rule, perms) 494 495 try: 496 rule_string += " [ {0} ]".format(rule.conditional) 497 except AttributeError: 498 pass 499 print(" * {0}".format(rule_string)) 500 501 print() 502 503 if all_differences or args.allowxperm: 504 if diff.added_allowxperms or diff.removed_allowxperms or diff.modified_allowxperms \ 505 or args.allowxperm: 506 507 print("Allowxperm Rules ({0} Added, {1} Removed, {2} Modified)".format( 508 len(diff.added_allowxperms), len(diff.removed_allowxperms), 509 len(diff.modified_allowxperms))) 510 511 if diff.added_allowxperms and not args.stats: 512 print(" Added Allowxperm Rules: {0}".format(len(diff.added_allowxperms))) 513 for r in sorted(diff.added_allowxperms): 514 print(" + {0}".format(r)) 515 516 if diff.removed_allowxperms and not args.stats: 517 print(" Removed Allowxperm Rules: {0}".format(len(diff.removed_allowxperms))) 518 for r in sorted(diff.removed_allowxperms): 519 print(" - {0}".format(r)) 520 521 if diff.modified_allowxperms and not args.stats: 522 print(" Modified Allowxperm Rules: {0}".format(len(diff.modified_allowxperms))) 523 524 for rule, added_perms, removed_perms, matched_perms in sorted( 525 diff.modified_allowxperms, key=lambda x: x.rule): 526 527 # Process the string representation of the sets 528 # so hex representation and ranges are preserved. 529 # Check if the perm sets have contents, otherwise 530 # split on empty string will be an empty string. 531 # Add brackets to added and removed permissions 532 # in case there is a range of permissions. 533 perms = [] 534 if matched_perms: 535 for p in str(matched_perms).split(" "): 536 perms.append(p) 537 if added_perms: 538 for p in str(added_perms).split(" "): 539 if '-' in p: 540 perms.append("+[{0}]".format(p)) 541 else: 542 perms.append("+{0}".format(p)) 543 if removed_perms: 544 for p in str(removed_perms).split(" "): 545 if '-' in p: 546 perms.append("-[{0}]".format(p)) 547 else: 548 perms.append("-{0}".format(p)) 549 550 rule_string = \ 551 "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \ 552 format(rule, perms) 553 554 print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} " 555 "{{ {1} }};".format(rule, " ".join(perms))) 556 557 print() 558 559 if all_differences or args.neverallow: 560 if diff.added_neverallows or diff.removed_neverallows or diff.modified_neverallows or \ 561 args.neverallow: 562 print("Neverallow Rules ({0} Added, {1} Removed, {2} Modified)".format( 563 len(diff.added_neverallows), len(diff.removed_neverallows), 564 len(diff.modified_neverallows))) 565 566 if diff.added_neverallows and not args.stats: 567 print(" Added Neverallow Rules: {0}".format(len(diff.added_neverallows))) 568 for r in sorted(diff.added_neverallows): 569 print(" + {0}".format(r)) 570 571 if diff.removed_neverallows and not args.stats: 572 print(" Removed Neverallow Rules: {0}".format(len(diff.removed_neverallows))) 573 for r in sorted(diff.removed_neverallows): 574 print(" - {0}".format(r)) 575 576 if diff.modified_neverallows and not args.stats: 577 print(" Modified Neverallow Rules: {0}".format(len(diff.modified_neverallows))) 578 579 for rule, added_perms, removed_perms, matched_perms in sorted( 580 diff.modified_neverallows, key=lambda x: x.rule): 581 perms = " ".join(chain((p for p in matched_perms), 582 ("+" + p for p in added_perms), 583 ("-" + p for p in removed_perms))) 584 rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format( 585 rule, perms) 586 587 try: 588 rule_string += " [ {0} ]".format(rule.conditional) 589 except AttributeError: 590 pass 591 print(" * {0}".format(rule_string)) 592 593 print() 594 595 if all_differences or args.neverallowxperm: 596 if diff.added_neverallowxperms or diff.removed_neverallowxperms or \ 597 diff.modified_neverallowxperms or args.neverallowxperm: 598 599 print("Neverallowxperm Rules ({0} Added, {1} Removed, {2} Modified)".format( 600 len(diff.added_neverallowxperms), len(diff.removed_neverallowxperms), 601 len(diff.modified_neverallowxperms))) 602 603 if diff.added_neverallowxperms and not args.stats: 604 print(" Added Neverallowxperm Rules: {0}".format( 605 len(diff.added_neverallowxperms))) 606 for r in sorted(diff.added_neverallowxperms): 607 print(" + {0}".format(r)) 608 609 if diff.removed_neverallowxperms and not args.stats: 610 print(" Removed Neverallowxperm Rules: {0}".format( 611 len(diff.removed_neverallowxperms))) 612 for r in sorted(diff.removed_neverallowxperms): 613 print(" - {0}".format(r)) 614 615 if diff.modified_neverallowxperms and not args.stats: 616 print(" Modified Neverallowxperm Rules: {0}".format( 617 len(diff.modified_neverallowxperms))) 618 619 for rule, added_perms, removed_perms, matched_perms in sorted( 620 diff.modified_neverallowxperms, key=lambda x: x.rule): 621 622 # Process the string representation of the sets 623 # so hex representation and ranges are preserved. 624 # Check if the perm sets have contents, otherwise 625 # split on empty string will be an empty string. 626 # Add brackets to added and removed permissions 627 # in case there is a range of permissions. 628 perms = [] 629 if matched_perms: 630 for p in str(matched_perms).split(" "): 631 perms.append(p) 632 if added_perms: 633 for p in str(added_perms).split(" "): 634 if '-' in p: 635 perms.append("+[{0}]".format(p)) 636 else: 637 perms.append("+{0}".format(p)) 638 if removed_perms: 639 for p in str(removed_perms).split(" "): 640 if '-' in p: 641 perms.append("-[{0}]".format(p)) 642 else: 643 perms.append("-{0}".format(p)) 644 645 rule_string = \ 646 "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \ 647 format(rule, perms) 648 649 print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} " 650 "{{ {1} }};".format(rule, " ".join(perms))) 651 652 print() 653 654 if all_differences or args.auditallow: 655 if diff.added_auditallows or diff.removed_auditallows or diff.modified_auditallows or \ 656 args.auditallow: 657 print("Auditallow Rules ({0} Added, {1} Removed, {2} Modified)".format( 658 len(diff.added_auditallows), len(diff.removed_auditallows), 659 len(diff.modified_auditallows))) 660 661 if diff.added_auditallows and not args.stats: 662 print(" Added Auditallow Rules: {0}".format(len(diff.added_auditallows))) 663 for r in sorted(diff.added_auditallows): 664 print(" + {0}".format(r)) 665 666 if diff.removed_auditallows and not args.stats: 667 print(" Removed Auditallow Rules: {0}".format(len(diff.removed_auditallows))) 668 for r in sorted(diff.removed_auditallows): 669 print(" - {0}".format(r)) 670 671 if diff.modified_auditallows and not args.stats: 672 print(" Modified Auditallow Rules: {0}".format(len(diff.modified_auditallows))) 673 674 for rule, added_perms, removed_perms, matched_perms in sorted( 675 diff.modified_auditallows, key=lambda x: x.rule): 676 perms = " ".join(chain((p for p in matched_perms), 677 ("+" + p for p in added_perms), 678 ("-" + p for p in removed_perms))) 679 rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format( 680 rule, perms) 681 682 try: 683 rule_string += " [ {0} ]".format(rule.conditional) 684 except AttributeError: 685 pass 686 print(" * {0}".format(rule_string)) 687 688 print() 689 690 if all_differences or args.auditallowxperm: 691 if diff.added_auditallowxperms or diff.removed_auditallowxperms or \ 692 diff.modified_auditallowxperms or args.auditallowxperm: 693 694 print("Auditallowxperm Rules ({0} Added, {1} Removed, {2} Modified)".format( 695 len(diff.added_auditallowxperms), len(diff.removed_auditallowxperms), 696 len(diff.modified_auditallowxperms))) 697 698 if diff.added_auditallowxperms and not args.stats: 699 print(" Added Auditallowxperm Rules: {0}".format( 700 len(diff.added_auditallowxperms))) 701 for r in sorted(diff.added_auditallowxperms): 702 print(" + {0}".format(r)) 703 704 if diff.removed_auditallowxperms and not args.stats: 705 print(" Removed Auditallowxperm Rules: {0}".format( 706 len(diff.removed_auditallowxperms))) 707 for r in sorted(diff.removed_auditallowxperms): 708 print(" - {0}".format(r)) 709 710 if diff.modified_auditallowxperms and not args.stats: 711 print(" Modified Auditallowxperm Rules: {0}".format( 712 len(diff.modified_auditallowxperms))) 713 714 for rule, added_perms, removed_perms, matched_perms in sorted( 715 diff.modified_auditallowxperms, key=lambda x: x.rule): 716 717 # Process the string representation of the sets 718 # so hex representation and ranges are preserved. 719 # Check if the perm sets have contents, otherwise 720 # split on empty string will be an empty string. 721 # Add brackets to added and removed permissions 722 # in case there is a range of permissions. 723 perms = [] 724 if matched_perms: 725 for p in str(matched_perms).split(" "): 726 perms.append(p) 727 if added_perms: 728 for p in str(added_perms).split(" "): 729 if '-' in p: 730 perms.append("+[{0}]".format(p)) 731 else: 732 perms.append("+{0}".format(p)) 733 if removed_perms: 734 for p in str(removed_perms).split(" "): 735 if '-' in p: 736 perms.append("-[{0}]".format(p)) 737 else: 738 perms.append("-{0}".format(p)) 739 740 rule_string = \ 741 "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \ 742 format(rule, perms) 743 744 print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} " 745 "{{ {1} }};".format(rule, " ".join(perms))) 746 747 print() 748 749 if all_differences or args.dontaudit: 750 if diff.added_dontaudits or diff.removed_dontaudits or diff.modified_dontaudits or \ 751 args.dontaudit: 752 print("Dontaudit Rules ({0} Added, {1} Removed, {2} Modified)".format( 753 len(diff.added_dontaudits), len(diff.removed_dontaudits), 754 len(diff.modified_dontaudits))) 755 756 if diff.added_dontaudits and not args.stats: 757 print(" Added Dontaudit Rules: {0}".format(len(diff.added_dontaudits))) 758 for r in sorted(diff.added_dontaudits): 759 print(" + {0}".format(r)) 760 761 if diff.removed_dontaudits and not args.stats: 762 print(" Removed Dontaudit Rules: {0}".format(len(diff.removed_dontaudits))) 763 for r in sorted(diff.removed_dontaudits): 764 print(" - {0}".format(r)) 765 766 if diff.modified_dontaudits and not args.stats: 767 print(" Modified Dontaudit Rules: {0}".format(len(diff.modified_dontaudits))) 768 769 for rule, added_perms, removed_perms, matched_perms in sorted( 770 diff.modified_dontaudits, key=lambda x: x.rule): 771 perms = " ".join(chain((p for p in matched_perms), 772 ("+" + p for p in added_perms), 773 ("-" + p for p in removed_perms))) 774 rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format( 775 rule, perms) 776 777 try: 778 rule_string += " [ {0} ]".format(rule.conditional) 779 except AttributeError: 780 pass 781 print(" * {0}".format(rule_string)) 782 783 print() 784 785 if all_differences or args.dontauditxperm: 786 if diff.added_dontauditxperms or diff.removed_dontauditxperms or \ 787 diff.modified_dontauditxperms or args.dontauditxperm: 788 789 print("Dontauditxperm Rules ({0} Added, {1} Removed, {2} Modified)".format( 790 len(diff.added_dontauditxperms), len(diff.removed_dontauditxperms), 791 len(diff.modified_dontauditxperms))) 792 793 if diff.added_dontauditxperms and not args.stats: 794 print(" Added Dontauditxperm Rules: {0}".format( 795 len(diff.added_dontauditxperms))) 796 for r in sorted(diff.added_dontauditxperms): 797 print(" + {0}".format(r)) 798 799 if diff.removed_dontauditxperms and not args.stats: 800 print(" Removed Dontauditxperm Rules: {0}".format( 801 len(diff.removed_dontauditxperms))) 802 for r in sorted(diff.removed_dontauditxperms): 803 print(" - {0}".format(r)) 804 805 if diff.modified_dontauditxperms and not args.stats: 806 print(" Modified Dontauditxperm Rules: {0}".format( 807 len(diff.modified_dontauditxperms))) 808 809 for rule, added_perms, removed_perms, matched_perms in sorted( 810 diff.modified_dontauditxperms, key=lambda x: x.rule): 811 812 # Process the string representation of the sets 813 # so hex representation and ranges are preserved. 814 # Check if the perm sets have contents, otherwise 815 # split on empty string will be an empty string. 816 # Add brackets to added and removed permissions 817 # in case there is a range of permissions. 818 perms = [] 819 if matched_perms: 820 for p in str(matched_perms).split(" "): 821 perms.append(p) 822 if added_perms: 823 for p in str(added_perms).split(" "): 824 if '-' in p: 825 perms.append("+[{0}]".format(p)) 826 else: 827 perms.append("+{0}".format(p)) 828 if removed_perms: 829 for p in str(removed_perms).split(" "): 830 if '-' in p: 831 perms.append("-[{0}]".format(p)) 832 else: 833 perms.append("-{0}".format(p)) 834 835 rule_string = \ 836 "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \ 837 format(rule, perms) 838 839 print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} " 840 "{{ {1} }};".format(rule, " ".join(perms))) 841 842 print() 843 844 if all_differences or args.type_trans: 845 if diff.added_type_transitions or diff.removed_type_transitions or \ 846 diff.modified_type_transitions or args.type_trans: 847 print("Type_transition Rules ({0} Added, {1} Removed, {2} Modified)".format( 848 len(diff.added_type_transitions), len(diff.removed_type_transitions), 849 len(diff.modified_type_transitions))) 850 851 if diff.added_type_transitions and not args.stats: 852 print(" Added Type_transition Rules: {0}".format( 853 len(diff.added_type_transitions))) 854 for r in sorted(diff.added_type_transitions): 855 print(" + {0}".format(r)) 856 857 if diff.removed_type_transitions and not args.stats: 858 print(" Removed Type_transition Rules: {0}".format( 859 len(diff.removed_type_transitions))) 860 for r in sorted(diff.removed_type_transitions): 861 print(" - {0}".format(r)) 862 863 if diff.modified_type_transitions and not args.stats: 864 print(" Modified Type_transition Rules: {0}".format( 865 len(diff.modified_type_transitions))) 866 867 for rule, added_default, removed_default in sorted(diff.modified_type_transitions, 868 key=lambda x: x.rule): 869 rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format( 870 rule, added_default, removed_default) 871 872 try: 873 rule_string += " {0}".format(rule.filename) 874 except AttributeError: 875 pass 876 877 rule_string += ";" 878 879 try: 880 rule_string += " [ {0} ]".format(rule.conditional) 881 except AttributeError: 882 pass 883 884 print(" * {0}".format(rule_string)) 885 886 print() 887 888 if all_differences or args.type_change: 889 if diff.added_type_changes or diff.removed_type_changes or \ 890 diff.modified_type_changes or args.type_change: 891 print("Type_change Rules ({0} Added, {1} Removed, {2} Modified)".format( 892 len(diff.added_type_changes), len(diff.removed_type_changes), 893 len(diff.modified_type_changes))) 894 895 if diff.added_type_changes and not args.stats: 896 print(" Added Type_change Rules: {0}".format(len(diff.added_type_changes))) 897 for r in sorted(diff.added_type_changes): 898 print(" + {0}".format(r)) 899 900 if diff.removed_type_changes and not args.stats: 901 print(" Removed Type_change Rules: {0}".format(len(diff.removed_type_changes))) 902 for r in sorted(diff.removed_type_changes): 903 print(" - {0}".format(r)) 904 905 if diff.modified_type_changes and not args.stats: 906 print(" Modified Type_change Rules: {0}".format(len(diff.modified_type_changes))) 907 908 for rule, added_default, removed_default in sorted(diff.modified_type_changes, 909 key=lambda x: x.rule): 910 rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format( 911 rule, added_default, removed_default) 912 913 try: 914 rule_string += " {0}".format(rule.filename) 915 except AttributeError: 916 pass 917 918 rule_string += ";" 919 920 try: 921 rule_string += " [ {0} ]".format(rule.conditional) 922 except AttributeError: 923 pass 924 925 print(" * {0}".format(rule_string)) 926 927 print() 928 929 if all_differences or args.type_member: 930 if diff.added_type_members or diff.removed_type_members or \ 931 diff.modified_type_members or args.type_member: 932 print("Type_member Rules ({0} Added, {1} Removed, {2} Modified)".format( 933 len(diff.added_type_members), len(diff.removed_type_members), 934 len(diff.modified_type_members))) 935 936 if diff.added_type_members and not args.stats: 937 print(" Added Type_member Rules: {0}".format(len(diff.added_type_members))) 938 for r in sorted(diff.added_type_members): 939 print(" + {0}".format(r)) 940 941 if diff.removed_type_members and not args.stats: 942 print(" Removed Type_member Rules: {0}".format(len(diff.removed_type_members))) 943 for r in sorted(diff.removed_type_members): 944 print(" - {0}".format(r)) 945 946 if diff.modified_type_members and not args.stats: 947 print(" Modified Type_member Rules: {0}".format(len(diff.modified_type_members))) 948 949 for rule, added_default, removed_default in sorted(diff.modified_type_members, 950 key=lambda x: x.rule): 951 rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format( 952 rule, added_default, removed_default) 953 954 try: 955 rule_string += " {0}".format(rule.filename) 956 except AttributeError: 957 pass 958 959 rule_string += ";" 960 961 try: 962 rule_string += " [ {0} ]".format(rule.conditional) 963 except AttributeError: 964 pass 965 966 print(" * {0}".format(rule_string)) 967 968 print() 969 970 if all_differences or args.role_allow: 971 if diff.added_role_allows or diff.removed_role_allows or args.role_allow: 972 print("Role allow Rules ({0} Added, {1} Removed)".format( 973 len(diff.added_role_allows), len(diff.removed_role_allows))) 974 975 if diff.added_role_allows and not args.stats: 976 print(" Added Role Allow Rules: {0}".format( 977 len(diff.added_role_allows))) 978 for r in sorted(diff.added_role_allows): 979 print(" + {0}".format(r)) 980 981 if diff.removed_role_allows and not args.stats: 982 print(" Removed Role Allow Rules: {0}".format( 983 len(diff.removed_role_allows))) 984 for r in sorted(diff.removed_role_allows): 985 print(" - {0}".format(r)) 986 987 print() 988 989 if all_differences or args.role_trans: 990 if diff.added_role_transitions or diff.removed_role_transitions or \ 991 diff.modified_role_transitions or args.role_trans: 992 print("Role_transition Rules ({0} Added, {1} Removed, {2} Modified)".format( 993 len(diff.added_role_transitions), len(diff.removed_role_transitions), 994 len(diff.modified_role_transitions))) 995 996 if diff.added_role_transitions and not args.stats: 997 print(" Added Role_transition Rules: {0}".format( 998 len(diff.added_role_transitions))) 999 for r in sorted(diff.added_role_transitions): 1000 print(" + {0}".format(r)) 1001 1002 if diff.removed_role_transitions and not args.stats: 1003 print(" Removed Role_transition Rules: {0}".format( 1004 len(diff.removed_role_transitions))) 1005 for r in sorted(diff.removed_role_transitions): 1006 print(" - {0}".format(r)) 1007 1008 if diff.modified_role_transitions and not args.stats: 1009 print(" Modified Role_transition Rules: {0}".format( 1010 len(diff.modified_role_transitions))) 1011 1012 for rule, added_default, removed_default in sorted(diff.modified_role_transitions, 1013 key=lambda x: x.rule): 1014 rule_string = \ 1015 "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format( 1016 rule, added_default, removed_default) 1017 1018 print(" * {0}".format(rule_string)) 1019 1020 print() 1021 1022 if all_differences or args.range_trans: 1023 if diff.added_range_transitions or diff.removed_range_transitions or \ 1024 diff.modified_range_transitions or args.range_trans: 1025 print("Range_transition Rules ({0} Added, {1} Removed, {2} Modified)".format( 1026 len(diff.added_range_transitions), len(diff.removed_range_transitions), 1027 len(diff.modified_range_transitions))) 1028 1029 if diff.added_range_transitions and not args.stats: 1030 print(" Added Range_transition Rules: {0}".format( 1031 len(diff.added_range_transitions))) 1032 for r in sorted(diff.added_range_transitions): 1033 print(" + {0}".format(r)) 1034 1035 if diff.removed_range_transitions and not args.stats: 1036 print(" Removed Range_transition Rules: {0}".format( 1037 len(diff.removed_range_transitions))) 1038 for r in sorted(diff.removed_range_transitions): 1039 print(" - {0}".format(r)) 1040 1041 if diff.modified_range_transitions and not args.stats: 1042 print(" Modified Range_transition Rules: {0}".format( 1043 len(diff.modified_range_transitions))) 1044 1045 for rule, added_default, removed_default in sorted(diff.modified_range_transitions, 1046 key=lambda x: x.rule): 1047 # added brackets around range change for clarity since ranges 1048 # can have '-' and spaces. 1049 rule_string = \ 1050 "{0.ruletype} {0.source} {0.target}:{0.tclass} +[{1}] -[{2}]".format( 1051 rule, added_default, removed_default) 1052 1053 print(" * {0}".format(rule_string)) 1054 1055 print() 1056 1057 if all_differences or args.constrain: 1058 if diff.added_constrains or diff.removed_constrains or args.constrain: 1059 print("Constraints ({0} Added, {1} Removed)".format( 1060 len(diff.added_constrains), len(diff.removed_constrains))) 1061 1062 if diff.added_constrains and not args.stats: 1063 print(" Added Constraints: {0}".format( 1064 len(diff.added_constrains))) 1065 for r in sorted(diff.added_constrains): 1066 print(" + {0}".format(r)) 1067 1068 if diff.removed_constrains and not args.stats: 1069 print(" Removed Constraints: {0}".format( 1070 len(diff.removed_constrains))) 1071 for r in sorted(diff.removed_constrains): 1072 print(" - {0}".format(r)) 1073 1074 print() 1075 1076 if all_differences or args.mlsconstrain: 1077 if diff.added_mlsconstrains or diff.removed_mlsconstrains or args.mlsconstrain: 1078 print("MLS Constraints ({0} Added, {1} Removed)".format( 1079 len(diff.added_mlsconstrains), len(diff.removed_mlsconstrains))) 1080 1081 if diff.added_mlsconstrains and not args.stats: 1082 print(" Added MLS Constraints: {0}".format( 1083 len(diff.added_mlsconstrains))) 1084 for r in sorted(diff.added_mlsconstrains): 1085 print(" + {0}".format(r)) 1086 1087 if diff.removed_mlsconstrains and not args.stats: 1088 print(" Removed MLS Constraints: {0}".format( 1089 len(diff.removed_mlsconstrains))) 1090 for r in sorted(diff.removed_mlsconstrains): 1091 print(" - {0}".format(r)) 1092 1093 print() 1094 1095 if all_differences or args.validatetrans: 1096 if diff.added_validatetrans or diff.removed_validatetrans or args.validatetrans: 1097 print("Validatetrans ({0} Added, {1} Removed)".format( 1098 len(diff.added_validatetrans), len(diff.removed_validatetrans))) 1099 1100 if diff.added_validatetrans and not args.stats: 1101 print(" Added Validatetrans: {0}".format( 1102 len(diff.added_validatetrans))) 1103 for r in sorted(diff.added_validatetrans): 1104 print(" + {0}".format(r)) 1105 1106 if diff.removed_validatetrans and not args.stats: 1107 print(" Removed Validatetrans: {0}".format( 1108 len(diff.removed_validatetrans))) 1109 for r in sorted(diff.removed_validatetrans): 1110 print(" - {0}".format(r)) 1111 1112 print() 1113 1114 if all_differences or args.mlsvalidatetrans: 1115 if diff.added_mlsvalidatetrans or diff.removed_mlsvalidatetrans or args.mlsvalidatetrans: 1116 print("MLS Validatetrans ({0} Added, {1} Removed)".format( 1117 len(diff.added_mlsvalidatetrans), len(diff.removed_mlsvalidatetrans))) 1118 1119 if diff.added_mlsvalidatetrans and not args.stats: 1120 print(" Added MLS Validatetrans: {0}".format( 1121 len(diff.added_mlsvalidatetrans))) 1122 for r in sorted(diff.added_mlsvalidatetrans): 1123 print(" + {0}".format(r)) 1124 1125 if diff.removed_mlsvalidatetrans and not args.stats: 1126 print(" Removed MLS Validatetrans: {0}".format( 1127 len(diff.removed_mlsvalidatetrans))) 1128 for r in sorted(diff.removed_mlsvalidatetrans): 1129 print(" - {0}".format(r)) 1130 1131 print() 1132 1133 if all_differences or args.initialsid: 1134 if diff.added_initialsids or diff.removed_initialsids or diff.modified_initialsids \ 1135 or args.initialsid: 1136 print("Initial SIDs ({0} Added, {1} Removed, {2} Modified)".format( 1137 len(diff.added_initialsids), len(diff.removed_initialsids), 1138 len(diff.modified_initialsids))) 1139 if diff.added_initialsids and not args.stats: 1140 print(" Added Initial SIDs: {0}".format(len(diff.added_initialsids))) 1141 for s in sorted(diff.added_initialsids): 1142 print(" + {0}".format(s.statement())) 1143 if diff.removed_initialsids and not args.stats: 1144 print(" Removed Initial SIDs: {0}".format(len(diff.removed_initialsids))) 1145 for s in sorted(diff.removed_initialsids): 1146 print(" - {0}".format(s.statement())) 1147 if diff.modified_initialsids and not args.stats: 1148 print(" Modified Initial SIDs: {0}".format(len(diff.modified_initialsids))) 1149 for name, mod in sorted(diff.modified_initialsids.items()): 1150 print(" * {0} +[{1.added_context}] -[{1.removed_context}];".format( 1151 name, mod)) 1152 1153 print() 1154 1155 if all_differences or args.fs_use: 1156 if diff.added_fs_uses or diff.removed_fs_uses or diff.modified_fs_uses \ 1157 or args.fs_use: 1158 print("Fs_use ({0} Added, {1} Removed, {2} Modified)".format( 1159 len(diff.added_fs_uses), len(diff.removed_fs_uses), 1160 len(diff.modified_fs_uses))) 1161 if diff.added_fs_uses and not args.stats: 1162 print(" Added Fs_use: {0}".format(len(diff.added_fs_uses))) 1163 for s in sorted(diff.added_fs_uses): 1164 print(" + {0}".format(s)) 1165 if diff.removed_fs_uses and not args.stats: 1166 print(" Removed Fs_use: {0}".format(len(diff.removed_fs_uses))) 1167 for s in sorted(diff.removed_fs_uses): 1168 print(" - {0}".format(s)) 1169 if diff.modified_fs_uses and not args.stats: 1170 print(" Modified Fs_use: {0}".format(len(diff.modified_fs_uses))) 1171 for entry in sorted(diff.modified_fs_uses, key=lambda x: x.rule): 1172 print(" * {0.ruletype} {0.fs} +[{1}] -[{2}];".format( 1173 entry.rule, entry.added_context, entry.removed_context)) 1174 1175 print() 1176 1177 if all_differences or args.genfscon: 1178 if diff.added_genfscons or diff.removed_genfscons or diff.modified_genfscons \ 1179 or args.genfscon: 1180 print("Genfscons ({0} Added, {1} Removed, {2} Modified)".format( 1181 len(diff.added_genfscons), len(diff.removed_genfscons), 1182 len(diff.modified_genfscons))) 1183 if diff.added_genfscons and not args.stats: 1184 print(" Added Genfscons: {0}".format(len(diff.added_genfscons))) 1185 for s in sorted(diff.added_genfscons): 1186 print(" + {0}".format(s)) 1187 if diff.removed_genfscons and not args.stats: 1188 print(" Removed Genfscons: {0}".format(len(diff.removed_genfscons))) 1189 for s in sorted(diff.removed_genfscons): 1190 print(" - {0}".format(s)) 1191 if diff.modified_genfscons and not args.stats: 1192 print(" Modified Genfscons: {0}".format(len(diff.modified_genfscons))) 1193 for entry in sorted(diff.modified_genfscons, key=lambda x: x.rule): 1194 print(" * genfscon {0.fs} {0.path} {0.filetype} +[{1}] -[{2}];".format( 1195 entry.rule, entry.added_context, entry.removed_context)) 1196 1197 print() 1198 1199 if all_differences or args.netifcon: 1200 if diff.added_netifcons or diff.removed_netifcons or \ 1201 diff.modified_netifcons or args.netifcon: 1202 print("Netifcons ({0} Added, {1} Removed, {2} Modified)".format( 1203 len(diff.added_netifcons), len(diff.removed_netifcons), 1204 len(diff.modified_netifcons))) 1205 if diff.added_netifcons and not args.stats: 1206 print(" Added Netifcons: {0}".format(len(diff.added_netifcons))) 1207 for n in sorted(diff.added_netifcons): 1208 print(" + {0}".format(n)) 1209 if diff.removed_netifcons and not args.stats: 1210 print(" Removed Netifcons: {0}".format(len(diff.removed_netifcons))) 1211 for n in sorted(diff.removed_netifcons): 1212 print(" - {0}".format(n)) 1213 if diff.modified_netifcons and not args.stats: 1214 print(" Modified Netifcons: {0}".format(len(diff.modified_netifcons))) 1215 for entry in sorted(diff.modified_netifcons, key=lambda x: x.rule): 1216 # This output is different than other statements because 1217 # it becomes difficult to read if this was condensed 1218 # into a single line, especially if both contexts 1219 # are modified. 1220 change = [] 1221 if entry.removed_context: 1222 change.append("Modified Context") 1223 if entry.removed_packet: 1224 change.append("Modified Packet Context") 1225 1226 print(" * {0.netif} ({1})".format(entry.rule, ", ".join(change))) 1227 1228 if entry.removed_context: 1229 print(" Context:") 1230 print(" + {0}".format(entry.added_context)) 1231 print(" - {0}".format(entry.removed_context)) 1232 if entry.removed_packet: 1233 print(" Packet Context:") 1234 print(" + {0}".format(entry.added_packet)) 1235 print(" - {0}".format(entry.removed_packet)) 1236 1237 print() 1238 1239 if all_differences or args.nodecon: 1240 if diff.added_nodecons or diff.removed_nodecons or diff.modified_nodecons \ 1241 or args.nodecon: 1242 print("Nodecons ({0} Added, {1} Removed, {2} Modified)".format( 1243 len(diff.added_nodecons), len(diff.removed_nodecons), 1244 len(diff.modified_nodecons))) 1245 if diff.added_nodecons and not args.stats: 1246 print(" Added Nodecons: {0}".format(len(diff.added_nodecons))) 1247 for n in sorted(diff.added_nodecons): 1248 print(" + {0}".format(n)) 1249 if diff.removed_nodecons and not args.stats: 1250 print(" Removed Nodecons: {0}".format(len(diff.removed_nodecons))) 1251 for n in sorted(diff.removed_nodecons): 1252 print(" - {0}".format(n)) 1253 if diff.modified_nodecons and not args.stats: 1254 print(" Modified Nodecons: {0}".format(len(diff.modified_nodecons))) 1255 for con, added_context, removed_context in sorted(diff.modified_nodecons, 1256 key=lambda x: x.rule): 1257 print(" * nodecon {0.address} {0.netmask} +[{1}] -[{2}];".format( 1258 con, added_context, removed_context)) 1259 1260 print() 1261 1262 if all_differences or args.portcon: 1263 if diff.added_portcons or diff.removed_portcons or diff.modified_portcons \ 1264 or args.portcon: 1265 print("Portcons ({0} Added, {1} Removed, {2} Modified)".format( 1266 len(diff.added_portcons), len(diff.removed_portcons), 1267 len(diff.modified_portcons))) 1268 if diff.added_portcons and not args.stats: 1269 print(" Added Portcons: {0}".format(len(diff.added_portcons))) 1270 for n in sorted(diff.added_portcons): 1271 print(" + {0}".format(n)) 1272 if diff.removed_portcons and not args.stats: 1273 print(" Removed Portcons: {0}".format(len(diff.removed_portcons))) 1274 for n in sorted(diff.removed_portcons): 1275 print(" - {0}".format(n)) 1276 if diff.modified_portcons and not args.stats: 1277 print(" Modified Portcons: {0}".format(len(diff.modified_portcons))) 1278 for con, added_context, removed_context in sorted(diff.modified_portcons, 1279 key=lambda x: x.rule): 1280 low, high = con.ports 1281 if low == high: 1282 print(" * portcon {0.protocol} {1} +[{2}] -[{3}];".format( 1283 con, low, added_context, removed_context)) 1284 else: 1285 print(" * portcon {0.protocol} {1}-{2} +[{3}] -[{4}];".format( 1286 con, low, high, added_context, removed_context)) 1287 1288 print() 1289 1290 if all_differences or args.polcap: 1291 if diff.added_polcaps or diff.removed_polcaps or args.polcap: 1292 print("Policy Capabilities ({0} Added, {1} Removed)".format( 1293 len(diff.added_polcaps), len(diff.removed_polcaps))) 1294 if diff.added_polcaps and not args.stats: 1295 print(" Added Policy Capabilities: {0}".format(len(diff.added_polcaps))) 1296 for n in sorted(diff.added_polcaps): 1297 print(" + {0}".format(n)) 1298 if diff.removed_polcaps and not args.stats: 1299 print(" Removed Policy Capabilities: {0}".format(len(diff.removed_polcaps))) 1300 for n in sorted(diff.removed_polcaps): 1301 print(" - {0}".format(n)) 1302 1303 print() 1304 1305 if all_differences or args.default: 1306 if diff.added_defaults or diff.removed_defaults or args.default: 1307 print("Defaults ({0} Added, {1} Removed, {2} Modified)".format( 1308 len(diff.added_defaults), len(diff.removed_defaults), len(diff.modified_defaults))) 1309 if diff.added_defaults and not args.stats: 1310 print(" Added Defaults: {0}".format(len(diff.added_defaults))) 1311 for d in sorted(diff.added_defaults): 1312 print(" + {0}".format(d)) 1313 if diff.removed_defaults and not args.stats: 1314 print(" Removed Defaults: {0}".format(len(diff.removed_defaults))) 1315 for d in sorted(diff.removed_defaults): 1316 print(" - {0}".format(d)) 1317 if diff.modified_defaults and not args.stats: 1318 print(" Modified Defaults: {0}".format(len(diff.modified_defaults))) 1319 for default, added_default, removed_default, added_range, removed_range in sorted( 1320 diff.modified_defaults, key=lambda x: x.rule): 1321 line = " * {0.ruletype} {0.tclass} ".format(default) 1322 if removed_default: 1323 line += "+{0} -{1}".format(added_default, removed_default) 1324 else: 1325 line += default.default 1326 1327 if removed_range: 1328 line += " +{0} -{1};".format(added_range, removed_range) 1329 else: 1330 try: 1331 line += " {0};".format(default.default_range) 1332 except AttributeError: 1333 line += ";" 1334 print(line) 1335 1336 print() 1337 1338 if all_differences or args.typebounds: 1339 if diff.added_typebounds or diff.removed_typebounds or args.typebounds: 1340 print("Typebounds ({0} Added, {1} Removed, {2} Modified)".format( 1341 len(diff.added_typebounds), len(diff.removed_typebounds), 1342 len(diff.modified_typebounds))) 1343 if diff.added_typebounds and not args.stats: 1344 print(" Added Typebounds: {0}".format(len(diff.added_typebounds))) 1345 for d in sorted(diff.added_typebounds): 1346 print(" + {0}".format(d)) 1347 if diff.removed_typebounds and not args.stats: 1348 print(" Removed Typebounds: {0}".format(len(diff.removed_typebounds))) 1349 for d in sorted(diff.removed_typebounds): 1350 print(" - {0}".format(d)) 1351 if diff.modified_typebounds and not args.stats: 1352 print(" Modified Typebounds: {0}".format(len(diff.modified_typebounds))) 1353 for bound, added_bound, removed_bound in sorted( 1354 diff.modified_typebounds, key=lambda x: x.rule): 1355 print(" * {0.ruletype} +{1} -{2} {0.child};".format( 1356 bound, added_bound, removed_bound)) 1357 1358 print() 1359 1360except Exception as err: 1361 if args.debug: 1362 logging.exception(str(err)) 1363 else: 1364 print(err) 1365 1366 sys.exit(1) 1367