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