• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2007-2012 Red Hat
2# see file 'COPYING' for use and warranty information
3#
4# policygentool is a tool for the initial generation of SELinux policy
5#
6#    This program is free software; you can redistribute it and/or
7#    modify it under the terms of the GNU General Public License as
8#    published by the Free Software Foundation; either version 2 of
9#    the License, or (at your option) any later version.
10#
11#    This program 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 this program; if not, write to the Free Software
18#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19#                                        02111-1307  USA
20#
21#
22import os
23import sys
24import stat
25import re
26import sepolicy
27from sepolicy import get_all_types, get_all_attributes, get_all_roles
28import time
29
30from .templates import executable
31from .templates import boolean
32from .templates import etc_rw
33from .templates import unit_file
34from .templates import var_cache
35from .templates import var_spool
36from .templates import var_lib
37from .templates import var_log
38from .templates import var_run
39from .templates import tmp
40from .templates import rw
41from .templates import network
42from .templates import script
43from .templates import spec
44from .templates import user
45import sepolgen.interfaces as interfaces
46import sepolgen.defaults as defaults
47
48##
49## I18N
50##
51PROGNAME = "selinux-python"
52try:
53    import gettext
54    kwargs = {}
55    if sys.version_info < (3,):
56        kwargs['unicode'] = True
57    t = gettext.translation(PROGNAME,
58                    localedir="/usr/share/locale",
59                    **kwargs,
60                    fallback=True)
61    _ = t.gettext
62except:
63    try:
64        import builtins
65        builtins.__dict__['_'] = str
66    except ImportError:
67        import __builtin__
68        __builtin__.__dict__['_'] = unicode
69
70
71def get_rpm_nvr_from_header(hdr):
72    'Given an RPM header return the package NVR as a string'
73    name = hdr['name']
74    version = hdr['version']
75    release = hdr['release']
76    release_version = version + "-" + release.split(".")[0]
77    os_version = release.split(".")[1]
78
79    return [name, release_version, os_version]
80
81
82def get_rpm_nvr_list(package):
83    try:
84        import rpm
85        nvr = None
86        ts = rpm.ts()
87        mi = ts.dbMatch(rpm.RPMTAG_NAME, package)
88        for h in mi:
89            nvr = get_rpm_nvr_from_header(h)
90            break
91    except:
92        print(("Failed to retrieve rpm info for %s") % package)
93        nvr = None
94
95    return nvr
96
97
98def get_all_ports():
99    dict = {}
100    for p in sepolicy.info(sepolicy.PORT):
101        if p['type'] == "reserved_port_t" or \
102                p['type'] == "port_t" or \
103                p['type'] == "hi_reserved_port_t":
104            continue
105        dict[(p['low'], p['high'], p['protocol'])] = (p['type'], p.get('range'))
106    return dict
107
108
109def get_all_users():
110    users = [x['name'] for x in sepolicy.info(sepolicy.USER)]
111    users.remove("system_u")
112    users.remove("root")
113    users.sort()
114    return users
115
116ALL = 0
117RESERVED = 1
118UNRESERVED = 2
119PORTS = 3
120ADMIN_TRANSITION_INTERFACE = "_admin$"
121USER_TRANSITION_INTERFACE = "_role$"
122
123DAEMON = 0
124DBUS = 1
125INETD = 2
126CGI = 3
127SANDBOX = 4
128USER = 5
129EUSER = 6
130TUSER = 7
131XUSER = 8
132LUSER = 9
133AUSER = 10
134RUSER = 11
135NEWTYPE = 12
136
137poltype = {}
138poltype[DAEMON] = _("Standard Init Daemon")
139poltype[DBUS] = _("DBUS System Daemon")
140poltype[INETD] = _("Internet Services Daemon")
141poltype[CGI] = _("Web Application/Script (CGI)")
142poltype[SANDBOX] = _("Sandbox")
143poltype[USER] = _("User Application")
144poltype[EUSER] = _("Existing Domain Type")
145poltype[TUSER] = _("Minimal Terminal Login User Role")
146poltype[XUSER] = _("Minimal X Windows Login User Role")
147poltype[LUSER] = _("Desktop Login User Role")
148poltype[AUSER] = _("Administrator Login User Role")
149poltype[RUSER] = _("Confined Root Administrator Role")
150poltype[NEWTYPE] = _("Module information for a new type")
151
152
153def get_poltype_desc():
154    keys = poltype.keys()
155    keys.sort()
156    msg = _("Valid Types:\n")
157    for k in keys:
158        msg += "%2s: %s\n" % (k, poltype[k])
159    return msg
160
161APPLICATIONS = [DAEMON, DBUS, INETD, USER, CGI]
162USERS = [XUSER, TUSER, LUSER, AUSER, RUSER]
163
164
165def verify_ports(ports):
166    if ports == "":
167        return []
168    max_port = 2 ** 16
169    try:
170        temp = []
171        for a in ports.split(","):
172            r = a.split("-")
173            if len(r) > 2:
174                raise ValueError
175            if len(r) == 1:
176                begin = int(r[0])
177                end = int(r[0])
178            else:
179                begin = int(r[0])
180                end = int(r[1])
181
182                if begin > end:
183                    raise ValueError
184
185            for p in range(begin, end + 1):
186                if p < 1 or p > max_port:
187                    raise ValueError
188                temp.append(p)
189        return temp
190    except ValueError:
191        raise ValueError(_("Ports must be numbers or ranges of numbers from 1 to %d ") % max_port)
192
193
194class policy:
195
196    def __init__(self, name, type):
197        self.rpms = []
198        self.ports = {}
199        self.all_roles = get_all_roles()
200        self.types = []
201
202        if type not in poltype:
203            raise ValueError(_("You must enter a valid policy type"))
204
205        if not name:
206            raise ValueError(_("You must enter a name for your policy module for your '%s'.") % poltype[type])
207        try:
208            self.ports = get_all_ports()
209        except ValueError as e:
210            print("Can not get port types, must be root for this information")
211        except RuntimeError as e:
212            print("Can not get port types", e)
213
214        self.symbols = {}
215        self.symbols["openlog"] = "set_use_kerberos(True)"
216        self.symbols["openlog"] = "set_use_kerb_rcache(True)"
217        self.symbols["openlog"] = "set_use_syslog(True)"
218        self.symbols["gethostby"] = "set_use_resolve(True)"
219        self.symbols["getaddrinfo"] = "set_use_resolve(True)"
220        self.symbols["getnameinfo"] = "set_use_resolve(True)"
221        self.symbols["krb"] = "set_use_kerberos(True)"
222        self.symbols["gss_accept_sec_context"] = "set_manage_krb5_rcache(True)"
223        self.symbols["krb5_verify_init_creds"] = "set_manage_krb5_rcache(True)"
224        self.symbols["krb5_rd_req"] = "set_manage_krb5_rcache(True)"
225        self.symbols["__syslog_chk"] = "set_use_syslog(True)"
226        self.symbols["getpwnam"] = "set_use_uid(True)"
227        self.symbols["getpwuid"] = "set_use_uid(True)"
228        self.symbols["dbus_"] = "set_use_dbus(True)"
229        self.symbols["pam_"] = "set_use_pam(True)"
230        self.symbols["pam_"] = "set_use_audit(True)"
231        self.symbols["fork"] = "add_process('fork')"
232        self.symbols["transition"] = "add_process('transition')"
233        self.symbols["sigchld"] = "add_process('sigchld')"
234        self.symbols["sigkill"] = "add_process('sigkill')"
235        self.symbols["sigstop"] = "add_process('sigstop')"
236        self.symbols["signull"] = "add_process('signull')"
237        self.symbols["ptrace"] = "add_process('ptrace')"
238        self.symbols["getsched"] = "add_process('getsched')"
239        self.symbols["setsched"] = "add_process('setsched')"
240        self.symbols["getsession"] = "add_process('getsession')"
241        self.symbols["getpgid"] = "add_process('getpgid')"
242        self.symbols["setpgid"] = "add_process('setpgid')"
243        self.symbols["getcap"] = "add_process('getcap')"
244        self.symbols["setcap"] = "add_process('setcap')"
245        self.symbols["share"] = "add_process('share')"
246        self.symbols["getattr"] = "add_process('getattr')"
247        self.symbols["setexec"] = "add_process('setexec')"
248        self.symbols["setfscreate"] = "add_process('setfscreate')"
249        self.symbols["noatsecure"] = "add_process('noatsecure')"
250        self.symbols["siginh"] = "add_process('siginh')"
251        self.symbols["kill"] = "add_process('signal_perms')"
252        self.symbols["setrlimit"] = "add_process('setrlimit')"
253        self.symbols["rlimitinh"] = "add_process('rlimitinh')"
254        self.symbols["dyntransition"] = "add_process('dyntransition')"
255        self.symbols["setcurrent"] = "add_process('setcurrent')"
256        self.symbols["execmem"] = "add_process('execmem')"
257        self.symbols["execstack"] = "add_process('execstack')"
258        self.symbols["execheap"] = "add_process('execheap')"
259        self.symbols["setkeycreate"] = "add_process('setkeycreate')"
260        self.symbols["setsockcreate"] = "add_process('setsockcreate')"
261
262        self.symbols["chown"] = "add_capability('chown')"
263        self.symbols["dac_override"] = "add_capability('dac_override')"
264        self.symbols["dac_read_search"] = "add_capability('dac_read_search')"
265        self.symbols["fowner"] = "add_capability('fowner')"
266        self.symbols["fsetid"] = "add_capability('fsetid')"
267        self.symbols["setgid"] = "add_capability('setgid')"
268        self.symbols["setegid"] = "add_capability('setgid')"
269        self.symbols["setresgid"] = "add_capability('setgid')"
270        self.symbols["setregid"] = "add_capability('setgid')"
271        self.symbols["setresuid"] = "add_capability('setuid')"
272        self.symbols["setuid"] = "add_capability('setuid')"
273        self.symbols["seteuid"] = "add_capability('setuid')"
274        self.symbols["setreuid"] = "add_capability('setuid')"
275        self.symbols["setresuid"] = "add_capability('setuid')"
276        self.symbols["setpcap"] = "add_capability('setpcap')"
277        self.symbols["linux_immutable"] = "add_capability('linux_immutable')"
278        self.symbols["net_bind_service"] = "add_capability('net_bind_service')"
279        self.symbols["net_broadcast"] = "add_capability('net_broadcast')"
280        self.symbols["net_admin"] = "add_capability('net_admin')"
281        self.symbols["net_raw"] = "add_capability('net_raw')"
282        self.symbols["ipc_lock"] = "add_capability('ipc_lock')"
283        self.symbols["ipc_owner"] = "add_capability('ipc_owner')"
284        self.symbols["sys_module"] = "add_capability('sys_module')"
285        self.symbols["sys_rawio"] = "add_capability('sys_rawio')"
286        self.symbols["chroot"] = "add_capability('sys_chroot')"
287        self.symbols["sys_chroot"] = "add_capability('sys_chroot')"
288        self.symbols["sys_ptrace"] = "add_capability('sys_ptrace')"
289        self.symbols["sys_pacct"] = "add_capability('sys_pacct')"
290        self.symbols["mount"] = "add_capability('sys_admin')"
291        self.symbols["unshare"] = "add_capability('sys_admin')"
292        self.symbols["sys_admin"] = "add_capability('sys_admin')"
293        self.symbols["sys_boot"] = "add_capability('sys_boot')"
294        self.symbols["sys_nice"] = "add_capability('sys_nice')"
295        self.symbols["sys_resource"] = "add_capability('sys_resource')"
296        self.symbols["sys_time"] = "add_capability('sys_time')"
297        self.symbols["sys_tty_config"] = "add_capability('sys_tty_config')"
298        self.symbols["mknod"] = "add_capability('mknod')"
299        self.symbols["lease"] = "add_capability('lease')"
300        self.symbols["audit_write"] = "add_capability('audit_write')"
301        self.symbols["audit_control"] = "add_capability('audit_control')"
302        self.symbols["setfcap"] = "add_capability('setfcap')"
303
304        self.DEFAULT_DIRS = {}
305        self.DEFAULT_DIRS["/etc"] = ["etc_rw", [], etc_rw]
306        self.DEFAULT_DIRS["/tmp"] = ["tmp", [], tmp]
307        self.DEFAULT_DIRS["rw"] = ["rw", [], rw]
308        self.DEFAULT_DIRS["/usr/lib/systemd/system"] = ["unit_file", [], unit_file]
309        self.DEFAULT_DIRS["/lib/systemd/system"] = ["unit_file", [], unit_file]
310        self.DEFAULT_DIRS["/etc/systemd/system"] = ["unit_file", [], unit_file]
311        self.DEFAULT_DIRS["/var/cache"] = ["var_cache", [], var_cache]
312        self.DEFAULT_DIRS["/var/lib"] = ["var_lib", [], var_lib]
313        self.DEFAULT_DIRS["/var/log"] = ["var_log", [], var_log]
314        self.DEFAULT_DIRS["/var/run"] = ["var_run", [], var_run]
315        self.DEFAULT_DIRS["/var/spool"] = ["var_spool", [], var_spool]
316
317        self.DEFAULT_EXT = {}
318        self.DEFAULT_EXT["_tmp_t"] = tmp
319        self.DEFAULT_EXT["_unit_file_t"] = unit_file
320        self.DEFAULT_EXT["_var_cache_t"] = var_cache
321        self.DEFAULT_EXT["_var_lib_t"] = var_lib
322        self.DEFAULT_EXT["_var_log_t"] = var_log
323        self.DEFAULT_EXT["_var_run_t"] = var_run
324        self.DEFAULT_EXT["_var_spool_t"] = var_spool
325        self.DEFAULT_EXT["_port_t"] = network
326
327        self.DEFAULT_KEYS = ["/etc", "/var/cache", "/var/log", "/tmp", "rw", "/var/lib", "/var/run", "/var/spool", "/etc/systemd/system", "/usr/lib/systemd/system", "/lib/systemd/system"]
328
329        self.DEFAULT_TYPES = (
330            (self.generate_daemon_types, self.generate_daemon_rules),
331            (self.generate_dbusd_types, self.generate_dbusd_rules),
332            (self.generate_inetd_types, self.generate_inetd_rules),
333            (self.generate_cgi_types, self.generate_cgi_rules),
334            (self.generate_sandbox_types, self.generate_sandbox_rules),
335            (self.generate_userapp_types, self.generate_userapp_rules),
336            (self.generate_existing_user_types, self.generate_existing_user_rules),
337            (self.generate_min_login_user_types, self.generate_login_user_rules),
338            (self.generate_x_login_user_types, self.generate_x_login_user_rules),
339            (self.generate_login_user_types, self.generate_login_user_rules),
340            (self.generate_admin_user_types, self.generate_login_user_rules),
341            (self.generate_root_user_types, self.generate_root_user_rules),
342            (self.generate_new_types, self.generate_new_rules))
343        if not re.match(r"^[a-zA-Z0-9-_]+$", name):
344            raise ValueError(_("Name must be alphanumeric with no spaces. Consider using option \"-n MODULENAME\""))
345
346        if type == CGI:
347            self.name = "httpd_%s_script" % name
348        else:
349            self.name = name
350
351        self.file_name = name
352
353        self.capabilities = []
354        self.processes = []
355        self.type = type
356        self.initscript = ""
357        self.program = None
358        self.in_tcp = [False, False, False, []]
359        self.in_udp = [False, False, False, []]
360        self.out_tcp = [False, False, False, []]
361        self.out_udp = [False, False, False, []]
362        self.use_resolve = False
363        self.use_tmp = False
364        self.use_uid = False
365        self.use_syslog = False
366        self.use_kerberos = False
367        self.manage_krb5_rcache = False
368        self.use_pam = False
369        self.use_dbus = False
370        self.use_audit = False
371        self.use_etc = self.type not in [EUSER, NEWTYPE]
372        self.use_localization = self.type not in [EUSER, NEWTYPE]
373        self.use_fd = self.type not in [EUSER, NEWTYPE]
374        self.use_terminal = False
375        self.use_mail = False
376        self.booleans = {}
377        self.files = {}
378        self.dirs = {}
379        self.found_tcp_ports = []
380        self.found_udp_ports = []
381        self.need_tcp_type = False
382        self.need_udp_type = False
383        self.admin_domains = []
384        self.existing_domains = []
385        self.transition_domains = []
386        self.transition_users = []
387        self.roles = []
388
389    def __isnetset(self, l):
390        return l[ALL] or l[RESERVED] or l[UNRESERVED] or len(l[PORTS]) > 0
391
392    def set_admin_domains(self, admin_domains):
393        self.admin_domains = admin_domains
394
395    def set_existing_domains(self, existing_domains):
396        self.existing_domains = existing_domains
397
398    def set_admin_roles(self, roles):
399        self.roles = roles
400
401    def set_transition_domains(self, transition_domains):
402        self.transition_domains = transition_domains
403
404    def set_transition_users(self, transition_users):
405        self.transition_users = transition_users
406
407    def use_in_udp(self):
408        return self.__isnetset(self.in_udp)
409
410    def use_out_udp(self):
411        return self.__isnetset(self.out_udp)
412
413    def use_udp(self):
414        return self.use_in_udp() or self.use_out_udp()
415
416    def use_in_tcp(self):
417        return self.__isnetset(self.in_tcp)
418
419    def use_out_tcp(self):
420        return self.__isnetset(self.out_tcp)
421
422    def use_tcp(self):
423        return self.use_in_tcp() or self.use_out_tcp()
424
425    def use_network(self):
426        return self.use_tcp() or self.use_udp()
427
428    def find_port(self, port, protocol="tcp"):
429        for begin, end, p in self.ports.keys():
430            if port >= begin and port <= end and protocol == p:
431                return self.ports[begin, end, protocol]
432        return None
433
434    def set_program(self, program):
435        if self.type not in APPLICATIONS:
436            raise ValueError(_("User Role types can not be assigned executables."))
437
438        self.program = program
439
440    def set_init_script(self, initscript):
441        if self.type != DAEMON:
442            raise ValueError(_("Only Daemon apps can use an init script."))
443
444        self.initscript = initscript
445
446    def set_in_tcp(self, all, reserved, unreserved, ports):
447        self.in_tcp = [all, reserved, unreserved, verify_ports(ports)]
448
449    def set_in_udp(self, all, reserved, unreserved, ports):
450        self.in_udp = [all, reserved, unreserved, verify_ports(ports)]
451
452    def set_out_tcp(self, all, ports):
453        self.out_tcp = [all, False, False, verify_ports(ports)]
454
455    def set_out_udp(self, all, ports):
456        self.out_udp = [all, False, False, verify_ports(ports)]
457
458    def set_use_resolve(self, val):
459        if type(val) is not bool:
460            raise ValueError(_("use_resolve must be a boolean value "))
461
462        self.use_resolve = val
463
464    def set_use_syslog(self, val):
465        if type(val) is not bool:
466            raise ValueError(_("use_syslog must be a boolean value "))
467
468        self.use_syslog = val
469
470    def set_use_kerberos(self, val):
471        if type(val) is not bool:
472            raise ValueError(_("use_kerberos must be a boolean value "))
473
474        self.use_kerberos = val
475
476    def set_manage_krb5_rcache(self, val):
477        if type(val) is not bool:
478            raise ValueError(_("manage_krb5_rcache must be a boolean value "))
479
480        self.manage_krb5_rcache = val
481
482    def set_use_pam(self, val):
483        self.use_pam = (val is True)
484
485    def set_use_dbus(self, val):
486        self.use_dbus = (val is True)
487
488    def set_use_audit(self, val):
489        self.use_audit = (val is True)
490
491    def set_use_etc(self, val):
492        self.use_etc = (val is True)
493
494    def set_use_localization(self, val):
495        self.use_localization = (val is True)
496
497    def set_use_fd(self, val):
498        self.use_fd = (val is True)
499
500    def set_use_terminal(self, val):
501        self.use_terminal = (val is True)
502
503    def set_use_mail(self, val):
504        self.use_mail = (val is True)
505
506    def set_use_tmp(self, val):
507        if self.type in USERS:
508            raise ValueError(_("USER Types automatically get a tmp type"))
509
510        if val:
511            self.DEFAULT_DIRS["/tmp"][1].append("/tmp")
512        else:
513            self.DEFAULT_DIRS["/tmp"][1] = []
514
515    def set_use_uid(self, val):
516        self.use_uid = (val is True)
517
518    def generate_uid_rules(self):
519        if self.use_uid:
520            return re.sub("TEMPLATETYPE", self.name, executable.te_uid_rules)
521        else:
522            return ""
523
524    def generate_syslog_rules(self):
525        if self.use_syslog:
526            return re.sub("TEMPLATETYPE", self.name, executable.te_syslog_rules)
527        else:
528            return ""
529
530    def generate_resolve_rules(self):
531        if self.use_resolve:
532            return re.sub("TEMPLATETYPE", self.name, executable.te_resolve_rules)
533        else:
534            return ""
535
536    def generate_kerberos_rules(self):
537        if self.use_kerberos:
538            return re.sub("TEMPLATETYPE", self.name, executable.te_kerberos_rules)
539        else:
540            return ""
541
542    def generate_manage_krb5_rcache_rules(self):
543        if self.manage_krb5_rcache:
544            return re.sub("TEMPLATETYPE", self.name, executable.te_manage_krb5_rcache_rules)
545        else:
546            return ""
547
548    def generate_pam_rules(self):
549        newte = ""
550        if self.use_pam:
551            newte = re.sub("TEMPLATETYPE", self.name, executable.te_pam_rules)
552        return newte
553
554    def generate_audit_rules(self):
555        newte = ""
556        if self.use_audit:
557            newte = re.sub("TEMPLATETYPE", self.name, executable.te_audit_rules)
558        return newte
559
560    def generate_etc_rules(self):
561        newte = ""
562        if self.use_etc:
563            newte = re.sub("TEMPLATETYPE", self.name, executable.te_etc_rules)
564        return newte
565
566    def generate_fd_rules(self):
567        newte = ""
568        if self.use_fd:
569            newte = re.sub("TEMPLATETYPE", self.name, executable.te_fd_rules)
570        return newte
571
572    def generate_localization_rules(self):
573        newte = ""
574        if self.use_localization:
575            newte = re.sub("TEMPLATETYPE", self.name, executable.te_localization_rules)
576        return newte
577
578    def generate_dbus_rules(self):
579        newte = ""
580        if self.type != DBUS and self.use_dbus:
581            newte = re.sub("TEMPLATETYPE", self.name, executable.te_dbus_rules)
582        return newte
583
584    def generate_mail_rules(self):
585        newte = ""
586        if self.use_mail:
587            newte = re.sub("TEMPLATETYPE", self.name, executable.te_mail_rules)
588        return newte
589
590    def generate_network_action(self, protocol, action, port_name):
591        line = ""
592        method = "corenet_%s_%s_%s" % (protocol, action, port_name)
593        if method in sepolicy.get_methods():
594            line = "%s(%s_t)\n" % (method, self.name)
595        else:
596            line = """
597gen_require(`
598    type %s_t;
599')
600allow %s_t %s_t:%s_socket name_%s;
601""" % (port_name, self.name, port_name, protocol, action)
602        return line
603
604    def generate_network_types(self):
605        for i in self.in_tcp[PORTS]:
606            rec = self.find_port(int(i), "tcp")
607            if rec is None:
608                self.need_tcp_type = True
609            else:
610                port_name = rec[0][:-2]
611                line = self.generate_network_action("tcp", "bind", port_name)
612#                   line = "corenet_tcp_bind_%s(%s_t)\n" % (port_name, self.name)
613                if line not in self.found_tcp_ports:
614                    self.found_tcp_ports.append(line)
615
616        for i in self.out_tcp[PORTS]:
617            rec = self.find_port(int(i), "tcp")
618            if rec is None:
619                self.need_tcp_type = True
620            else:
621                port_name = rec[0][:-2]
622                line = self.generate_network_action("tcp", "connect", port_name)
623#                   line = "corenet_tcp_connect_%s(%s_t)\n" % (port_name, self.name)
624                if line not in self.found_tcp_ports:
625                    self.found_tcp_ports.append(line)
626
627        for i in self.in_udp[PORTS]:
628            rec = self.find_port(int(i), "udp")
629            if rec is None:
630                self.need_udp_type = True
631            else:
632                port_name = rec[0][:-2]
633                line = self.generate_network_action("udp", "bind", port_name)
634#                   line = "corenet_udp_bind_%s(%s_t)\n" % (port_name, self.name)
635                if line not in self.found_udp_ports:
636                    self.found_udp_ports.append(line)
637
638        if self.need_udp_type is True or self.need_tcp_type is True:
639            return re.sub("TEMPLATETYPE", self.name, network.te_types)
640        return ""
641
642    def __find_path(self, file):
643        for d in self.DEFAULT_DIRS:
644            if file.find(d) == 0:
645                self.DEFAULT_DIRS[d][1].append(file)
646                return self.DEFAULT_DIRS[d]
647        self.DEFAULT_DIRS["rw"][1].append(file)
648        return self.DEFAULT_DIRS["rw"]
649
650    def add_capability(self, capability):
651        if capability not in self.capabilities:
652            self.capabilities.append(capability)
653
654    def set_types(self, types):
655        self.types = types
656
657    def add_process(self, process):
658        if process not in self.processes:
659            self.processes.append(process)
660
661    def add_boolean(self, name, description):
662        self.booleans[name] = description
663
664    def add_file(self, file):
665        self.files[file] = self.__find_path(file)
666
667    def add_dir(self, file):
668        self.dirs[file] = self.__find_path(file)
669
670    def generate_capabilities(self):
671        newte = ""
672        self.capabilities.sort()
673        if len(self.capabilities) > 0:
674            newte = "allow %s_t self:capability { %s };\n" % (self.name, " ".join(self.capabilities))
675        return newte
676
677    def generate_process(self):
678        newte = ""
679        self.processes.sort()
680        if len(self.processes) > 0:
681            newte = "allow %s_t self:process { %s };\n" % (self.name, " ".join(self.processes))
682        return newte
683
684    def generate_network_rules(self):
685        newte = ""
686        if self.use_network():
687            newte = "\n"
688
689            newte += re.sub("TEMPLATETYPE", self.name, network.te_network)
690
691            if self.use_tcp():
692                newte += "\n"
693                newte += re.sub("TEMPLATETYPE", self.name, network.te_tcp)
694
695                if self.use_in_tcp():
696                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_tcp)
697
698                    if self.need_tcp_type and len(self.in_tcp[PORTS]) > 0:
699                        newte += re.sub("TEMPLATETYPE", self.name, network.te_in_need_port_tcp)
700
701                if self.need_tcp_type and len(self.out_tcp[PORTS]) > 0:
702                    newte += re.sub("TEMPLATETYPE", self.name, network.te_out_need_port_tcp)
703
704                if self.in_tcp[ALL]:
705                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_all_ports_tcp)
706                if self.in_tcp[RESERVED]:
707                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_reserved_ports_tcp)
708                if self.in_tcp[UNRESERVED]:
709                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_unreserved_ports_tcp)
710
711                if self.out_tcp[ALL]:
712                    newte += re.sub("TEMPLATETYPE", self.name, network.te_out_all_ports_tcp)
713                if self.out_tcp[RESERVED]:
714                    newte += re.sub("TEMPLATETYPE", self.name, network.te_out_reserved_ports_tcp)
715                if self.out_tcp[UNRESERVED]:
716                    newte += re.sub("TEMPLATETYPE", self.name, network.te_out_unreserved_ports_tcp)
717
718                for i in self.found_tcp_ports:
719                    newte += i
720
721            if self.use_udp():
722                newte += "\n"
723                newte += re.sub("TEMPLATETYPE", self.name, network.te_udp)
724
725                if self.need_udp_type:
726                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_need_port_udp)
727                if self.use_in_udp():
728                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_udp)
729                if self.in_udp[ALL]:
730                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_all_ports_udp)
731                if self.in_udp[RESERVED]:
732                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_reserved_ports_udp)
733                if self.in_udp[UNRESERVED]:
734                    newte += re.sub("TEMPLATETYPE", self.name, network.te_in_unreserved_ports_udp)
735
736                for i in self.found_udp_ports:
737                    newte += i
738        return newte
739
740    def generate_transition_rules(self):
741        newte = ""
742        for app in self.transition_domains:
743            tmp = re.sub("TEMPLATETYPE", self.name, user.te_transition_rules)
744            newte += re.sub("APPLICATION", app, tmp)
745
746        if self.type == USER:
747            for u in self.transition_users:
748                temp = re.sub("TEMPLATETYPE", self.name, executable.te_run_rules)
749                newte += re.sub("USER", u.split("_u")[0], temp)
750
751        return newte
752
753    def generate_admin_rules(self):
754        newte = ""
755        if self.type == EUSER:
756            for d in self.existing_domains:
757                name = d.split("_t")[0]
758                role = name + "_r"
759                for app in self.admin_domains:
760                    tmp = re.sub("TEMPLATETYPE", name, user.te_admin_domain_rules)
761                    if role not in self.all_roles:
762                        tmp = re.sub(role, "system_r", tmp)
763
764                    newte += re.sub("APPLICATION", app, tmp)
765
766            return newte
767
768        if self.type == RUSER:
769            newte += re.sub("TEMPLATETYPE", self.name, user.te_admin_rules)
770
771            for app in self.admin_domains:
772                tmp = re.sub("TEMPLATETYPE", self.name, user.te_admin_domain_rules)
773                newte += re.sub("APPLICATION", app, tmp)
774
775            for u in self.transition_users:
776                role = u.split("_u")[0]
777
778                if (role + "_r") in self.all_roles:
779                    tmp = re.sub("TEMPLATETYPE", self.name, user.te_admin_trans_rules)
780                    newte += re.sub("USER", role, tmp)
781
782        return newte
783
784    def generate_dbus_if(self):
785        newif = ""
786        if self.use_dbus:
787            newif = re.sub("TEMPLATETYPE", self.name, executable.if_dbus_rules)
788        return newif
789
790    def generate_sandbox_if(self):
791        newif = ""
792        if self.type != SANDBOX:
793            return newif
794        newif = re.sub("TEMPLATETYPE", self.name, executable.if_sandbox_rules)
795        return newif
796
797    def generate_admin_if(self):
798        newif = ""
799        newtypes = ""
800        if self.initscript != "":
801            newtypes += re.sub("TEMPLATETYPE", self.name, executable.if_initscript_admin_types)
802            newif += re.sub("TEMPLATETYPE", self.name, executable.if_initscript_admin)
803        for d in self.DEFAULT_KEYS:
804            if len(self.DEFAULT_DIRS[d][1]) > 0:
805                newtypes += re.sub("TEMPLATETYPE", self.name, self.DEFAULT_DIRS[d][2].if_admin_types)
806                newif += re.sub("TEMPLATETYPE", self.name, self.DEFAULT_DIRS[d][2].if_admin_rules)
807
808        if newif != "":
809            ret = re.sub("TEMPLATETYPE", self.name, executable.if_begin_admin)
810            ret += newtypes
811
812            ret += re.sub("TEMPLATETYPE", self.name, executable.if_middle_admin)
813            ret += newif
814            ret += re.sub("TEMPLATETYPE", self.name, executable.if_end_admin)
815            return ret
816
817        return ""
818
819    def generate_cgi_types(self):
820        return re.sub("TEMPLATETYPE", self.file_name, executable.te_cgi_types)
821
822    def generate_sandbox_types(self):
823        return re.sub("TEMPLATETYPE", self.file_name, executable.te_sandbox_types)
824
825    def generate_userapp_types(self):
826        return re.sub("TEMPLATETYPE", self.name, executable.te_userapp_types)
827
828    def generate_inetd_types(self):
829        return re.sub("TEMPLATETYPE", self.name, executable.te_inetd_types)
830
831    def generate_dbusd_types(self):
832        return re.sub("TEMPLATETYPE", self.name, executable.te_dbusd_types)
833
834    def generate_min_login_user_types(self):
835        return re.sub("TEMPLATETYPE", self.name, user.te_min_login_user_types)
836
837    def generate_login_user_types(self):
838        return re.sub("TEMPLATETYPE", self.name, user.te_login_user_types)
839
840    def generate_admin_user_types(self):
841        return re.sub("TEMPLATETYPE", self.name, user.te_admin_user_types)
842
843    def generate_existing_user_types(self):
844        if len(self.existing_domains) == 0:
845            raise ValueError(_("'%s' policy modules require existing domains") % poltype[self.type])
846        newte = re.sub("TEMPLATETYPE", self.name, user.te_existing_user_types)
847        newte += """gen_require(`"""
848
849        for d in self.existing_domains:
850            newte += """
851        type %s;""" % d
852            role = d.split("_t")[0] + "_r"
853            if role in self.all_roles:
854                newte += """
855	role %s;""" % role
856        newte += """
857')
858"""
859        return newte
860
861    def generate_x_login_user_types(self):
862        return re.sub("TEMPLATETYPE", self.name, user.te_x_login_user_types)
863
864    def generate_root_user_types(self):
865        return re.sub("TEMPLATETYPE", self.name, user.te_root_user_types)
866
867    def generate_new_types(self):
868        newte = ""
869        if len(self.types) == 0:
870            raise ValueError(_("Type field required"))
871
872        for t in self.types:
873            for i in self.DEFAULT_EXT:
874                if t.endswith(i):
875                    print(t, t[:-len(i)])
876                    newte += re.sub("TEMPLATETYPE", t[:-len(i)], self.DEFAULT_EXT[i].te_types)
877                    break
878
879        if NEWTYPE and newte == "":
880            default_ext = []
881            for i in self.DEFAULT_EXT:
882                default_ext.append(i)
883            raise ValueError(_("You need to define a new type which ends with: \n %s") % "\n ".join(default_ext))
884
885        return newte
886
887    def generate_new_rules(self):
888        return ""
889
890    def generate_daemon_types(self):
891        newte = re.sub("TEMPLATETYPE", self.name, executable.te_daemon_types)
892        if self.initscript != "":
893            newte += re.sub("TEMPLATETYPE", self.name, executable.te_initscript_types)
894        return newte
895
896    def generate_tmp_types(self):
897        if self.use_tmp:
898            return re.sub("TEMPLATETYPE", self.name, tmp.te_types)
899        else:
900            return ""
901
902    def generate_booleans(self):
903        newte = ""
904        for b in self.booleans:
905            tmp = re.sub("BOOLEAN", b, boolean.te_boolean)
906            newte += re.sub("DESCRIPTION", self.booleans[b], tmp)
907        return newte
908
909    def generate_boolean_rules(self):
910        newte = ""
911        for b in self.booleans:
912            newte += re.sub("BOOLEAN", b, boolean.te_rules)
913        return newte
914
915    def generate_sandbox_te(self):
916        return re.sub("TEMPLATETYPE", self.name, executable.te_sandbox_types)
917
918    def generate_cgi_te(self):
919        return re.sub("TEMPLATETYPE", self.name, executable.te_cgi_types)
920
921    def generate_daemon_rules(self):
922        newif = re.sub("TEMPLATETYPE", self.name, executable.te_daemon_rules)
923
924        return newif
925
926    def generate_new_type_if(self):
927        newif = ""
928        for t in self.types:
929            for i in self.DEFAULT_EXT:
930                if t.endswith(i):
931                    reqtype = t[:-len(i)] + "_t"
932                    newif += re.sub("TEMPLATETYPE", t[:-len(i)], self.DEFAULT_EXT[i].if_rules)
933                    break
934        return newif
935
936    def generate_login_user_rules(self):
937        return re.sub("TEMPLATETYPE", self.name, user.te_login_user_rules)
938
939    def generate_existing_user_rules(self):
940        nerules = re.sub("TEMPLATETYPE", self.name, user.te_existing_user_rules)
941        return nerules
942
943    def generate_x_login_user_rules(self):
944        return re.sub("TEMPLATETYPE", self.name, user.te_x_login_user_rules)
945
946    def generate_root_user_rules(self):
947        newte = re.sub("TEMPLATETYPE", self.name, user.te_root_user_rules)
948        return newte
949
950    def generate_userapp_rules(self):
951        return re.sub("TEMPLATETYPE", self.name, executable.te_userapp_rules)
952
953    def generate_inetd_rules(self):
954        return re.sub("TEMPLATETYPE", self.name, executable.te_inetd_rules)
955
956    def generate_dbusd_rules(self):
957        return re.sub("TEMPLATETYPE", self.name, executable.te_dbusd_rules)
958
959    def generate_tmp_rules(self):
960        if self.use_tmp:
961            return re.sub("TEMPLATETYPE", self.name, tmp.te_rules)
962        else:
963            return ""
964
965    def generate_cgi_rules(self):
966        newte = ""
967        newte += re.sub("TEMPLATETYPE", self.name, executable.te_cgi_rules)
968        return newte
969
970    def generate_sandbox_rules(self):
971        newte = ""
972        newte += re.sub("TEMPLATETYPE", self.name, executable.te_sandbox_rules)
973        return newte
974
975    def generate_user_if(self):
976        newif = ""
977        if self.use_terminal or self.type == USER:
978            newif = re.sub("TEMPLATETYPE", self.name, executable.if_user_program_rules)
979
980        if self.type in (TUSER, XUSER, AUSER, LUSER):
981            newif += re.sub("TEMPLATETYPE", self.name, executable.if_role_change_rules)
982        return newif
983
984    def generate_if(self):
985        newif = ""
986        newif += re.sub("TEMPLATETYPE", self.name, executable.if_heading_rules)
987        if self.program:
988            newif += re.sub("TEMPLATETYPE", self.name, executable.if_program_rules)
989        if self.initscript != "":
990            newif += re.sub("TEMPLATETYPE", self.name, executable.if_initscript_rules)
991
992        for d in self.DEFAULT_KEYS:
993            if len(self.DEFAULT_DIRS[d][1]) > 0:
994                newif += re.sub("TEMPLATETYPE", self.name, self.DEFAULT_DIRS[d][2].if_rules)
995                for i in self.DEFAULT_DIRS[d][1]:
996                    if os.path.exists(i) and stat.S_ISSOCK(os.stat(i)[stat.ST_MODE]):
997                        newif += re.sub("TEMPLATETYPE", self.name, self.DEFAULT_DIRS[d][2].if_stream_rules)
998                        break
999        newif += self.generate_user_if()
1000        newif += self.generate_dbus_if()
1001        newif += self.generate_admin_if()
1002        newif += self.generate_sandbox_if()
1003        newif += self.generate_new_type_if()
1004        newif += self.generate_new_rules()
1005
1006        return newif
1007
1008    def generate_default_types(self):
1009        return self.DEFAULT_TYPES[self.type][0]()
1010
1011    def generate_default_rules(self):
1012        if self.DEFAULT_TYPES[self.type][1]:
1013            return self.DEFAULT_TYPES[self.type][1]()
1014        return ""
1015
1016    def generate_roles_rules(self):
1017        newte = ""
1018        if self.type in (TUSER, XUSER, AUSER, LUSER):
1019            roles = ""
1020            if len(self.roles) > 0:
1021                newte += re.sub("TEMPLATETYPE", self.name, user.te_sudo_rules)
1022                newte += re.sub("TEMPLATETYPE", self.name, user.te_newrole_rules)
1023                for role in self.roles:
1024                    tmp = re.sub("TEMPLATETYPE", self.name, user.te_roles_rules)
1025                    newte += re.sub("ROLE", role, tmp)
1026        return newte
1027
1028    def generate_te(self):
1029        newte = self.generate_default_types()
1030        for d in self.DEFAULT_KEYS:
1031            if len(self.DEFAULT_DIRS[d][1]) > 0:
1032                # CGI scripts already have a rw_t
1033                if self.type != CGI or d != "rw":
1034                    newte += re.sub("TEMPLATETYPE", self.name, self.DEFAULT_DIRS[d][2].te_types)
1035
1036        if self.type != EUSER:
1037            newte += """
1038########################################
1039#
1040# %s local policy
1041#
1042""" % self.name
1043        newte += self.generate_capabilities()
1044        newte += self.generate_process()
1045        newte += self.generate_network_types()
1046        newte += self.generate_tmp_types()
1047        newte += self.generate_booleans()
1048        newte += self.generate_default_rules()
1049        newte += self.generate_boolean_rules()
1050
1051        for d in self.DEFAULT_KEYS:
1052            if len(self.DEFAULT_DIRS[d][1]) > 0:
1053                if self.type == EUSER:
1054                    newte_tmp = ""
1055                    for domain in self.existing_domains:
1056                        newte_tmp += re.sub("TEMPLATETYPE_t", domain[:-2] + "_t", self.DEFAULT_DIRS[d][2].te_rules)
1057                        newte += re.sub("TEMPLATETYPE_rw_t", self.name + "_rw_t", newte_tmp)
1058                else:
1059                    newte += re.sub("TEMPLATETYPE", self.name, self.DEFAULT_DIRS[d][2].te_rules)
1060                for i in self.DEFAULT_DIRS[d][1]:
1061                    if os.path.exists(i) and stat.S_ISSOCK(os.stat(i)[stat.ST_MODE]):
1062                        if self.type == EUSER:
1063                            for domain in self.existing_domains:
1064                                newte += re.sub("TEMPLATETYPE", domain[:-2], self.DEFAULT_DIRS[d][2].te_stream_rules)
1065
1066                        else:
1067                            newte += re.sub("TEMPLATETYPE", self.name, self.DEFAULT_DIRS[d][2].te_stream_rules)
1068                        break
1069
1070        newte += self.generate_tmp_rules()
1071        newte += self.generate_network_rules()
1072        newte += self.generate_fd_rules()
1073        newte += self.generate_etc_rules()
1074        newte += self.generate_pam_rules()
1075        newte += self.generate_uid_rules()
1076        newte += self.generate_audit_rules()
1077        newte += self.generate_syslog_rules()
1078        newte += self.generate_localization_rules()
1079        newte += self.generate_resolve_rules()
1080        newte += self.generate_roles_rules()
1081        newte += self.generate_mail_rules()
1082        newte += self.generate_transition_rules()
1083        newte += self.generate_admin_rules()
1084        newte += self.generate_dbus_rules()
1085        newte += self.generate_kerberos_rules()
1086        newte += self.generate_manage_krb5_rcache_rules()
1087
1088        return newte
1089
1090    def generate_fc(self):
1091        newfc = ""
1092        fclist = []
1093        for i in self.files.keys():
1094            if os.path.exists(i) and stat.S_ISSOCK(os.stat(i)[stat.ST_MODE]):
1095                t1 = re.sub("TEMPLATETYPE", self.name, self.files[i][2].fc_sock_file)
1096            else:
1097                t1 = re.sub("TEMPLATETYPE", self.name, self.files[i][2].fc_file)
1098            t2 = re.sub("FILENAME", i, t1)
1099            fclist.append(re.sub("FILETYPE", self.files[i][0], t2))
1100
1101        for i in self.dirs.keys():
1102            t1 = re.sub("TEMPLATETYPE", self.name, self.dirs[i][2].fc_dir)
1103            t2 = re.sub("FILENAME", i, t1)
1104            fclist.append(re.sub("FILETYPE", self.dirs[i][0], t2))
1105
1106        if self.type in USERS + [SANDBOX]:
1107            if len(fclist) == 0:
1108                return executable.fc_user
1109
1110        if self.type not in USERS + [SANDBOX, EUSER, NEWTYPE] and not self.program:
1111            raise ValueError(_("You must enter the executable path for your confined process"))
1112
1113        if self.program:
1114            t1 = re.sub("EXECUTABLE", self.program, executable.fc_program)
1115            fclist.append(re.sub("TEMPLATETYPE", self.name, t1))
1116
1117        if self.initscript != "":
1118            t1 = re.sub("EXECUTABLE", self.initscript, executable.fc_initscript)
1119            fclist.append(re.sub("TEMPLATETYPE", self.name, t1))
1120
1121        fclist.sort()
1122        newfc = "\n".join(fclist)
1123        return newfc
1124
1125    def generate_user_sh(self):
1126        newsh = ""
1127        if self.type not in (TUSER, XUSER, AUSER, LUSER, RUSER):
1128            return newsh
1129
1130        roles = ""
1131        for role in self.roles:
1132            roles += " %s_r" % role
1133        if roles != "":
1134            roles += " system_r"
1135        tmp = re.sub("TEMPLATETYPE", self.name, script.users)
1136        newsh += re.sub("ROLES", roles, tmp)
1137
1138        if self.type == RUSER or self.type == AUSER:
1139            for u in self.transition_users:
1140                tmp = re.sub("TEMPLATETYPE", self.name, script.admin_trans)
1141                newsh += re.sub("USER", u, tmp)
1142
1143        if self.type == LUSER:
1144            newsh += re.sub("TEMPLATETYPE", self.name, script.min_login_user_default_context)
1145        else:
1146            newsh += re.sub("TEMPLATETYPE", self.name, script.x_login_user_default_context)
1147
1148        return newsh
1149
1150    def generate_sh(self):
1151        temp = re.sub("TEMPLATETYPE", self.file_name, script.compile)
1152        temp = re.sub("DOMAINTYPE", self.name, temp)
1153        if self.type == EUSER:
1154            newsh = re.sub("TEMPLATEFILE", "%s" % self.file_name, temp)
1155        else:
1156            newsh = re.sub("TEMPLATEFILE", self.file_name, temp)
1157            newsh += re.sub("DOMAINTYPE", self.name, script.manpage)
1158
1159        if self.program:
1160            newsh += re.sub("FILENAME", self.program, script.restorecon)
1161        if self.initscript != "":
1162            newsh += re.sub("FILENAME", self.initscript, script.restorecon)
1163
1164        for i in self.files.keys():
1165            newsh += re.sub("FILENAME", i, script.restorecon)
1166
1167        for i in self.dirs.keys():
1168            newsh += re.sub("FILENAME", i, script.restorecon)
1169
1170        for i in self.in_tcp[PORTS] + self.out_tcp[PORTS]:
1171            if self.find_port(i, "tcp") is None:
1172                t1 = re.sub("PORTNUM", "%d" % i, script.tcp_ports)
1173                newsh += re.sub("TEMPLATETYPE", self.name, t1)
1174
1175        for i in self.in_udp[PORTS]:
1176            if self.find_port(i, "udp") is None:
1177                t1 = re.sub("PORTNUM", "%d" % i, script.udp_ports)
1178                newsh += re.sub("TEMPLATETYPE", self.name, t1)
1179
1180        newsh += self.generate_user_sh()
1181        newsh += re.sub("TEMPLATEFILE", self.file_name, script.rpm)
1182
1183        return newsh
1184
1185    def generate_spec(self):
1186        newspec = ""
1187
1188        selinux_policynvr = get_rpm_nvr_list("selinux-policy")
1189
1190        if selinux_policynvr is None:
1191            selinux_policyver = "0.0.0"
1192        else:
1193            selinux_policyver = selinux_policynvr[1]
1194
1195        newspec += spec.header_comment_section
1196        if self.type in APPLICATIONS:
1197            newspec += spec.define_relabel_files_begin
1198            if self.program:
1199                newspec += re.sub("FILENAME", self.program, spec.define_relabel_files_end)
1200            if self.initscript != "":
1201                newspec += re.sub("FILENAME", self.initscript, spec.define_relabel_files_end)
1202            for i in self.files.keys():
1203                newspec += re.sub("FILENAME", i, spec.define_relabel_files_end)
1204            for i in self.dirs.keys():
1205                newspec += re.sub("FILENAME", i, spec.define_relabel_files_end)
1206
1207        newspec += re.sub("VERSION", selinux_policyver, spec.base_section)
1208        newspec = re.sub("MODULENAME", self.file_name, newspec)
1209        newspec = re.sub("DOMAINNAME", self.name, newspec)
1210        if len(self.rpms) > 0:
1211            newspec += "Requires(post): %s\n" % ", ".join(self.rpms)
1212        newspec += re.sub("MODULENAME", self.file_name, spec.mid_section)
1213        newspec = re.sub("DOMAINNAME", self.name, newspec)
1214        newspec = re.sub("TODAYSDATE", time.strftime("%a %b %e %Y"), newspec)
1215
1216        if self.type not in APPLICATIONS:
1217            newspec = re.sub("%relabel_files", "", newspec)
1218
1219        # Remove man pages from EUSER spec file
1220        if self.type == EUSER:
1221            newspec = re.sub(".*%s_selinux.8.*" % self.name, "", newspec)
1222        # Remove user context file from non users spec file
1223        if self.type not in (TUSER, XUSER, AUSER, LUSER, RUSER):
1224            newspec = re.sub(".*%s_u.*" % self.name, "", newspec)
1225        return newspec
1226
1227    def write_spec(self, out_dir):
1228        specfile = "%s/%s_selinux.spec" % (out_dir, self.file_name)
1229        fd = open(specfile, "w")
1230        fd.write(self.generate_spec())
1231        fd.close()
1232
1233        return specfile
1234
1235    def write_te(self, out_dir):
1236        tefile = "%s/%s.te" % (out_dir, self.file_name)
1237        fd = open(tefile, "w")
1238        fd.write(self.generate_te())
1239        fd.close()
1240        return tefile
1241
1242    def write_sh(self, out_dir):
1243        shfile = "%s/%s.sh" % (out_dir, self.file_name)
1244        fd = open(shfile, "w")
1245        fd.write(self.generate_sh())
1246        fd.close()
1247        os.chmod(shfile, 0o750)
1248        return shfile
1249
1250    def write_if(self, out_dir):
1251        iffile = "%s/%s.if" % (out_dir, self.file_name)
1252        fd = open(iffile, "w")
1253        fd.write(self.generate_if())
1254        fd.close()
1255        return iffile
1256
1257    def write_fc(self, out_dir):
1258        fcfile = "%s/%s.fc" % (out_dir, self.file_name)
1259        fd = open(fcfile, "w")
1260        fd.write(self.generate_fc())
1261        fd.close()
1262        return fcfile
1263
1264    def __extract_rpms(self):
1265        import yum
1266        yb = yum.YumBase()
1267        yb.setCacheDir()
1268
1269        for pkg in yb.rpmdb.searchProvides(self.program):
1270            self.rpms.append(pkg.name)
1271            for fname in pkg.dirlist + pkg.filelist + pkg.ghostlist:
1272                for b in self.DEFAULT_DIRS:
1273                    if b == "/etc":
1274                        continue
1275                    if fname.startswith(b):
1276                        if os.path.isfile(fname):
1277                            self.add_file(fname)
1278                        else:
1279                            self.add_dir(fname)
1280
1281            for bpkg in yb.rpmdb.searchNames([pkg.base_package_name]):
1282                for fname in bpkg.dirlist + bpkg.filelist + bpkg.ghostlist:
1283                    for b in self.DEFAULT_DIRS:
1284                        if b == "/etc":
1285                            continue
1286                        if fname.startswith(b):
1287                            if os.path.isfile(fname):
1288                                self.add_file(fname)
1289                            else:
1290                                self.add_dir(fname)
1291
1292        # some packages have own systemd subpackage
1293        # tor-systemd for example
1294        binary_name = self.program.split("/")[-1]
1295        for bpkg in yb.rpmdb.searchNames(["%s-systemd" % binary_name]):
1296            for fname in bpkg.filelist + bpkg.ghostlist + bpkg.dirlist:
1297                for b in self.DEFAULT_DIRS:
1298                    if b == "/etc":
1299                        continue
1300                    if fname.startswith(b):
1301                        if os.path.isfile(fname):
1302                            self.add_file(fname)
1303                        else:
1304                            self.add_dir(fname)
1305
1306    def gen_writeable(self):
1307        try:
1308            self.__extract_rpms()
1309        except ImportError:
1310            pass
1311
1312        if os.path.isfile("/var/run/%s.pid" % self.name):
1313            self.add_file("/var/run/%s.pid" % self.name)
1314
1315        if os.path.isdir("/var/run/%s" % self.name):
1316            self.add_dir("/var/run/%s" % self.name)
1317
1318        if os.path.isdir("/var/log/%s" % self.name):
1319            self.add_dir("/var/log/%s" % self.name)
1320
1321        if os.path.isfile("/var/log/%s.log" % self.name):
1322            self.add_file("/var/log/%s.log" % self.name)
1323
1324        if os.path.isdir("/var/lib/%s" % self.name):
1325            self.add_dir("/var/lib/%s" % self.name)
1326
1327        if os.path.isfile("/etc/rc.d/init.d/%s" % self.name):
1328            self.set_init_script(r"/etc/rc\.d/init\.d/%s" % self.name)
1329
1330        # we don't want to have subdir in the .fc policy file
1331        # if we already specify labeling for parent dir
1332        temp_basepath = []
1333        for p in self.DEFAULT_DIRS.keys():
1334            temp_dirs = []
1335            try:
1336                temp_basepath = self.DEFAULT_DIRS[p][1][0] + "/"
1337            except IndexError:
1338                continue
1339
1340            for i in self.DEFAULT_DIRS[p][1]:
1341                if i.startswith(temp_basepath):
1342                    temp_dirs.append(i)
1343                else:
1344                    continue
1345
1346            if len(temp_dirs) != 0:
1347                for i in temp_dirs:
1348                    if i in self.dirs.keys():
1349                        del self.dirs[i]
1350                    elif i in self.files.keys():
1351                        del self.files[i]
1352                    else:
1353                        continue
1354
1355                self.DEFAULT_DIRS[p][1] = list(set(self.DEFAULT_DIRS[p][1]) - set(temp_dirs))
1356
1357    def gen_symbols(self):
1358        if self.type not in APPLICATIONS:
1359            return
1360        if not os.path.exists(self.program):
1361            sys.stderr.write("""
1362***************************************
1363Warning %s does not exist
1364***************************************
1365
1366""" % self.program)
1367            return
1368        fd = os.popen("nm -D %s | grep U" % self.program)
1369        for s in fd.read().split():
1370            for b in self.symbols:
1371                if s.startswith(b):
1372                    exec("self.%s" % self.symbols[b])
1373        fd.close()
1374
1375    def generate(self, out_dir=os.getcwd()):
1376        out = _("Created the following files:\n")
1377        out += "%s # %s\n" % (self.write_te(out_dir), _("Type Enforcement file"))
1378        out += "%s # %s\n" % (self.write_if(out_dir), _("Interface file"))
1379        out += "%s # %s\n" % (self.write_fc(out_dir), _("File Contexts file"))
1380        if self.type != NEWTYPE:
1381            out += "%s # %s\n" % (self.write_spec(out_dir), _("Spec file"))
1382            out += "%s # %s\n" % (self.write_sh(out_dir), _("Setup Script"))
1383        return out
1384