diff --git a/Makefile b/Makefile index f838328..67e74fa 100644 --- 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 +POLKIT_DIR := $(PREFIX)/share/polkit-1 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_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 -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 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/; \ diff --git a/dbus/id.waydro.Container.policy b/dbus/id.waydro.Container.policy new file mode 100644 index 0000000..52cb807 --- /dev/null +++ b/dbus/id.waydro.Container.policy @@ -0,0 +1,18 @@ + + + + + Waydroid + https://waydro.id + + Waydroid Initialization + Initialize Waydroid with user-provided OTA channels. Do you trust the source? + + auth_admin + auth_admin + auth_admin_keep + + + diff --git a/debian/control b/debian/control index 89a4cd4..51e416b 100644 --- a/debian/control +++ b/debian/control @@ -19,7 +19,8 @@ Depends: ${misc:Depends}, 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. diff --git a/tools/actions/initializer.py b/tools/actions/initializer.py index 5238b3c..7fec732 100644 --- a/tools/actions/initializer.py +++ b/tools/actions/initializer.py @@ -152,15 +152,38 @@ class DbusInitializer(dbus.service.Object): 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() +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): @@ -249,6 +272,8 @@ def remote_init_client(args): 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") @@ -259,14 +284,14 @@ def remote_init_client(args): 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() - 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() @@ -342,9 +367,12 @@ def remote_init_client(args): "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