mirror of
https://github.com/systemd/systemd.git
synced 2024-12-19 07:03:34 +08:00
cryptsetup: add a configurable token waiting timeout
Let's add configurable timeout how long to wait for FIDO2/PKCS#11 devices to show up. Once the timeout is hit, let's automatically revert to querying via passphrase. Fixes: #19739
This commit is contained in:
parent
40091021c3
commit
5cbe70af02
@ -83,6 +83,7 @@ static char *arg_tpm2_device = NULL;
|
||||
static bool arg_tpm2_device_auto = false;
|
||||
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
|
||||
static bool arg_headless = false;
|
||||
static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_hash, freep);
|
||||
@ -410,7 +411,15 @@ static int parse_one_option(const char *option) {
|
||||
} else if (streq(option, "headless"))
|
||||
arg_headless = true;
|
||||
|
||||
else if (!streq(option, "x-initrd.attach"))
|
||||
else if ((val = startswith(option, "token-timeout="))) {
|
||||
|
||||
r = parse_sec_fix_0(val, &arg_token_timeout_usec);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (!streq(option, "x-initrd.attach"))
|
||||
log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
|
||||
|
||||
return 0;
|
||||
@ -711,11 +720,25 @@ static char *make_bindname(const char *volume) {
|
||||
return s;
|
||||
}
|
||||
|
||||
static int make_security_device_monitor(sd_event *event, sd_device_monitor **ret) {
|
||||
static int make_security_device_monitor(
|
||||
sd_event **ret_event,
|
||||
sd_device_monitor **ret_monitor) {
|
||||
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
assert(ret_event);
|
||||
assert(ret_monitor);
|
||||
|
||||
/* Waits for a device with "security-device" tag to show up in udev */
|
||||
|
||||
r = sd_event_default(&event);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||
|
||||
r = sd_event_add_time_relative(event, NULL, CLOCK_MONOTONIC, arg_token_timeout_usec, USEC_PER_SEC, NULL, INT_TO_PTR(-ETIMEDOUT));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install timeout event source: %m");
|
||||
|
||||
r = sd_device_monitor_new(&monitor);
|
||||
if (r < 0)
|
||||
@ -733,10 +756,49 @@ static int make_security_device_monitor(sd_event *event, sd_device_monitor **ret
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to start device monitor: %m");
|
||||
|
||||
*ret = TAKE_PTR(monitor);
|
||||
*ret_event = TAKE_PTR(event);
|
||||
*ret_monitor = TAKE_PTR(monitor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_security_device_monitor(
|
||||
sd_event *event,
|
||||
sd_device_monitor *monitor) {
|
||||
bool processed = false;
|
||||
int r;
|
||||
|
||||
assert(event);
|
||||
assert(monitor);
|
||||
|
||||
/* Runs the event loop for the device monitor until either something happens, or the time-out is
|
||||
* hit. */
|
||||
|
||||
for (;;) {
|
||||
int x;
|
||||
|
||||
r = sd_event_get_exit_code(event, &x);
|
||||
if (r < 0) {
|
||||
if (r != -ENODATA)
|
||||
return log_error_errno(r, "Failed to query exit code from event loop: %m");
|
||||
|
||||
/* On ENODATA we aren't told to exit yet. */
|
||||
} else {
|
||||
assert(x == -ETIMEDOUT);
|
||||
return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
|
||||
"Timed out waiting for security device, aborting security device based authentication attempt.");
|
||||
}
|
||||
|
||||
/* Wait for one event, and then eat all subsequent events until there are no further ones */
|
||||
r = sd_event_run(event, processed ? 0 : UINT64_MAX);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to run event loop: %m");
|
||||
if (r == 0) /* no events queued anymore */
|
||||
return 0;
|
||||
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool libcryptsetup_plugins_support(void) {
|
||||
#if HAVE_LIBCRYPTSETUP_PLUGINS
|
||||
int r;
|
||||
@ -906,8 +968,6 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
return log_oom();
|
||||
|
||||
for (;;) {
|
||||
bool processed = false;
|
||||
|
||||
if (use_libcryptsetup_plugin && !arg_fido2_cid) {
|
||||
r = attach_luks2_by_fido2(cd, name, until, arg_headless, arg_fido2_device, flags);
|
||||
if (IN_SET(r, -ENOTUNIQ, -ENXIO, -ENOENT))
|
||||
@ -941,11 +1001,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
|
||||
assert(!event);
|
||||
|
||||
r = sd_event_default(&event);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||
|
||||
r = make_security_device_monitor(event, &monitor);
|
||||
r = make_security_device_monitor(&event, &monitor);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -956,17 +1012,9 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* Wait for one event, and then eat all subsequent events until there are no
|
||||
* further ones */
|
||||
r = sd_event_run(event, processed ? 0 : UINT64_MAX);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to run event loop: %m");
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
processed = true;
|
||||
}
|
||||
r = run_security_device_monitor(event, monitor);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_debug("Got one or more potentially relevant udev events, rescanning FIDO2...");
|
||||
}
|
||||
@ -1069,8 +1117,6 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||
return log_oom();
|
||||
|
||||
for (;;) {
|
||||
bool processed = false;
|
||||
|
||||
if (use_libcryptsetup_plugin && arg_pkcs11_uri_auto)
|
||||
r = attach_luks2_by_pkcs11(cd, name, friendly, until, arg_headless, flags);
|
||||
else {
|
||||
@ -1096,11 +1142,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||
|
||||
assert(!event);
|
||||
|
||||
r = sd_event_default(&event);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||
|
||||
r = make_security_device_monitor(event, &monitor);
|
||||
r = make_security_device_monitor(&event, &monitor);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1112,17 +1154,9 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* Wait for one event, and then eat all subsequent events until there are no
|
||||
* further ones */
|
||||
r = sd_event_run(event, processed ? 0 : UINT64_MAX);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to run event loop: %m");
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
processed = true;
|
||||
}
|
||||
r = run_security_device_monitor(event, monitor);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_debug("Got one or more potentially relevant udev events, rescanning PKCS#11...");
|
||||
}
|
||||
@ -1157,11 +1191,24 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_tpm2_device_monitor(sd_event *event, sd_device_monitor **ret) {
|
||||
static int make_tpm2_device_monitor(
|
||||
sd_event **ret_event,
|
||||
sd_device_monitor **ret_monitor) {
|
||||
|
||||
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
assert(ret_event);
|
||||
assert(ret_monitor);
|
||||
|
||||
r = sd_event_default(&event);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||
|
||||
r = sd_event_add_time_relative(event, NULL, CLOCK_MONOTONIC, arg_token_timeout_usec, USEC_PER_SEC, NULL, INT_TO_PTR(-ETIMEDOUT));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install timeout event source: %m");
|
||||
|
||||
r = sd_device_monitor_new(&monitor);
|
||||
if (r < 0)
|
||||
@ -1179,7 +1226,8 @@ static int make_tpm2_device_monitor(sd_event *event, sd_device_monitor **ret) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to start device monitor: %m");
|
||||
|
||||
*ret = TAKE_PTR(monitor);
|
||||
*ret_event = TAKE_PTR(event);
|
||||
*ret_monitor = TAKE_PTR(monitor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1236,8 +1284,6 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
return log_oom();
|
||||
|
||||
for (;;) {
|
||||
bool processed = false;
|
||||
|
||||
if (key_file || key_data) {
|
||||
/* If key data is specified, use that */
|
||||
|
||||
@ -1341,11 +1387,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
|
||||
"No TPM2 hardware discovered and EFI bios indicates no support for it either, assuming TPM2-less system, falling back to traditional unocking.");
|
||||
|
||||
r = sd_event_default(&event);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||
|
||||
r = make_tpm2_device_monitor(event, &monitor);
|
||||
r = make_tpm2_device_monitor(&event, &monitor);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1356,17 +1398,9 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* Wait for one event, and then eat all subsequent events until there are no
|
||||
* further ones */
|
||||
r = sd_event_run(event, processed ? 0 : UINT64_MAX);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to run event loop: %m");
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
processed = true;
|
||||
}
|
||||
r = run_security_device_monitor(event, monitor);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_debug("Got one or more potentially relevant udev events, rescanning for TPM2...");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user