1#!/usr/bin/python 2 3# Author: Dan Walsh <dwalsh@redhat.com> 4# Author: Ryan Hallisey <rhallise@redhat.com> 5 6import _policy 7import selinux 8import glob 9PROGNAME = "policycoreutils" 10import gettext 11import sepolgen.defaults as defaults 12import sepolgen.interfaces as interfaces 13import sys 14gettext.bindtextdomain(PROGNAME, "/usr/share/locale") 15gettext.textdomain(PROGNAME) 16try: 17 gettext.install(PROGNAME, 18 localedir="/usr/share/locale", 19 unicode=False, 20 codeset='utf-8') 21except IOError: 22 import __builtin__ 23 __builtin__.__dict__['_'] = unicode 24 25TYPE = _policy.TYPE 26ROLE = _policy.ROLE 27ATTRIBUTE = _policy.ATTRIBUTE 28PORT = _policy.PORT 29USER = _policy.USER 30BOOLEAN = _policy.BOOLEAN 31TCLASS = _policy.CLASS 32 33ALLOW = 'allow' 34AUDITALLOW = 'auditallow' 35NEVERALLOW = 'neverallow' 36DONTAUDIT = 'dontaudit' 37SOURCE = 'source' 38TARGET = 'target' 39PERMS = 'permlist' 40CLASS = 'class' 41TRANSITION = 'transition' 42ROLE_ALLOW = 'role_allow' 43 44 45def info(setype, name=None): 46 dict_list = _policy.info(setype, name) 47 return dict_list 48 49 50def search(types, info={}): 51 seinfo = info 52 valid_types = [ALLOW, AUDITALLOW, NEVERALLOW, DONTAUDIT, TRANSITION, ROLE_ALLOW] 53 for setype in types: 54 if setype not in valid_types: 55 raise ValueError("Type has to be in %s" % valid_types) 56 seinfo[setype] = True 57 58 perms = [] 59 if PERMS in seinfo: 60 perms = info[PERMS] 61 seinfo[PERMS] = ",".join(seinfo[PERMS]) 62 63 dict_list = _policy.search(seinfo) 64 if dict_list and len(perms) != 0: 65 dict_list = filter(lambda x: _dict_has_perms(x, perms), dict_list) 66 return dict_list 67 68 69def get_conditionals(src, dest, tclass, perm): 70 tdict = {} 71 tlist = [] 72 if dest.endswith("_t"): 73 allows = search([ALLOW], {SOURCE: src, TARGET: dest, CLASS: tclass, PERMS: perm}) 74 else: 75 # to include attribute 76 allows = search([ALLOW], {SOURCE: src, CLASS: tclass, PERMS: perm}) 77 for i in allows: 78 if i['target'] == dest: 79 allows = [] 80 allows.append(i) 81 try: 82 for i in map(lambda y: (y), filter(lambda x: set(perm).issubset(x[PERMS]) and x['boolean'], allows)): 83 tdict.update({'source': i['source'], 'boolean': i['boolean']}) 84 if tdict not in tlist: 85 tlist.append(tdict) 86 tdict = {} 87 except KeyError: 88 return(tlist) 89 90 return (tlist) 91 92 93def get_conditionals_format_text(cond): 94 enabled = len(filter(lambda x: x['boolean'][0][1], cond)) > 0 95 return _("-- Allowed %s [ %s ]") % (enabled, " || ".join(set(map(lambda x: "%s=%d" % (x['boolean'][0][0], x['boolean'][0][1]), cond)))) 96 97 98def get_types_from_attribute(attribute): 99 return info(ATTRIBUTE, attribute)[0]["types"] 100 101file_type_str = {} 102file_type_str["a"] = _("all files") 103file_type_str["f"] = _("regular file") 104file_type_str["d"] = _("directory") 105file_type_str["c"] = _("character device") 106file_type_str["b"] = _("block device") 107file_type_str["s"] = _("socket file") 108file_type_str["l"] = _("symbolic link") 109file_type_str["p"] = _("named pipe") 110 111trans_file_type_str = {} 112trans_file_type_str[""] = "a" 113trans_file_type_str["--"] = "f" 114trans_file_type_str["-d"] = "d" 115trans_file_type_str["-c"] = "c" 116trans_file_type_str["-b"] = "b" 117trans_file_type_str["-s"] = "s" 118trans_file_type_str["-l"] = "l" 119trans_file_type_str["-p"] = "p" 120 121 122def get_file_types(setype): 123 flist = [] 124 mpaths = {} 125 for f in get_all_file_types(): 126 if f.startswith(gen_short_name(setype)): 127 flist.append(f) 128 fcdict = get_fcdict() 129 for f in flist: 130 try: 131 mpaths[f] = (fcdict[f]["regex"], file_type_str[fcdict[f]["ftype"]]) 132 except KeyError: 133 mpaths[f] = [] 134 return mpaths 135 136 137def get_writable_files(setype): 138 all_attributes = get_all_attributes() 139 file_types = get_all_file_types() 140 all_writes = [] 141 mpaths = {} 142 permlist = search([ALLOW], {'source': setype, 'permlist': ['open', 'write'], 'class': 'file'}) 143 if permlist == None or len(permlist) == 0: 144 return mpaths 145 146 fcdict = get_fcdict() 147 148 attributes = ["proc_type", "sysctl_type"] 149 for i in permlist: 150 if i['target'] in attributes: 151 continue 152 if "enabled" in i: 153 if not i["enabled"]: 154 continue 155 if i['target'].endswith("_t"): 156 if i['target'] not in file_types: 157 continue 158 if i['target'] not in all_writes: 159 if i['target'] != setype: 160 all_writes.append(i['target']) 161 else: 162 for t in get_types_from_attribute(i['target']): 163 if t not in all_writes: 164 all_writes.append(t) 165 166 for f in all_writes: 167 try: 168 mpaths[f] = (fcdict[f]["regex"], file_type_str[fcdict[f]["ftype"]]) 169 except KeyError: 170 mpaths[f] = [] # {"regex":[],"paths":[]} 171 return mpaths 172 173import os 174import re 175import sys 176 177 178def find_file(reg): 179 if os.path.exists(reg): 180 return [reg] 181 try: 182 pat = re.compile(r"%s$" % reg) 183 except: 184 print "bad reg:", reg 185 return [] 186 p = reg 187 if p.endswith("(/.*)?"): 188 p = p[:-6] + "/" 189 190 path = os.path.dirname(p) 191 192 try: # Bug fix: when "all files on system" 193 if path[-1] != "/": # is pass in it breaks without try block 194 path += "/" 195 except IndexError: 196 print "try failed got an IndexError" 197 pass 198 199 try: 200 pat = re.compile(r"%s$" % reg) 201 return filter(pat.match, map(lambda x: path + x, os.listdir(path))) 202 except: 203 return [] 204 205 206def find_all_files(domain, exclude_list=[]): 207 all_entrypoints = [] 208 executable_files = get_entrypoints(domain) 209 for exe in executable_files.keys(): 210 if exe.endswith("_exec_t") and exe not in exclude_list: 211 for path in executable_files[exe]: 212 for f in find_file(path): 213 return f 214 #all_entrypoints.append(f) 215 return None 216 217#return all_entrypoints 218 219 220def find_entrypoint_path(exe, exclude_list=[]): 221 fcdict = get_fcdict() 222 try: 223 if exe.endswith("_exec_t") and exe not in exclude_list: 224 for path in fcdict[exe]["regex"]: 225 for f in find_file(path): 226 return f 227 except KeyError: 228 pass 229 return None 230 231 232def read_file_equiv(edict, fc_path, modify): 233 fd = open(fc_path, "r") 234 fc = fd.readlines() 235 fd.close() 236 for e in fc: 237 f = e.split() 238 edict[f[0]] = {"equiv": f[1], "modify": modify} 239 return edict 240 241file_equiv_modified = None 242 243 244def get_file_equiv_modified(fc_path=selinux.selinux_file_context_path()): 245 global file_equiv_modified 246 if file_equiv_modified: 247 return file_equiv_modified 248 file_equiv_modified = {} 249 file_equiv_modified = read_file_equiv(file_equiv_modified, fc_path + ".subs", modify=True) 250 return file_equiv_modified 251 252file_equiv = None 253 254 255def get_file_equiv(fc_path=selinux.selinux_file_context_path()): 256 global file_equiv 257 if file_equiv: 258 return file_equiv 259 file_equiv = get_file_equiv_modified(fc_path) 260 file_equiv = read_file_equiv(file_equiv, fc_path + ".subs_dist", modify=False) 261 return file_equiv 262 263local_files = None 264 265 266def get_local_file_paths(fc_path=selinux.selinux_file_context_path()): 267 global local_files 268 if local_files: 269 return local_files 270 local_files = [] 271 fd = open(fc_path + ".local", "r") 272 fc = fd.readlines() 273 fd.close() 274 for i in fc: 275 rec = i.split() 276 if len(rec) == 0: 277 continue 278 try: 279 if len(rec) > 2: 280 ftype = trans_file_type_str[rec[1]] 281 else: 282 ftype = "a" 283 284 local_files.append((rec[0], ftype)) 285 except KeyError: 286 pass 287 return local_files 288 289fcdict = None 290 291 292def get_fcdict(fc_path=selinux.selinux_file_context_path()): 293 global fcdict 294 if fcdict: 295 return fcdict 296 fd = open(fc_path, "r") 297 fc = fd.readlines() 298 fd.close() 299 fd = open(fc_path + ".homedirs", "r") 300 fc += fd.readlines() 301 fd.close() 302 fcdict = {} 303 fd = open(fc_path + ".local", "r") 304 fc += fd.readlines() 305 fd.close() 306 307 for i in fc: 308 rec = i.split() 309 try: 310 if len(rec) > 2: 311 ftype = trans_file_type_str[rec[1]] 312 else: 313 ftype = "a" 314 315 t = rec[-1].split(":")[2] 316 if t in fcdict: 317 fcdict[t]["regex"].append(rec[0]) 318 else: 319 fcdict[t] = {"regex": [rec[0]], "ftype": ftype} 320 except: 321 pass 322 323 fcdict["logfile"] = {"regex": ["all log files"]} 324 fcdict["user_tmp_type"] = {"regex": ["all user tmp files"]} 325 fcdict["user_home_type"] = {"regex": ["all user home files"]} 326 fcdict["virt_image_type"] = {"regex": ["all virtual image files"]} 327 fcdict["noxattrfs"] = {"regex": ["all files on file systems which do not support extended attributes"]} 328 fcdict["sandbox_tmpfs_type"] = {"regex": ["all sandbox content in tmpfs file systems"]} 329 fcdict["user_tmpfs_type"] = {"regex": ["all user content in tmpfs file systems"]} 330 fcdict["file_type"] = {"regex": ["all files on the system"]} 331 fcdict["samba_share_t"] = {"regex": ["use this label for random content that will be shared using samba"]} 332 return fcdict 333 334 335def get_transitions_into(setype): 336 try: 337 return filter(lambda x: x["transtype"] == setype, search([TRANSITION], {'class': 'process'})) 338 except TypeError: 339 pass 340 return None 341 342 343def get_transitions(setype): 344 try: 345 return search([TRANSITION], {'source': setype, 'class': 'process'}) 346 except TypeError: 347 pass 348 return None 349 350 351def get_file_transitions(setype): 352 try: 353 return filter(lambda x: x['class'] != "process", search([TRANSITION], {'source': setype})) 354 except TypeError: 355 pass 356 return None 357 358 359def get_boolean_rules(setype, boolean): 360 boollist = [] 361 permlist = search([ALLOW], {'source': setype}) 362 for p in permlist: 363 if "boolean" in p: 364 try: 365 for b in p["boolean"]: 366 if boolean in b: 367 boollist.append(p) 368 except: 369 pass 370 return boollist 371 372 373def get_all_entrypoints(): 374 return get_types_from_attribute("entry_type") 375 376 377def get_entrypoint_types(setype): 378 entrypoints = [] 379 try: 380 entrypoints = map(lambda x: x['target'], filter(lambda x: x['source'] == setype, search([ALLOW], {'source': setype, 'permlist': ['entrypoint'], 'class': 'file'}))) 381 except TypeError: 382 pass 383 return entrypoints 384 385 386def get_init_transtype(path): 387 entrypoint = selinux.getfilecon(path)[1].split(":")[2] 388 try: 389 entrypoints = filter(lambda x: x['target'] == entrypoint, search([TRANSITION], {'source': "init_t", 'class': 'process'})) 390 if len(entrypoints) == 0: 391 return None 392 return entrypoints[0]["transtype"] 393 except TypeError: 394 pass 395 return None 396 397 398def get_init_entrypoint(transtype): 399 try: 400 entrypoints = filter(lambda x: x['transtype'] == transtype, search([TRANSITION], {'source': "init_t", 'class': 'process'})) 401 if len(entrypoints) == 0: 402 return None 403 return entrypoints[0]["target"] 404 except TypeError: 405 pass 406 return None 407 408 409def get_init_entrypoint_target(entrypoint): 410 try: 411 entrypoints = map(lambda x: x['transtype'], search([TRANSITION], {'source': "init_t", 'target': entrypoint, 'class': 'process'})) 412 return entrypoints[0] 413 except TypeError: 414 pass 415 return None 416 417 418def get_entrypoints(setype): 419 fcdict = get_fcdict() 420 mpaths = {} 421 for f in get_entrypoint_types(setype): 422 try: 423 mpaths[f] = (fcdict[f]["regex"], file_type_str[fcdict[f]["ftype"]]) 424 except KeyError: 425 mpaths[f] = [] 426 return mpaths 427 428 429def get_installed_policy(root="/"): 430 try: 431 path = root + selinux.selinux_binary_policy_path() 432 policies = glob.glob("%s.*" % path) 433 policies.sort() 434 return policies[-1] 435 except: 436 pass 437 raise ValueError(_("No SELinux Policy installed")) 438 439methods = [] 440 441 442def get_methods(): 443 global methods 444 if len(methods) > 0: 445 return methods 446 gen_interfaces() 447 fn = defaults.interface_info() 448 try: 449 fd = open(fn) 450 # List of per_role_template interfaces 451 ifs = interfaces.InterfaceSet() 452 ifs.from_file(fd) 453 methods = ifs.interfaces.keys() 454 fd.close() 455 except: 456 sys.stderr.write("could not open interface info [%s]\n" % fn) 457 sys.exit(1) 458 459 methods.sort() 460 return methods 461 462all_types = None 463 464 465def get_all_types(): 466 global all_types 467 if all_types == None: 468 all_types = map(lambda x: x['name'], info(TYPE)) 469 return all_types 470 471user_types = None 472 473 474def get_user_types(): 475 global user_types 476 if user_types == None: 477 user_types = info(ATTRIBUTE, "userdomain")[0]["types"] 478 return user_types 479 480role_allows = None 481 482 483def get_all_role_allows(): 484 global role_allows 485 if role_allows: 486 return role_allows 487 role_allows = {} 488 for r in search([ROLE_ALLOW]): 489 if r["source"] == "system_r" or r["target"] == "system_r": 490 continue 491 if r["source"] in role_allows: 492 role_allows[r["source"]].append(r["target"]) 493 else: 494 role_allows[r["source"]] = [r["target"]] 495 496 return role_allows 497 498 499def get_all_entrypoint_domains(): 500 import re 501 all_domains = [] 502 types = get_all_types() 503 types.sort() 504 for i in types: 505 m = re.findall("(.*)%s" % "_exec_t$", i) 506 if len(m) > 0: 507 if len(re.findall("(.*)%s" % "_initrc$", m[0])) == 0 and m[0] not in all_domains: 508 all_domains.append(m[0]) 509 return all_domains 510 511portrecs = None 512portrecsbynum = None 513 514 515def gen_interfaces(): 516 import commands 517 ifile = defaults.interface_info() 518 headers = defaults.headers() 519 rebuild = False 520 try: 521 if os.stat(headers).st_mtime <= os.stat(ifile).st_mtime: 522 return 523 except OSError: 524 pass 525 526 if os.getuid() != 0: 527 raise ValueError(_("You must regenerate interface info by running /usr/bin/sepolgen-ifgen")) 528 print commands.getstatusoutput("/usr/bin/sepolgen-ifgen")[1] 529 530 531def gen_port_dict(): 532 global portrecs 533 global portrecsbynum 534 if portrecs: 535 return (portrecs, portrecsbynum) 536 portrecsbynum = {} 537 portrecs = {} 538 for i in info(PORT): 539 if i['low'] == i['high']: 540 port = str(i['low']) 541 else: 542 port = "%s-%s" % (str(i['low']), str(i['high'])) 543 544 if (i['type'], i['protocol']) in portrecs: 545 portrecs[(i['type'], i['protocol'])].append(port) 546 else: 547 portrecs[(i['type'], i['protocol'])] = [port] 548 549 if 'range' in i: 550 portrecsbynum[(i['low'], i['high'], i['protocol'])] = (i['type'], i['range']) 551 else: 552 portrecsbynum[(i['low'], i['high'], i['protocol'])] = (i['type']) 553 554 return (portrecs, portrecsbynum) 555 556all_domains = None 557 558 559def get_all_domains(): 560 global all_domains 561 if not all_domains: 562 all_domains = info(ATTRIBUTE, "domain")[0]["types"] 563 return all_domains 564 565roles = None 566 567 568def get_all_roles(): 569 global roles 570 if roles: 571 return roles 572 roles = map(lambda x: x['name'], info(ROLE)) 573 roles.remove("object_r") 574 roles.sort() 575 return roles 576 577selinux_user_list = None 578 579 580def get_selinux_users(): 581 global selinux_user_list 582 if not selinux_user_list: 583 selinux_user_list = info(USER) 584 for x in selinux_user_list: 585 x['range'] = "".join(x['range'].split(" ")) 586 return selinux_user_list 587 588login_mappings = None 589 590 591def get_login_mappings(): 592 global login_mappings 593 if login_mappings: 594 return login_mappings 595 596 fd = open(selinux.selinux_usersconf_path(), "r") 597 buf = fd.read() 598 fd.close() 599 login_mappings = [] 600 for b in buf.split("\n"): 601 b = b.strip() 602 if len(b) == 0 or b.startswith("#"): 603 continue 604 x = b.split(":") 605 login_mappings.append({"name": x[0], "seuser": x[1], "mls": ":".join(x[2:])}) 606 return login_mappings 607 608 609def get_all_users(): 610 users = map(lambda x: x['name'], get_selinux_users()) 611 users.sort() 612 return users 613 614file_types = None 615 616 617def get_all_file_types(): 618 global file_types 619 if file_types: 620 return file_types 621 file_types = info(ATTRIBUTE, "file_type")[0]["types"] 622 file_types.sort() 623 return file_types 624 625port_types = None 626 627 628def get_all_port_types(): 629 global port_types 630 if port_types: 631 return port_types 632 port_types = info(ATTRIBUTE, "port_type")[0]["types"] 633 port_types.sort() 634 return port_types 635 636bools = None 637 638 639def get_all_bools(): 640 global bools 641 if not bools: 642 bools = info(BOOLEAN) 643 return bools 644 645 646def prettyprint(f, trim): 647 return " ".join(f[:-len(trim)].split("_")) 648 649 650def markup(f): 651 return f 652 653# Autofill for adding files ************************* 654DEFAULT_DIRS = {} 655DEFAULT_DIRS["/etc"] = "etc_t" 656DEFAULT_DIRS["/tmp"] = "tmp_t" 657DEFAULT_DIRS["/usr/lib/systemd/system"] = "unit_file_t" 658DEFAULT_DIRS["/lib/systemd/system"] = "unit_file_t" 659DEFAULT_DIRS["/etc/systemd/system"] = "unit_file_t" 660DEFAULT_DIRS["/var/cache"] = "var_cache_t" 661DEFAULT_DIRS["/var/lib"] = "var_lib_t" 662DEFAULT_DIRS["/var/log"] = "log_t" 663DEFAULT_DIRS["/var/run"] = "var_run_t" 664DEFAULT_DIRS["/run"] = "var_run_t" 665DEFAULT_DIRS["/run/lock"] = "var_lock_t" 666DEFAULT_DIRS["/var/run/lock"] = "var_lock_t" 667DEFAULT_DIRS["/var/spool"] = "var_spool_t" 668DEFAULT_DIRS["/var/www"] = "content_t" 669 670 671def get_description(f, markup=markup): 672 673 txt = "Set files with the %s type, if you want to " % markup(f) 674 675 if f.endswith("_var_run_t"): 676 return txt + "store the %s files under the /run or /var/run directory." % prettyprint(f, "_var_run_t") 677 if f.endswith("_pid_t"): 678 return txt + "store the %s files under the /run directory." % prettyprint(f, "_pid_t") 679 if f.endswith("_var_lib_t"): 680 return txt + "store the %s files under the /var/lib directory." % prettyprint(f, "_var_lib_t") 681 if f.endswith("_var_t"): 682 return txt + "store the %s files under the /var directory." % prettyprint(f, "_var_lib_t") 683 if f.endswith("_var_spool_t"): 684 return txt + "store the %s files under the /var/spool directory." % prettyprint(f, "_spool_t") 685 if f.endswith("_spool_t"): 686 return txt + "store the %s files under the /var/spool directory." % prettyprint(f, "_spool_t") 687 if f.endswith("_cache_t") or f.endswith("_var_cache_t"): 688 return txt + "store the files under the /var/cache directory." 689 if f.endswith("_keytab_t"): 690 return txt + "treat the files as kerberos keytab files." 691 if f.endswith("_lock_t"): 692 return txt + "treat the files as %s lock data, stored under the /var/lock directory" % prettyprint(f, "_lock_t") 693 if f.endswith("_log_t"): 694 return txt + "treat the data as %s log data, usually stored under the /var/log directory." % prettyprint(f, "_log_t") 695 if f.endswith("_config_t"): 696 return txt + "treat the files as %s configuration data, usually stored under the /etc directory." % prettyprint(f, "_config_t") 697 if f.endswith("_conf_t"): 698 return txt + "treat the files as %s configuration data, usually stored under the /etc directory." % prettyprint(f, "_conf_t") 699 if f.endswith("_exec_t"): 700 return txt + "transition an executable to the %s_t domain." % f[:-len("_exec_t")] 701 if f.endswith("_cgi_content_t"): 702 return txt + "treat the files as %s cgi content." % prettyprint(f, "_cgi_content_t") 703 if f.endswith("_rw_content_t"): 704 return txt + "treat the files as %s read/write content." % prettyprint(f, "_rw_content_t") 705 if f.endswith("_rw_t"): 706 return txt + "treat the files as %s read/write content." % prettyprint(f, "_rw_t") 707 if f.endswith("_write_t"): 708 return txt + "treat the files as %s read/write content." % prettyprint(f, "_write_t") 709 if f.endswith("_db_t"): 710 return txt + "treat the files as %s database content." % prettyprint(f, "_db_t") 711 if f.endswith("_ra_content_t"): 712 return txt + "treat the files as %s read/append content." % prettyprint(f, "_ra_conten_t") 713 if f.endswith("_cert_t"): 714 return txt + "treat the files as %s certificate data." % prettyprint(f, "_cert_t") 715 if f.endswith("_key_t"): 716 return txt + "treat the files as %s key data." % prettyprint(f, "_key_t") 717 718 if f.endswith("_secret_t"): 719 return txt + "treat the files as %s secret data." % prettyprint(f, "_key_t") 720 721 if f.endswith("_ra_t"): 722 return txt + "treat the files as %s read/append content." % prettyprint(f, "_ra_t") 723 724 if f.endswith("_ro_t"): 725 return txt + "treat the files as %s read/only content." % prettyprint(f, "_ro_t") 726 727 if f.endswith("_modules_t"): 728 return txt + "treat the files as %s modules." % prettyprint(f, "_modules_t") 729 730 if f.endswith("_content_t"): 731 return txt + "treat the files as %s content." % prettyprint(f, "_content_t") 732 733 if f.endswith("_state_t"): 734 return txt + "treat the files as %s state data." % prettyprint(f, "_state_t") 735 736 if f.endswith("_files_t"): 737 return txt + "treat the files as %s content." % prettyprint(f, "_files_t") 738 739 if f.endswith("_file_t"): 740 return txt + "treat the files as %s content." % prettyprint(f, "_file_t") 741 742 if f.endswith("_data_t"): 743 return txt + "treat the files as %s content." % prettyprint(f, "_data_t") 744 745 if f.endswith("_file_t"): 746 return txt + "treat the data as %s content." % prettyprint(f, "_file_t") 747 748 if f.endswith("_tmp_t"): 749 return txt + "store %s temporary files in the /tmp directories." % prettyprint(f, "_tmp_t") 750 if f.endswith("_etc_t"): 751 return txt + "store %s files in the /etc directories." % prettyprint(f, "_tmp_t") 752 if f.endswith("_home_t"): 753 return txt + "store %s files in the users home directory." % prettyprint(f, "_home_t") 754 if f.endswith("_tmpfs_t"): 755 return txt + "store %s files on a tmpfs file system." % prettyprint(f, "_tmpfs_t") 756 if f.endswith("_unit_file_t"): 757 return txt + "treat files as a systemd unit file." 758 if f.endswith("_htaccess_t"): 759 return txt + "treat the file as a %s access file." % prettyprint(f, "_htaccess_t") 760 761 return txt + "treat the files as %s data." % prettyprint(f, "_t") 762 763all_attributes = None 764 765 766def get_all_attributes(): 767 global all_attributes 768 if not all_attributes: 769 all_attributes = map(lambda x: x['name'], info(ATTRIBUTE)) 770 return all_attributes 771 772 773def policy(policy_file): 774 global all_domains 775 global all_attributes 776 global bools 777 global all_types 778 global role_allows 779 global users 780 global roles 781 global file_types 782 global port_types 783 all_domains = None 784 all_attributes = None 785 bools = None 786 all_types = None 787 role_allows = None 788 users = None 789 roles = None 790 file_types = None 791 port_types = None 792 try: 793 _policy.policy(policy_file) 794 except: 795 raise ValueError(_("Failed to read %s policy file") % policy_file) 796 797try: 798 policy_file = get_installed_policy() 799 policy(policy_file) 800except ValueError, e: 801 if selinux.is_selinux_enabled() == 1: 802 raise e 803 804 805def _dict_has_perms(dict, perms): 806 for perm in perms: 807 if perm not in dict[PERMS]: 808 return False 809 return True 810 811 812def gen_short_name(setype): 813 all_domains = get_all_domains() 814 if setype.endswith("_t"): 815 domainname = setype[:-2] 816 else: 817 domainname = setype 818 if domainname + "_t" not in all_domains: 819 raise ValueError("domain %s_t does not exist" % domainname) 820 if domainname[-1] == 'd': 821 short_name = domainname[:-1] + "_" 822 else: 823 short_name = domainname + "_" 824 return (domainname, short_name) 825 826 827def get_bools(setype): 828 bools = [] 829 domainbools = [] 830 domainname, short_name = gen_short_name(setype) 831 for i in map(lambda x: x['boolean'], filter(lambda x: 'boolean' in x, search([ALLOW], {'source': setype}))): 832 for b in i: 833 if not isinstance(b, tuple): 834 continue 835 try: 836 enabled = selinux.security_get_boolean_active(b[0]) 837 except OSError: 838 enabled = b[1] 839 if b[0].startswith(short_name) or b[0].startswith(domainname): 840 if (b[0], enabled) not in domainbools and (b[0], not enabled) not in domainbools: 841 domainbools.append((b[0], enabled)) 842 else: 843 if (b[0], enabled) not in bools and (b[0], not enabled) not in bools: 844 bools.append((b[0], enabled)) 845 return (domainbools, bools) 846 847booleans = None 848 849 850def get_all_booleans(): 851 global booleans 852 if not booleans: 853 booleans = selinux.security_get_boolean_names()[1] 854 return booleans 855 856booleans_dict = None 857import gzip 858 859 860def policy_xml(path="/usr/share/selinux/devel/policy.xml"): 861 try: 862 fd = gzip.open(path) 863 buf = fd.read() 864 fd.close() 865 except IOError: 866 fd = open(path) 867 buf = fd.read() 868 fd.close() 869 return buf 870 871 872def gen_bool_dict(path="/usr/share/selinux/devel/policy.xml"): 873 global booleans_dict 874 if booleans_dict: 875 return booleans_dict 876 import xml.etree.ElementTree 877 import re 878 booleans_dict = {} 879 try: 880 tree = xml.etree.ElementTree.fromstring(policy_xml(path)) 881 for l in tree.findall("layer"): 882 for m in l.findall("module"): 883 for b in m.findall("tunable"): 884 desc = b.find("desc").find("p").text.strip("\n") 885 desc = re.sub("\n", " ", desc) 886 booleans_dict[b.get('name')] = (m.get("name"), b.get('dftval'), desc) 887 for b in m.findall("bool"): 888 desc = b.find("desc").find("p").text.strip("\n") 889 desc = re.sub("\n", " ", desc) 890 booleans_dict[b.get('name')] = (m.get("name"), b.get('dftval'), desc) 891 for i in tree.findall("bool"): 892 desc = i.find("desc").find("p").text.strip("\n") 893 desc = re.sub("\n", " ", desc) 894 booleans_dict[i.get('name')] = ("global", i.get('dftval'), desc) 895 for i in tree.findall("tunable"): 896 desc = i.find("desc").find("p").text.strip("\n") 897 desc = re.sub("\n", " ", desc) 898 booleans_dict[i.get('name')] = ("global", i.get('dftval'), desc) 899 except IOError, e: 900 pass 901 return booleans_dict 902 903 904def boolean_category(boolean): 905 booleans_dict = gen_bool_dict() 906 if boolean in booleans_dict: 907 return _(booleans_dict[boolean][0]) 908 else: 909 return _("unknown") 910 911 912def boolean_desc(boolean): 913 booleans_dict = gen_bool_dict() 914 if boolean in booleans_dict: 915 return _(booleans_dict[boolean][2]) 916 else: 917 desc = boolean.split("_") 918 return "Allow %s to %s" % (desc[0], " ".join(desc[1:])) 919 920 921def get_os_version(): 922 os_version = "" 923 pkg_name = "selinux-policy" 924 try: 925 import commands 926 rc, output = commands.getstatusoutput("rpm -q '%s'" % pkg_name) 927 if rc == 0: 928 os_version = output.split(".")[-2] 929 except: 930 os_version = "" 931 932 if os_version[0:2] == "fc": 933 os_version = "Fedora" + os_version[2:] 934 elif os_version[0:2] == "el": 935 os_version = "RHEL" + os_version[2:] 936 else: 937 os_version = "" 938 939 return os_version 940 941 942def reinit(): 943 global all_attributes 944 global all_domains 945 global all_types 946 global booleans 947 global booleans_dict 948 global bools 949 global fcdict 950 global file_types 951 global local_files 952 global methods 953 global methods 954 global portrecs 955 global portrecsbynum 956 global port_types 957 global role_allows 958 global roles 959 global login_mappings 960 global selinux_user_list 961 global user_types 962 all_attributes = None 963 all_domains = None 964 all_types = None 965 booleans = None 966 booleans_dict = None 967 bools = None 968 fcdict = None 969 file_types = None 970 local_files = None 971 methods = None 972 methods = None 973 portrecs = None 974 portrecsbynum = None 975 port_types = None 976 role_allows = None 977 roles = None 978 user_types = None 979 login_mappings = None 980 selinux_user_list = None 981