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