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);
} 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;
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)
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;
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))
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;
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...");
}
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 {
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;
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...");
}
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)
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;
}
return log_oom();
for (;;) {
- bool processed = false;
-
if (key_file || key_data) {
/* If key data is specified, use that */
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;
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...");
}