From fc35f5280fab7e2e3c70fe977fedbe43a8901f32 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 10 Apr 2025 23:10:37 +0100 Subject: [PATCH] fido2: hook up with plymouth for notifications 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 | 31 +++++++++++++++++++++++++++++-- src/shared/plymouth-util.c | 23 +++++++++++++++++++++++ src/shared/plymouth-util.h | 1 + src/storagetm/storagetm.c | 28 +++------------------------- 4 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/shared/libfido2-util.c b/src/shared/libfido2-util.c index 48140ade21d..4a44fe5ff56 100644 --- a/src/shared/libfido2-util.c +++ b/src/shared/libfido2-util.c @@ -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; } diff --git a/src/shared/plymouth-util.c b/src/shared/plymouth-util.c index 31ab3409311..46de29b2671 100644 --- a/src/shared/plymouth-util.c +++ b/src/shared/plymouth-util.c @@ -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; +} diff --git a/src/shared/plymouth-util.h b/src/shared/plymouth-util.h index 04aec707b70..d7600767b58 100644 --- a/src/shared/plymouth-util.h +++ b/src/shared/plymouth-util.h @@ -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); diff --git a/src/storagetm/storagetm.c b/src/storagetm/storagetm.c index 1e3f10ca0a9..fbdf35df995 100644 --- a/src/storagetm/storagetm.c +++ b/src/storagetm/storagetm.c @@ -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) { -- 2.47.3