]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tty-ask-password-agent: support for watching both system-wide and per-user askpw dir
authorLennart Poettering <lennart@poettering.net>
Fri, 13 Sep 2024 11:54:36 +0000 (13:54 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 21 Oct 2024 12:13:45 +0000 (14:13 +0200)
Fixes: #1232 #2217
src/shared/ask-password-api.c
src/shared/ask-password-api.h
src/tty-ask-password-agent/tty-ask-password-agent.c

index 0bb6611c64b17553d92810ecc821c83431028cc4..53d1f986b85c1ba0babe8901e5b4bb3873b45740 100644 (file)
@@ -36,6 +36,7 @@
 #include "missing_syscall.h"
 #include "mkdir-label.h"
 #include "nulstr-util.h"
+#include "path-lookup.h"
 #include "plymouth-util.h"
 #include "process-util.h"
 #include "random-util.h"
@@ -1021,3 +1022,18 @@ int ask_password_auto(
 
         return -EUNATCH;
 }
+
+int acquire_user_ask_password_directory(char **ret) {
+        int r;
+
+        r = xdg_user_runtime_dir("systemd/ask-password", ret);
+        if (r == -ENXIO) {
+                if (ret)
+                        *ret = NULL;
+                return 0;
+        }
+        if (r < 0)
+                return r;
+
+        return 1;
+}
index e851d6d087d5a85a0cc7d344e55e9973cbf56f31..9b197230e963526f70e407d43b573e597746f6e3 100644 (file)
@@ -31,3 +31,5 @@ int ask_password_tty(int tty_fd, const AskPasswordRequest *req, usec_t until, As
 int ask_password_plymouth(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
 int ask_password_agent(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret);
 int ask_password_auto(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret);
+
+int acquire_user_ask_password_directory(char **ret);
index 1e4eb9b7684e5f7fc0532041f6e6b61580a58c89..ce0a598d87e4b111b19dc9e51b631b9ac98c4124 100644 (file)
@@ -295,19 +295,21 @@ static int wall_tty_block(void) {
         return fd;
 }
 
-static int process_password_files(void) {
+static int process_password_files(const char *path) {
         _cleanup_closedir_ DIR *d = NULL;
         int ret = 0, r;
 
-        d = opendir("/run/systemd/ask-password");
+        assert(path);
+
+        d = opendir(path);
         if (!d) {
                 if (errno == ENOENT)
                         return 0;
 
-                return log_error_errno(errno, "Failed to open /run/systemd/ask-password: %m");
+                return log_error_errno(errno, "Failed to open '%s': %m", path);
         }
 
-        FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory: %m")) {
+        FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory '%s': %m", path)) {
                 _cleanup_free_ char *p = NULL;
 
                 if (!IN_SET(de->d_type, DT_REG, DT_UNKNOWN))
@@ -316,7 +318,7 @@ static int process_password_files(void) {
                 if (!startswith(de->d_name, "ask."))
                         continue;
 
-                p = path_join("/run/systemd/ask-password", de->d_name);
+                p = path_join(path, de->d_name);
                 if (!p)
                         return log_oom();
 
@@ -340,6 +342,7 @@ static int process_and_watch_password_files(bool watch) {
                 _FD_MAX
         };
 
+        _cleanup_free_ char *user_ask_password_directory = NULL;
         _unused_ _cleanup_close_ int tty_block_fd = -EBADF;
         _cleanup_close_ int notify = -EBADF, signal_fd = -EBADF;
         struct pollfd pollfd[_FD_MAX];
@@ -350,6 +353,12 @@ static int process_and_watch_password_files(bool watch) {
 
         (void) mkdir_p_label("/run/systemd/ask-password", 0755);
 
+        r = acquire_user_ask_password_directory(&user_ask_password_directory);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine per-user password directory: %m");
+        if (r > 0)
+                (void) mkdir_p_label(user_ask_password_directory, 0755);
+
         assert_se(sigemptyset(&mask) >= 0);
         assert_se(sigset_add_many(&mask, SIGTERM) >= 0);
         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0);
@@ -365,17 +374,25 @@ static int process_and_watch_password_files(bool watch) {
                 if (notify < 0)
                         return log_error_errno(errno, "Failed to allocate directory watch: %m");
 
-                r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO);
+                r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO|IN_ONLYDIR);
                 if (r < 0)
                         return r;
 
+                if (user_ask_password_directory) {
+                        r = inotify_add_watch_and_warn(notify, user_ask_password_directory, IN_CLOSE_WRITE|IN_MOVED_TO|IN_ONLYDIR);
+                        if (r < 0)
+                                return r;
+                }
+
                 pollfd[FD_INOTIFY] = (struct pollfd) { .fd = notify, .events = POLLIN };
         }
 
         for (;;) {
                 usec_t timeout = USEC_INFINITY;
 
-                r = process_password_files();
+                r = process_password_files("/run/systemd/ask-password");
+                if (user_ask_password_directory)
+                        RET_GATHER(r, process_password_files(user_ask_password_directory));
                 if (r == -ECANCELED)
                         /* Disable poll() timeout since at least one password has been skipped and therefore
                          * one file remains and is unlikely to trigger any events. */