]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fido2: hook up with plymouth for notifications
authorLuca Boccassi <luca.boccassi@gmail.com>
Thu, 10 Apr 2025 22:10:37 +0000 (23:10 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 11 Apr 2025 22:07:38 +0000 (23:07 +0100)
Show notifications for fido2 messages in plymouth, so that they
show up in the initrd like the passphrase prompt already does.

src/shared/libfido2-util.c
src/shared/plymouth-util.c
src/shared/plymouth-util.h
src/storagetm/storagetm.c

index 48140ade21d1805b85eebd053459b9525c2648cc..4a44fe5ff5687df119c36e204e8b3df3467373f2 100644 (file)
@@ -11,6 +11,7 @@
 #include "glyph-util.h"
 #include "log.h"
 #include "memory-util.h"
+#include "plymouth-util.h"
 #include "strv.h"
 #include "unistd.h"
 
@@ -362,6 +363,26 @@ static int fido2_is_cred_in_specific_token(
         }
 }
 
+static void plymouth_start_interaction(const char *text, bool *ret_displayed) {
+        assert(ret_displayed);
+
+        if (plymouth_send_msg(text, /* pause_spinner= */ true) < 0)
+                return;
+
+        *ret_displayed = true;
+}
+
+static void plymouth_end_interaction(bool *displayed) {
+        assert(displayed);
+
+        if (!*displayed)
+                return;
+
+        /* In theory 'm' should hide a message, but it doesn't work (long standing issue).
+         * As a workaround, sending a single NUL byte hides the previous messages. */
+        (void) plymouth_send_msg("", /* pause_spinner= */ false);
+}
+
 static int fido2_use_hmac_hash_specific_token(
                 const char *path,
                 const char *rp_id,
@@ -374,6 +395,7 @@ static int fido2_use_hmac_hash_specific_token(
                 void **ret_hmac,
                 size_t *ret_hmac_size) {
 
+        _cleanup_(plymouth_end_interaction) bool plymouth_displayed = false;
         _cleanup_(fido_assert_free_wrapper) fido_assert_t *a = NULL;
         _cleanup_(fido_dev_free_wrapper) fido_dev_t *d = NULL;
         _cleanup_(erase_and_freep) void *hmac_copy = NULL;
@@ -445,10 +467,12 @@ static int fido2_use_hmac_hash_specific_token(
                                                enable_disable(FLAGS_SET(required, FIDO2ENROLL_UP)),
                                                sym_fido_strerr(r));
 
-                if (FLAGS_SET(required, FIDO2ENROLL_UP))
+                if (FLAGS_SET(required, FIDO2ENROLL_UP)) {
                         log_notice("%s%sPlease confirm presence on security token to unlock.",
                                    emoji_enabled() ? glyph(GLYPH_TOUCH) : "",
                                    emoji_enabled() ? " " : "");
+                        plymouth_start_interaction("Please confirm presence on security token to unlock.", &plymouth_displayed);
+                }
         }
 
         if (has_uv && !FLAGS_SET(required, FIDO2ENROLL_UV_OMIT)) {
@@ -459,10 +483,12 @@ static int fido2_use_hmac_hash_specific_token(
                                                enable_disable(FLAGS_SET(required, FIDO2ENROLL_UV)),
                                                sym_fido_strerr(r));
 
-                if (FLAGS_SET(required, FIDO2ENROLL_UV))
+                if (FLAGS_SET(required, FIDO2ENROLL_UV)) {
                         log_notice("%s%sPlease verify user on security token to unlock.",
                                    emoji_enabled() ? glyph(GLYPH_TOUCH) : "",
                                    emoji_enabled() ? " " : "");
+                        plymouth_start_interaction("Please verify user on security token to unlock.", &plymouth_displayed);
+                }
         }
 
         for (;;) {
@@ -502,6 +528,7 @@ static int fido2_use_hmac_hash_specific_token(
                                 log_notice("%s%sPlease confirm presence on security to unlock.",
                                            emoji_enabled() ? glyph(GLYPH_TOUCH) : "",
                                            emoji_enabled() ? " " : "");
+                                plymouth_start_interaction("Please confirm presence on security token to unlock.", &plymouth_displayed);
                                 retry_with_up = true;
                         }
 
index 31ab34093118d3faeeddedc267be0038382b7e67..46de29b2671d8d3922f38e222345dee5fd74e2aa 100644 (file)
@@ -31,3 +31,26 @@ int plymouth_send_raw(const void *raw, size_t size, int flags) {
 
         return loop_write(fd, raw, size);
 }
+
+int plymouth_send_msg(const char *text, bool pause_spinner) {
+        _cleanup_free_ char *plymouth_message = NULL;
+        int c, r;
+
+        assert(text);
+        assert(strlen(text) < UCHAR_MAX);
+
+        c = asprintf(&plymouth_message,
+                     "M\x02%c%s%c"
+                     "%c%c", /* pause/resume spinner */
+                     (int) strlen(text) + 1, text, '\x00',
+                     pause_spinner ? 'A' : 'a', '\x00');
+        if (c < 0)
+                return log_oom();
+
+        r = plymouth_send_raw(plymouth_message, c, SOCK_NONBLOCK);
+        if (r < 0)
+                return log_full_errno(ERRNO_IS_NO_PLYMOUTH(r) ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Failed to communicate with plymouth, ignoring: %m");
+
+        return 0;
+}
index 04aec707b70e9fc93effedabb499375eb6d182aa..d7600767b586c6110967b35d7c00aaf2527fadea 100644 (file)
@@ -7,6 +7,7 @@
 
 int plymouth_connect(int flags);
 int plymouth_send_raw(const void *raw, size_t size, int flags);
+int plymouth_send_msg(const char *text, bool pause_spinner);
 
 static inline bool ERRNO_IS_NO_PLYMOUTH(int r) {
         return IN_SET(abs(r), EAGAIN, ENOENT) || ERRNO_IS_DISCONNECT(r);
index 1e3f10ca0a975e58dc6cb34b16ec95fce25e265c..fbdf35df9954b84b365963175a61cefc3d6fb76b 100644 (file)
@@ -726,28 +726,6 @@ static int nvme_subsystem_report(NvmeSubsystem *subsystem, NvmePort *ipv4, NvmeP
         return 0;
 }
 
-static int plymouth_send_text(const char *text) {
-        _cleanup_free_ char *plymouth_message = NULL;
-        int c, r;
-
-        assert(text);
-
-        c = asprintf(&plymouth_message,
-                     "M\x02%c%s%c"
-                     "A%c", /* pause spinner */
-                     (int) strlen(text) + 1, text, '\x00',
-                     '\x00');
-        if (c < 0)
-                return log_oom();
-
-        r = plymouth_send_raw(plymouth_message, c, SOCK_NONBLOCK);
-        if (r < 0)
-                return log_full_errno(ERRNO_IS_NO_PLYMOUTH(r) ? LOG_DEBUG : LOG_WARNING, r,
-                                      "Failed to communicate with plymouth, ignoring: %m");
-
-        return 0;
-}
-
 static int plymouth_notify_port(NvmePort *port, struct local_address *a) {
         _cleanup_free_ char *m = NULL;
 
@@ -757,7 +735,7 @@ static int plymouth_notify_port(NvmePort *port, struct local_address *a) {
         if (asprintf(&m, "nvme connect-all -t tcp -a %s -s %" PRIu16, IN_ADDR_TO_STRING(a->family, &a->address), port->portnr) < 0)
                 return log_oom();
 
-        return plymouth_send_text(m);
+        return plymouth_send_msg(m, /* pause_spinner= */ true);
 }
 
 static int nvme_port_report(NvmePort *port, bool *plymouth_done) {
@@ -1077,7 +1055,7 @@ static int on_display_refresh(sd_event_source *s, uint64_t usec, void *userdata)
         (void) nvme_port_report(c->ipv6_port, &plymouth_done);
 
         if (!plymouth_done)
-                (void) plymouth_send_text("Network disconnected.");
+                (void) plymouth_send_msg("Network disconnected.", /* pause_spinner= */ true);
 
         NvmeSubsystem *i;
         HASHMAP_FOREACH(i, c->subsystems)
@@ -1179,7 +1157,7 @@ static int run(int argc, char* argv[]) {
         }
 
         if (!plymouth_done)
-                (void) plymouth_send_text("Network disconnected.");
+                (void) plymouth_send_msg("Network disconnected.", /* pause_spinner= */ true);
 
         NvmeSubsystem *i;
         HASHMAP_FOREACH(i, context.subsystems) {