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