seobject.py revision 468a0dbac8a396c16bf36aa41736642ee19cef2c
1#! /usr/bin/python -Es
2# Copyright (C) 2005-2013 Red Hat
3# see file 'COPYING' for use and warranty information
4#
5# semanage is a tool for managing SELinux configuration files
6#
7#    This program is free software; you can redistribute it and/or
8#    modify it under the terms of the GNU General Public License as
9#    published by the Free Software Foundation; either version 2 of
10#    the License, or (at your option) any later version.
11#
12#    This program is distributed in the hope that it will be useful,
13#    but WITHOUT ANY WARRANTY; without even the implied warranty of
14#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15#    GNU General Public License for more details.
16#
17#    You should have received a copy of the GNU General Public License
18#    along with this program; if not, write to the Free Software
19#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20#                                        02111-1307  USA
21#
22#
23
24import pwd
25import grp
26import selinux
27import os
28import re
29import sys
30import stat
31import socket
32from semanage import *
33PROGNAME = "policycoreutils"
34import sepolicy
35from IPy import IP
36
37try:
38    import gettext
39    kwargs = {}
40    if sys.version_info < (3,):
41        kwargs['unicode'] = True
42    gettext.install(PROGNAME,
43                    localedir="/usr/share/locale",
44                    codeset='utf-8',
45                    **kwargs)
46except:
47    try:
48        import builtins
49        builtins.__dict__['_'] = str
50    except ImportError:
51        import __builtin__
52        __builtin__.__dict__['_'] = unicode
53
54import syslog
55
56file_types = {}
57file_types[""] = SEMANAGE_FCONTEXT_ALL
58file_types["all files"] = SEMANAGE_FCONTEXT_ALL
59file_types["a"] = SEMANAGE_FCONTEXT_ALL
60file_types["regular file"] = SEMANAGE_FCONTEXT_REG
61file_types["--"] = SEMANAGE_FCONTEXT_REG
62file_types["f"] = SEMANAGE_FCONTEXT_REG
63file_types["-d"] = SEMANAGE_FCONTEXT_DIR
64file_types["directory"] = SEMANAGE_FCONTEXT_DIR
65file_types["d"] = SEMANAGE_FCONTEXT_DIR
66file_types["-c"] = SEMANAGE_FCONTEXT_CHAR
67file_types["character device"] = SEMANAGE_FCONTEXT_CHAR
68file_types["c"] = SEMANAGE_FCONTEXT_CHAR
69file_types["-b"] = SEMANAGE_FCONTEXT_BLOCK
70file_types["block device"] = SEMANAGE_FCONTEXT_BLOCK
71file_types["b"] = SEMANAGE_FCONTEXT_BLOCK
72file_types["-s"] = SEMANAGE_FCONTEXT_SOCK
73file_types["socket"] = SEMANAGE_FCONTEXT_SOCK
74file_types["s"] = SEMANAGE_FCONTEXT_SOCK
75file_types["-l"] = SEMANAGE_FCONTEXT_LINK
76file_types["l"] = SEMANAGE_FCONTEXT_LINK
77file_types["symbolic link"] = SEMANAGE_FCONTEXT_LINK
78file_types["p"] = SEMANAGE_FCONTEXT_PIPE
79file_types["-p"] = SEMANAGE_FCONTEXT_PIPE
80file_types["named pipe"] = SEMANAGE_FCONTEXT_PIPE
81
82file_type_str_to_option = {"all files": "a",
83                           "regular file": "f",
84                           "directory": "d",
85                           "character device": "c",
86                           "block device": "b",
87                           "socket file": "s",
88                           "symbolic link": "l",
89                           "named pipe": "p"}
90
91ftype_to_audit = {"": "any",
92                  "a" : "any",
93                  "b": "block",
94                  "c": "char",
95                  "d": "dir",
96                  "f": "file",
97                  "l": "symlink",
98                  "p": "pipe",
99                  "s": "socket"}
100
101try:
102    import audit
103
104    class logger:
105
106        def __init__(self):
107            self.audit_fd = audit.audit_open()
108            self.log_list = []
109            self.log_change_list = []
110
111        def log(self, msg, name="", sename="", serole="", serange="", oldsename="", oldserole="", oldserange=""):
112
113            sep = "-"
114            if sename != oldsename:
115                msg += sep + "sename"
116                sep = ","
117            if serole != oldserole:
118                msg += sep + "role"
119                sep = ","
120            if serange != oldserange:
121                msg += sep + "range"
122                sep = ","
123
124            self.log_list.append([self.audit_fd, audit.AUDIT_ROLE_ASSIGN, sys.argv[0], str(msg), name, 0, sename, serole, serange, oldsename, oldserole, oldserange, "", "", ""])
125
126        def log_remove(self, msg, name="", sename="", serole="", serange="", oldsename="", oldserole="", oldserange=""):
127            self.log_list.append([self.audit_fd, audit.AUDIT_ROLE_REMOVE, sys.argv[0], str(msg), name, 0, sename, serole, serange, oldsename, oldserole, oldserange, "", "", ""])
128
129        def log_change(self, msg):
130            self.log_change_list.append([self.audit_fd, audit.AUDIT_USER_MAC_CONFIG_CHANGE, str(msg), "semanage", "", "", ""])
131
132        def commit(self, success):
133            for l in self.log_list:
134                audit.audit_log_semanage_message(*(l + [success]))
135            for l in self.log_change_list:
136                audit.audit_log_user_comm_message(*(l + [success]))
137
138            self.log_list = []
139            self.log_change_list = []
140except:
141    class logger:
142
143        def __init__(self):
144            self.log_list = []
145
146        def log(self, msg, name="", sename="", serole="", serange="", oldsename="", oldserole="", oldserange=""):
147            message = " %s name=%s" % (msg, name)
148            if sename != "":
149                message += " sename=" + sename
150            if oldsename != "":
151                message += " oldsename=" + oldsename
152            if serole != "":
153                message += " role=" + serole
154            if oldserole != "":
155                message += " old_role=" + oldserole
156            if serange != "" and serange is not None:
157                message += " MLSRange=" + serange
158            if oldserange != "" and oldserange is not None:
159                message += " old_MLSRange=" + oldserange
160            self.log_list.append(message)
161
162        def log_remove(self, msg, name="", sename="", serole="", serange="", oldsename="", oldserole="", oldserange=""):
163            self.log(msg, name, sename, serole, serange, oldsename, oldserole, oldserange)
164
165        def log_change(self, msg):
166            self.log_list.append(" %s" % msg)
167
168        def commit(self, success):
169            if success == 1:
170                message = "Successful: "
171            else:
172                message = "Failed: "
173            for l in self.log_list:
174                syslog.syslog(syslog.LOG_INFO, message + l)
175
176
177class nulllogger:
178
179    def log(self, msg, name="", sename="", serole="", serange="", oldsename="", oldserole="", oldserange=""):
180        pass
181
182    def log_remove(self, msg, name="", sename="", serole="", serange="", oldsename="", oldserole="", oldserange=""):
183        pass
184
185    def log_change(self, msg):
186        pass
187
188    def commit(self, success):
189        pass
190
191
192def validate_level(raw):
193    sensitivity = "s[0-9]*"
194    category = "c[0-9]*"
195    cat_range = category + "(\." + category + ")?"
196    categories = cat_range + "(\," + cat_range + ")*"
197    reg = sensitivity + "(-" + sensitivity + ")?" + "(:" + categories + ")?"
198    return re.search("^" + reg + "$", raw)
199
200
201def translate(raw, prepend=1):
202    filler = "a:b:c:"
203    if prepend == 1:
204        context = "%s%s" % (filler, raw)
205    else:
206        context = raw
207    (rc, trans) = selinux.selinux_raw_to_trans_context(context)
208    if rc != 0:
209        return raw
210    if prepend:
211        trans = trans[len(filler):]
212    if trans == "":
213        return raw
214    else:
215        return trans
216
217
218def untranslate(trans, prepend=1):
219    filler = "a:b:c:"
220    if prepend == 1:
221        context = "%s%s" % (filler, trans)
222    else:
223        context = trans
224
225    (rc, raw) = selinux.selinux_trans_to_raw_context(context)
226    if rc != 0:
227        return trans
228    if prepend:
229        raw = raw[len(filler):]
230    if raw == "":
231        return trans
232    else:
233        return raw
234
235
236class semanageRecords:
237    transaction = False
238    handle = None
239    store = None
240
241    def __init__(self, store):
242        global handle
243        self.load = True
244        self.sh = self.get_handle(store)
245
246        rc, localstore = selinux.selinux_getpolicytype()
247        if store == "" or store == localstore:
248            self.mylog = logger()
249        else:
250            self.mylog = nulllogger()
251
252    def set_reload(self, load):
253        self.load = load
254
255    def get_handle(self, store):
256        global is_mls_enabled
257
258        if semanageRecords.handle:
259            return semanageRecords.handle
260
261        handle = semanage_handle_create()
262        if not handle:
263            raise ValueError(_("Could not create semanage handle"))
264
265        if not semanageRecords.transaction and store != "":
266            semanage_select_store(handle, store, SEMANAGE_CON_DIRECT)
267            semanageRecords.store = store
268
269        if not semanage_is_managed(handle):
270            semanage_handle_destroy(handle)
271            raise ValueError(_("SELinux policy is not managed or store cannot be accessed."))
272
273        rc = semanage_access_check(handle)
274        if rc < SEMANAGE_CAN_READ:
275            semanage_handle_destroy(handle)
276            raise ValueError(_("Cannot read policy store."))
277
278        rc = semanage_connect(handle)
279        if rc < 0:
280            semanage_handle_destroy(handle)
281            raise ValueError(_("Could not establish semanage connection"))
282
283        is_mls_enabled = semanage_mls_enabled(handle)
284        if is_mls_enabled < 0:
285            semanage_handle_destroy(handle)
286            raise ValueError(_("Could not test MLS enabled status"))
287
288        semanageRecords.handle = handle
289        return semanageRecords.handle
290
291    def deleteall(self):
292        raise ValueError(_("Not yet implemented"))
293
294    def start(self):
295        if semanageRecords.transaction:
296            raise ValueError(_("Semanage transaction already in progress"))
297        self.begin()
298        semanageRecords.transaction = True
299
300    def begin(self):
301        if semanageRecords.transaction:
302            return
303        rc = semanage_begin_transaction(self.sh)
304        if rc < 0:
305            raise ValueError(_("Could not start semanage transaction"))
306
307    def customized(self):
308        raise ValueError(_("Not yet implemented"))
309
310    def commit(self):
311        if semanageRecords.transaction:
312            return
313
314        semanage_set_reload(self.sh, self.load)
315        rc = semanage_commit(self.sh)
316        if rc < 0:
317            self.mylog.commit(0)
318            raise ValueError(_("Could not commit semanage transaction"))
319        self.mylog.commit(1)
320
321    def finish(self):
322        if not semanageRecords.transaction:
323            raise ValueError(_("Semanage transaction not in progress"))
324        semanageRecords.transaction = False
325        self.commit()
326
327
328class moduleRecords(semanageRecords):
329
330    def __init__(self, store):
331        semanageRecords.__init__(self, store)
332
333    def get_all(self):
334        l = []
335        (rc, mlist, number) = semanage_module_list_all(self.sh)
336        if rc < 0:
337            raise ValueError(_("Could not list SELinux modules"))
338
339        for i in range(number):
340            mod = semanage_module_list_nth(mlist, i)
341
342            rc, name = semanage_module_info_get_name(self.sh, mod)
343            if rc < 0:
344                raise ValueError(_("Could not get module name"))
345
346            rc, enabled = semanage_module_info_get_enabled(self.sh, mod)
347            if rc < 0:
348                raise ValueError(_("Could not get module enabled"))
349
350            rc, priority = semanage_module_info_get_priority(self.sh, mod)
351            if rc < 0:
352                raise ValueError(_("Could not get module priority"))
353
354            rc, lang_ext = semanage_module_info_get_lang_ext(self.sh, mod)
355            if rc < 0:
356                raise ValueError(_("Could not get module lang_ext"))
357
358            l.append((name, enabled, priority, lang_ext))
359
360        # sort the list so they are in name order, but with higher priorities coming first
361        l.sort(key=lambda t: t[3], reverse=True)
362        l.sort(key=lambda t: t[0])
363        return l
364
365    def customized(self):
366        all = self.get_all()
367        if len(all) == 0:
368            return
369        return ["-d %s" % x[0] for x in [t for t in all if t[1] == 0]]
370
371    def list(self, heading=1, locallist=0):
372        all = self.get_all()
373        if len(all) == 0:
374            return
375
376        if heading:
377            print("\n%-25s %-9s %s\n" % (_("Module Name"), _("Priority"), _("Language")))
378        for t in all:
379            if t[1] == 0:
380                disabled = _("Disabled")
381            else:
382                if locallist:
383                    continue
384                disabled = ""
385            print("%-25s %-9s %-5s %s" % (t[0], t[2], t[3], disabled))
386
387    def add(self, file, priority):
388        if not os.path.exists(file):
389            raise ValueError(_("Module does not exists %s ") % file)
390
391        rc = semanage_set_default_priority(self.sh, priority)
392        if rc < 0:
393            raise ValueError(_("Invalid priority %d (needs to be between 1 and 999)") % priority)
394
395        rc = semanage_module_install_file(self.sh, file)
396        if rc >= 0:
397            self.commit()
398
399    def set_enabled(self, module, enable):
400        for m in module.split():
401            rc, key = semanage_module_key_create(self.sh)
402            if rc < 0:
403                raise ValueError(_("Could not create module key"))
404
405            rc = semanage_module_key_set_name(self.sh, key, m)
406            if rc < 0:
407                raise ValueError(_("Could not set module key name"))
408
409            rc = semanage_module_set_enabled(self.sh, key, enable)
410            if rc < 0:
411                if enable:
412                    raise ValueError(_("Could not enable module %s") % m)
413                else:
414                    raise ValueError(_("Could not disable module %s") % m)
415        self.commit()
416
417    def modify(self, file):
418        rc = semanage_module_update_file(self.sh, file)
419        if rc >= 0:
420            self.commit()
421
422    def delete(self, module, priority):
423        rc = semanage_set_default_priority(self.sh, priority)
424        if rc < 0:
425            raise ValueError(_("Invalid priority %d (needs to be between 1 and 999)") % priority)
426
427        for m in module.split():
428            rc = semanage_module_remove(self.sh, m)
429            if rc < 0 and rc != -2:
430                raise ValueError(_("Could not remove module %s (remove failed)") % m)
431
432        self.commit()
433
434    def deleteall(self):
435        l = [x[0] for x in [t for t in self.get_all() if t[1] == 0]]
436        for m in l:
437            self.set_enabled(m, True)
438
439
440class dontauditClass(semanageRecords):
441
442    def __init__(self, store):
443        semanageRecords.__init__(self, store)
444
445    def toggle(self, dontaudit):
446        if dontaudit not in ["on", "off"]:
447            raise ValueError(_("dontaudit requires either 'on' or 'off'"))
448        self.begin()
449        semanage_set_disable_dontaudit(self.sh, dontaudit == "off")
450        self.commit()
451
452
453class permissiveRecords(semanageRecords):
454
455    def __init__(self, store):
456        semanageRecords.__init__(self, store)
457
458    def get_all(self):
459        l = []
460        (rc, mlist, number) = semanage_module_list(self.sh)
461        if rc < 0:
462            raise ValueError(_("Could not list SELinux modules"))
463
464        for i in range(number):
465            mod = semanage_module_list_nth(mlist, i)
466            name = semanage_module_get_name(mod)
467            if name and name.startswith("permissive_"):
468                l.append(name.split("permissive_")[1])
469        return l
470
471    def list(self, heading=1, locallist=0):
472        all = [y["name"] for y in [x for x in sepolicy.info(sepolicy.TYPE) if x["permissive"]]]
473        if len(all) == 0:
474            return
475
476        if heading:
477            print("\n%-25s\n" % (_("Builtin Permissive Types")))
478        customized = self.get_all()
479        for t in all:
480            if t not in customized:
481                print(t)
482
483        if len(customized) == 0:
484            return
485
486        if heading:
487            print("\n%-25s\n" % (_("Customized Permissive Types")))
488        for t in customized:
489            print(t)
490
491    def add(self, type):
492        try:
493            import sepolgen.module as module
494        except ImportError:
495            raise ValueError(_("The sepolgen python module is required to setup permissive domains.\nIn some distributions it is included in the policycoreutils-devel patckage.\n# yum install policycoreutils-devel\nOr similar for your distro."))
496
497        name = "permissive_%s" % type
498        modtxt = "(typepermissive %s)" % type
499
500        rc = semanage_module_install(self.sh, modtxt, len(modtxt), name, "cil")
501        if rc >= 0:
502            self.commit()
503
504        if rc < 0:
505            raise ValueError(_("Could not set permissive domain %s (module installation failed)") % name)
506
507    def delete(self, name):
508        for n in name.split():
509            rc = semanage_module_remove(self.sh, "permissive_%s" % n)
510            if rc < 0:
511                raise ValueError(_("Could not remove permissive domain %s (remove failed)") % name)
512
513        self.commit()
514
515    def deleteall(self):
516        l = self.get_all()
517        if len(l) > 0:
518            all = " ".join(l)
519            self.delete(all)
520
521
522class loginRecords(semanageRecords):
523
524    def __init__(self, store=""):
525        semanageRecords.__init__(self, store)
526        self.oldsename = None
527        self.oldserange = None
528        self.sename = None
529        self.serange = None
530
531    def __add(self, name, sename, serange):
532        rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
533        if sename == "":
534            sename = "user_u"
535
536        userrec = seluserRecords()
537        range, (rc, oldserole) = userrec.get(self.oldsename)
538        range, (rc, serole) = userrec.get(sename)
539
540        if is_mls_enabled == 1:
541            if serange != "":
542                serange = untranslate(serange)
543            else:
544                serange = range
545
546        (rc, k) = semanage_seuser_key_create(self.sh, name)
547        if rc < 0:
548            raise ValueError(_("Could not create a key for %s") % name)
549
550        (rc, exists) = semanage_seuser_exists(self.sh, k)
551        if rc < 0:
552            raise ValueError(_("Could not check if login mapping for %s is defined") % name)
553        if exists:
554            raise ValueError(_("Login mapping for %s is already defined") % name)
555        if name[0] == '%':
556            try:
557                grp.getgrnam(name[1:])
558            except:
559                raise ValueError(_("Linux Group %s does not exist") % name[1:])
560        else:
561            try:
562                pwd.getpwnam(name)
563            except:
564                raise ValueError(_("Linux User %s does not exist") % name)
565
566        (rc, u) = semanage_seuser_create(self.sh)
567        if rc < 0:
568            raise ValueError(_("Could not create login mapping for %s") % name)
569
570        rc = semanage_seuser_set_name(self.sh, u, name)
571        if rc < 0:
572            raise ValueError(_("Could not set name for %s") % name)
573
574        if (is_mls_enabled == 1) and (serange != ""):
575            rc = semanage_seuser_set_mlsrange(self.sh, u, serange)
576            if rc < 0:
577                raise ValueError(_("Could not set MLS range for %s") % name)
578
579        rc = semanage_seuser_set_sename(self.sh, u, sename)
580        if rc < 0:
581            raise ValueError(_("Could not set SELinux user for %s") % name)
582
583        rc = semanage_seuser_modify_local(self.sh, k, u)
584        if rc < 0:
585            raise ValueError(_("Could not add login mapping for %s") % name)
586
587        semanage_seuser_key_free(k)
588        semanage_seuser_free(u)
589        self.mylog.log("login", name, sename=sename, serange=serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
590
591    def add(self, name, sename, serange):
592        try:
593            self.begin()
594            self.__add(name, sename, serange)
595            self.commit()
596        except ValueError as error:
597            self.mylog.commit(0)
598            raise error
599
600    def __modify(self, name, sename="", serange=""):
601        rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
602        if sename == "" and serange == "":
603            raise ValueError(_("Requires seuser or serange"))
604
605        userrec = seluserRecords()
606        range, (rc, oldserole) = userrec.get(self.oldsename)
607
608        if sename != "":
609            range, (rc, serole) = userrec.get(sename)
610        else:
611            serole = oldserole
612
613        if serange != "":
614            self.serange = serange
615        else:
616            self.serange = range
617
618        (rc, k) = semanage_seuser_key_create(self.sh, name)
619        if rc < 0:
620            raise ValueError(_("Could not create a key for %s") % name)
621
622        (rc, exists) = semanage_seuser_exists(self.sh, k)
623        if rc < 0:
624            raise ValueError(_("Could not check if login mapping for %s is defined") % name)
625        if not exists:
626            raise ValueError(_("Login mapping for %s is not defined") % name)
627
628        (rc, u) = semanage_seuser_query(self.sh, k)
629        if rc < 0:
630            raise ValueError(_("Could not query seuser for %s") % name)
631
632        self.oldserange = semanage_seuser_get_mlsrange(u)
633        self.oldsename = semanage_seuser_get_sename(u)
634        if (is_mls_enabled == 1) and (serange != ""):
635            semanage_seuser_set_mlsrange(self.sh, u, untranslate(serange))
636
637        if sename != "":
638            semanage_seuser_set_sename(self.sh, u, sename)
639            self.sename = sename
640        else:
641            self.sename = self.oldsename
642
643        rc = semanage_seuser_modify_local(self.sh, k, u)
644        if rc < 0:
645            raise ValueError(_("Could not modify login mapping for %s") % name)
646
647        semanage_seuser_key_free(k)
648        semanage_seuser_free(u)
649        self.mylog.log("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
650
651    def modify(self, name, sename="", serange=""):
652        try:
653            self.begin()
654            self.__modify(name, sename, serange)
655            self.commit()
656        except ValueError as error:
657            self.mylog.commit(0)
658            raise error
659
660    def __delete(self, name):
661        rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
662        userrec = seluserRecords()
663        range, (rc, oldserole) = userrec.get(self.oldsename)
664
665        (rc, k) = semanage_seuser_key_create(self.sh, name)
666        if rc < 0:
667            raise ValueError(_("Could not create a key for %s") % name)
668
669        (rc, exists) = semanage_seuser_exists(self.sh, k)
670        if rc < 0:
671            raise ValueError(_("Could not check if login mapping for %s is defined") % name)
672        if not exists:
673            raise ValueError(_("Login mapping for %s is not defined") % name)
674
675        (rc, exists) = semanage_seuser_exists_local(self.sh, k)
676        if rc < 0:
677            raise ValueError(_("Could not check if login mapping for %s is defined") % name)
678        if not exists:
679            raise ValueError(_("Login mapping for %s is defined in policy, cannot be deleted") % name)
680
681        rc = semanage_seuser_del_local(self.sh, k)
682        if rc < 0:
683            raise ValueError(_("Could not delete login mapping for %s") % name)
684
685        semanage_seuser_key_free(k)
686
687        rec, self.sename, self.serange = selinux.getseuserbyname("__default__")
688        range, (rc, serole) = userrec.get(self.sename)
689
690        self.mylog.log_remove("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
691
692    def delete(self, name):
693        try:
694            self.begin()
695            self.__delete(name)
696            self.commit()
697
698        except ValueError as error:
699            self.mylog.commit(0)
700            raise error
701
702    def deleteall(self):
703        (rc, ulist) = semanage_seuser_list_local(self.sh)
704        if rc < 0:
705            raise ValueError(_("Could not list login mappings"))
706
707        try:
708            self.begin()
709            for u in ulist:
710                self.__delete(semanage_seuser_get_name(u))
711            self.commit()
712        except ValueError as error:
713            self.mylog.commit(0)
714            raise error
715
716    def get_all_logins(self):
717        ddict = {}
718        self.logins_path = selinux.selinux_policy_root() + "/logins"
719        for path, dirs, files in os.walk(self.logins_path):
720            if path == self.logins_path:
721                for name in files:
722                    try:
723                        fd = open(path + "/" + name)
724                        rec = fd.read().rstrip().split(":")
725                        fd.close()
726                        ddict[name] = (rec[1], rec[2], rec[0])
727                    except IndexError:
728                        pass
729        return ddict
730
731    def get_all(self, locallist=0):
732        ddict = {}
733        if locallist:
734            (rc, self.ulist) = semanage_seuser_list_local(self.sh)
735        else:
736            (rc, self.ulist) = semanage_seuser_list(self.sh)
737        if rc < 0:
738            raise ValueError(_("Could not list login mappings"))
739
740        for u in self.ulist:
741            name = semanage_seuser_get_name(u)
742            ddict[name] = (semanage_seuser_get_sename(u), semanage_seuser_get_mlsrange(u), "*")
743        return ddict
744
745    def customized(self):
746        l = []
747        ddict = self.get_all(True)
748        for k in sorted(ddict.keys()):
749            l.append("-a -s %s -r '%s' %s" % (ddict[k][0], ddict[k][1], k))
750        return l
751
752    def list(self, heading=1, locallist=0):
753        ddict = self.get_all(locallist)
754        ldict = self.get_all_logins()
755        lkeys = sorted(ldict.keys())
756        keys = sorted(ddict.keys())
757        if len(keys) == 0 and len(lkeys) == 0:
758            return
759
760        if is_mls_enabled == 1:
761            if heading:
762                print("\n%-20s %-20s %-20s %s\n" % (_("Login Name"), _("SELinux User"), _("MLS/MCS Range"), _("Service")))
763            for k in keys:
764                u = ddict[k]
765                print("%-20s %-20s %-20s %s" % (k, u[0], translate(u[1]), u[2]))
766            if len(lkeys):
767                print("\nLocal customization in %s" % self.logins_path)
768
769            for k in lkeys:
770                u = ldict[k]
771                print("%-20s %-20s %-20s %s" % (k, u[0], translate(u[1]), u[2]))
772        else:
773            if heading:
774                print("\n%-25s %-25s\n" % (_("Login Name"), _("SELinux User")))
775            for k in keys:
776                print("%-25s %-25s" % (k, ddict[k][0]))
777
778
779class seluserRecords(semanageRecords):
780
781    def __init__(self, store=""):
782        semanageRecords.__init__(self, store)
783
784    def get(self, name):
785        (rc, k) = semanage_user_key_create(self.sh, name)
786        if rc < 0:
787            raise ValueError(_("Could not create a key for %s") % name)
788        (rc, exists) = semanage_user_exists(self.sh, k)
789        if rc < 0:
790            raise ValueError(_("Could not check if SELinux user %s is defined") % name)
791        (rc, u) = semanage_user_query(self.sh, k)
792        if rc < 0:
793            raise ValueError(_("Could not query user for %s") % name)
794        serange = semanage_user_get_mlsrange(u)
795        serole = semanage_user_get_roles(self.sh, u)
796        semanage_user_key_free(k)
797        semanage_user_free(u)
798        return serange, serole
799
800    def __add(self, name, roles, selevel, serange, prefix):
801        if is_mls_enabled == 1:
802            if serange == "":
803                serange = "s0"
804            else:
805                serange = untranslate(serange)
806
807            if selevel == "":
808                selevel = "s0"
809            else:
810                selevel = untranslate(selevel)
811
812        if len(roles) < 1:
813            raise ValueError(_("You must add at least one role for %s") % name)
814
815        (rc, k) = semanage_user_key_create(self.sh, name)
816        if rc < 0:
817            raise ValueError(_("Could not create a key for %s") % name)
818
819        (rc, exists) = semanage_user_exists(self.sh, k)
820        if rc < 0:
821            raise ValueError(_("Could not check if SELinux user %s is defined") % name)
822        if exists:
823            raise ValueError(_("SELinux user %s is already defined") % name)
824
825        (rc, u) = semanage_user_create(self.sh)
826        if rc < 0:
827            raise ValueError(_("Could not create SELinux user for %s") % name)
828
829        rc = semanage_user_set_name(self.sh, u, name)
830        if rc < 0:
831            raise ValueError(_("Could not set name for %s") % name)
832
833        for r in roles:
834            rc = semanage_user_add_role(self.sh, u, r)
835            if rc < 0:
836                raise ValueError(_("Could not add role %s for %s") % (r, name))
837
838        if is_mls_enabled == 1:
839            rc = semanage_user_set_mlsrange(self.sh, u, serange)
840            if rc < 0:
841                raise ValueError(_("Could not set MLS range for %s") % name)
842
843            rc = semanage_user_set_mlslevel(self.sh, u, selevel)
844            if rc < 0:
845                raise ValueError(_("Could not set MLS level for %s") % name)
846        rc = semanage_user_set_prefix(self.sh, u, prefix)
847        if rc < 0:
848            raise ValueError(_("Could not add prefix %s for %s") % (r, prefix))
849        (rc, key) = semanage_user_key_extract(self.sh, u)
850        if rc < 0:
851            raise ValueError(_("Could not extract key for %s") % name)
852
853        rc = semanage_user_modify_local(self.sh, k, u)
854        if rc < 0:
855            raise ValueError(_("Could not add SELinux user %s") % name)
856
857        semanage_user_key_free(k)
858        semanage_user_free(u)
859        self.mylog.log("seuser", sename=name, serole=",".join(roles), serange=serange)
860
861    def add(self, name, roles, selevel, serange, prefix):
862        try:
863            self.begin()
864            self.__add(name, roles, selevel, serange, prefix)
865            self.commit()
866        except ValueError as error:
867            self.mylog.commit(0)
868            raise error
869
870    def __modify(self, name, roles=[], selevel="", serange="", prefix=""):
871        oldserole = ""
872        oldserange = ""
873        newroles = " ".join(roles)
874        if prefix == "" and len(roles) == 0 and serange == "" and selevel == "":
875            if is_mls_enabled == 1:
876                raise ValueError(_("Requires prefix, roles, level or range"))
877            else:
878                raise ValueError(_("Requires prefix or roles"))
879
880        (rc, k) = semanage_user_key_create(self.sh, name)
881        if rc < 0:
882            raise ValueError(_("Could not create a key for %s") % name)
883
884        (rc, exists) = semanage_user_exists(self.sh, k)
885        if rc < 0:
886            raise ValueError(_("Could not check if SELinux user %s is defined") % name)
887        if not exists:
888            raise ValueError(_("SELinux user %s is not defined") % name)
889
890        (rc, u) = semanage_user_query(self.sh, k)
891        if rc < 0:
892            raise ValueError(_("Could not query user for %s") % name)
893
894        oldserange = semanage_user_get_mlsrange(u)
895        (rc, rlist) = semanage_user_get_roles(self.sh, u)
896        if rc >= 0:
897            oldserole = " ".join(rlist)
898
899        if (is_mls_enabled == 1) and (serange != ""):
900            semanage_user_set_mlsrange(self.sh, u, untranslate(serange))
901        if (is_mls_enabled == 1) and (selevel != ""):
902            semanage_user_set_mlslevel(self.sh, u, untranslate(selevel))
903
904        if prefix != "":
905            semanage_user_set_prefix(self.sh, u, prefix)
906
907        if len(roles) != 0:
908            for r in rlist:
909                if r not in roles:
910                    semanage_user_del_role(u, r)
911            for r in roles:
912                if r not in rlist:
913                    semanage_user_add_role(self.sh, u, r)
914
915        rc = semanage_user_modify_local(self.sh, k, u)
916        if rc < 0:
917            raise ValueError(_("Could not modify SELinux user %s") % name)
918
919        semanage_user_key_free(k)
920        semanage_user_free(u)
921
922        role = ",".join(newroles.split())
923        oldserole = ",".join(oldserole.split())
924        self.mylog.log("seuser", sename=name, oldsename=name, serole=role, serange=serange, oldserole=oldserole, oldserange=oldserange)
925
926    def modify(self, name, roles=[], selevel="", serange="", prefix=""):
927        try:
928            self.begin()
929            self.__modify(name, roles, selevel, serange, prefix)
930            self.commit()
931        except ValueError as error:
932            self.mylog.commit(0)
933            raise error
934
935    def __delete(self, name):
936        (rc, k) = semanage_user_key_create(self.sh, name)
937        if rc < 0:
938            raise ValueError(_("Could not create a key for %s") % name)
939
940        (rc, exists) = semanage_user_exists(self.sh, k)
941        if rc < 0:
942            raise ValueError(_("Could not check if SELinux user %s is defined") % name)
943        if not exists:
944            raise ValueError(_("SELinux user %s is not defined") % name)
945
946        (rc, exists) = semanage_user_exists_local(self.sh, k)
947        if rc < 0:
948            raise ValueError(_("Could not check if SELinux user %s is defined") % name)
949        if not exists:
950            raise ValueError(_("SELinux user %s is defined in policy, cannot be deleted") % name)
951
952        (rc, u) = semanage_user_query(self.sh, k)
953        if rc < 0:
954            raise ValueError(_("Could not query user for %s") % name)
955        oldserange = semanage_user_get_mlsrange(u)
956        (rc, rlist) = semanage_user_get_roles(self.sh, u)
957        oldserole = ",".join(rlist)
958
959        rc = semanage_user_del_local(self.sh, k)
960        if rc < 0:
961            raise ValueError(_("Could not delete SELinux user %s") % name)
962
963        semanage_user_key_free(k)
964        semanage_user_free(u)
965
966        self.mylog.log_remove("seuser", oldsename=name, oldserange=oldserange, oldserole=oldserole)
967
968    def delete(self, name):
969        try:
970            self.begin()
971            self.__delete(name)
972            self.commit()
973
974        except ValueError as error:
975            self.mylog.commit(0)
976            raise error
977
978    def deleteall(self):
979        (rc, ulist) = semanage_user_list_local(self.sh)
980        if rc < 0:
981            raise ValueError(_("Could not list login mappings"))
982
983        try:
984            self.begin()
985            for u in ulist:
986                self.__delete(semanage_user_get_name(u))
987            self.commit()
988        except ValueError as error:
989            self.mylog.commit(0)
990            raise error
991
992    def get_all(self, locallist=0):
993        ddict = {}
994        if locallist:
995            (rc, self.ulist) = semanage_user_list_local(self.sh)
996        else:
997            (rc, self.ulist) = semanage_user_list(self.sh)
998        if rc < 0:
999            raise ValueError(_("Could not list SELinux users"))
1000
1001        for u in self.ulist:
1002            name = semanage_user_get_name(u)
1003            (rc, rlist) = semanage_user_get_roles(self.sh, u)
1004            if rc < 0:
1005                raise ValueError(_("Could not list roles for user %s") % name)
1006
1007            roles = " ".join(rlist)
1008            ddict[semanage_user_get_name(u)] = (semanage_user_get_prefix(u), semanage_user_get_mlslevel(u), semanage_user_get_mlsrange(u), roles)
1009
1010        return ddict
1011
1012    def customized(self):
1013        l = []
1014        ddict = self.get_all(True)
1015        for k in sorted(ddict.keys()):
1016            l.append("-a -L %s -r %s -R '%s' %s" % (ddict[k][1], ddict[k][2], ddict[k][3], k))
1017        return l
1018
1019    def list(self, heading=1, locallist=0):
1020        ddict = self.get_all(locallist)
1021        if len(ddict) == 0:
1022            return
1023        keys = sorted(ddict.keys())
1024
1025        if is_mls_enabled == 1:
1026            if heading:
1027                print("\n%-15s %-10s %-10s %-30s" % ("", _("Labeling"), _("MLS/"), _("MLS/")))
1028                print("%-15s %-10s %-10s %-30s %s\n" % (_("SELinux User"), _("Prefix"), _("MCS Level"), _("MCS Range"), _("SELinux Roles")))
1029            for k in keys:
1030                print("%-15s %-10s %-10s %-30s %s" % (k, ddict[k][0], translate(ddict[k][1]), translate(ddict[k][2]), ddict[k][3]))
1031        else:
1032            if heading:
1033                print("%-15s %s\n" % (_("SELinux User"), _("SELinux Roles")))
1034            for k in keys:
1035                print("%-15s %s" % (k, ddict[k][3]))
1036
1037
1038class portRecords(semanageRecords):
1039    try:
1040        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"])
1041    except RuntimeError:
1042        valid_types = []
1043
1044    def __init__(self, store=""):
1045        semanageRecords.__init__(self, store)
1046
1047    def __genkey(self, port, proto):
1048        if proto == "tcp":
1049            proto_d = SEMANAGE_PROTO_TCP
1050        else:
1051            if proto == "udp":
1052                proto_d = SEMANAGE_PROTO_UDP
1053            else:
1054                raise ValueError(_("Protocol udp or tcp is required"))
1055        if port == "":
1056            raise ValueError(_("Port is required"))
1057
1058        ports = port.split("-")
1059        if len(ports) == 1:
1060            high = low = int(ports[0])
1061        else:
1062            low = int(ports[0])
1063            high = int(ports[1])
1064
1065        if high > 65535:
1066            raise ValueError(_("Invalid Port"))
1067
1068        (rc, k) = semanage_port_key_create(self.sh, low, high, proto_d)
1069        if rc < 0:
1070            raise ValueError(_("Could not create a key for %s/%s") % (proto, port))
1071        return (k, proto_d, low, high)
1072
1073    def __add(self, port, proto, serange, type):
1074        if is_mls_enabled == 1:
1075            if serange == "":
1076                serange = "s0"
1077            else:
1078                serange = untranslate(serange)
1079
1080        if type == "":
1081            raise ValueError(_("Type is required"))
1082
1083        if type not in self.valid_types:
1084            raise ValueError(_("Type %s is invalid, must be a port type") % type)
1085
1086        (k, proto_d, low, high) = self.__genkey(port, proto)
1087
1088        (rc, exists) = semanage_port_exists(self.sh, k)
1089        if rc < 0:
1090            raise ValueError(_("Could not check if port %s/%s is defined") % (proto, port))
1091        if exists:
1092            raise ValueError(_("Port %s/%s already defined") % (proto, port))
1093
1094        (rc, p) = semanage_port_create(self.sh)
1095        if rc < 0:
1096            raise ValueError(_("Could not create port for %s/%s") % (proto, port))
1097
1098        semanage_port_set_proto(p, proto_d)
1099        semanage_port_set_range(p, low, high)
1100        (rc, con) = semanage_context_create(self.sh)
1101        if rc < 0:
1102            raise ValueError(_("Could not create context for %s/%s") % (proto, port))
1103
1104        rc = semanage_context_set_user(self.sh, con, "system_u")
1105        if rc < 0:
1106            raise ValueError(_("Could not set user in port context for %s/%s") % (proto, port))
1107
1108        rc = semanage_context_set_role(self.sh, con, "object_r")
1109        if rc < 0:
1110            raise ValueError(_("Could not set role in port context for %s/%s") % (proto, port))
1111
1112        rc = semanage_context_set_type(self.sh, con, type)
1113        if rc < 0:
1114            raise ValueError(_("Could not set type in port context for %s/%s") % (proto, port))
1115
1116        if (is_mls_enabled == 1) and (serange != ""):
1117            rc = semanage_context_set_mls(self.sh, con, serange)
1118            if rc < 0:
1119                raise ValueError(_("Could not set mls fields in port context for %s/%s") % (proto, port))
1120
1121        rc = semanage_port_set_con(self.sh, p, con)
1122        if rc < 0:
1123            raise ValueError(_("Could not set port context for %s/%s") % (proto, port))
1124
1125        rc = semanage_port_modify_local(self.sh, k, p)
1126        if rc < 0:
1127            raise ValueError(_("Could not add port %s/%s") % (proto, port))
1128
1129        semanage_context_free(con)
1130        semanage_port_key_free(k)
1131        semanage_port_free(p)
1132
1133        self.mylog.log_change("resrc=port op=add lport=%s proto=%s tcontext=%s:%s:%s:%s" % (port, socket.getprotobyname(proto), "system_u", "object_r", type, serange))
1134
1135    def add(self, port, proto, serange, type):
1136        self.begin()
1137        self.__add(port, proto, serange, type)
1138        self.commit()
1139
1140    def __modify(self, port, proto, serange, setype):
1141        if serange == "" and setype == "":
1142            if is_mls_enabled == 1:
1143                raise ValueError(_("Requires setype or serange"))
1144            else:
1145                raise ValueError(_("Requires setype"))
1146
1147        if setype and setype not in self.valid_types:
1148            raise ValueError(_("Type %s is invalid, must be a port type") % setype)
1149
1150        (k, proto_d, low, high) = self.__genkey(port, proto)
1151
1152        (rc, exists) = semanage_port_exists(self.sh, k)
1153        if rc < 0:
1154            raise ValueError(_("Could not check if port %s/%s is defined") % (proto, port))
1155        if not exists:
1156            raise ValueError(_("Port %s/%s is not defined") % (proto, port))
1157
1158        (rc, p) = semanage_port_query(self.sh, k)
1159        if rc < 0:
1160            raise ValueError(_("Could not query port %s/%s") % (proto, port))
1161
1162        con = semanage_port_get_con(p)
1163
1164        if is_mls_enabled == 1:
1165            if serange == "":
1166                serange = "s0"
1167            else:
1168                semanage_context_set_mls(self.sh, con, untranslate(serange))
1169        if setype != "":
1170            semanage_context_set_type(self.sh, con, setype)
1171
1172        rc = semanage_port_modify_local(self.sh, k, p)
1173        if rc < 0:
1174            raise ValueError(_("Could not modify port %s/%s") % (proto, port))
1175
1176        semanage_port_key_free(k)
1177        semanage_port_free(p)
1178
1179        self.mylog.log_change("resrc=port op=modify lport=%s proto=%s tcontext=%s:%s:%s:%s" % (port, socket.getprotobyname(proto), "system_u", "object_r", setype, serange))
1180
1181    def modify(self, port, proto, serange, setype):
1182        self.begin()
1183        self.__modify(port, proto, serange, setype)
1184        self.commit()
1185
1186    def deleteall(self):
1187        (rc, plist) = semanage_port_list_local(self.sh)
1188        if rc < 0:
1189            raise ValueError(_("Could not list the ports"))
1190
1191        self.begin()
1192
1193        for port in plist:
1194            proto = semanage_port_get_proto(port)
1195            proto_str = semanage_port_get_proto_str(proto)
1196            low = semanage_port_get_low(port)
1197            high = semanage_port_get_high(port)
1198            port_str = "%s-%s" % (low, high)
1199
1200            (k, proto_d, low, high) = self.__genkey(port_str, proto_str)
1201            if rc < 0:
1202                raise ValueError(_("Could not create a key for %s") % port_str)
1203
1204            rc = semanage_port_del_local(self.sh, k)
1205            if rc < 0:
1206                raise ValueError(_("Could not delete the port %s") % port_str)
1207            semanage_port_key_free(k)
1208
1209            if low == high:
1210                port_str = low
1211
1212            self.mylog.log_change("resrc=port op=delete lport=%s proto=%s" % (port_str, socket.getprotobyname(proto_str)))
1213
1214        self.commit()
1215
1216    def __delete(self, port, proto):
1217        (k, proto_d, low, high) = self.__genkey(port, proto)
1218        (rc, exists) = semanage_port_exists(self.sh, k)
1219        if rc < 0:
1220            raise ValueError(_("Could not check if port %s/%s is defined") % (proto, port))
1221        if not exists:
1222            raise ValueError(_("Port %s/%s is not defined") % (proto, port))
1223
1224        (rc, exists) = semanage_port_exists_local(self.sh, k)
1225        if rc < 0:
1226            raise ValueError(_("Could not check if port %s/%s is defined") % (proto, port))
1227        if not exists:
1228            raise ValueError(_("Port %s/%s is defined in policy, cannot be deleted") % (proto, port))
1229
1230        rc = semanage_port_del_local(self.sh, k)
1231        if rc < 0:
1232            raise ValueError(_("Could not delete port %s/%s") % (proto, port))
1233
1234        semanage_port_key_free(k)
1235
1236        self.mylog.log_change("resrc=port op=delete lport=%s proto=%s" % (port, socket.getprotobyname(proto)))
1237
1238    def delete(self, port, proto):
1239        self.begin()
1240        self.__delete(port, proto)
1241        self.commit()
1242
1243    def get_all(self, locallist=0):
1244        ddict = {}
1245        if locallist:
1246            (rc, self.plist) = semanage_port_list_local(self.sh)
1247        else:
1248            (rc, self.plist) = semanage_port_list(self.sh)
1249        if rc < 0:
1250            raise ValueError(_("Could not list ports"))
1251
1252        for port in self.plist:
1253            con = semanage_port_get_con(port)
1254            ctype = semanage_context_get_type(con)
1255            level = semanage_context_get_mls(con)
1256            proto = semanage_port_get_proto(port)
1257            proto_str = semanage_port_get_proto_str(proto)
1258            low = semanage_port_get_low(port)
1259            high = semanage_port_get_high(port)
1260            ddict[(low, high, proto_str)] = (ctype, level)
1261        return ddict
1262
1263    def get_all_by_type(self, locallist=0):
1264        ddict = {}
1265        if locallist:
1266            (rc, self.plist) = semanage_port_list_local(self.sh)
1267        else:
1268            (rc, self.plist) = semanage_port_list(self.sh)
1269        if rc < 0:
1270            raise ValueError(_("Could not list ports"))
1271
1272        for port in self.plist:
1273            con = semanage_port_get_con(port)
1274            ctype = semanage_context_get_type(con)
1275            proto = semanage_port_get_proto(port)
1276            proto_str = semanage_port_get_proto_str(proto)
1277            low = semanage_port_get_low(port)
1278            high = semanage_port_get_high(port)
1279            if (ctype, proto_str) not in ddict.keys():
1280                ddict[(ctype, proto_str)] = []
1281            if low == high:
1282                ddict[(ctype, proto_str)].append("%d" % low)
1283            else:
1284                ddict[(ctype, proto_str)].append("%d-%d" % (low, high))
1285        return ddict
1286
1287    def customized(self):
1288        l = []
1289        ddict = self.get_all(True)
1290        for k in sorted(ddict.keys()):
1291            if k[0] == k[1]:
1292                l.append("-a -t %s -p %s %s" % (ddict[k][0], k[2], k[0]))
1293            else:
1294                l.append("-a -t %s -p %s %s-%s" % (ddict[k][0], k[2], k[0], k[1]))
1295        return l
1296
1297    def list(self, heading=1, locallist=0):
1298        ddict = self.get_all_by_type(locallist)
1299        if len(ddict) == 0:
1300            return
1301        keys = sorted(ddict.keys())
1302
1303        if heading:
1304            print("%-30s %-8s %s\n" % (_("SELinux Port Type"), _("Proto"), _("Port Number")))
1305        for i in keys:
1306            rec = "%-30s %-8s " % i
1307            rec += "%s" % ddict[i][0]
1308            for p in ddict[i][1:]:
1309                rec += ", %s" % p
1310            print(rec)
1311
1312
1313class nodeRecords(semanageRecords):
1314    try:
1315        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "node_type"))[0]["types"])
1316    except RuntimeError:
1317        valid_types = []
1318
1319    def __init__(self, store=""):
1320        semanageRecords.__init__(self, store)
1321        self.protocol = ["ipv4", "ipv6"]
1322
1323    def validate(self, addr, mask, protocol):
1324        newaddr = addr
1325        newmask = mask
1326        newprotocol = ""
1327
1328        if addr == "":
1329            raise ValueError(_("Node Address is required"))
1330
1331        # verify valid comination
1332        if len(mask) == 0 or mask[0] == "/":
1333            i = IP(addr + mask)
1334            newaddr = i.strNormal(0)
1335            newmask = str(i.netmask())
1336            if newmask == "0.0.0.0" and i.version() == 6:
1337                newmask = "::"
1338
1339            protocol = "ipv%d" % i.version()
1340
1341        try:
1342            newprotocol = self.protocol.index(protocol)
1343        except:
1344            raise ValueError(_("Unknown or missing protocol"))
1345
1346        return newaddr, newmask, newprotocol
1347
1348    def __add(self, addr, mask, proto, serange, ctype):
1349        addr, mask, proto = self.validate(addr, mask, proto)
1350
1351        if is_mls_enabled == 1:
1352            if serange == "":
1353                serange = "s0"
1354            else:
1355                serange = untranslate(serange)
1356
1357        if ctype == "":
1358            raise ValueError(_("SELinux node type is required"))
1359
1360        if ctype not in self.valid_types:
1361            raise ValueError(_("Type %s is invalid, must be a node type") % ctype)
1362
1363        (rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
1364        if rc < 0:
1365            raise ValueError(_("Could not create key for %s") % addr)
1366        if rc < 0:
1367            raise ValueError(_("Could not check if addr %s is defined") % addr)
1368
1369        (rc, exists) = semanage_node_exists(self.sh, k)
1370        if exists:
1371            raise ValueError(_("Addr %s already defined") % addr)
1372
1373        (rc, node) = semanage_node_create(self.sh)
1374        if rc < 0:
1375            raise ValueError(_("Could not create addr for %s") % addr)
1376        semanage_node_set_proto(node, proto)
1377
1378        rc = semanage_node_set_addr(self.sh, node, proto, addr)
1379        (rc, con) = semanage_context_create(self.sh)
1380        if rc < 0:
1381            raise ValueError(_("Could not create context for %s") % addr)
1382
1383        rc = semanage_node_set_mask(self.sh, node, proto, mask)
1384        if rc < 0:
1385            raise ValueError(_("Could not set mask for %s") % addr)
1386
1387        rc = semanage_context_set_user(self.sh, con, "system_u")
1388        if rc < 0:
1389            raise ValueError(_("Could not set user in addr context for %s") % addr)
1390
1391        rc = semanage_context_set_role(self.sh, con, "object_r")
1392        if rc < 0:
1393            raise ValueError(_("Could not set role in addr context for %s") % addr)
1394
1395        rc = semanage_context_set_type(self.sh, con, ctype)
1396        if rc < 0:
1397            raise ValueError(_("Could not set type in addr context for %s") % addr)
1398
1399        if (is_mls_enabled == 1) and (serange != ""):
1400            rc = semanage_context_set_mls(self.sh, con, serange)
1401            if rc < 0:
1402                raise ValueError(_("Could not set mls fields in addr context for %s") % addr)
1403
1404        rc = semanage_node_set_con(self.sh, node, con)
1405        if rc < 0:
1406            raise ValueError(_("Could not set addr context for %s") % addr)
1407
1408        rc = semanage_node_modify_local(self.sh, k, node)
1409        if rc < 0:
1410            raise ValueError(_("Could not add addr %s") % addr)
1411
1412        semanage_context_free(con)
1413        semanage_node_key_free(k)
1414        semanage_node_free(node)
1415
1416        self.mylog.log_change("resrc=node op=add laddr=%s netmask=%s proto=%s tcontext=%s:%s:%s:%s" % (addr, mask, socket.getprotobyname(self.protocol[proto]), "system_u", "object_r", ctype, serange))
1417
1418    def add(self, addr, mask, proto, serange, ctype):
1419        self.begin()
1420        self.__add(addr, mask, proto, serange, ctype)
1421        self.commit()
1422
1423    def __modify(self, addr, mask, proto, serange, setype):
1424        addr, mask, proto = self.validate(addr, mask, proto)
1425
1426        if serange == "" and setype == "":
1427            raise ValueError(_("Requires setype or serange"))
1428
1429        if setype and setype not in self.valid_types:
1430            raise ValueError(_("Type %s is invalid, must be a node type") % setype)
1431
1432        (rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
1433        if rc < 0:
1434            raise ValueError(_("Could not create key for %s") % addr)
1435
1436        (rc, exists) = semanage_node_exists(self.sh, k)
1437        if rc < 0:
1438            raise ValueError(_("Could not check if addr %s is defined") % addr)
1439        if not exists:
1440            raise ValueError(_("Addr %s is not defined") % addr)
1441
1442        (rc, node) = semanage_node_query(self.sh, k)
1443        if rc < 0:
1444            raise ValueError(_("Could not query addr %s") % addr)
1445
1446        con = semanage_node_get_con(node)
1447        if (is_mls_enabled == 1) and (serange != ""):
1448            semanage_context_set_mls(self.sh, con, untranslate(serange))
1449        if setype != "":
1450            semanage_context_set_type(self.sh, con, setype)
1451
1452        rc = semanage_node_modify_local(self.sh, k, node)
1453        if rc < 0:
1454            raise ValueError(_("Could not modify addr %s") % addr)
1455
1456        semanage_node_key_free(k)
1457        semanage_node_free(node)
1458
1459        self.mylog.log_change("resrc=node op=modify laddr=%s netmask=%s proto=%s tcontext=%s:%s:%s:%s" % (addr, mask, socket.getprotobyname(self.protocol[proto]), "system_u", "object_r", setype, serange))
1460
1461    def modify(self, addr, mask, proto, serange, setype):
1462        self.begin()
1463        self.__modify(addr, mask, proto, serange, setype)
1464        self.commit()
1465
1466    def __delete(self, addr, mask, proto):
1467
1468        addr, mask, proto = self.validate(addr, mask, proto)
1469
1470        (rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
1471        if rc < 0:
1472            raise ValueError(_("Could not create key for %s") % addr)
1473
1474        (rc, exists) = semanage_node_exists(self.sh, k)
1475        if rc < 0:
1476            raise ValueError(_("Could not check if addr %s is defined") % addr)
1477        if not exists:
1478            raise ValueError(_("Addr %s is not defined") % addr)
1479
1480        (rc, exists) = semanage_node_exists_local(self.sh, k)
1481        if rc < 0:
1482            raise ValueError(_("Could not check if addr %s is defined") % addr)
1483        if not exists:
1484            raise ValueError(_("Addr %s is defined in policy, cannot be deleted") % addr)
1485
1486        rc = semanage_node_del_local(self.sh, k)
1487        if rc < 0:
1488            raise ValueError(_("Could not delete addr %s") % addr)
1489
1490        semanage_node_key_free(k)
1491
1492        self.mylog.log_change("resrc=node op=delete laddr=%s netmask=%s proto=%s" % (addr, mask, socket.getprotobyname(self.protocol[proto])))
1493
1494    def delete(self, addr, mask, proto):
1495        self.begin()
1496        self.__delete(addr, mask, proto)
1497        self.commit()
1498
1499    def deleteall(self):
1500        (rc, nlist) = semanage_node_list_local(self.sh)
1501        if rc < 0:
1502            raise ValueError(_("Could not deleteall node mappings"))
1503
1504        self.begin()
1505        for node in nlist:
1506            self.__delete(semanage_node_get_addr(self.sh, node)[1], semanage_node_get_mask(self.sh, node)[1], self.protocol[semanage_node_get_proto(node)])
1507        self.commit()
1508
1509    def get_all(self, locallist=0):
1510        ddict = {}
1511        if locallist:
1512            (rc, self.ilist) = semanage_node_list_local(self.sh)
1513        else:
1514            (rc, self.ilist) = semanage_node_list(self.sh)
1515        if rc < 0:
1516            raise ValueError(_("Could not list addrs"))
1517
1518        for node in self.ilist:
1519            con = semanage_node_get_con(node)
1520            addr = semanage_node_get_addr(self.sh, node)
1521            mask = semanage_node_get_mask(self.sh, node)
1522            proto = self.protocol[semanage_node_get_proto(node)]
1523            ddict[(addr[1], mask[1], proto)] = (semanage_context_get_user(con), semanage_context_get_role(con), semanage_context_get_type(con), semanage_context_get_mls(con))
1524
1525        return ddict
1526
1527    def customized(self):
1528        l = []
1529        ddict = self.get_all(True)
1530        for k in sorted(ddict.keys()):
1531            l.append("-a -M %s -p %s -t %s %s" % (k[1], k[2], ddict[k][2], k[0]))
1532        return l
1533
1534    def list(self, heading=1, locallist=0):
1535        ddict = self.get_all(locallist)
1536        if len(ddict) == 0:
1537            return
1538        keys = sorted(ddict.keys())
1539
1540        if heading:
1541            print("%-18s %-18s %-5s %-5s\n" % ("IP Address", "Netmask", "Protocol", "Context"))
1542        if is_mls_enabled:
1543            for k in keys:
1544                val = ''
1545                for fields in k:
1546                    val = val + '\t' + str(fields)
1547                print("%-18s %-18s %-5s %s:%s:%s:%s " % (k[0], k[1], k[2], ddict[k][0], ddict[k][1], ddict[k][2], translate(ddict[k][3], False)))
1548        else:
1549            for k in keys:
1550                print("%-18s %-18s %-5s %s:%s:%s " % (k[0], k[1], k[2], ddict[k][0], ddict[k][1], ddict[k][2]))
1551
1552
1553class interfaceRecords(semanageRecords):
1554
1555    def __init__(self, store=""):
1556        semanageRecords.__init__(self, store)
1557
1558    def __add(self, interface, serange, ctype):
1559        if is_mls_enabled == 1:
1560            if serange == "":
1561                serange = "s0"
1562            else:
1563                serange = untranslate(serange)
1564
1565        if ctype == "":
1566            raise ValueError(_("SELinux Type is required"))
1567
1568        (rc, k) = semanage_iface_key_create(self.sh, interface)
1569        if rc < 0:
1570            raise ValueError(_("Could not create key for %s") % interface)
1571
1572        (rc, exists) = semanage_iface_exists(self.sh, k)
1573        if rc < 0:
1574            raise ValueError(_("Could not check if interface %s is defined") % interface)
1575        if exists:
1576            raise ValueError(_("Interface %s already defined") % interface)
1577
1578        (rc, iface) = semanage_iface_create(self.sh)
1579        if rc < 0:
1580            raise ValueError(_("Could not create interface for %s") % interface)
1581
1582        rc = semanage_iface_set_name(self.sh, iface, interface)
1583        (rc, con) = semanage_context_create(self.sh)
1584        if rc < 0:
1585            raise ValueError(_("Could not create context for %s") % interface)
1586
1587        rc = semanage_context_set_user(self.sh, con, "system_u")
1588        if rc < 0:
1589            raise ValueError(_("Could not set user in interface context for %s") % interface)
1590
1591        rc = semanage_context_set_role(self.sh, con, "object_r")
1592        if rc < 0:
1593            raise ValueError(_("Could not set role in interface context for %s") % interface)
1594
1595        rc = semanage_context_set_type(self.sh, con, ctype)
1596        if rc < 0:
1597            raise ValueError(_("Could not set type in interface context for %s") % interface)
1598
1599        if (is_mls_enabled == 1) and (serange != ""):
1600            rc = semanage_context_set_mls(self.sh, con, serange)
1601            if rc < 0:
1602                raise ValueError(_("Could not set mls fields in interface context for %s") % interface)
1603
1604        rc = semanage_iface_set_ifcon(self.sh, iface, con)
1605        if rc < 0:
1606            raise ValueError(_("Could not set interface context for %s") % interface)
1607
1608        rc = semanage_iface_set_msgcon(self.sh, iface, con)
1609        if rc < 0:
1610            raise ValueError(_("Could not set message context for %s") % interface)
1611
1612        rc = semanage_iface_modify_local(self.sh, k, iface)
1613        if rc < 0:
1614            raise ValueError(_("Could not add interface %s") % interface)
1615
1616        semanage_context_free(con)
1617        semanage_iface_key_free(k)
1618        semanage_iface_free(iface)
1619
1620        self.mylog.log_change("resrc=interface op=add netif=%s tcontext=%s:%s:%s:%s" % (interface, "system_u", "object_r", ctype, serange))
1621
1622    def add(self, interface, serange, ctype):
1623        self.begin()
1624        self.__add(interface, serange, ctype)
1625        self.commit()
1626
1627    def __modify(self, interface, serange, setype):
1628        if serange == "" and setype == "":
1629            raise ValueError(_("Requires setype or serange"))
1630
1631        (rc, k) = semanage_iface_key_create(self.sh, interface)
1632        if rc < 0:
1633            raise ValueError(_("Could not create key for %s") % interface)
1634
1635        (rc, exists) = semanage_iface_exists(self.sh, k)
1636        if rc < 0:
1637            raise ValueError(_("Could not check if interface %s is defined") % interface)
1638        if not exists:
1639            raise ValueError(_("Interface %s is not defined") % interface)
1640
1641        (rc, iface) = semanage_iface_query(self.sh, k)
1642        if rc < 0:
1643            raise ValueError(_("Could not query interface %s") % interface)
1644
1645        con = semanage_iface_get_ifcon(iface)
1646
1647        if (is_mls_enabled == 1) and (serange != ""):
1648            semanage_context_set_mls(self.sh, con, untranslate(serange))
1649        if setype != "":
1650            semanage_context_set_type(self.sh, con, setype)
1651
1652        rc = semanage_iface_modify_local(self.sh, k, iface)
1653        if rc < 0:
1654            raise ValueError(_("Could not modify interface %s") % interface)
1655
1656        semanage_iface_key_free(k)
1657        semanage_iface_free(iface)
1658
1659        self.mylog.log_change("resrc=interface op=modify netif=%s tcontext=%s:%s:%s:%s" % (interface, "system_u", "object_r", setype, serange))
1660
1661    def modify(self, interface, serange, setype):
1662        self.begin()
1663        self.__modify(interface, serange, setype)
1664        self.commit()
1665
1666    def __delete(self, interface):
1667        (rc, k) = semanage_iface_key_create(self.sh, interface)
1668        if rc < 0:
1669            raise ValueError(_("Could not create key for %s") % interface)
1670
1671        (rc, exists) = semanage_iface_exists(self.sh, k)
1672        if rc < 0:
1673            raise ValueError(_("Could not check if interface %s is defined") % interface)
1674        if not exists:
1675            raise ValueError(_("Interface %s is not defined") % interface)
1676
1677        (rc, exists) = semanage_iface_exists_local(self.sh, k)
1678        if rc < 0:
1679            raise ValueError(_("Could not check if interface %s is defined") % interface)
1680        if not exists:
1681            raise ValueError(_("Interface %s is defined in policy, cannot be deleted") % interface)
1682
1683        rc = semanage_iface_del_local(self.sh, k)
1684        if rc < 0:
1685            raise ValueError(_("Could not delete interface %s") % interface)
1686
1687        semanage_iface_key_free(k)
1688
1689        self.mylog.log_change("resrc=interface op=delete netif=%s" % interface)
1690
1691    def delete(self, interface):
1692        self.begin()
1693        self.__delete(interface)
1694        self.commit()
1695
1696    def deleteall(self):
1697        (rc, ulist) = semanage_iface_list_local(self.sh)
1698        if rc < 0:
1699            raise ValueError(_("Could not delete all interface  mappings"))
1700
1701        self.begin()
1702        for i in ulist:
1703            self.__delete(semanage_iface_get_name(i))
1704        self.commit()
1705
1706    def get_all(self, locallist=0):
1707        ddict = {}
1708        if locallist:
1709            (rc, self.ilist) = semanage_iface_list_local(self.sh)
1710        else:
1711            (rc, self.ilist) = semanage_iface_list(self.sh)
1712        if rc < 0:
1713            raise ValueError(_("Could not list interfaces"))
1714
1715        for interface in self.ilist:
1716            con = semanage_iface_get_ifcon(interface)
1717            ddict[semanage_iface_get_name(interface)] = (semanage_context_get_user(con), semanage_context_get_role(con), semanage_context_get_type(con), semanage_context_get_mls(con))
1718
1719        return ddict
1720
1721    def customized(self):
1722        l = []
1723        ddict = self.get_all(True)
1724        for k in sorted(ddict.keys()):
1725            l.append("-a -t %s %s" % (ddict[k][2], k))
1726        return l
1727
1728    def list(self, heading=1, locallist=0):
1729        ddict = self.get_all(locallist)
1730        if len(ddict) == 0:
1731            return
1732        keys = sorted(ddict.keys())
1733
1734        if heading:
1735            print("%-30s %s\n" % (_("SELinux Interface"), _("Context")))
1736        if is_mls_enabled:
1737            for k in keys:
1738                print("%-30s %s:%s:%s:%s " % (k, ddict[k][0], ddict[k][1], ddict[k][2], translate(ddict[k][3], False)))
1739        else:
1740            for k in keys:
1741                print("%-30s %s:%s:%s " % (k, ddict[k][0], ddict[k][1], ddict[k][2]))
1742
1743
1744class fcontextRecords(semanageRecords):
1745    try:
1746        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "file_type"))[0]["types"])
1747        valid_types += list(list(sepolicy.info(sepolicy.ATTRIBUTE, "device_node"))[0]["types"])
1748        valid_types.append("<<none>>")
1749    except RuntimeError:
1750        valid_types = []
1751
1752    def __init__(self, store=""):
1753        semanageRecords.__init__(self, store)
1754        self.equiv = {}
1755        self.equiv_dist = {}
1756        self.equal_ind = False
1757        try:
1758            fd = open(selinux.selinux_file_context_subs_path(), "r")
1759            for i in fd.readlines():
1760                i = i.strip()
1761                if len(i) == 0:
1762                    continue
1763                if i.startswith("#"):
1764                    continue
1765                target, substitute = i.split()
1766                self.equiv[target] = substitute
1767            fd.close()
1768        except IOError:
1769            pass
1770        try:
1771            fd = open(selinux.selinux_file_context_subs_dist_path(), "r")
1772            for i in fd.readlines():
1773                i = i.strip()
1774                if len(i) == 0:
1775                    continue
1776                if i.startswith("#"):
1777                    continue
1778                target, substitute = i.split()
1779                self.equiv_dist[target] = substitute
1780            fd.close()
1781        except IOError:
1782            pass
1783
1784    def commit(self):
1785        if self.equal_ind:
1786            subs_file = selinux.selinux_file_context_subs_path()
1787            tmpfile = "%s.tmp" % subs_file
1788            fd = open(tmpfile, "w")
1789            for target in self.equiv.keys():
1790                fd.write("%s %s\n" % (target, self.equiv[target]))
1791            fd.close()
1792            try:
1793                os.chmod(tmpfile, os.stat(subs_file)[stat.ST_MODE])
1794            except:
1795                pass
1796            os.rename(tmpfile, subs_file)
1797            self.equal_ind = False
1798        semanageRecords.commit(self)
1799
1800    def add_equal(self, target, substitute):
1801        self.begin()
1802        if target != "/" and target[-1] == "/":
1803            raise ValueError(_("Target %s is not valid. Target is not allowed to end with '/'") % target)
1804
1805        if substitute != "/" and substitute[-1] == "/":
1806            raise ValueError(_("Substiture %s is not valid. Substitute is not allowed to end with '/'") % substitute)
1807
1808        if target in self.equiv.keys():
1809            raise ValueError(_("Equivalence class for %s already exists") % target)
1810        self.validate(target)
1811
1812        for fdict in (self.equiv, self.equiv_dist):
1813            for i in fdict:
1814                if i.startswith(target + "/"):
1815                    raise ValueError(_("File spec %s conflicts with equivalency rule '%s %s'") % (target, i, fdict[i]))
1816
1817        self.mylog.log_change("resrc=fcontext op=add-equal %s %s" % (audit.audit_encode_nv_string("sglob", target, 0), audit.audit_encode_nv_string("tglob", substitute, 0)))
1818
1819        self.equiv[target] = substitute
1820        self.equal_ind = True
1821        self.commit()
1822
1823    def modify_equal(self, target, substitute):
1824        self.begin()
1825        if target not in self.equiv.keys():
1826            raise ValueError(_("Equivalence class for %s does not exists") % target)
1827        self.equiv[target] = substitute
1828        self.equal_ind = True
1829
1830        self.mylog.log_change("resrc=fcontext op=modify-equal %s %s" % (audit.audit_encode_nv_string("sglob", target, 0), audit.audit_encode_nv_string("tglob", substitute, 0)))
1831
1832        self.commit()
1833
1834    def createcon(self, target, seuser="system_u"):
1835        (rc, con) = semanage_context_create(self.sh)
1836        if rc < 0:
1837            raise ValueError(_("Could not create context for %s") % target)
1838        if seuser == "":
1839            seuser = "system_u"
1840
1841        rc = semanage_context_set_user(self.sh, con, seuser)
1842        if rc < 0:
1843            raise ValueError(_("Could not set user in file context for %s") % target)
1844
1845        rc = semanage_context_set_role(self.sh, con, "object_r")
1846        if rc < 0:
1847            raise ValueError(_("Could not set role in file context for %s") % target)
1848
1849        if is_mls_enabled == 1:
1850            rc = semanage_context_set_mls(self.sh, con, "s0")
1851            if rc < 0:
1852                raise ValueError(_("Could not set mls fields in file context for %s") % target)
1853
1854        return con
1855
1856    def validate(self, target):
1857        if target == "" or target.find("\n") >= 0:
1858            raise ValueError(_("Invalid file specification"))
1859        if target.find(" ") != -1:
1860            raise ValueError(_("File specification can not include spaces"))
1861        for fdict in (self.equiv, self.equiv_dist):
1862            for i in fdict:
1863                if target.startswith(i + "/"):
1864                    t = re.sub(i, fdict[i], target)
1865                    raise ValueError(_("File spec %s conflicts with equivalency rule '%s %s'; Try adding '%s' instead") % (target, i, fdict[i], t))
1866
1867    def __add(self, target, type, ftype="", serange="", seuser="system_u"):
1868        self.validate(target)
1869
1870        if is_mls_enabled == 1:
1871            serange = untranslate(serange)
1872
1873        if type == "":
1874            raise ValueError(_("SELinux Type is required"))
1875
1876        if type not in self.valid_types:
1877            raise ValueError(_("Type %s is invalid, must be a file or device type") % type)
1878
1879        (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype])
1880        if rc < 0:
1881            raise ValueError(_("Could not create key for %s") % target)
1882
1883        (rc, exists) = semanage_fcontext_exists(self.sh, k)
1884        if rc < 0:
1885            raise ValueError(_("Could not check if file context for %s is defined") % target)
1886
1887        if not exists:
1888            (rc, exists) = semanage_fcontext_exists_local(self.sh, k)
1889            if rc < 0:
1890                raise ValueError(_("Could not check if file context for %s is defined") % target)
1891
1892        if exists:
1893            raise ValueError(_("File context for %s already defined") % target)
1894
1895        (rc, fcontext) = semanage_fcontext_create(self.sh)
1896        if rc < 0:
1897            raise ValueError(_("Could not create file context for %s") % target)
1898
1899        rc = semanage_fcontext_set_expr(self.sh, fcontext, target)
1900        if type != "<<none>>":
1901            con = self.createcon(target, seuser)
1902
1903            rc = semanage_context_set_type(self.sh, con, type)
1904            if rc < 0:
1905                raise ValueError(_("Could not set type in file context for %s") % target)
1906
1907            if (is_mls_enabled == 1) and (serange != ""):
1908                rc = semanage_context_set_mls(self.sh, con, serange)
1909                if rc < 0:
1910                    raise ValueError(_("Could not set mls fields in file context for %s") % target)
1911            rc = semanage_fcontext_set_con(self.sh, fcontext, con)
1912            if rc < 0:
1913                raise ValueError(_("Could not set file context for %s") % target)
1914
1915        semanage_fcontext_set_type(fcontext, file_types[ftype])
1916
1917        rc = semanage_fcontext_modify_local(self.sh, k, fcontext)
1918        if rc < 0:
1919            raise ValueError(_("Could not add file context for %s") % target)
1920
1921        if type != "<<none>>":
1922            semanage_context_free(con)
1923        semanage_fcontext_key_free(k)
1924        semanage_fcontext_free(fcontext)
1925
1926        if not seuser:
1927            seuser = "system_u"
1928
1929        self.mylog.log_change("resrc=fcontext op=add %s ftype=%s tcontext=%s:%s:%s:%s" % (audit.audit_encode_nv_string("tglob", target, 0), ftype_to_audit[ftype], seuser, "object_r", type, serange))
1930
1931    def add(self, target, type, ftype="", serange="", seuser="system_u"):
1932        self.begin()
1933        self.__add(target, type, ftype, serange, seuser)
1934        self.commit()
1935
1936    def __modify(self, target, setype, ftype, serange, seuser):
1937        if serange == "" and setype == "" and seuser == "":
1938            raise ValueError(_("Requires setype, serange or seuser"))
1939        if setype and setype not in self.valid_types:
1940            raise ValueError(_("Type %s is invalid, must be a file or device type") % setype)
1941
1942        self.validate(target)
1943
1944        (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype])
1945        if rc < 0:
1946            raise ValueError(_("Could not create a key for %s") % target)
1947
1948        (rc, exists) = semanage_fcontext_exists(self.sh, k)
1949        if rc < 0:
1950            raise ValueError(_("Could not check if file context for %s is defined") % target)
1951        if not exists:
1952            (rc, exists) = semanage_fcontext_exists_local(self.sh, k)
1953            if not exists:
1954                raise ValueError(_("File context for %s is not defined") % target)
1955
1956        try:
1957            (rc, fcontext) = semanage_fcontext_query_local(self.sh, k)
1958        except OSError:
1959            try:
1960                (rc, fcontext) = semanage_fcontext_query(self.sh, k)
1961            except OSError:
1962                raise ValueError(_("Could not query file context for %s") % target)
1963
1964        if setype != "<<none>>":
1965            con = semanage_fcontext_get_con(fcontext)
1966
1967            if con is None:
1968                con = self.createcon(target)
1969
1970            if (is_mls_enabled == 1) and (serange != ""):
1971                semanage_context_set_mls(self.sh, con, untranslate(serange))
1972            if seuser != "":
1973                semanage_context_set_user(self.sh, con, seuser)
1974
1975            if setype != "":
1976                semanage_context_set_type(self.sh, con, setype)
1977
1978            rc = semanage_fcontext_set_con(self.sh, fcontext, con)
1979            if rc < 0:
1980                raise ValueError(_("Could not set file context for %s") % target)
1981        else:
1982            rc = semanage_fcontext_set_con(self.sh, fcontext, None)
1983            if rc < 0:
1984                raise ValueError(_("Could not set file context for %s") % target)
1985
1986        rc = semanage_fcontext_modify_local(self.sh, k, fcontext)
1987        if rc < 0:
1988            raise ValueError(_("Could not modify file context for %s") % target)
1989
1990        semanage_fcontext_key_free(k)
1991        semanage_fcontext_free(fcontext)
1992
1993        if not seuser:
1994            seuser = "system_u"
1995
1996        self.mylog.log_change("resrc=fcontext op=modify %s ftype=%s tcontext=%s:%s:%s:%s" % (audit.audit_encode_nv_string("tglob", target, 0), ftype_to_audit[ftype], seuser, "object_r", setype, serange))
1997
1998    def modify(self, target, setype, ftype, serange, seuser):
1999        self.begin()
2000        self.__modify(target, setype, ftype, serange, seuser)
2001        self.commit()
2002
2003    def deleteall(self):
2004        (rc, flist) = semanage_fcontext_list_local(self.sh)
2005        if rc < 0:
2006            raise ValueError(_("Could not list the file contexts"))
2007
2008        self.begin()
2009
2010        for fcontext in flist:
2011            target = semanage_fcontext_get_expr(fcontext)
2012            ftype = semanage_fcontext_get_type(fcontext)
2013            ftype_str = semanage_fcontext_get_type_str(ftype)
2014            (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype_str])
2015            if rc < 0:
2016                raise ValueError(_("Could not create a key for %s") % target)
2017
2018            rc = semanage_fcontext_del_local(self.sh, k)
2019            if rc < 0:
2020                raise ValueError(_("Could not delete the file context %s") % target)
2021            semanage_fcontext_key_free(k)
2022
2023            self.mylog.log_change("resrc=fcontext op=delete %s ftype=%s" % (audit.audit_encode_nv_string("tglob", target, 0), ftype_to_audit[file_type_str_to_option[ftype_str]]))
2024
2025        self.equiv = {}
2026        self.equal_ind = True
2027        self.commit()
2028
2029    def __delete(self, target, ftype):
2030        if target in self.equiv.keys():
2031            self.equiv.pop(target)
2032            self.equal_ind = True
2033
2034            self.mylog.log_change("resrc=fcontext op=delete-equal %s" % (audit.audit_encode_nv_string("tglob", target, 0)))
2035
2036            return
2037
2038        (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype])
2039        if rc < 0:
2040            raise ValueError(_("Could not create a key for %s") % target)
2041
2042        (rc, exists) = semanage_fcontext_exists_local(self.sh, k)
2043        if rc < 0:
2044            raise ValueError(_("Could not check if file context for %s is defined") % target)
2045        if not exists:
2046            (rc, exists) = semanage_fcontext_exists(self.sh, k)
2047            if rc < 0:
2048                raise ValueError(_("Could not check if file context for %s is defined") % target)
2049            if exists:
2050                raise ValueError(_("File context for %s is defined in policy, cannot be deleted") % target)
2051            else:
2052                raise ValueError(_("File context for %s is not defined") % target)
2053
2054        rc = semanage_fcontext_del_local(self.sh, k)
2055        if rc < 0:
2056            raise ValueError(_("Could not delete file context for %s") % target)
2057
2058        semanage_fcontext_key_free(k)
2059
2060        self.mylog.log_change("resrc=fcontext op=delete %s ftype=%s" % (audit.audit_encode_nv_string("tglob", target, 0), ftype_to_audit[ftype]))
2061
2062    def delete(self, target, ftype):
2063        self.begin()
2064        self.__delete(target, ftype)
2065        self.commit()
2066
2067    def get_all(self, locallist=0):
2068        if locallist:
2069            (rc, self.flist) = semanage_fcontext_list_local(self.sh)
2070        else:
2071            (rc, self.flist) = semanage_fcontext_list(self.sh)
2072            if rc < 0:
2073                raise ValueError(_("Could not list file contexts"))
2074
2075            (rc, fclocal) = semanage_fcontext_list_local(self.sh)
2076            if rc < 0:
2077                raise ValueError(_("Could not list local file contexts"))
2078
2079            self.flist += fclocal
2080
2081        ddict = {}
2082        for fcontext in self.flist:
2083            expr = semanage_fcontext_get_expr(fcontext)
2084            ftype = semanage_fcontext_get_type(fcontext)
2085            ftype_str = semanage_fcontext_get_type_str(ftype)
2086            con = semanage_fcontext_get_con(fcontext)
2087            if con:
2088                ddict[(expr, ftype_str)] = (semanage_context_get_user(con), semanage_context_get_role(con), semanage_context_get_type(con), semanage_context_get_mls(con))
2089            else:
2090                ddict[(expr, ftype_str)] = con
2091
2092        return ddict
2093
2094    def customized(self):
2095        l = []
2096        fcon_dict = self.get_all(True)
2097        for k in sorted(fcon_dict.keys()):
2098            if fcon_dict[k]:
2099                l.append("-a -f %s -t %s '%s'" % (file_type_str_to_option[k[1]], fcon_dict[k][2], k[0]))
2100
2101        if len(self.equiv):
2102            for target in self.equiv.keys():
2103                l.append("-a -e %s %s" % (self.equiv[target], target))
2104        return l
2105
2106    def list(self, heading=1, locallist=0):
2107        fcon_dict = self.get_all(locallist)
2108        if len(fcon_dict) != 0:
2109            if heading:
2110                print("%-50s %-18s %s\n" % (_("SELinux fcontext"), _("type"), _("Context")))
2111            for k in sorted(fcon_dict.keys()):
2112                if fcon_dict[k]:
2113                    if is_mls_enabled:
2114                        print("%-50s %-18s %s:%s:%s:%s " % (k[0], k[1], fcon_dict[k][0], fcon_dict[k][1], fcon_dict[k][2], translate(fcon_dict[k][3], False)))
2115                    else:
2116                        print("%-50s %-18s %s:%s:%s " % (k[0], k[1], fcon_dict[k][0], fcon_dict[k][1], fcon_dict[k][2]))
2117                else:
2118                    print("%-50s %-18s <<None>>" % (k[0], k[1]))
2119
2120        if len(self.equiv_dist):
2121            if not locallist:
2122                if heading:
2123                    print(_("\nSELinux Distribution fcontext Equivalence \n"))
2124                for target in self.equiv_dist.keys():
2125                    print("%s = %s" % (target, self.equiv_dist[target]))
2126        if len(self.equiv):
2127            if heading:
2128                print(_("\nSELinux Local fcontext Equivalence \n"))
2129
2130            for target in self.equiv.keys():
2131                print("%s = %s" % (target, self.equiv[target]))
2132
2133
2134class booleanRecords(semanageRecords):
2135
2136    def __init__(self, store=""):
2137        semanageRecords.__init__(self, store)
2138        self.dict = {}
2139        self.dict["TRUE"] = 1
2140        self.dict["FALSE"] = 0
2141        self.dict["ON"] = 1
2142        self.dict["OFF"] = 0
2143        self.dict["1"] = 1
2144        self.dict["0"] = 0
2145
2146        try:
2147            rc, self.current_booleans = selinux.security_get_boolean_names()
2148            rc, ptype = selinux.selinux_getpolicytype()
2149        except:
2150            self.current_booleans = []
2151            ptype = None
2152
2153        if self.store is None or self.store == ptype:
2154            self.modify_local = True
2155        else:
2156            self.modify_local = False
2157
2158    def __mod(self, name, value):
2159        name = selinux.selinux_boolean_sub(name)
2160
2161        (rc, k) = semanage_bool_key_create(self.sh, name)
2162        if rc < 0:
2163            raise ValueError(_("Could not create a key for %s") % name)
2164        (rc, exists) = semanage_bool_exists(self.sh, k)
2165        if rc < 0:
2166            raise ValueError(_("Could not check if boolean %s is defined") % name)
2167        if not exists:
2168            raise ValueError(_("Boolean %s is not defined") % name)
2169
2170        (rc, b) = semanage_bool_query(self.sh, k)
2171        if rc < 0:
2172            raise ValueError(_("Could not query file context %s") % name)
2173
2174        if value.upper() in self.dict:
2175            semanage_bool_set_value(b, self.dict[value.upper()])
2176        else:
2177            raise ValueError(_("You must specify one of the following values: %s") % ", ".join(self.dict.keys()))
2178
2179        if self.modify_local and name in self.current_booleans:
2180            rc = semanage_bool_set_active(self.sh, k, b)
2181            if rc < 0:
2182                raise ValueError(_("Could not set active value of boolean %s") % name)
2183        rc = semanage_bool_modify_local(self.sh, k, b)
2184        if rc < 0:
2185            raise ValueError(_("Could not modify boolean %s") % name)
2186        semanage_bool_key_free(k)
2187        semanage_bool_free(b)
2188
2189    def modify(self, name, value=None, use_file=False):
2190        self.begin()
2191        if use_file:
2192            fd = open(name)
2193            for b in fd.read().split("\n"):
2194                b = b.strip()
2195                if len(b) == 0:
2196                    continue
2197
2198                try:
2199                    boolname, val = b.split("=")
2200                except ValueError:
2201                    raise ValueError(_("Bad format %s: Record %s" % (name, b)))
2202                self.__mod(boolname.strip(), val.strip())
2203            fd.close()
2204        else:
2205            self.__mod(name, value)
2206
2207        self.commit()
2208
2209    def __delete(self, name):
2210        name = selinux.selinux_boolean_sub(name)
2211
2212        (rc, k) = semanage_bool_key_create(self.sh, name)
2213        if rc < 0:
2214            raise ValueError(_("Could not create a key for %s") % name)
2215        (rc, exists) = semanage_bool_exists(self.sh, k)
2216        if rc < 0:
2217            raise ValueError(_("Could not check if boolean %s is defined") % name)
2218        if not exists:
2219            raise ValueError(_("Boolean %s is not defined") % name)
2220
2221        (rc, exists) = semanage_bool_exists_local(self.sh, k)
2222        if rc < 0:
2223            raise ValueError(_("Could not check if boolean %s is defined") % name)
2224        if not exists:
2225            raise ValueError(_("Boolean %s is defined in policy, cannot be deleted") % name)
2226
2227        rc = semanage_bool_del_local(self.sh, k)
2228        if rc < 0:
2229            raise ValueError(_("Could not delete boolean %s") % name)
2230
2231        semanage_bool_key_free(k)
2232
2233    def delete(self, name):
2234        self.begin()
2235        self.__delete(name)
2236        self.commit()
2237
2238    def deleteall(self):
2239        (rc, self.blist) = semanage_bool_list_local(self.sh)
2240        if rc < 0:
2241            raise ValueError(_("Could not list booleans"))
2242
2243        self.begin()
2244
2245        for boolean in self.blist:
2246            name = semanage_bool_get_name(boolean)
2247            self.__delete(name)
2248
2249        self.commit()
2250
2251    def get_all(self, locallist=0):
2252        ddict = {}
2253        if locallist:
2254            (rc, self.blist) = semanage_bool_list_local(self.sh)
2255        else:
2256            (rc, self.blist) = semanage_bool_list(self.sh)
2257        if rc < 0:
2258            raise ValueError(_("Could not list booleans"))
2259
2260        for boolean in self.blist:
2261            value = []
2262            name = semanage_bool_get_name(boolean)
2263            value.append(semanage_bool_get_value(boolean))
2264            if self.modify_local and boolean in self.current_booleans:
2265                value.append(selinux.security_get_boolean_pending(name))
2266                value.append(selinux.security_get_boolean_active(name))
2267            else:
2268                value.append(value[0])
2269                value.append(value[0])
2270            ddict[name] = value
2271
2272        return ddict
2273
2274    def get_desc(self, name):
2275        name = selinux.selinux_boolean_sub(name)
2276        return sepolicy.boolean_desc(name)
2277
2278    def get_category(self, name):
2279        name = selinux.selinux_boolean_sub(name)
2280        return sepolicy.boolean_category(name)
2281
2282    def customized(self):
2283        l = []
2284        ddict = self.get_all(True)
2285        for k in sorted(ddict.keys()):
2286            if ddict[k]:
2287                l.append("-m -%s %s" % (ddict[k][2], k))
2288        return l
2289
2290    def list(self, heading=True, locallist=False, use_file=False):
2291        on_off = (_("off"), _("on"))
2292        if use_file:
2293            ddict = self.get_all(locallist)
2294            for k in sorted(ddict.keys()):
2295                if ddict[k]:
2296                    print("%s=%s" % (k, ddict[k][2]))
2297            return
2298        ddict = self.get_all(locallist)
2299        if len(ddict) == 0:
2300            return
2301
2302        if heading:
2303            print("%-30s %s  %s %s\n" % (_("SELinux boolean"), _("State"), _("Default"), _("Description")))
2304        for k in sorted(ddict.keys()):
2305            if ddict[k]:
2306                print("%-30s (%-5s,%5s)  %s" % (k, on_off[selinux.security_get_boolean_active(k)], on_off[ddict[k][2]], self.get_desc(k)))
2307