Home | History | Annotate | Download | only in dbus
      1 #!/usr/bin/python
      2 
      3 import dbus
      4 import dbus.service
      5 import dbus.mainloop.glib
      6 from gi.repository import GObject
      7 import slip.dbus.service
      8 from slip.dbus import polkit
      9 import os
     10 import selinux
     11 from subprocess import Popen, PIPE, STDOUT
     12 
     13 
     14 class selinux_server(slip.dbus.service.Object):
     15     default_polkit_auth_required = "org.selinux.semanage"
     16 
     17     def __init__(self, *p, **k):
     18         super(selinux_server, self).__init__(*p, **k)
     19 
     20     #
     21     # The semanage method runs a transaction on a series of semanage commands,
     22     # these commnds can take the output of customized
     23     #
     24     @slip.dbus.polkit.require_auth("org.selinux.semanage")
     25     @dbus.service.method("org.selinux", in_signature='s')
     26     def semanage(self, buf):
     27         p = Popen(["/usr/sbin/semanage", "import"], stdout=PIPE, stderr=PIPE, stdin=PIPE, universal_newlines=True)
     28         p.stdin.write(buf)
     29         output = p.communicate()
     30         if p.returncode and p.returncode != 0:
     31             raise dbus.exceptions.DBusException(output[1])
     32 
     33     #
     34     # The customized method will return all of the custommizations for policy
     35     # on the server.  This output can be used with the semanage method on
     36     # another server to make the two systems have duplicate policy.
     37     #
     38     @slip.dbus.polkit.require_auth("org.selinux.customized")
     39     @dbus.service.method("org.selinux", in_signature='', out_signature='s')
     40     def customized(self):
     41         p = Popen(["/usr/sbin/semanage", "export"], stdout=PIPE, stderr=PIPE, universal_newlines=True)
     42         buf = p.stdout.read()
     43         output = p.communicate()
     44         if p.returncode and p.returncode != 0:
     45             raise OSError("Failed to read SELinux configuration: %s", output)
     46         return buf
     47 
     48     #
     49     # The semodule_list method will return the output of semodule --list=full, using the customized polkit,
     50     # since this is a readonly behaviour
     51     #
     52     @slip.dbus.polkit.require_auth("org.selinux.semodule_list")
     53     @dbus.service.method("org.selinux", in_signature='', out_signature='s')
     54     def semodule_list(self):
     55         p = Popen(["/usr/sbin/semodule", "--list=full"], stdout=PIPE, stderr=PIPE, universal_newlines=True)
     56         buf = p.stdout.read()
     57         output = p.communicate()
     58         if p.returncode and p.returncode != 0:
     59             raise OSError("Failed to list SELinux modules: %s", output)
     60         return buf
     61 
     62     #
     63     # The restorecon method modifies any file path to the default system label
     64     #
     65     @slip.dbus.polkit.require_auth("org.selinux.restorecon")
     66     @dbus.service.method("org.selinux", in_signature='s')
     67     def restorecon(self, path):
     68         selinux.restorecon(str(path), recursive=1)
     69 
     70     #
     71     # The setenforce method turns off the current enforcement of SELinux
     72     #
     73     @slip.dbus.polkit.require_auth("org.selinux.setenforce")
     74     @dbus.service.method("org.selinux", in_signature='i')
     75     def setenforce(self, value):
     76         selinux.security_setenforce(value)
     77 
     78     #
     79     # The setenforce method turns off the current enforcement of SELinux
     80     #
     81     @slip.dbus.polkit.require_auth("org.selinux.relabel_on_boot")
     82     @dbus.service.method("org.selinux", in_signature='i')
     83     def relabel_on_boot(self, value):
     84         if value == 1:
     85             fd = open("/.autorelabel", "w")
     86             fd.close()
     87         else:
     88             os.unlink("/.autorelabel")
     89 
     90     def write_selinux_config(self, enforcing=None, policy=None):
     91         path = selinux.selinux_path() + "config"
     92         backup_path = path + ".bck"
     93         fd = open(path)
     94         lines = fd.readlines()
     95         fd.close()
     96         fd = open(backup_path, "w")
     97         for l in lines:
     98             if enforcing and l.startswith("SELINUX="):
     99                 fd.write("SELINUX=%s\n" % enforcing)
    100                 continue
    101             if policy and l.startswith("SELINUXTYPE="):
    102                 fd.write("SELINUXTYPE=%s\n" % policy)
    103                 continue
    104             fd.write(l)
    105         fd.close()
    106         os.rename(backup_path, path)
    107 
    108     #
    109     # The change_default_enforcement modifies the current enforcement mode
    110     #
    111     @slip.dbus.polkit.require_auth("org.selinux.change_default_mode")
    112     @dbus.service.method("org.selinux", in_signature='s')
    113     def change_default_mode(self, value):
    114         values = ["enforcing", "permissive", "disabled"]
    115         if value not in values:
    116             raise ValueError("Enforcement mode must be %s" % ", ".join(values))
    117         self.write_selinux_config(enforcing=value)
    118 
    119     #
    120     # The change_default_policy method modifies the policy type
    121     #
    122     @slip.dbus.polkit.require_auth("org.selinux.change_default_policy")
    123     @dbus.service.method("org.selinux", in_signature='s')
    124     def change_default_policy(self, value):
    125         path = selinux.selinux_path() + value
    126         if os.path.isdir(path):
    127             return self.write_selinux_config(policy=value)
    128         raise ValueError("%s does not exist" % path)
    129 
    130 if __name__ == "__main__":
    131     mainloop = GObject.MainLoop()
    132     dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    133     system_bus = dbus.SystemBus()
    134     name = dbus.service.BusName("org.selinux", system_bus)
    135     object = selinux_server(system_bus, "/org/selinux/object")
    136     slip.dbus.service.set_mainloop(mainloop)
    137     mainloop.run()
    138