chiark / gitweb /
ask-password: ask for passphrases not only on the first console of /dev/console
authorWerner Fink <werner@suse.de>
Wed, 18 Nov 2015 11:28:30 +0000 (12:28 +0100)
committerSven Eden <yamakuzure@gmx.net>
Fri, 16 Jun 2017 08:12:58 +0000 (10:12 +0200)
but also on all other consoles.  This does help on e.g. mainframes
where often a serial console together with other consoles are
used.  Even rack based servers attachted to both a serial console
as well as having a virtual console do sometimes miss a connected
monitor.

To be able to ask on all terminal devices of /dev/console the devices
are collected. If more than one device are found, then on each of the
terminals a inquiring task for passphrase is forked and do not return
to the caller.

Every task has its own session and its own controlling terminal.
If one of the tasks does handle a password, the remaining tasks
will be terminated.

Also let contradictory options on the command of
elogind-tty-ask-password-agent fail.

Spwan for each device of the system console /dev/console a own process.
Replace the system call wait() with with system call waitid().
Use SIGTERM instead of SIGHUP to get unresponsive childs down.

Port the collect_consoles() function forward to a pulbic and strv
based function "get_kernel_consoles()" in terminal-util.c and use this
in tty-ask-password-agent.c.

src/basic/terminal-util.c

index cb75ad7..8f46c92 100644 (file)
@@ -50,6 +50,7 @@
 #include "socket-util.h"
 #include "stat-util.h"
 #include "string-util.h"
+#include "strv.h"
 #include "terminal-util.h"
 #include "time-util.h"
 #include "util.h"
@@ -715,6 +716,64 @@ char *resolve_dev_console(char **active) {
         return tty;
 }
 
+int get_kernel_consoles(char ***consoles) {
+        _cleanup_strv_free_ char **con = NULL;
+        _cleanup_free_ char *line = NULL;
+        const char *active;
+        int r;
+
+        assert(consoles);
+
+        r = read_one_line_file("/sys/class/tty/console/active", &line);
+        if (r < 0)
+                return r;
+
+        active = line;
+        for (;;) {
+                _cleanup_free_ char *tty = NULL;
+                char *path;
+
+                r = extract_first_word(&active, &tty, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                if (streq(tty, "tty0")) {
+                        tty = mfree(tty);
+                        r = read_one_line_file("/sys/class/tty/tty0/active", &tty);
+                        if (r < 0)
+                                return r;
+                }
+
+                path = strappend("/dev/", tty);
+                if (!path)
+                        return -ENOMEM;
+
+                if (access(path, F_OK) < 0) {
+                        log_debug_errno(errno, "Console device %s is not accessible, skipping: %m", path);
+                        free(path);
+                        continue;
+                }
+
+                r = strv_consume(&con, path);
+                if (r < 0)
+                        return r;
+        }
+
+        if (strv_isempty(con)) {
+                log_debug("No devices found for system console");
+
+                r = strv_extend(&con, "/dev/console");
+                if (r < 0)
+                        return r;
+        }
+
+        *consoles = con;
+        con = NULL;
+        return 0;
+}
+
 bool tty_is_vc_resolve(const char *tty) {
         _cleanup_free_ char *active = NULL;