]> glassweightruler.freedombox.rocks Git - waydroid.git/commitdiff
initializer: Require admin authentication for remote initialization with custom channels
authorAlessandro Astone <ales.astone@gmail.com>
Mon, 2 Jan 2023 18:16:27 +0000 (19:16 +0100)
committerAlessandro Astone <ales.astone@gmail.com>
Tue, 3 Jan 2023 15:03:12 +0000 (16:03 +0100)
Makefile
dbus/id.waydro.Container.policy [new file with mode: 0644]
debian/control
tools/actions/initializer.py

index f838328df09927fce28abbef084290ff0d10bbbd..67e74fa9045e1c8aa5cf17b55dea12a08fefcf52 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ APPS_DIR := $(PREFIX)/share/applications
 METAINFO_DIR := $(PREFIX)/share/metainfo
 SYSD_DIR := $(PREFIX)/lib/systemd/system
 DBUS_DIR := $(PREFIX)/share/dbus-1
 METAINFO_DIR := $(PREFIX)/share/metainfo
 SYSD_DIR := $(PREFIX)/lib/systemd/system
 DBUS_DIR := $(PREFIX)/share/dbus-1
+POLKIT_DIR := $(PREFIX)/share/polkit-1
 APPARMOR_DIR := /etc/apparmor.d
 
 INSTALL_WAYDROID_DIR := $(DESTDIR)$(WAYDROID_DIR)
 APPARMOR_DIR := /etc/apparmor.d
 
 INSTALL_WAYDROID_DIR := $(DESTDIR)$(WAYDROID_DIR)
@@ -18,18 +19,20 @@ INSTALL_APPS_DIR := $(DESTDIR)$(APPS_DIR)
 INSTALL_METAINFO_DIR := $(DESTDIR)$(METAINFO_DIR)
 INSTALL_SYSD_DIR := $(DESTDIR)$(SYSD_DIR)
 INSTALL_DBUS_DIR := $(DESTDIR)$(DBUS_DIR)
 INSTALL_METAINFO_DIR := $(DESTDIR)$(METAINFO_DIR)
 INSTALL_SYSD_DIR := $(DESTDIR)$(SYSD_DIR)
 INSTALL_DBUS_DIR := $(DESTDIR)$(DBUS_DIR)
+INSTALL_POLKIT_DIR := $(DESTDIR)$(POLKIT_DIR)
 INSTALL_APPARMOR_DIR := $(DESTDIR)$(APPARMOR_DIR)
 
 build:
        @echo "Nothing to build, run 'make install' to copy the files!"
 
 install:
 INSTALL_APPARMOR_DIR := $(DESTDIR)$(APPARMOR_DIR)
 
 build:
        @echo "Nothing to build, run 'make install' to copy the files!"
 
 install:
-       install -d $(INSTALL_WAYDROID_DIR) $(INSTALL_BIN_DIR) $(INSTALL_APPS_DIR) $(INSTALL_METAINFO_DIR) $(INSTALL_DBUS_DIR)/system.d
+       install -d $(INSTALL_WAYDROID_DIR) $(INSTALL_BIN_DIR) $(INSTALL_APPS_DIR) $(INSTALL_METAINFO_DIR) $(INSTALL_DBUS_DIR)/system.d $(INSTALL_POLKIT_DIR)/actions
        cp -a data tools waydroid.py $(INSTALL_WAYDROID_DIR)
        ln -sf $(WAYDROID_DIR)/waydroid.py $(INSTALL_BIN_DIR)/waydroid
        mv $(INSTALL_WAYDROID_DIR)/data/*.desktop $(INSTALL_APPS_DIR)
        mv $(INSTALL_WAYDROID_DIR)/data/*.metainfo.xml $(INSTALL_METAINFO_DIR)
        cp dbus/id.waydro.Container.conf $(INSTALL_DBUS_DIR)/system.d/
        cp -a data tools waydroid.py $(INSTALL_WAYDROID_DIR)
        ln -sf $(WAYDROID_DIR)/waydroid.py $(INSTALL_BIN_DIR)/waydroid
        mv $(INSTALL_WAYDROID_DIR)/data/*.desktop $(INSTALL_APPS_DIR)
        mv $(INSTALL_WAYDROID_DIR)/data/*.metainfo.xml $(INSTALL_METAINFO_DIR)
        cp dbus/id.waydro.Container.conf $(INSTALL_DBUS_DIR)/system.d/
+       cp dbus/id.waydro.Container.policy $(INSTALL_POLKIT_DIR)/actions/
        if [ $(USE_DBUS_ACTIVATION) = 1 ]; then \
                install -d $(INSTALL_DBUS_DIR)/system-services; \
                cp dbus/id.waydro.Container.service $(INSTALL_DBUS_DIR)/system-services/; \
        if [ $(USE_DBUS_ACTIVATION) = 1 ]; then \
                install -d $(INSTALL_DBUS_DIR)/system-services; \
                cp dbus/id.waydro.Container.service $(INSTALL_DBUS_DIR)/system-services/; \
diff --git a/dbus/id.waydro.Container.policy b/dbus/id.waydro.Container.policy
new file mode 100644 (file)
index 0000000..52cb807
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<policyconfig>
+  <vendor>Waydroid</vendor>
+  <vendor_url>https://waydro.id</vendor_url>
+  <action id="id.waydro.Initializer.Init">
+    <description>Waydroid Initialization</description>
+    <message>Initialize Waydroid with user-provided OTA channels. Do you trust the source?</message>
+    <defaults>
+      <allow_any>auth_admin</allow_any>
+      <allow_inactive>auth_admin</allow_inactive>
+      <allow_active>auth_admin_keep</allow_active>
+    </defaults>
+  </action>
+</policyconfig>
index 89a4cd47bab479ceba2a518e3dc6044827c0a49d..51e416b171919fda3f4c8318b5f68db6c89ceedf 100644 (file)
@@ -19,7 +19,8 @@ Depends: ${misc:Depends},
          python3-gi,
          gir1.2-gtk-3.0,
          python3-dbus,
          python3-gi,
          gir1.2-gtk-3.0,
          python3-dbus,
-         dbus
+         dbus,
+         policykit-1
 Description: Androidâ„¢ application support
  waydroid allows running a separate Androidâ„¢ environment
  confined to a LXC container.
 Description: Androidâ„¢ application support
  waydroid allows running a separate Androidâ„¢ environment
  confined to a LXC container.
index 5238b3ce0e247e6137c61538b4f3cdfdd846daeb..7fec7325f2cb905daf411e0672fa7184c20c258d 100644 (file)
@@ -152,15 +152,38 @@ class DbusInitializer(dbus.service.Object):
         self.looper = looper
         dbus.service.Object.__init__(self, bus, object_path)
 
         self.looper = looper
         dbus.service.Object.__init__(self, bus, object_path)
 
-    @dbus.service.method("id.waydro.Initializer", in_signature='a{ss}', out_signature='')
-    def Init(self, params):
-        threading.Thread(target=remote_init_server, args=(self.args, params)).start()
+    @dbus.service.method("id.waydro.Initializer", in_signature='a{ss}', out_signature='', sender_keyword="sender", connection_keyword="conn")
+    def Init(self, params, sender=None, conn=None):
+        channels_cfg = tools.config.load_channels()
+        no_auth = params["system_channel"] == channels_cfg["channels"]["system_channel"] and \
+                  params["vendor_channel"] == channels_cfg["channels"]["vendor_channel"]
+        if no_auth or ensure_polkit_auth(sender, conn, "id.waydro.Initializer.Init"):
+            threading.Thread(target=remote_init_server, args=(self.args, params)).start()
+        else:
+            raise PermissionError("Polkit: Authentication failed")
 
     @dbus.service.method("id.waydro.Initializer", in_signature='', out_signature='')
     def Done(self):
         if is_initialized(self.args):
             self.looper.quit()
 
 
     @dbus.service.method("id.waydro.Initializer", in_signature='', out_signature='')
     def Done(self):
         if is_initialized(self.args):
             self.looper.quit()
 
+def ensure_polkit_auth(sender, conn, privilege):
+    dbus_info = dbus.Interface(conn.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", False), "org.freedesktop.DBus")
+    pid = dbus_info.GetConnectionUnixProcessID(sender)
+    polkit = dbus.Interface(dbus.SystemBus().get_object("org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", False), "org.freedesktop.PolicyKit1.Authority")
+    try:
+        (is_auth, _, _) = polkit.CheckAuthorization(
+            ("unix-process", {
+                "pid": dbus.UInt32(pid, variant_level=1),
+                "start-time": dbus.UInt64(0, variant_level=1)}),
+            privilege, {"AllowUserInteraction": "true"},
+            dbus.UInt32(1),
+            "",
+            timeout=300)
+        return is_auth
+    except dbus.DBusException:
+        raise PermissionError("Polkit: Authentication timed out")
+
 def background_remote_init_process(args):
     with helpers.ipc.open_channel("remote_init_output", "wb") as channel_out:
         class StdoutRedirect(logging.StreamHandler):
 def background_remote_init_process(args):
     with helpers.ipc.open_channel("remote_init_output", "wb") as channel_out:
         class StdoutRedirect(logging.StreamHandler):
@@ -249,6 +272,8 @@ def remote_init_client(args):
     class WaydroidInitWindow(Gtk.Window):
         def __init__(self):
             super().__init__(title="Initialize Waydroid")
     class WaydroidInitWindow(Gtk.Window):
         def __init__(self):
             super().__init__(title="Initialize Waydroid")
+            channels_cfg = tools.config.load_channels()
+
             self.set_default_size(600, 250)
             self.set_icon_from_file(tools.config.tools_src + "/data/AppIcon.png")
 
             self.set_default_size(600, 250)
             self.set_icon_from_file(tools.config.tools_src + "/data/AppIcon.png")
 
@@ -259,14 +284,14 @@ def remote_init_client(args):
 
             sysOtaLabel = Gtk.Label("System OTA")
             sysOtaEntry = Gtk.Entry()
 
             sysOtaLabel = Gtk.Label("System OTA")
             sysOtaEntry = Gtk.Entry()
-            sysOtaEntry.set_text(tools.config.channels_defaults["system_channel"])
+            sysOtaEntry.set_text(channels_cfg["channels"]["system_channel"])
             grid.attach(sysOtaLabel, 0, 0, 1, 1)
             grid.attach_next_to(sysOtaEntry ,sysOtaLabel, Gtk.PositionType.RIGHT, 2, 1)
             self.sysOta = sysOtaEntry.get_buffer()
 
             vndOtaLabel = Gtk.Label("Vendor OTA")
             vndOtaEntry = Gtk.Entry()
             grid.attach(sysOtaLabel, 0, 0, 1, 1)
             grid.attach_next_to(sysOtaEntry ,sysOtaLabel, Gtk.PositionType.RIGHT, 2, 1)
             self.sysOta = sysOtaEntry.get_buffer()
 
             vndOtaLabel = Gtk.Label("Vendor OTA")
             vndOtaEntry = Gtk.Entry()
-            vndOtaEntry.set_text(tools.config.channels_defaults["vendor_channel"])
+            vndOtaEntry.set_text(channels_cfg["channels"]["vendor_channel"])
             grid.attach(vndOtaLabel, 0, 1, 1, 1)
             grid.attach_next_to(vndOtaEntry, vndOtaLabel, Gtk.PositionType.RIGHT, 2, 1)
             self.vndOta = vndOtaEntry.get_buffer()
             grid.attach(vndOtaLabel, 0, 1, 1, 1)
             grid.attach_next_to(vndOtaEntry, vndOtaLabel, Gtk.PositionType.RIGHT, 2, 1)
             self.vndOta = vndOtaEntry.get_buffer()
@@ -342,9 +367,12 @@ def remote_init_client(args):
                     "vendor_channel": self.vndOta.get_text(),
                     "system_type": self.sysType.get_active_text()
                 }
                     "vendor_channel": self.vndOta.get_text(),
                     "system_type": self.sysType.get_active_text()
                 }
-                tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer").Init(params)
-            except:
-                draw("The waydroid container service is not listening\n")
+                tools.helpers.ipc.DBusContainerService("/Initializer", "id.waydro.Initializer").Init(params, timeout=310)
+            except dbus.DBusException as e:
+                if e.get_dbus_name() == "org.freedesktop.DBus.Python.PermissionError":
+                    draw(e.get_dbus_message().splitlines()[-1] + "\n")
+                else:
+                    draw("The waydroid container service is not listening\n")
                 GLib.idle_add(self.downloadBtn.set_sensitive, True)
                 return
 
                 GLib.idle_add(self.downloadBtn.set_sensitive, True)
                 return