From b9be947d9435bb4933948fcd95dcb40d994bbaa6 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Sat, 23 Dec 2023 13:24:46 +0100 Subject: [PATCH] Spawn goldwarden daemon automatically on boot; fix biometrics --- agent/sockets/callingcontext.go | 26 +++++++++++++++++++++----- agent/systemauth/biometrics/polkit.go | 3 +++ agent/systemauth/systemauth.go | 1 + com.quexten.Goldwarden.yml | 7 +++++-- ui/goldwarden.py | 22 +++++++++++++++++++++- ui/main.py | 15 +++++++++++++++ ui/settings.py | 21 +++++++++++++-------- 7 files changed, 79 insertions(+), 16 deletions(-) diff --git a/agent/sockets/callingcontext.go b/agent/sockets/callingcontext.go index 76d3063..4a725f0 100644 --- a/agent/sockets/callingcontext.go +++ b/agent/sockets/callingcontext.go @@ -3,6 +3,7 @@ package sockets import ( "net" "os/user" + "time" gops "github.com/mitchellh/go-ps" "inet.af/peercred" @@ -20,11 +21,26 @@ type CallingContext struct { func GetCallingContext(connection net.Conn) CallingContext { creds, err := peercred.Get(connection) + errorContext := CallingContext{ + UserName: "unknown user", + ProcessName: "unknown process", + ParentProcessName: "unknown parent", + GrandParentProcessName: "unknown grandparent", + ProcessPid: time.Now().UTC().Nanosecond(), + ParentProcessPid: time.Now().UTC().Nanosecond(), + GrandParentProcessPid: time.Now().UTC().Nanosecond(), + } if err != nil { - panic(err) + return errorContext } pid, _ := creds.PID() process, err := gops.FindProcess(pid) + if err != nil { + return errorContext + } + if process == nil { + return errorContext + } // git is epheremal and spawns ssh-keygen and ssh so we need to anchor to git if process.Executable() == "ssh-keygen" || process.Executable() == "ssh" { @@ -38,22 +54,22 @@ func GetCallingContext(connection net.Conn) CallingContext { uid, _ := creds.UserID() ppid := process.PPid() if err != nil { - panic(err) + return errorContext } parentProcess, err := gops.FindProcess(ppid) if err != nil { - panic(err) + return errorContext } parentParentProcess, err := gops.FindProcess(parentProcess.PPid()) if err != nil { - panic(err) + return errorContext } username, err := user.LookupId(uid) if err != nil { - panic(err) + return errorContext } return CallingContext{ diff --git a/agent/systemauth/biometrics/polkit.go b/agent/systemauth/biometrics/polkit.go index dcb7565..7a08647 100644 --- a/agent/systemauth/biometrics/polkit.go +++ b/agent/systemauth/biometrics/polkit.go @@ -78,15 +78,18 @@ func BiometricsWorking() bool { authority, err := polkit.NewAuthority() if err != nil { + log.Warn("Failed to create polkit authority: %s", err.Error()) return false } result, err := authority.EnumerateActions("en") if err != nil { + log.Warn("Failed to enumerate polkit actions: %s", err.Error()) return false } if len(result) == 0 { + log.Warn("No polkit actions found") return false } diff --git a/agent/systemauth/systemauth.go b/agent/systemauth/systemauth.go index 931a5cc..5ebf567 100644 --- a/agent/systemauth/systemauth.go +++ b/agent/systemauth/systemauth.go @@ -87,6 +87,7 @@ func GetPermission(sessionType SessionType, ctx sockets.CallingContext, config * return false, nil } } else { + log.Warn("Biometrics is not available, asking for pin") pin, err := pinentry.GetPassword("Enter PIN", "Biometrics is not available. Enter your pin to authorize this action. "+message) if err != nil { return false, err diff --git a/com.quexten.Goldwarden.yml b/com.quexten.Goldwarden.yml index a5994ab..434dbe4 100644 --- a/com.quexten.Goldwarden.yml +++ b/com.quexten.Goldwarden.yml @@ -8,9 +8,12 @@ finish-args: - --share=network - --socket=wayland - --socket=fallback-x11 - - --filesystem=home - # todo remove this + - --device=dri + # - --filesystem=home + - --filesystem=host + # polkit & locking.. should filter this later on - --socket=session-bus + - --socket=system-bus modules: - name: goldwarden buildsystem: simple diff --git a/ui/goldwarden.py b/ui/goldwarden.py index 72ef2f5..dca8047 100644 --- a/ui/goldwarden.py +++ b/ui/goldwarden.py @@ -106,4 +106,24 @@ def autotype(username, password): restic_cmd = f"{BINARY_PATH} autotype --username {username}" result = subprocess.run(restic_cmd.split(), capture_output=True, text=True, env=env) if result.returncode != 0: - raise Exception("Failed to initialize repository, err", result.stderr) \ No newline at end of file + raise Exception("Failed to initialize repository, err", result.stderr) + +def is_daemon_running(): + restic_cmd = f"{BINARY_PATH} vault status" + result = subprocess.run(restic_cmd.split(), capture_output=True, text=True) + if result.returncode != 0: + return False + daemon_not_running = ("daemon running?" in result.stderr or "daemon running" in result.stderr) + return not daemon_not_running + +def run_daemon(): + restic_cmd = f"{BINARY_PATH} daemonize" + # print while running + result = subprocess.Popen(restic_cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if result.returncode != 0: + print("Failed err", result.stderr) + for line in result.stdout: + print(line.decode("utf-8")) + result.wait() + print("quitting goldwarden daemon") + return result.returncode \ No newline at end of file diff --git a/ui/main.py b/ui/main.py index c3480a3..627dccd 100644 --- a/ui/main.py +++ b/ui/main.py @@ -4,6 +4,8 @@ import subprocess from tendo import singleton import monitors.dbus_autofill_monitor import sys +import goldwarden +from threading import Thread try: subprocess.Popen(["python3", "/app/bin/background.py"], start_new_session=True) @@ -21,6 +23,19 @@ try: except: exit() +def run_daemon(): + # todo: do a proper check + time.sleep(20) + if not goldwarden.is_daemon_running(): + goldwarden.run_daemon() + +if not goldwarden.is_daemon_running(): + print("daemon not running.. autostarting") + daemonThread = Thread(target=run_daemon) + daemonThread.start() + +print("starting autofill monitor") + def on_autofill(): subprocess.Popen(["python3", "/app/bin/autofill.py"], start_new_session=True) monitors.dbus_autofill_monitor.on_autofill = on_autofill diff --git a/ui/settings.py b/ui/settings.py index 2c823f4..343ccab 100644 --- a/ui/settings.py +++ b/ui/settings.py @@ -123,14 +123,19 @@ class SettingsWinvdow(Gtk.ApplicationWindow): def update_labels(): pin_set = goldwarden.is_pin_enabled() status = goldwarden.get_vault_status() - locked = status["locked"] - self.login_button.set_sensitive(pin_set and not locked) - self.set_pin_button.set_sensitive(not pin_set or not locked) - self.status_row.set_subtitle(str("Unlocked" if not locked else "Locked")) - self.login_row.set_subtitle(str(status["loginEntries"])) - self.notes_row.set_subtitle(str(status["noteEntries"])) - self.unlock_button.set_sensitive(True) - self.unlock_button.set_label("Unlock" if locked else "Lock") + if status != None: + locked = status["locked"] + self.login_button.set_sensitive(pin_set and not locked) + self.set_pin_button.set_sensitive(not pin_set or not locked) + self.status_row.set_subtitle(str("Unlocked" if not locked else "Locked")) + self.login_row.set_subtitle(str(status["loginEntries"])) + self.notes_row.set_subtitle(str(status["noteEntries"])) + self.unlock_button.set_sensitive(True) + self.unlock_button.set_label("Unlock" if locked else "Lock") + else: + is_daemon_running = goldwarden.is_daemon_running() + if not is_daemon_running: + self.status_row.set_subtitle("Daemon not running") GLib.timeout_add(1000, update_labels) GLib.timeout_add(1000, update_labels)