]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tty-ask-password-agent: minor modernizations
authorLennart Poettering <lennart@poettering.net>
Fri, 13 Sep 2024 09:06:28 +0000 (11:06 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 21 Oct 2024 12:13:41 +0000 (14:13 +0200)
src/tty-ask-password-agent/tty-ask-password-agent.c

index df21f3d28fb3f57622d06e47d046e39c32f3ba4e..1e4eb9b7684e5f7fc0532041f6e6b61580a58c89 100644 (file)
@@ -55,40 +55,35 @@ static bool arg_console = false;
 static const char *arg_device = NULL;
 
 static int send_passwords(const char *socket_name, char **passwords) {
-        _cleanup_(erase_and_freep) char *packet = NULL;
-        _cleanup_close_ int socket_fd = -EBADF;
-        union sockaddr_union sa;
-        socklen_t sa_len;
-        size_t packet_length = 1;
-        char *d;
-        ssize_t n;
         int r;
 
         assert(socket_name);
 
+        union sockaddr_union sa;
         r = sockaddr_un_set_path(&sa.un, socket_name);
         if (r < 0)
                 return r;
-        sa_len = r;
+        socklen_t sa_len = r;
 
+        size_t packet_length = 1;
         STRV_FOREACH(p, passwords)
                 packet_length += strlen(*p) + 1;
 
-        packet = new(char, packet_length);
+        _cleanup_(erase_and_freep) char *packet = new(char, packet_length);
         if (!packet)
                 return -ENOMEM;
 
         packet[0] = '+';
 
-        d = packet + 1;
+        char *d = packet + 1;
         STRV_FOREACH(p, passwords)
                 d = stpcpy(d, *p) + 1;
 
-        socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+        _cleanup_close_ int socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
         if (socket_fd < 0)
                 return log_debug_errno(errno, "socket(): %m");
 
-        n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, sa_len);
+        ssize_t n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, sa_len);
         if (n < 0)
                 return log_debug_errno(errno, "sendto(): %m");
 
@@ -96,12 +91,9 @@ static int send_passwords(const char *socket_name, char **passwords) {
 }
 
 static bool wall_tty_match(const char *path, bool is_local, void *userdata) {
-        _cleanup_free_ char *p = NULL;
-        _cleanup_close_ int fd = -EBADF;
-        struct stat st;
-
         assert(path_is_absolute(path));
 
+        struct stat st;
         if (lstat(path, &st) < 0) {
                 log_debug_errno(errno, "Failed to stat %s: %m", path);
                 return true;
@@ -120,12 +112,13 @@ static bool wall_tty_match(const char *path, bool is_local, void *userdata) {
          * advantage that the block will automatically go away if the
          * process dies. */
 
+        _cleanup_free_ char *p = NULL;
         if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) {
-                log_oom();
+                log_oom_debug();
                 return true;
         }
 
-        fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+        _cleanup_close_ int fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
         if (fd < 0) {
                 log_debug_errno(errno, "Failed to open the wall pipe: %m");
                 return 1;
@@ -162,6 +155,7 @@ static int agent_ask_password_tty(
         r = ask_password_tty(tty_fd, &req, until, flags, flag_file, ret);
 
         if (arg_console) {
+                assert(tty_fd >= 0);
                 tty_fd = safe_close(tty_fd);
                 release_terminal();
 
@@ -172,7 +166,7 @@ static int agent_ask_password_tty(
         return r;
 }
 
-static int process_one_password_file(const char *filename) {
+static int process_one_password_file(const char *filename, FILE *f) {
         _cleanup_free_ char *socket_name = NULL, *message = NULL;
         bool accept_cached = false, echo = false, silent = false;
         uint64_t not_after = 0;
@@ -192,13 +186,17 @@ static int process_one_password_file(const char *filename) {
         int r;
 
         assert(filename);
-
-        r = config_parse(NULL, filename, NULL,
-                         NULL,
-                         config_item_table_lookup, items,
+        assert(f);
+
+        r = config_parse(/* unit= */ NULL,
+                         filename,
+                         f,
+                         /* sections= */ "Ask\0",
+                         config_item_table_lookup,
+                         items,
                          CONFIG_PARSE_RELAXED|CONFIG_PARSE_WARN,
-                         NULL,
-                         NULL);
+                         /* userdata= */ NULL,
+                         /* ret_stat= */ NULL);
         if (r < 0)
                 return r;
 
@@ -299,7 +297,7 @@ static int wall_tty_block(void) {
 
 static int process_password_files(void) {
         _cleanup_closedir_ DIR *d = NULL;
-        int r = 0;
+        int ret = 0, r;
 
         d = opendir("/run/systemd/ask-password");
         if (!d) {
@@ -311,12 +309,8 @@ static int process_password_files(void) {
 
         FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory: %m")) {
                 _cleanup_free_ char *p = NULL;
-                int q;
-
-                /* We only support /run on tmpfs, hence we can rely on
-                 * d_type to be reliable */
 
-                if (de->d_type != DT_REG)
+                if (!IN_SET(de->d_type, DT_REG, DT_UNKNOWN))
                         continue;
 
                 if (!startswith(de->d_name, "ask."))
@@ -326,12 +320,17 @@ static int process_password_files(void) {
                 if (!p)
                         return log_oom();
 
-                q = process_one_password_file(p);
-                if (q < 0 && r == 0)
-                        r = q;
+                _cleanup_fclose_ FILE *f = NULL;
+                r = xfopenat(dirfd(d), de->d_name, "re", O_NOFOLLOW, &f);
+                if (r < 0) {
+                        log_warning_errno(r, "Failed to open '%s', ignoring: %m", p);
+                        continue;
+                }
+
+                RET_GATHER(ret, process_one_password_file(p, f));
         }
 
-        return r;
+        return ret;
 }
 
 static int process_and_watch_password_files(bool watch) {
@@ -377,18 +376,15 @@ static int process_and_watch_password_files(bool watch) {
                 usec_t timeout = USEC_INFINITY;
 
                 r = process_password_files();
-                if (r < 0) {
-                        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. */
-                                timeout = 0;
-                        else
-                                /* FIXME: we should do something here since otherwise the service
-                                 * requesting the password won't notice the error and will wait
-                                 * indefinitely. */
-                                log_error_errno(r, "Failed to process password: %m");
-                }
+                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. */
+                        timeout = 0;
+                else if (r < 0)
+                        /* FIXME: we should do something here since otherwise the service
+                         * requesting the password won't notice the error and will wait
+                         * indefinitely. */
+                        log_warning_errno(r, "Failed to process password, ignoring: %m");
 
                 if (!watch)
                         break;