cryptenroll: collect all enrollment parameters in an EnrollContext
Introduce an EnrollContext structure that carries everything the enrollment and unlocking helpers need, and route all enroll_*()/load_volume_key_*()/ wipe_slots() calls through it. The command line still populates the existing arg_* globals as before; once parsing is complete they are copied into a self-contained EnrollContext (which owns its strings/arrays) and the rest of the code only ever reads from the context. This is preparation for the upcoming varlinkification of systemd-cryptenroll: a Varlink dispatcher (and later an interactive first-boot wizard) can populate the very same EnrollContext without going through the arg_* parsing layer. To support non-interactive (e.g. Varlink) callers, the context carries an 'interactive' flag: when false, every credential prompt is disabled and the helpers fail with -ENOPKG (the established "querying disabled via headless" code) instead of blocking on a tty. Passwords, FIDO2 PINs and PKCS#11 PINs are all covered, and an optional FIDO2 PIN can be supplied directly via the context. enroll_recovery() additionally grows a quiet mode that returns the recovery key instead of printing it. This also adds one new field to EnrollContext which didn't exist before: the unlock_password is useful for the Varlink hookup later. No change in command line behaviour.
This commit is contained in:
+54
-35
@@ -746,6 +746,8 @@ int fido2_generate_hmac_hash(
|
||||
const char *user_icon,
|
||||
const char *askpw_icon,
|
||||
const char *askpw_credential,
|
||||
AskPasswordFlags askpw_flags,
|
||||
const char *pin,
|
||||
Fido2EnrollFlags lock_with,
|
||||
int cred_alg,
|
||||
const struct iovec *salt,
|
||||
@@ -920,48 +922,57 @@ int fido2_generate_hmac_hash(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Token asks for PIN but doesn't advertise 'clientPin' feature.");
|
||||
|
||||
AskPasswordFlags askpw_flags = ASK_PASSWORD_ACCEPT_CACHED;
|
||||
AskPasswordFlags pin_askpw_flags = askpw_flags | ASK_PASSWORD_ACCEPT_CACHED;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_strv_free_erase_ char **pin = NULL;
|
||||
_cleanup_free_ char *ask_pin_msg = NULL;
|
||||
int pin_retries = -1;
|
||||
_cleanup_strv_free_erase_ char **pins = NULL;
|
||||
|
||||
r = sym_fido_dev_get_retry_count(d, &pin_retries);
|
||||
if (r != FIDO_OK) {
|
||||
log_warning("Failed to obtain number of retries before lock-out for PIN "
|
||||
"authentication, ignoring: %s", sym_fido_strerr(r));
|
||||
pin_retries = -1;
|
||||
}
|
||||
|
||||
if (pin_retries >= 0) {
|
||||
ask_pin_msg = asprintf_safe(_("Please enter security token PIN "
|
||||
"(remaining attempts before lock-out: %d):"),
|
||||
pin_retries);
|
||||
if (!ask_pin_msg)
|
||||
if (pin) {
|
||||
/* A PIN was supplied by the caller: use it directly, don't prompt. */
|
||||
pins = strv_new(pin);
|
||||
if (!pins)
|
||||
return log_oom();
|
||||
} else if (FLAGS_SET(askpw_flags, ASK_PASSWORD_HEADLESS))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option.");
|
||||
else {
|
||||
int pin_retries = -1;
|
||||
r = sym_fido_dev_get_retry_count(d, &pin_retries);
|
||||
if (r != FIDO_OK) {
|
||||
log_warning("Failed to obtain number of retries before lock-out for PIN "
|
||||
"authentication, ignoring: %s", sym_fido_strerr(r));
|
||||
pin_retries = -1;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *ask_pin_msg = NULL;
|
||||
if (pin_retries >= 0) {
|
||||
ask_pin_msg = asprintf_safe(_("Please enter security token PIN "
|
||||
"(remaining attempts before lock-out: %d):"),
|
||||
pin_retries);
|
||||
if (!ask_pin_msg)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = pin_retries >= 0
|
||||
? ask_pin_msg
|
||||
: _("Please enter security token PIN:"),
|
||||
.icon = askpw_icon,
|
||||
.keyring = "fido2-pin",
|
||||
.credential = askpw_credential,
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, pin_askpw_flags, &pins);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire user PIN: %m");
|
||||
|
||||
pin_askpw_flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
}
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = pin_retries >= 0
|
||||
? ask_pin_msg
|
||||
: _("Please enter security token PIN:"),
|
||||
.icon = askpw_icon,
|
||||
.keyring = "fido2-pin",
|
||||
.credential = askpw_credential,
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, askpw_flags, &pin);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire user PIN: %m");
|
||||
|
||||
askpw_flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
|
||||
r = FIDO_ERR_PIN_INVALID;
|
||||
STRV_FOREACH(i, pin) {
|
||||
STRV_FOREACH(i, pins) {
|
||||
if (isempty(*i)) {
|
||||
log_notice("PIN may not be empty.");
|
||||
continue;
|
||||
@@ -981,6 +992,11 @@ int fido2_generate_hmac_hash(
|
||||
if (r != FIDO_ERR_PIN_INVALID)
|
||||
break;
|
||||
|
||||
/* A caller-supplied PIN that's wrong won't get better by retrying: fail instead of
|
||||
* looping forever (we'd never prompt). */
|
||||
if (pin)
|
||||
break;
|
||||
|
||||
log_notice("PIN incorrect, please try again.");
|
||||
}
|
||||
}
|
||||
@@ -996,6 +1012,9 @@ int fido2_generate_hmac_hash(
|
||||
if (r == FIDO_ERR_UNSUPPORTED_ALGORITHM)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Token doesn't support credential algorithm %s.", fido2_algorithm_to_string(cred_alg));
|
||||
if (r == FIDO_ERR_PIN_INVALID)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"PIN incorrect.");
|
||||
if (r != FIDO_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to generate FIDO2 credential: %s", sym_fido_strerr(r));
|
||||
|
||||
@@ -117,6 +117,8 @@ int fido2_generate_hmac_hash(
|
||||
const char *user_icon,
|
||||
const char *askpw_icon,
|
||||
const char *askpw_credential,
|
||||
AskPasswordFlags askpw_flags,
|
||||
const char *pin,
|
||||
Fido2EnrollFlags lock_with,
|
||||
int cred_alg,
|
||||
const struct iovec *salt,
|
||||
|
||||
Reference in New Issue
Block a user