fido2: hook up with plymouth for notifications (#37089)

Show notifications for fido2 messages in plymouth, so that they
show up in the initrd like the passphrase prompt already does.
This commit is contained in:
Luca Boccassi
2025-04-12 01:06:31 +01:00
committed by GitHub
6 changed files with 59 additions and 28 deletions
+2
View File
@@ -140,6 +140,8 @@ Credentials=
tty.serial.hvc0.login.noauth=yes
tty.console.agetty.autologin=root
tty.console.login.noauth=yes
tty.virtual.tty1.agetty.autologin=root
tty.virtual.tty1.login.noauth=yes
RuntimeBuildSources=yes
RuntimeScratch=no
CPUs=2
@@ -9,5 +9,5 @@ Environment=
GIT_URL=https://salsa.debian.org/systemd-team/systemd.git
GIT_SUBDIR=debian
GIT_BRANCH=debian/master
GIT_COMMIT=11efce9445f987f1e588719c182a93794eba2565
GIT_COMMIT=91a4d114e0b5a01385477f8862caedc1056fa68b
PKG_SUBDIR=debian
+29 -2
View 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;
}
+23
View 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;
}
+1
View 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);
+3 -25
View 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) {