]> git.proxmox.com Git - systemd.git/blobdiff - src/tty-ask-password-agent/tty-ask-password-agent.c
New upstream version 240
[systemd.git] / src / tty-ask-password-agent / tty-ask-password-agent.c
index 40d594896b4b02771c2a1cde8b489190be353a12..fc165ffc01ca686062ebc6ff581908bbd2cb87ff 100644 (file)
 #include "hashmap.h"
 #include "io-util.h"
 #include "macro.h"
+#include "main-func.h"
 #include "mkdir.h"
 #include "path-util.h"
+#include "pretty-print.h"
 #include "process-util.h"
 #include "signal-util.h"
 #include "socket-util.h"
@@ -228,21 +230,25 @@ static int ask_password_plymouth(
         r = 0;
 
 finish:
-        explicit_bzero(buffer, sizeof(buffer));
+        explicit_bzero_safe(buffer, sizeof(buffer));
         return r;
 }
 
 static int send_passwords(const char *socket_name, char **passwords) {
         _cleanup_free_ char *packet = NULL;
         _cleanup_close_ int socket_fd = -1;
-        union sockaddr_union sa = { .un.sun_family = AF_UNIX };
+        union sockaddr_union sa = {};
         size_t packet_length = 1;
         char **p, *d;
         ssize_t n;
-        int r;
+        int r, salen;
 
         assert(socket_name);
 
+        salen = sockaddr_un_set_path(&sa.un, socket_name);
+        if (salen < 0)
+                return salen;
+
         STRV_FOREACH(p, passwords)
                 packet_length += strlen(*p) + 1;
 
@@ -262,9 +268,7 @@ static int send_passwords(const char *socket_name, char **passwords) {
                 goto finish;
         }
 
-        strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path));
-
-        n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, SOCKADDR_UN_LEN(sa.un));
+        n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, salen);
         if (n < 0) {
                 r = log_debug_errno(errno, "sendto(): %m");
                 goto finish;
@@ -273,7 +277,7 @@ static int send_passwords(const char *socket_name, char **passwords) {
         r = (int) n;
 
 finish:
-        explicit_bzero(packet, packet_length);
+        explicit_bzero_safe(packet, packet_length);
         return r;
 }
 
@@ -304,10 +308,9 @@ static int parse_password(const char *filename, char **wall) {
         if (r < 0)
                 return r;
 
-        if (!socket_name) {
-                log_error("Invalid password file %s", filename);
-                return -EBADMSG;
-        }
+        if (!socket_name)
+                return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
+                                       "Invalid password file %s", filename);
 
         if (not_after > 0 && now(CLOCK_MONOTONIC) > not_after)
                 return 0;
@@ -323,7 +326,7 @@ static int parse_password(const char *filename, char **wall) {
 
                 if (asprintf(&_wall,
                              "%s%sPassword entry required for \'%s\' (PID %u).\r\n"
-                             "Please enter password with the systemd-tty-ask-password-agent tool!",
+                             "Please enter password with the systemd-tty-ask-password-agent tool:",
                              strempty(*wall),
                              *wall ? "\r\n\r\n" : "",
                              message,
@@ -348,7 +351,6 @@ static int parse_password(const char *filename, char **wall) {
                 if (arg_plymouth)
                         r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords);
                 else {
-                        char *password = NULL;
                         int tty_fd = -1;
 
                         if (arg_console) {
@@ -366,18 +368,12 @@ static int parse_password(const char *filename, char **wall) {
                         r = ask_password_tty(tty_fd, message, NULL, not_after,
                                              (echo ? ASK_PASSWORD_ECHO : 0) |
                                              (arg_console ? ASK_PASSWORD_CONSOLE_COLOR : 0),
-                                             filename, &password);
+                                             filename, &passwords);
 
                         if (arg_console) {
                                 tty_fd = safe_close(tty_fd);
                                 release_terminal();
                         }
-
-                        if (r >= 0)
-                                r = strv_push(&passwords, password);
-
-                        if (r < 0)
-                                string_free_erase(password);
                 }
 
                 /* If the query went away, that's OK */
@@ -524,8 +520,12 @@ static int watch_passwords(void) {
         if (notify < 0)
                 return log_error_errno(errno, "Failed to allocate directory watch: %m");
 
-        if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO) < 0)
-                return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: %m");
+        if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO) < 0) {
+                if (errno == ENOSPC)
+                        return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: inotify watch limit reached");
+                else
+                        return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: %m");
+        }
 
         assert_se(sigemptyset(&mask) >= 0);
         assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0);
@@ -562,7 +562,14 @@ static int watch_passwords(void) {
         return 0;
 }
 
-static void help(void) {
+static int help(void) {
+        _cleanup_free_ char *link = NULL;
+        int r;
+
+        r = terminal_urlify_man("systemd-tty-ask-password-agent", "1", &link);
+        if (r < 0)
+                return log_oom();
+
         printf("%s [OPTIONS...]\n\n"
                "Process system password requests.\n\n"
                "  -h --help     Show this help\n"
@@ -572,8 +579,13 @@ static void help(void) {
                "     --watch    Continuously process password requests\n"
                "     --wall     Continuously forward password requests to wall\n"
                "     --plymouth Ask question with Plymouth instead of on TTY\n"
-               "     --console  Ask question on /dev/console instead of current TTY\n",
-               program_invocation_short_name);
+               "     --console  Ask question on /dev/console instead of current TTY\n"
+               "\nSee the %s for details.\n"
+               , program_invocation_short_name
+               , link
+        );
+
+        return 0;
 }
 
 static int parse_argv(int argc, char *argv[]) {
@@ -610,8 +622,7 @@ static int parse_argv(int argc, char *argv[]) {
                 switch (c) {
 
                 case 'h':
-                        help();
-                        return 0;
+                        return help();
 
                 case ARG_VERSION:
                         return version();
@@ -640,10 +651,9 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_console = true;
                         if (optarg) {
 
-                                if (isempty(optarg)) {
-                                        log_error("Empty console device path is not allowed.");
-                                        return -EINVAL;
-                                }
+                                if (isempty(optarg))
+                                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                               "Empty console device path is not allowed.");
 
                                 arg_device = optarg;
                         }
@@ -656,22 +666,19 @@ static int parse_argv(int argc, char *argv[]) {
                         assert_not_reached("Unhandled option");
                 }
 
-        if (optind != argc) {
-                log_error("%s takes no arguments.", program_invocation_short_name);
-                return -EINVAL;
-        }
+        if (optind != argc)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "%s takes no arguments.", program_invocation_short_name);
 
         if (arg_plymouth || arg_console) {
 
-                if (!IN_SET(arg_action, ACTION_QUERY, ACTION_WATCH)) {
-                        log_error("Options --query and --watch conflict.");
-                        return -EINVAL;
-                }
+                if (!IN_SET(arg_action, ACTION_QUERY, ACTION_WATCH))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "Options --query and --watch conflict.");
 
-                if (arg_plymouth && arg_console) {
-                        log_error("Options --plymouth and --console conflict.");
-                        return -EINVAL;
-                }
+                if (arg_plymouth && arg_console)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "Options --plymouth and --console conflict.");
         }
 
         return 1;
@@ -826,42 +833,37 @@ static int ask_on_consoles(int argc, char *argv[]) {
         return 0;
 }
 
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
         int r;
 
-        log_set_target(LOG_TARGET_AUTO);
-        log_parse_environment();
-        log_open();
+        log_setup_service();
 
         umask(0022);
 
         r = parse_argv(argc, argv);
         if (r <= 0)
-                goto finish;
+                return r;
 
         if (arg_console && !arg_device)
                 /*
-                 * Spawn for each console device a separate process.
+                 * Spawn a separate process for each console device.
                  */
-                r = ask_on_consoles(argc, argv);
-        else {
-
-                if (arg_device) {
-                        /*
-                         * Later on, a controlling terminal will be acquired,
-                         * therefore the current process has to become a session
-                         * leader and should not have a controlling terminal already.
-                         */
-                        (void) setsid();
-                        (void) release_terminal();
-                }
+                return ask_on_consoles(argc, argv);
 
-                if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL))
-                        r = watch_passwords();
-                else
-                        r = show_passwords();
+        if (arg_device) {
+                /*
+                 * Later on, a controlling terminal will be acquired,
+                 * therefore the current process has to become a session
+                 * leader and should not have a controlling terminal already.
+                 */
+                (void) setsid();
+                (void) release_terminal();
         }
 
-finish:
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL))
+                return watch_passwords();
+        else
+                return show_passwords();
 }
+
+DEFINE_MAIN_FUNCTION(run);