mirror of
https://github.com/systemd/systemd
synced 2026-03-17 18:44:46 +01:00
Compare commits
13 Commits
a8f76a8db7
...
8e1422036a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e1422036a | ||
|
|
358b1f68b0 | ||
|
|
c719805ecb | ||
|
|
2f67864064 | ||
|
|
e9252faee9 | ||
|
|
0608e2d3a5 | ||
|
|
71eceff645 | ||
|
|
e49614278d | ||
|
|
bfc0cc1a25 | ||
|
|
17e7561a97 | ||
|
|
7dba77a67e | ||
|
|
9cb5bf913d | ||
|
|
e390c34d00 |
@ -628,18 +628,21 @@ user records.
|
||||
`fido2HmacSalt` → An array of objects, implementing authentication support with
|
||||
FIDO2 devices that implement the `hmac-secret` extension. Each element of the
|
||||
array should be an object consisting of three string fields: `credential`,
|
||||
`salt`, `hashedPassword`. The first two shall contain Base64-encoded binary
|
||||
`salt`, `hashedPassword`, and three boolean fields: `up`, `uv` and
|
||||
`clientPin`. The first two string fields shall contain Base64-encoded binary
|
||||
data: the FIDO2 credential ID and the salt value to pass to the FIDO2
|
||||
device. During authentication this salt along with the credential ID is sent to
|
||||
the FIDO2 token, which will HMAC hash the salt with its internal secret key and
|
||||
return the result. This resulting binary key should then be Base64-encoded and
|
||||
used as string password for the further layers of the stack. The
|
||||
`hashedPassword` field of the `fido2HmacSalt` field shall be a UNIX password
|
||||
hash to test this derived secret key against for authentication. It is
|
||||
generally recommended that for each entry in `fido2HmacSalt` there's also a
|
||||
matching one in `fido2HmacCredential`, and vice versa, with the same credential
|
||||
ID, appearing in the same order, but this should not be required by
|
||||
applications processing user records.
|
||||
hash to test this derived secret key against for authentication. The `up`, `uv`
|
||||
and `clientPin` booleans map to the FIDO2 concepts of the same name and encode
|
||||
whether the `uv`/`up` options are enabled during the authentication, and
|
||||
whether a PIN shall be required. It is generally recommended that for each
|
||||
entry in `fido2HmacSalt` there's also a matching one in `fido2HmacCredential`,
|
||||
and vice versa, with the same credential ID, appearing in the same order, but
|
||||
this should not be required by applications processing user records.
|
||||
|
||||
`recoveryKey`→ An array of objects, each defining a recovery key. The object
|
||||
has two mandatory fields: `type` indicates the type of recovery key. The only
|
||||
@ -927,8 +930,15 @@ user. If false or unset, authentication this way shall not be attempted.
|
||||
|
||||
`fido2UserPresencePermitted` → a boolean. If set to true allows the receiver to
|
||||
use the FIDO2 "user presence" flag. This is similar to the concept of
|
||||
`pkcs11ProtectedAuthenticationPathPermitted`, but exposes the FIDO2 concept
|
||||
behind it. If false or unset authentication this way shall not be attempted.
|
||||
`pkcs11ProtectedAuthenticationPathPermitted`, but exposes the FIDO2 "up"
|
||||
concept behind it. If false or unset authentication this way shall not be
|
||||
attempted.
|
||||
|
||||
`fido2UserVerificationPermitted` → a boolean. If set to true allows the
|
||||
receiver to use the FIDO2 "user verification" flag. This is similar to the
|
||||
concept of `pkcs11ProtectedAuthenticationPathPermitted`, but exposes the FIDO2
|
||||
"uv" concept behind it. If false or unset authentication this way shall not be
|
||||
attempted.
|
||||
|
||||
## Mapping to `struct passwd` and `struct spwd`
|
||||
|
||||
|
||||
@ -378,6 +378,35 @@
|
||||
discussion see above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fido2-with-client-pin=</option><replaceable>BOOL</replaceable></term>
|
||||
|
||||
<listitem><para>When enrolling a FIDO2 security token, controls whether to require the user to enter
|
||||
a PIN when unlocking the account (the FIDO2 <literal>clientPin</literal> feature). Defaults to
|
||||
<literal>yes</literal>. (Note: this setting is without effect if the security token does not support
|
||||
the <literal>clientPin</literal> feature at all, or does not allow enabling or disabling
|
||||
it.)</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fido2-with-user-presence=</option><replaceable>BOOL</replaceable></term>
|
||||
|
||||
<listitem><para>When enrolling a FIDO2 security token, controls whether to require the user to
|
||||
verify presence (tap the token, the FIDO2 <literal>up</literal> feature) when unlocking the account.
|
||||
Defaults to <literal>yes</literal>. (Note: this setting is without effect if the security token does not support
|
||||
the <literal>up</literal> feature at all, or does not allow enabling or disabling it.)
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fido2-with-user-verification=</option><replaceable>BOOL</replaceable></term>
|
||||
|
||||
<listitem><para>When enrolling a FIDO2 security token, controls whether to require user verification
|
||||
when unlocking the account (the FIDO2 <literal>uv</literal> feature). Defaults to
|
||||
<literal>no</literal>. (Note: this setting is without effect if the security token does not support
|
||||
the <literal>uv</literal> feature at all, or does not allow enabling or disabling it.)</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--recovery-key=</option><replaceable>BOOL</replaceable></term>
|
||||
|
||||
|
||||
@ -165,6 +165,15 @@
|
||||
usernames. </para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--emoji=yes|no|auto</option></term>
|
||||
|
||||
<listitem><para>Controls whether or not to prefix the query with a
|
||||
lock and key emoji (🔐), if the TTY settings permit this. The default
|
||||
is <literal>auto</literal>, which defaults to <literal>yes</literal>,
|
||||
unless <option>--echo</option> is given.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--no-tty</option></term>
|
||||
|
||||
|
||||
@ -2254,7 +2254,6 @@ if conf.get('ENABLE_HOMED') == 1
|
||||
include_directories : includes,
|
||||
link_with : [libshared],
|
||||
dependencies : [threads,
|
||||
libcryptsetup,
|
||||
libblkid,
|
||||
libcrypt,
|
||||
libopenssl,
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "main-func.h"
|
||||
#include "parse-argument.h"
|
||||
#include "pretty-print.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
@ -45,6 +46,8 @@ static int help(void) {
|
||||
" credentials\n"
|
||||
" --timeout=SEC Timeout in seconds\n"
|
||||
" --echo Do not mask input (useful for usernames)\n"
|
||||
" --emoji=yes|no|auto\n"
|
||||
" Show a lock and key emoji\n"
|
||||
" --no-tty Ask question via agent even on TTY\n"
|
||||
" --accept-cached Accept cached passwords\n"
|
||||
" --multiple List multiple passwords if available\n"
|
||||
@ -64,6 +67,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_ICON = 0x100,
|
||||
ARG_TIMEOUT,
|
||||
ARG_ECHO,
|
||||
ARG_EMOJI,
|
||||
ARG_NO_TTY,
|
||||
ARG_ACCEPT_CACHED,
|
||||
ARG_MULTIPLE,
|
||||
@ -80,6 +84,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "icon", required_argument, NULL, ARG_ICON },
|
||||
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
|
||||
{ "echo", no_argument, NULL, ARG_ECHO },
|
||||
{ "emoji", required_argument, NULL, ARG_EMOJI },
|
||||
{ "no-tty", no_argument, NULL, ARG_NO_TTY },
|
||||
{ "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED },
|
||||
{ "multiple", no_argument, NULL, ARG_MULTIPLE },
|
||||
@ -90,6 +95,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{}
|
||||
};
|
||||
|
||||
const char *emoji = NULL;
|
||||
int c;
|
||||
|
||||
assert(argc >= 0);
|
||||
@ -120,6 +126,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_flags |= ASK_PASSWORD_ECHO;
|
||||
break;
|
||||
|
||||
case ARG_EMOJI:
|
||||
emoji = optarg;
|
||||
break;
|
||||
|
||||
case ARG_NO_TTY:
|
||||
arg_flags |= ASK_PASSWORD_NO_TTY;
|
||||
break;
|
||||
@ -155,6 +165,18 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
if (isempty(emoji) || streq(emoji, "auto"))
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, FLAGS_SET(arg_flags, ASK_PASSWORD_ECHO));
|
||||
else {
|
||||
int r;
|
||||
bool b;
|
||||
|
||||
r = parse_boolean_argument("--emoji=", emoji, &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, !b);
|
||||
}
|
||||
|
||||
if (argc > optind) {
|
||||
arg_message = strv_join(argv + optind, " ");
|
||||
if (!arg_message)
|
||||
|
||||
@ -510,6 +510,8 @@ static int run(int argc, char *argv[]) {
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
cryptsetup_enable_logging(NULL);
|
||||
|
||||
if (arg_enroll_type < 0)
|
||||
r = prepare_luks(&cd, NULL, NULL); /* No need to unlock device if we don't need the volume key because we don't need to enroll anything */
|
||||
else
|
||||
|
||||
@ -1449,7 +1449,7 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
log_setup();
|
||||
|
||||
cryptsetup_enable_logging(cd);
|
||||
cryptsetup_enable_logging(NULL);
|
||||
|
||||
umask(0022);
|
||||
|
||||
|
||||
@ -68,7 +68,8 @@ static int add_fido2_salt(
|
||||
const void *fido2_salt,
|
||||
size_t fido2_salt_size,
|
||||
const void *secret,
|
||||
size_t secret_size) {
|
||||
size_t secret_size,
|
||||
Fido2EnrollFlags lock_with) {
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *l = NULL, *w = NULL, *e = NULL;
|
||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL, *hashed = NULL;
|
||||
@ -87,7 +88,11 @@ static int add_fido2_salt(
|
||||
r = json_build(&e, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("credential", JSON_BUILD_BASE64(cid, cid_size)),
|
||||
JSON_BUILD_PAIR("salt", JSON_BUILD_BASE64(fido2_salt, fido2_salt_size)),
|
||||
JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRING(hashed))));
|
||||
JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRING(hashed)),
|
||||
JSON_BUILD_PAIR("up", JSON_BUILD_BOOLEAN(FLAGS_SET(lock_with, FIDO2ENROLL_UP))),
|
||||
JSON_BUILD_PAIR("uv", JSON_BUILD_BOOLEAN(FLAGS_SET(lock_with, FIDO2ENROLL_UV))),
|
||||
JSON_BUILD_PAIR("clientPin", JSON_BUILD_BOOLEAN(FLAGS_SET(lock_with, FIDO2ENROLL_PIN)))));
|
||||
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build FIDO2 salt JSON key object: %m");
|
||||
|
||||
@ -112,7 +117,8 @@ static int add_fido2_salt(
|
||||
|
||||
int identity_add_fido2_parameters(
|
||||
JsonVariant **v,
|
||||
const char *device) {
|
||||
const char *device,
|
||||
Fido2EnrollFlags lock_with) {
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
JsonVariant *un, *realm, *rn;
|
||||
@ -158,12 +164,12 @@ int identity_add_fido2_parameters(
|
||||
/* user_display_name= */ rn ? json_variant_string(rn) : NULL,
|
||||
/* user_icon_name= */ NULL,
|
||||
/* askpw_icon_name= */ "user-home",
|
||||
FIDO2ENROLL_PIN | FIDO2ENROLL_UP, // FIXME: add a --lock-with-pin/up parameter like cryptenroll
|
||||
lock_with,
|
||||
&cid, &cid_size,
|
||||
&salt, &salt_size,
|
||||
&secret, &secret_size,
|
||||
&used_pin,
|
||||
NULL);
|
||||
&lock_with);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -181,7 +187,8 @@ int identity_add_fido2_parameters(
|
||||
salt,
|
||||
salt_size,
|
||||
secret,
|
||||
secret_size);
|
||||
secret_size,
|
||||
lock_with);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "json.h"
|
||||
#include "libfido2-util.h"
|
||||
|
||||
int identity_add_fido2_parameters(JsonVariant **v, const char *device);
|
||||
int identity_add_fido2_parameters(JsonVariant **v, const char *device, Fido2EnrollFlags lock_with);
|
||||
|
||||
@ -57,6 +57,7 @@ static uint64_t arg_disk_size = UINT64_MAX;
|
||||
static uint64_t arg_disk_size_relative = UINT64_MAX;
|
||||
static char **arg_pkcs11_token_uri = NULL;
|
||||
static char **arg_fido2_device = NULL;
|
||||
static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP;
|
||||
static bool arg_recovery_key = false;
|
||||
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||
static bool arg_and_resize = false;
|
||||
@ -380,7 +381,7 @@ static int handle_generic_user_record_error(
|
||||
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED)) {
|
||||
|
||||
log_notice("%s%sAuthentication requires presence verification on security token.",
|
||||
log_notice("%s%sPlease confirm presence on security token.",
|
||||
emoji_enabled() ? special_glyph(SPECIAL_GLYPH_TOUCH) : "",
|
||||
emoji_enabled() ? " " : "");
|
||||
|
||||
@ -388,6 +389,16 @@ static int handle_generic_user_record_error(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set FIDO2 user presence permitted flag: %m");
|
||||
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_USER_VERIFICATION_NEEDED)) {
|
||||
|
||||
log_notice("%s%sPlease verify user on security token.",
|
||||
emoji_enabled() ? special_glyph(SPECIAL_GLYPH_TOUCH) : "",
|
||||
emoji_enabled() ? " " : "");
|
||||
|
||||
r = user_record_set_fido2_user_verification_permitted(hr, true);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set FIDO2 user verification permitted flag: %m");
|
||||
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_LOCKED))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Security token PIN is locked, please unlock it first. (Hint: Removal and re-insertion might suffice.)");
|
||||
|
||||
@ -560,9 +571,9 @@ static void dump_home_record(UserRecord *hr) {
|
||||
_cleanup_(user_record_unrefp) UserRecord *stripped = NULL;
|
||||
|
||||
if (arg_export_format == EXPORT_FORMAT_STRIPPED)
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_EMBEDDED, &stripped);
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_EMBEDDED|USER_RECORD_PERMISSIVE, &stripped);
|
||||
else if (arg_export_format == EXPORT_FORMAT_MINIMAL)
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_SIGNABLE, &stripped);
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_SIGNABLE|USER_RECORD_PERMISSIVE, &stripped);
|
||||
else
|
||||
r = 0;
|
||||
if (r < 0)
|
||||
@ -667,7 +678,7 @@ static int inspect_home(int argc, char *argv[], void *userdata) {
|
||||
if (!hr)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_LOG);
|
||||
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_LOG|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0) {
|
||||
if (ret == 0)
|
||||
ret = r;
|
||||
@ -1027,7 +1038,7 @@ static int acquire_new_home_record(UserRecord **ret) {
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, arg_fido2_device) {
|
||||
r = identity_add_fido2_parameters(&v, *i);
|
||||
r = identity_add_fido2_parameters(&v, *i, arg_fido2_lock_with);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -1049,7 +1060,7 @@ static int acquire_new_home_record(UserRecord **ret) {
|
||||
if (!hr)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(hr, v, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_LOG);
|
||||
r = user_record_load(hr, v, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_LOG|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1397,7 +1408,7 @@ static int acquire_updated_home_record(
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, arg_fido2_device) {
|
||||
r = identity_add_fido2_parameters(&json, *i);
|
||||
r = identity_add_fido2_parameters(&json, *i, arg_fido2_lock_with);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -1415,7 +1426,7 @@ static int acquire_updated_home_record(
|
||||
if (!hr)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(hr, json, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SECRET|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_LOG);
|
||||
r = user_record_load(hr, json, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SECRET|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_LOG|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1440,6 +1451,10 @@ static int home_record_reset_human_interaction_permission(UserRecord *hr) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to reset FIDO2 user presence permission flag: %m");
|
||||
|
||||
r = user_record_set_fido2_user_verification_permitted(hr, -1);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to reset FIDO2 user verification permission flag: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2071,6 +2086,15 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" private key and matching X.509 certificate\n"
|
||||
" --fido2-device=PATH Path to FIDO2 hidraw device with hmac-secret\n"
|
||||
" extension\n"
|
||||
" --fido2-with-client-pin=BOOL\n"
|
||||
" Whether to require entering a PIN to unlock the\n"
|
||||
" account\n"
|
||||
" --fido2-with-user-presence=BOOL\n"
|
||||
" Whether to require user presence to unlock the\n"
|
||||
" account\n"
|
||||
" --fido2-with-user-verification=BOOL\n"
|
||||
" Whether to require user verification to unlock the\n"
|
||||
" account\n"
|
||||
" --recovery-key=BOOL Add a recovery key\n"
|
||||
"\n%4$sAccount Management User Record Properties:%5$s\n"
|
||||
" --locked=BOOL Set locked account state\n"
|
||||
@ -2220,6 +2244,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_AUTO_LOGIN,
|
||||
ARG_PKCS11_TOKEN_URI,
|
||||
ARG_FIDO2_DEVICE,
|
||||
ARG_FIDO2_WITH_PIN,
|
||||
ARG_FIDO2_WITH_UP,
|
||||
ARG_FIDO2_WITH_UV,
|
||||
ARG_RECOVERY_KEY,
|
||||
ARG_AND_RESIZE,
|
||||
ARG_AND_CHANGE_PASSWORD,
|
||||
@ -2299,6 +2326,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "export-format", required_argument, NULL, ARG_EXPORT_FORMAT },
|
||||
{ "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
|
||||
{ "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
|
||||
{ "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN },
|
||||
{ "fido2-with-user-presence", required_argument, NULL, ARG_FIDO2_WITH_UP },
|
||||
{ "fido2-with-user-verification",required_argument, NULL, ARG_FIDO2_WITH_UV },
|
||||
{ "recovery-key", required_argument, NULL, ARG_RECOVERY_KEY },
|
||||
{ "and-resize", required_argument, NULL, ARG_AND_RESIZE },
|
||||
{ "and-change-password", required_argument, NULL, ARG_AND_CHANGE_PASSWORD },
|
||||
@ -3323,7 +3353,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
r = strv_consume(&arg_fido2_device, TAKE_PTR(found));
|
||||
} else
|
||||
r = strv_extend(&arg_fido2_device, optarg);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -3331,6 +3360,39 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_FIDO2_WITH_PIN: {
|
||||
bool lock_with_pin;
|
||||
|
||||
r = parse_boolean_argument("--fido2-with-client-pin=", optarg, &lock_with_pin);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_PIN, lock_with_pin);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_FIDO2_WITH_UP: {
|
||||
bool lock_with_up;
|
||||
|
||||
r = parse_boolean_argument("--fido2-with-user-presence=", optarg, &lock_with_up);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UP, lock_with_up);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_FIDO2_WITH_UV: {
|
||||
bool lock_with_uv;
|
||||
|
||||
r = parse_boolean_argument("--fido2-with-user-verification=", optarg, &lock_with_uv);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UV, lock_with_uv);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_RECOVERY_KEY: {
|
||||
const char *p;
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ int bus_message_read_secret(sd_bus_message *m, UserRecord **ret, sd_bus_error *e
|
||||
if (!hr)
|
||||
return -ENOMEM;
|
||||
|
||||
r = user_record_load(hr, full, USER_RECORD_REQUIRE_SECRET);
|
||||
r = user_record_load(hr, full, USER_RECORD_REQUIRE_SECRET|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ int bus_home_get_record_json(
|
||||
trusted = false;
|
||||
}
|
||||
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE;
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE;
|
||||
if (trusted)
|
||||
flags |= USER_RECORD_ALLOW_PRIVILEGED;
|
||||
else
|
||||
@ -443,7 +443,7 @@ int bus_home_method_update(
|
||||
assert(message);
|
||||
assert(h);
|
||||
|
||||
r = bus_message_read_home_record(message, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_REQUIRE_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE, &hr, error);
|
||||
r = bus_message_read_home_record(message, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_REQUIRE_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE, &hr, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = user_record_clone(hr, USER_RECORD_LOAD_MASK_SECRET, &home->record);
|
||||
r = user_record_clone(hr, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE, &home->record);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -243,7 +243,7 @@ int home_set_record(Home *h, UserRecord *hr) {
|
||||
if (!new_hr)
|
||||
return -ENOMEM;
|
||||
|
||||
r = user_record_load(new_hr, v, USER_RECORD_LOAD_REFUSE_SECRET);
|
||||
r = user_record_load(new_hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -384,7 +384,7 @@ static int home_parse_worker_stdout(int _fd, UserRecord **ret) {
|
||||
if (!hr)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET);
|
||||
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load home record identity: %m");
|
||||
|
||||
@ -461,7 +461,9 @@ static int convert_worker_errno(Home *h, int e, sd_bus_error *error) {
|
||||
case -ERFKILL:
|
||||
return sd_bus_error_set(error, BUS_ERROR_TOKEN_PROTECTED_AUTHENTICATION_PATH_NEEDED, "Security token requires protected authentication path.");
|
||||
case -EMEDIUMTYPE:
|
||||
return sd_bus_error_set(error, BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED, "Security token requires user presence.");
|
||||
return sd_bus_error_set(error, BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED, "Security token requires presence confirmation.");
|
||||
case -ENOCSI:
|
||||
return sd_bus_error_set(error, BUS_ERROR_TOKEN_USER_VERIFICATION_NEEDED, "Security token requires user verification.");
|
||||
case -ENOSTR:
|
||||
return sd_bus_error_set(error, BUS_ERROR_TOKEN_ACTION_TIMEOUT, "Token action timeout. (User was supposed to verify presence or similar, by interacting with the token, and didn't do that in time.)");
|
||||
case -EOWNERDEAD:
|
||||
@ -1408,7 +1410,7 @@ static int home_update_internal(
|
||||
return sd_bus_error_set(error, BUS_ERROR_HOME_RECORD_DOWNGRADE, "Refusing to update to older home record.");
|
||||
|
||||
if (!secret && FLAGS_SET(hr->mask, USER_RECORD_SECRET)) {
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_SECRET, &saved_secret);
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_SECRET|USER_RECORD_PERMISSIVE, &saved_secret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1443,7 +1445,7 @@ static int home_update_internal(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = user_record_extend_with_binding(hr, h->record, USER_RECORD_LOAD_MASK_SECRET, &new_hr);
|
||||
r = user_record_extend_with_binding(hr, h->record, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE, &new_hr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1537,7 +1539,7 @@ int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *e
|
||||
if (h->signed_locally <= 0) /* Don't allow changing of records not signed only by us */
|
||||
return sd_bus_error_setf(error, BUS_ERROR_HOME_RECORD_SIGNED, "Home %s is signed and cannot be modified locally.", h->user_name);
|
||||
|
||||
r = user_record_clone(h->record, USER_RECORD_LOAD_REFUSE_SECRET, &c);
|
||||
r = user_record_clone(h->record, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1626,7 +1628,7 @@ int home_passwd(Home *h,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = user_record_clone(h->record, USER_RECORD_LOAD_REFUSE_SECRET, &c);
|
||||
r = user_record_clone(h->record, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -398,7 +398,7 @@ static int method_register_home(
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_message_read_home_record(message, USER_RECORD_LOAD_EMBEDDED, &hr, error);
|
||||
r = bus_message_read_home_record(message, USER_RECORD_LOAD_EMBEDDED|USER_RECORD_PERMISSIVE, &hr, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -513,7 +513,7 @@ static int method_update_home(sd_bus_message *message, void *userdata, sd_bus_er
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_message_read_home_record(message, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE, &hr, error);
|
||||
r = bus_message_read_home_record(message, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE, &hr, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -364,7 +364,7 @@ static int manager_add_home_by_record(
|
||||
if (!hr)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_LOG);
|
||||
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_LOG|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ static int build_user_json(Home *h, bool trusted, JsonVariant **ret) {
|
||||
assert(h);
|
||||
assert(ret);
|
||||
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE;
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE;
|
||||
if (trusted)
|
||||
flags |= USER_RECORD_ALLOW_PRIVILEGED;
|
||||
else
|
||||
|
||||
@ -185,7 +185,7 @@ int home_create_cifs(UserRecord *h, UserRecord **ret_home) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET, &new_home);
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE, &new_home);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to clone record: %m");
|
||||
|
||||
|
||||
@ -158,7 +158,7 @@ int home_create_directory_or_subvolume(UserRecord *h, UserRecord **ret_home) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET, &new_home);
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE, &new_home);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to clone record: %m");
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "homework-fido2.h"
|
||||
#include "libfido2-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int fido2_use_token(
|
||||
UserRecord *h,
|
||||
@ -15,6 +16,7 @@ int fido2_use_token(
|
||||
|
||||
_cleanup_(erase_and_freep) void *hmac = NULL;
|
||||
size_t hmac_size;
|
||||
Fido2EnrollFlags flags = 0;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
@ -22,13 +24,42 @@ int fido2_use_token(
|
||||
assert(salt);
|
||||
assert(ret);
|
||||
|
||||
/* If we know the up/uv/clientPin settings used during enrollment, let's pass this on for
|
||||
* authentication, or generate errors immediately if interactivity of the specified kind is not
|
||||
* allowed. */
|
||||
|
||||
if (salt->up > 0) {
|
||||
if (h->fido2_user_presence_permitted <= 0)
|
||||
return -EMEDIUMTYPE;
|
||||
|
||||
flags |= FIDO2ENROLL_UP;
|
||||
} else if (salt->up < 0) /* unset? */
|
||||
flags |= FIDO2ENROLL_UP_IF_NEEDED; /* compat with pre-248 */
|
||||
|
||||
if (salt->uv > 0) {
|
||||
if (h->fido2_user_verification_permitted <= 0)
|
||||
return -ENOCSI;
|
||||
|
||||
flags |= FIDO2ENROLL_UV;
|
||||
} else if (salt->uv < 0)
|
||||
flags |= FIDO2ENROLL_UV_OMIT; /* compat with pre-248 */
|
||||
|
||||
if (salt->client_pin > 0) {
|
||||
|
||||
if (strv_isempty(secret->token_pin))
|
||||
return -ENOANO;
|
||||
|
||||
flags |= FIDO2ENROLL_PIN;
|
||||
} else if (salt->client_pin < 0)
|
||||
flags |= FIDO2ENROLL_PIN_IF_NEEDED; /* compat with pre-248 */
|
||||
|
||||
r = fido2_use_hmac_hash(
|
||||
NULL,
|
||||
"io.systemd.home",
|
||||
salt->salt, salt->salt_size,
|
||||
salt->credential.id, salt->credential.size,
|
||||
secret->token_pin,
|
||||
FIDO2ENROLL_PIN | (h->fido2_user_presence_permitted > 0 ? FIDO2ENROLL_UP : 0), // FIXME: add a --lock-with-pin parameter like cryptenroll
|
||||
flags,
|
||||
&hmac,
|
||||
&hmac_size);
|
||||
if (r < 0)
|
||||
|
||||
@ -550,7 +550,7 @@ int home_create_fscrypt(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET, &new_home);
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE, &new_home);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to clone record: %m");
|
||||
|
||||
|
||||
@ -243,7 +243,7 @@ static int luks_try_passwords(
|
||||
STRV_FOREACH(pp, passwords) {
|
||||
size_t vks = *volume_key_size;
|
||||
|
||||
r = crypt_volume_key_get(
|
||||
r = sym_crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
volume_key,
|
||||
@ -276,7 +276,7 @@ static int luks_setup(
|
||||
void **ret_volume_key,
|
||||
size_t *ret_volume_key_size) {
|
||||
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(erase_and_freep) void *vk = NULL;
|
||||
sd_id128_t p;
|
||||
size_t vks;
|
||||
@ -287,17 +287,17 @@ static int luks_setup(
|
||||
assert(dm_name);
|
||||
assert(ret);
|
||||
|
||||
r = crypt_init(&cd, node);
|
||||
r = sym_crypt_init(&cd, node);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate libcryptsetup context: %m");
|
||||
|
||||
cryptsetup_enable_logging(cd);
|
||||
|
||||
r = crypt_load(cd, CRYPT_LUKS2, NULL);
|
||||
r = sym_crypt_load(cd, CRYPT_LUKS2, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load LUKS superblock: %m");
|
||||
|
||||
r = crypt_get_volume_key_size(cd);
|
||||
r = sym_crypt_get_volume_key_size(cd);
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
|
||||
vks = (size_t) r;
|
||||
@ -305,7 +305,7 @@ static int luks_setup(
|
||||
if (!sd_id128_is_null(uuid) || ret_found_uuid) {
|
||||
const char *s;
|
||||
|
||||
s = crypt_get_uuid(cd);
|
||||
s = sym_crypt_get_uuid(cd);
|
||||
if (!s)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "LUKS superblock has no UUID.");
|
||||
|
||||
@ -319,10 +319,10 @@ static int luks_setup(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "LUKS superblock has wrong UUID.");
|
||||
}
|
||||
|
||||
if (cipher && !streq_ptr(cipher, crypt_get_cipher(cd)))
|
||||
if (cipher && !streq_ptr(cipher, sym_crypt_get_cipher(cd)))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "LUKS superblock declares wrong cipher.");
|
||||
|
||||
if (cipher_mode && !streq_ptr(cipher_mode, crypt_get_cipher_mode(cd)))
|
||||
if (cipher_mode && !streq_ptr(cipher_mode, sym_crypt_get_cipher_mode(cd)))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "LUKS superblock declares wrong cipher mode.");
|
||||
|
||||
if (volume_key_size != UINT64_MAX && vks != volume_key_size)
|
||||
@ -343,7 +343,7 @@ static int luks_setup(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to unlocks LUKS superblock: %m");
|
||||
|
||||
r = crypt_activate_by_volume_key(
|
||||
r = sym_crypt_activate_by_volume_key(
|
||||
cd,
|
||||
dm_name,
|
||||
vk, vks,
|
||||
@ -374,7 +374,7 @@ static int luks_open(
|
||||
void **ret_volume_key,
|
||||
size_t *ret_volume_key_size) {
|
||||
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(erase_and_freep) void *vk = NULL;
|
||||
sd_id128_t p;
|
||||
char **list;
|
||||
@ -387,17 +387,17 @@ static int luks_open(
|
||||
/* Opens a LUKS device that is already set up. Re-validates the password while doing so (which also
|
||||
* provides us with the volume key, which we want). */
|
||||
|
||||
r = crypt_init_by_name(&cd, dm_name);
|
||||
r = sym_crypt_init_by_name(&cd, dm_name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", dm_name);
|
||||
|
||||
cryptsetup_enable_logging(cd);
|
||||
|
||||
r = crypt_load(cd, CRYPT_LUKS2, NULL);
|
||||
r = sym_crypt_load(cd, CRYPT_LUKS2, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load LUKS superblock: %m");
|
||||
|
||||
r = crypt_get_volume_key_size(cd);
|
||||
r = sym_crypt_get_volume_key_size(cd);
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
|
||||
vks = (size_t) r;
|
||||
@ -405,7 +405,7 @@ static int luks_open(
|
||||
if (ret_found_uuid) {
|
||||
const char *s;
|
||||
|
||||
s = crypt_get_uuid(cd);
|
||||
s = sym_crypt_get_uuid(cd);
|
||||
if (!s)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "LUKS superblock has no UUID.");
|
||||
|
||||
@ -433,7 +433,7 @@ static int luks_open(
|
||||
|
||||
/* This is needed so that crypt_resize() can operate correctly for pre-existing LUKS devices. We need
|
||||
* to tell libcryptsetup the volume key explicitly, so that it is in the kernel keyring. */
|
||||
r = crypt_activate_by_volume_key(cd, NULL, vk, vks, CRYPT_ACTIVATE_KEYRING_KEY);
|
||||
r = sym_crypt_activate_by_volume_key(cd, NULL, vk, vks, CRYPT_ACTIVATE_KEYRING_KEY);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to upload volume key again: %m");
|
||||
|
||||
@ -640,11 +640,11 @@ static int crypt_device_to_evp_cipher(struct crypt_device *cd, const EVP_CIPHER
|
||||
/* Let's find the right OpenSSL EVP_CIPHER object that matches the encryption settings of the LUKS
|
||||
* device */
|
||||
|
||||
cipher = crypt_get_cipher(cd);
|
||||
cipher = sym_crypt_get_cipher(cd);
|
||||
if (!cipher)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot get cipher from LUKS device.");
|
||||
|
||||
cipher_mode = crypt_get_cipher_mode(cd);
|
||||
cipher_mode = sym_crypt_get_cipher_mode(cd);
|
||||
if (!cipher_mode)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot get cipher mode from LUKS device.");
|
||||
|
||||
@ -652,7 +652,7 @@ static int crypt_device_to_evp_cipher(struct crypt_device *cd, const EVP_CIPHER
|
||||
if (e)
|
||||
cipher_mode = strndupa(cipher_mode, e - cipher_mode);
|
||||
|
||||
r = crypt_get_volume_key_size(cd);
|
||||
r = sym_crypt_get_volume_key_size(cd);
|
||||
if (r <= 0)
|
||||
return log_error_errno(r < 0 ? r : SYNTHETIC_ERRNO(EINVAL), "Cannot get volume key size from LUKS device.");
|
||||
|
||||
@ -703,7 +703,7 @@ static int luks_validate_home_record(
|
||||
unsigned line, column;
|
||||
const EVP_CIPHER *cc;
|
||||
|
||||
state = crypt_token_status(cd, token, &type);
|
||||
state = sym_crypt_token_status(cd, token, &type);
|
||||
if (state == CRYPT_TOKEN_INACTIVE) /* First unconfigured token, give up */
|
||||
break;
|
||||
if (IN_SET(state, CRYPT_TOKEN_INTERNAL, CRYPT_TOKEN_INTERNAL_UNKNOWN, CRYPT_TOKEN_EXTERNAL))
|
||||
@ -714,7 +714,7 @@ static int luks_validate_home_record(
|
||||
if (!streq(type, "systemd-homed"))
|
||||
continue;
|
||||
|
||||
r = crypt_token_json_get(cd, token, &text);
|
||||
r = sym_crypt_token_json_get(cd, token, &text);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read LUKS token %i: %m", token);
|
||||
|
||||
@ -779,7 +779,7 @@ static int luks_validate_home_record(
|
||||
if (!lhr)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(lhr, rr, USER_RECORD_LOAD_EMBEDDED);
|
||||
r = user_record_load(lhr, rr, USER_RECORD_LOAD_EMBEDDED|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse user record: %m");
|
||||
|
||||
@ -902,7 +902,7 @@ int home_store_header_identity_luks(
|
||||
* the file system, so that we can validate it first, and only then mount the file system. To keep
|
||||
* things simple we use the same encryption settings for this record as for the file system itself. */
|
||||
|
||||
r = user_record_clone(h, USER_RECORD_EXTRACT_EMBEDDED, &header_home);
|
||||
r = user_record_clone(h, USER_RECORD_EXTRACT_EMBEDDED|USER_RECORD_PERMISSIVE, &header_home);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine new header record: %m");
|
||||
|
||||
@ -919,7 +919,7 @@ int home_store_header_identity_luks(
|
||||
crypt_token_info state;
|
||||
const char *type;
|
||||
|
||||
state = crypt_token_status(setup->crypt_device, token, &type);
|
||||
state = sym_crypt_token_status(setup->crypt_device, token, &type);
|
||||
if (state == CRYPT_TOKEN_INACTIVE) /* First unconfigured token, we are done */
|
||||
break;
|
||||
if (IN_SET(state, CRYPT_TOKEN_INTERNAL, CRYPT_TOKEN_INTERNAL_UNKNOWN, CRYPT_TOKEN_EXTERNAL))
|
||||
@ -930,7 +930,7 @@ int home_store_header_identity_luks(
|
||||
if (!streq(type, "systemd-homed"))
|
||||
continue;
|
||||
|
||||
r = crypt_token_json_set(setup->crypt_device, token, text);
|
||||
r = sym_crypt_token_json_set(setup->crypt_device, token, text);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set JSON token for slot %i: %m", token);
|
||||
|
||||
@ -1048,7 +1048,7 @@ int home_prepare_luks(
|
||||
sd_id128_t found_partition_uuid, found_luks_uuid, found_fs_uuid;
|
||||
_cleanup_(user_record_unrefp) UserRecord *luks_home = NULL;
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(erase_and_freep) void *volume_key = NULL;
|
||||
_cleanup_close_ int root_fd = -1, image_fd = -1;
|
||||
bool dm_activated = false, mounted = false;
|
||||
@ -1064,6 +1064,10 @@ int home_prepare_luks(
|
||||
|
||||
assert(user_record_storage(h) == USER_LUKS);
|
||||
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (already_activated) {
|
||||
struct loop_info64 info;
|
||||
const char *n;
|
||||
@ -1082,7 +1086,7 @@ int home_prepare_luks(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
n = crypt_get_device_name(cd);
|
||||
n = sym_crypt_get_device_name(cd);
|
||||
if (!n)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine backing device for DM %s.", setup->dm_name);
|
||||
|
||||
@ -1265,7 +1269,7 @@ fail:
|
||||
(void) umount_verbose(LOG_ERR, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW);
|
||||
|
||||
if (dm_activated)
|
||||
(void) crypt_deactivate(cd, setup->dm_name);
|
||||
(void) sym_crypt_deactivate_by_name(cd, setup->dm_name, 0);
|
||||
|
||||
if (image_fd >= 0 && marked_dirty)
|
||||
(void) run_mark_dirty(image_fd, false);
|
||||
@ -1301,6 +1305,10 @@ int home_activate_luks(
|
||||
assert(user_record_storage(h) == USER_LUKS);
|
||||
assert(ret_home);
|
||||
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_se(hdo = user_record_home_directory(h));
|
||||
hd = strdupa(hdo); /* copy the string out, since it might change later in the home record object */
|
||||
|
||||
@ -1358,7 +1366,7 @@ int home_activate_luks(
|
||||
|
||||
loop_device_relinquish(setup.loop);
|
||||
|
||||
r = crypt_deactivate_by_name(NULL, setup.dm_name, CRYPT_DEACTIVATE_DEFERRED);
|
||||
r = sym_crypt_deactivate_by_name(NULL, setup.dm_name, CRYPT_DEACTIVATE_DEFERRED);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to relinquish DM device, ignoring: %m");
|
||||
|
||||
@ -1375,7 +1383,7 @@ int home_activate_luks(
|
||||
}
|
||||
|
||||
int home_deactivate_luks(UserRecord *h) {
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_free_ char *dm_name = NULL, *dm_node = NULL;
|
||||
bool we_detached;
|
||||
int r;
|
||||
@ -1386,11 +1394,15 @@ int home_deactivate_luks(UserRecord *h) {
|
||||
* don't bother about the loopback device because unlike the DM device it doesn't have a fixed
|
||||
* name. */
|
||||
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = make_dm_names(h->user_name, &dm_name, &dm_node);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = crypt_init_by_name(&cd, dm_name);
|
||||
r = sym_crypt_init_by_name(&cd, dm_name);
|
||||
if (IN_SET(r, -ENODEV, -EINVAL, -ENOENT)) {
|
||||
log_debug_errno(r, "LUKS device %s has already been detached.", dm_name);
|
||||
we_detached = false;
|
||||
@ -1401,7 +1413,7 @@ int home_deactivate_luks(UserRecord *h) {
|
||||
|
||||
cryptsetup_enable_logging(cd);
|
||||
|
||||
r = crypt_deactivate(cd, dm_name);
|
||||
r = sym_crypt_deactivate_by_name(cd, dm_name, 0);
|
||||
if (IN_SET(r, -ENODEV, -EINVAL, -ENOENT)) {
|
||||
log_debug_errno(r, "LUKS device %s is already detached.", dm_node);
|
||||
we_detached = false;
|
||||
@ -1477,7 +1489,7 @@ static int luks_format(
|
||||
struct crypt_device **ret) {
|
||||
|
||||
_cleanup_(user_record_unrefp) UserRecord *reduced = NULL;
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(erase_and_freep) void *volume_key = NULL;
|
||||
struct crypt_pbkdf_type good_pbkdf, minimal_pbkdf;
|
||||
char suuid[ID128_UUID_STRING_MAX], **pp;
|
||||
@ -1490,7 +1502,7 @@ static int luks_format(
|
||||
assert(hr);
|
||||
assert(ret);
|
||||
|
||||
r = crypt_init(&cd, node);
|
||||
r = sym_crypt_init(&cd, node);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate libcryptsetup context: %m");
|
||||
|
||||
@ -1511,7 +1523,7 @@ static int luks_format(
|
||||
|
||||
#if HAVE_CRYPT_SET_METADATA_SIZE
|
||||
/* Increase the metadata space to 4M, the largest LUKS2 supports */
|
||||
r = crypt_set_metadata_size(cd, 4096U*1024U, 0);
|
||||
r = sym_crypt_set_metadata_size(cd, 4096U*1024U, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change LUKS2 metadata size: %m");
|
||||
#endif
|
||||
@ -1519,7 +1531,7 @@ static int luks_format(
|
||||
build_good_pbkdf(&good_pbkdf, hr);
|
||||
build_minimal_pbkdf(&minimal_pbkdf, hr);
|
||||
|
||||
r = crypt_format(cd,
|
||||
r = sym_crypt_format(cd,
|
||||
CRYPT_LUKS2,
|
||||
user_record_luks_cipher(hr),
|
||||
user_record_luks_cipher_mode(hr),
|
||||
@ -1542,15 +1554,15 @@ static int luks_format(
|
||||
if (strv_contains(cache->pkcs11_passwords, *pp) ||
|
||||
strv_contains(cache->fido2_passwords, *pp)) {
|
||||
log_debug("Using minimal PBKDF for slot %i", slot);
|
||||
r = crypt_set_pbkdf_type(cd, &minimal_pbkdf);
|
||||
r = sym_crypt_set_pbkdf_type(cd, &minimal_pbkdf);
|
||||
} else {
|
||||
log_debug("Using good PBKDF for slot %i", slot);
|
||||
r = crypt_set_pbkdf_type(cd, &good_pbkdf);
|
||||
r = sym_crypt_set_pbkdf_type(cd, &good_pbkdf);
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to tweak PBKDF for slot %i: %m", slot);
|
||||
|
||||
r = crypt_keyslot_add_by_volume_key(
|
||||
r = sym_crypt_keyslot_add_by_volume_key(
|
||||
cd,
|
||||
slot,
|
||||
volume_key,
|
||||
@ -1564,7 +1576,7 @@ static int luks_format(
|
||||
slot++;
|
||||
}
|
||||
|
||||
r = crypt_activate_by_volume_key(
|
||||
r = sym_crypt_activate_by_volume_key(
|
||||
cd,
|
||||
dm_name,
|
||||
volume_key,
|
||||
@ -1575,7 +1587,7 @@ static int luks_format(
|
||||
|
||||
log_info("LUKS activation by volume key succeeded.");
|
||||
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_EMBEDDED, &reduced);
|
||||
r = user_record_clone(hr, USER_RECORD_EXTRACT_EMBEDDED|USER_RECORD_PERMISSIVE, &reduced);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to prepare home record for LUKS: %m");
|
||||
|
||||
@ -1583,7 +1595,7 @@ static int luks_format(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = crypt_token_json_set(cd, CRYPT_ANY_TOKEN, text);
|
||||
r = sym_crypt_token_json_set(cd, CRYPT_ANY_TOKEN, text);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set LUKS JSON token: %m");
|
||||
|
||||
@ -1876,7 +1888,7 @@ int home_create_luks(
|
||||
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
|
||||
sd_id128_t partition_uuid, fs_uuid, luks_uuid, disk_uuid;
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_close_ int image_fd = -1, root_fd = -1;
|
||||
const char *fstype, *ip;
|
||||
struct statfs sfs;
|
||||
@ -1886,6 +1898,10 @@ int home_create_luks(
|
||||
assert(h->storage < 0 || h->storage == USER_LUKS);
|
||||
assert(ret_home);
|
||||
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_se(ip = user_record_image_path(h));
|
||||
|
||||
fstype = user_record_file_system_type(h);
|
||||
@ -2139,7 +2155,7 @@ int home_create_luks(
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_LOG, &new_home);
|
||||
r = user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_LOG|USER_RECORD_PERMISSIVE, &new_home);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to clone record: %m");
|
||||
goto fail;
|
||||
@ -2152,8 +2168,8 @@ int home_create_luks(
|
||||
partition_uuid,
|
||||
luks_uuid,
|
||||
fs_uuid,
|
||||
crypt_get_cipher(cd),
|
||||
crypt_get_cipher_mode(cd),
|
||||
sym_crypt_get_cipher(cd),
|
||||
sym_crypt_get_cipher_mode(cd),
|
||||
luks_volume_key_size_convert(cd),
|
||||
fstype,
|
||||
NULL,
|
||||
@ -2178,13 +2194,13 @@ int home_create_luks(
|
||||
|
||||
mounted = false;
|
||||
|
||||
r = crypt_deactivate(cd, dm_name);
|
||||
r = sym_crypt_deactivate_by_name(cd, dm_name, 0);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to deactivate LUKS device: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
crypt_free(cd);
|
||||
sym_crypt_free(cd);
|
||||
cd = NULL;
|
||||
|
||||
dm_activated = false;
|
||||
@ -2245,7 +2261,7 @@ fail:
|
||||
(void) umount_verbose(LOG_WARNING, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW);
|
||||
|
||||
if (dm_activated)
|
||||
(void) crypt_deactivate(cd, dm_name);
|
||||
(void) sym_crypt_deactivate_by_name(cd, dm_name, 0);
|
||||
|
||||
loop = loop_device_unref(loop);
|
||||
|
||||
@ -2633,6 +2649,10 @@ int home_resize_luks(
|
||||
assert(setup);
|
||||
assert(ret_home);
|
||||
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_se(ipo = user_record_image_path(h));
|
||||
ip = strdupa(ipo); /* copy out since original might change later in home record object */
|
||||
|
||||
@ -2733,7 +2753,7 @@ int home_resize_luks(
|
||||
setup->partition_offset + new_partition_size > new_image_size)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "New partition doesn't fit into backing storage, refusing.");
|
||||
|
||||
crypto_offset = crypt_get_data_offset(setup->crypt_device);
|
||||
crypto_offset = sym_crypt_get_data_offset(setup->crypt_device);
|
||||
if (setup->partition_size / 512U <= crypto_offset)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Weird, old crypto payload offset doesn't actually fit in partition size?");
|
||||
if (new_partition_size / 512U <= crypto_offset)
|
||||
@ -2797,7 +2817,7 @@ int home_resize_luks(
|
||||
log_debug_errno(errno, "BLKRRPART failed on block device, ignoring: %m");
|
||||
|
||||
/* Tell LUKS about the new bigger size too */
|
||||
r = crypt_resize(setup->crypt_device, setup->dm_name, new_fs_size / 512U);
|
||||
r = sym_crypt_resize(setup->crypt_device, setup->dm_name, new_fs_size / 512U);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to grow LUKS device: %m");
|
||||
|
||||
@ -2838,7 +2858,7 @@ int home_resize_luks(
|
||||
if (new_fs_size < old_fs_size) {
|
||||
|
||||
/* Shrink the LUKS device now, matching the new file system size */
|
||||
r = crypt_resize(setup->crypt_device, setup->dm_name, new_fs_size / 512);
|
||||
r = sym_crypt_resize(setup->crypt_device, setup->dm_name, new_fs_size / 512);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to shrink LUKS device: %m");
|
||||
|
||||
@ -2919,16 +2939,20 @@ int home_passwd_luks(
|
||||
assert(user_record_storage(h) == USER_LUKS);
|
||||
assert(setup);
|
||||
|
||||
type = crypt_get_type(setup->crypt_device);
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
type = sym_crypt_get_type(setup->crypt_device);
|
||||
if (!type)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine crypto device type.");
|
||||
|
||||
r = crypt_keyslot_max(type);
|
||||
r = sym_crypt_keyslot_max(type);
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine number of key slots.");
|
||||
max_key_slots = r;
|
||||
|
||||
r = crypt_get_volume_key_size(setup->crypt_device);
|
||||
r = sym_crypt_get_volume_key_size(setup->crypt_device);
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine volume key size.");
|
||||
volume_key_size = (size_t) r;
|
||||
@ -2954,7 +2978,7 @@ int home_passwd_luks(
|
||||
build_minimal_pbkdf(&minimal_pbkdf, h);
|
||||
|
||||
for (size_t i = 0; i < max_key_slots; i++) {
|
||||
r = crypt_keyslot_destroy(setup->crypt_device, i);
|
||||
r = sym_crypt_keyslot_destroy(setup->crypt_device, i);
|
||||
if (r < 0 && !IN_SET(r, -ENOENT, -EINVAL)) /* Returns EINVAL or ENOENT if there's no key in this slot already */
|
||||
return log_error_errno(r, "Failed to destroy LUKS password: %m");
|
||||
|
||||
@ -2967,15 +2991,15 @@ int home_passwd_luks(
|
||||
if (strv_contains(cache->pkcs11_passwords, effective_passwords[i]) ||
|
||||
strv_contains(cache->fido2_passwords, effective_passwords[i])) {
|
||||
log_debug("Using minimal PBKDF for slot %zu", i);
|
||||
r = crypt_set_pbkdf_type(setup->crypt_device, &minimal_pbkdf);
|
||||
r = sym_crypt_set_pbkdf_type(setup->crypt_device, &minimal_pbkdf);
|
||||
} else {
|
||||
log_debug("Using good PBKDF for slot %zu", i);
|
||||
r = crypt_set_pbkdf_type(setup->crypt_device, &good_pbkdf);
|
||||
r = sym_crypt_set_pbkdf_type(setup->crypt_device, &good_pbkdf);
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to tweak PBKDF for slot %zu: %m", i);
|
||||
|
||||
r = crypt_keyslot_add_by_volume_key(
|
||||
r = sym_crypt_keyslot_add_by_volume_key(
|
||||
setup->crypt_device,
|
||||
i,
|
||||
volume_key,
|
||||
@ -2992,7 +3016,7 @@ int home_passwd_luks(
|
||||
}
|
||||
|
||||
int home_lock_luks(UserRecord *h) {
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_free_ char *dm_name = NULL, *dm_node = NULL;
|
||||
_cleanup_close_ int root_fd = -1;
|
||||
const char *p;
|
||||
@ -3009,7 +3033,11 @@ int home_lock_luks(UserRecord *h) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = crypt_init_by_name(&cd, dm_name);
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sym_crypt_init_by_name(&cd, dm_name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", dm_name);
|
||||
|
||||
@ -3025,7 +3053,7 @@ int home_lock_luks(UserRecord *h) {
|
||||
|
||||
/* Note that we don't invoke FIFREEZE here, it appears libcryptsetup/device-mapper already does that on its own for us */
|
||||
|
||||
r = crypt_suspend(cd, dm_name);
|
||||
r = sym_crypt_suspend(cd, dm_name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to suspend cryptsetup device: %s: %m", dm_node);
|
||||
|
||||
@ -3045,7 +3073,7 @@ static int luks_try_resume(
|
||||
assert(dm_name);
|
||||
|
||||
STRV_FOREACH(pp, password) {
|
||||
r = crypt_resume_by_passphrase(
|
||||
r = sym_crypt_resume_by_passphrase(
|
||||
cd,
|
||||
dm_name,
|
||||
CRYPT_ANY_SLOT,
|
||||
@ -3064,7 +3092,7 @@ static int luks_try_resume(
|
||||
|
||||
int home_unlock_luks(UserRecord *h, PasswordCache *cache) {
|
||||
_cleanup_free_ char *dm_name = NULL, *dm_node = NULL;
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
char **list;
|
||||
int r;
|
||||
|
||||
@ -3074,7 +3102,11 @@ int home_unlock_luks(UserRecord *h, PasswordCache *cache) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = crypt_init_by_name(&cd, dm_name);
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sym_crypt_init_by_name(&cd, dm_name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", dm_name);
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ static inline uint64_t luks_volume_key_size_convert(struct crypt_device *cd) {
|
||||
|
||||
/* Convert the "int" to uint64_t, which we usually use for byte sizes stored on disk. */
|
||||
|
||||
k = crypt_get_volume_key_size(cd);
|
||||
k = sym_crypt_get_volume_key_size(cd);
|
||||
if (k <= 0)
|
||||
return UINT64_MAX;
|
||||
|
||||
|
||||
@ -48,8 +48,10 @@ int user_record_authenticate(
|
||||
PasswordCache *cache,
|
||||
bool strict_verify) {
|
||||
|
||||
bool need_password = false, need_recovery_key = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false, need_user_presence_permitted = false,
|
||||
pin_locked = false, pin_incorrect = false, pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false, token_action_timeout = false;
|
||||
bool need_password = false, need_recovery_key = false, need_token = false, need_pin = false,
|
||||
need_protected_authentication_path_permitted = false, need_user_presence_permitted = false,
|
||||
need_user_verification_permitted = false, pin_locked = false, pin_incorrect = false,
|
||||
pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false, token_action_timeout = false;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
@ -125,7 +127,7 @@ int user_record_authenticate(
|
||||
return log_error_errno(r, "Failed to check supplied FIDO2 password: %m");
|
||||
if (r > 0) {
|
||||
log_info("Previously acquired FIDO2 password unlocks user record.");
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,7 +180,7 @@ int user_record_authenticate(
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
need_token = true;
|
||||
@ -208,6 +210,9 @@ int user_record_authenticate(
|
||||
case -EMEDIUMTYPE:
|
||||
need_user_presence_permitted = true;
|
||||
break;
|
||||
case -ENOCSI:
|
||||
need_user_verification_permitted = true;
|
||||
break;
|
||||
case -ENOSTR:
|
||||
token_action_timeout = true;
|
||||
break;
|
||||
@ -250,6 +255,8 @@ int user_record_authenticate(
|
||||
return -ERFKILL;
|
||||
if (need_user_presence_permitted)
|
||||
return -EMEDIUMTYPE;
|
||||
if (need_user_verification_permitted)
|
||||
return -ENOCSI;
|
||||
if (need_pin)
|
||||
return -ENOANO;
|
||||
if (need_token)
|
||||
@ -297,7 +304,7 @@ int home_setup_undo(HomeSetup *setup) {
|
||||
}
|
||||
|
||||
if (setup->undo_dm && setup->crypt_device && setup->dm_name) {
|
||||
q = crypt_deactivate(setup->crypt_device, setup->dm_name);
|
||||
q = sym_crypt_deactivate_by_name(setup->crypt_device, setup->dm_name, 0);
|
||||
if (q < 0)
|
||||
r = q;
|
||||
}
|
||||
@ -328,8 +335,10 @@ int home_setup_undo(HomeSetup *setup) {
|
||||
setup->dm_node = mfree(setup->dm_node);
|
||||
|
||||
setup->loop = loop_device_unref(setup->loop);
|
||||
crypt_free(setup->crypt_device);
|
||||
if (setup->crypt_device) {
|
||||
sym_crypt_free(setup->crypt_device);
|
||||
setup->crypt_device = NULL;
|
||||
}
|
||||
|
||||
explicit_bzero_safe(setup->volume_key, setup->volume_key_size);
|
||||
setup->volume_key = mfree(setup->volume_key);
|
||||
@ -517,7 +526,7 @@ int home_load_embedded_identity(
|
||||
if (!embedded_home)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(embedded_home, v, USER_RECORD_LOAD_EMBEDDED);
|
||||
r = user_record_load(embedded_home, v, USER_RECORD_LOAD_EMBEDDED|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -602,7 +611,7 @@ int home_store_embedded_identity(UserRecord *h, int root_fd, uid_t uid, UserReco
|
||||
assert(root_fd >= 0);
|
||||
assert(uid_is_valid(uid));
|
||||
|
||||
r = user_record_clone(h, USER_RECORD_EXTRACT_EMBEDDED, &embedded);
|
||||
r = user_record_clone(h, USER_RECORD_EXTRACT_EMBEDDED|USER_RECORD_PERMISSIVE, &embedded);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine new embedded record: %m");
|
||||
|
||||
@ -653,8 +662,8 @@ int home_extend_embedded_identity(UserRecord *h, UserRecord *used, HomeSetup *se
|
||||
setup->found_partition_uuid,
|
||||
setup->found_luks_uuid,
|
||||
setup->found_fs_uuid,
|
||||
setup->crypt_device ? crypt_get_cipher(setup->crypt_device) : NULL,
|
||||
setup->crypt_device ? crypt_get_cipher_mode(setup->crypt_device) : NULL,
|
||||
setup->crypt_device ? sym_crypt_get_cipher(setup->crypt_device) : NULL,
|
||||
setup->crypt_device ? sym_crypt_get_cipher_mode(setup->crypt_device) : NULL,
|
||||
setup->crypt_device ? luks_volume_key_size_convert(setup->crypt_device) : UINT64_MAX,
|
||||
file_system_type_fd(setup->root_fd),
|
||||
user_record_home_directory(used),
|
||||
@ -1086,15 +1095,21 @@ static int determine_default_storage(UserStorage *ret) {
|
||||
return log_error_errno(r, "Failed to determine whether we are in a container: %m");
|
||||
if (r == 0) {
|
||||
r = path_is_encrypted("/home");
|
||||
if (r > 0)
|
||||
log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
|
||||
else {
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine if /home is encrypted, ignoring: %m");
|
||||
if (r <= 0) {
|
||||
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
log_info("Not using '%s' storage, since libcryptsetup could not be loaded.", user_storage_to_string(USER_LUKS));
|
||||
else {
|
||||
log_info("Using automatic default storage of '%s'.", user_storage_to_string(USER_LUKS));
|
||||
*ret = USER_LUKS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
|
||||
}
|
||||
} else
|
||||
log_info("Running in container, not using '%s' storage.", user_storage_to_string(USER_LUKS));
|
||||
|
||||
@ -1661,7 +1676,7 @@ static int run(int argc, char *argv[]) {
|
||||
if (!home)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(home, v, USER_RECORD_LOAD_FULL|USER_RECORD_LOG);
|
||||
r = user_record_load(home, v, USER_RECORD_LOAD_FULL|USER_RECORD_LOG|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1680,6 +1695,7 @@ static int run(int argc, char *argv[]) {
|
||||
* ENOANO → suitable PKCS#11/FIDO2 device found, but PIN is missing to unlock it
|
||||
* ERFKILL → suitable PKCS#11 device found, but OK to ask for on-device interactive authentication not given
|
||||
* EMEDIUMTYPE → suitable FIDO2 device found, but OK to ask for user presence not given
|
||||
* ENOCSI → suitable FIDO2 device found, but OK to ask for user verification not given
|
||||
* ENOSTR → suitable FIDO2 device found, but user didn't react to action request on token quickly enough
|
||||
* EOWNERDEAD → suitable PKCS#11/FIDO2 device found, but its PIN is locked
|
||||
* ENOLCK → suitable PKCS#11/FIDO2 device found, but PIN incorrect
|
||||
|
||||
@ -216,7 +216,7 @@ static int acquire_user_record(
|
||||
if (!ur)
|
||||
return pam_log_oom(handle);
|
||||
|
||||
r = user_record_load(ur, v, USER_RECORD_LOAD_REFUSE_SECRET);
|
||||
r = user_record_load(ur, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0) {
|
||||
pam_syslog(handle, LOG_ERR, "Failed to load user record: %s", strerror_safe(r));
|
||||
return PAM_SERVICE_ERR;
|
||||
@ -377,7 +377,7 @@ static int handle_generic_user_record_error(
|
||||
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED)) {
|
||||
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Please verify presence on security token of user %s.", user_name);
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Please confirm presence on security token of user %s.", user_name);
|
||||
|
||||
r = user_record_set_fido2_user_presence_permitted(secret, true);
|
||||
if (r < 0) {
|
||||
@ -385,6 +385,16 @@ static int handle_generic_user_record_error(
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_USER_VERIFICATION_NEEDED)) {
|
||||
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Please verify user on security token of user %s.", user_name);
|
||||
|
||||
r = user_record_set_fido2_user_verification_permitted(secret, true);
|
||||
if (r < 0) {
|
||||
pam_syslog(handle, LOG_ERR, "Failed to set FIDO2 user verification permitted flag: %s", strerror_safe(r));
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_LOCKED)) {
|
||||
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token PIN is locked, please unlock it first. (Hint: Removal and re-insertion might suffice.)");
|
||||
|
||||
@ -14,7 +14,7 @@ static int user_record_signable_json(UserRecord *ur, char **ret) {
|
||||
assert(ur);
|
||||
assert(ret);
|
||||
|
||||
r = user_record_clone(ur, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_STRIP_SECRET|USER_RECORD_STRIP_BINDING|USER_RECORD_STRIP_STATUS|USER_RECORD_STRIP_SIGNATURE, &reduced);
|
||||
r = user_record_clone(ur, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_STRIP_SECRET|USER_RECORD_STRIP_BINDING|USER_RECORD_STRIP_STATUS|USER_RECORD_STRIP_SIGNATURE|USER_RECORD_PERMISSIVE, &reduced);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -95,7 +95,7 @@ int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) {
|
||||
if (!signed_ur)
|
||||
return log_oom();
|
||||
|
||||
r = user_record_load(signed_ur, v, USER_RECORD_LOAD_FULL);
|
||||
r = user_record_load(signed_ur, v, USER_RECORD_LOAD_FULL|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -252,7 +252,7 @@ int user_record_reconcile(
|
||||
if (!merged)
|
||||
return -ENOMEM;
|
||||
|
||||
r = user_record_load(merged, extended, USER_RECORD_LOAD_MASK_SECRET);
|
||||
r = user_record_load(merged, extended, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -261,7 +261,7 @@ int user_record_reconcile(
|
||||
}
|
||||
|
||||
/* Strip out secrets */
|
||||
r = user_record_clone(host, USER_RECORD_LOAD_MASK_SECRET, ret);
|
||||
r = user_record_clone(host, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1065,6 +1065,34 @@ int user_record_set_fido2_user_presence_permitted(UserRecord *h, int b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_record_set_fido2_user_verification_permitted(UserRecord *h, int b) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
|
||||
w = json_variant_ref(json_variant_by_key(h->json, "secret"));
|
||||
|
||||
if (b < 0)
|
||||
r = json_variant_filter(&w, STRV_MAKE("fido2UserVerificationPermitted"));
|
||||
else
|
||||
r = json_variant_set_field_boolean(&w, "fido2UserVerificationPermitted", b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (json_variant_is_blank_object(w))
|
||||
r = json_variant_filter(&h->json, STRV_MAKE("secret"));
|
||||
else
|
||||
r = json_variant_set_field(&h->json, "secret", w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
h->fido2_user_verification_permitted = b;
|
||||
|
||||
SET_FLAG(h->mask, USER_RECORD_SECRET, !json_variant_is_blank_object(w));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool per_machine_entry_empty(JsonVariant *v) {
|
||||
const char *k;
|
||||
_unused_ JsonVariant *e;
|
||||
@ -1167,6 +1195,14 @@ int user_record_merge_secret(UserRecord *h, UserRecord *secret) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (secret->fido2_user_verification_permitted >= 0) {
|
||||
r = user_record_set_fido2_user_verification_permitted(
|
||||
h,
|
||||
secret->fido2_user_verification_permitted);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ int user_record_set_hashed_password(UserRecord *h, char **hashed_password);
|
||||
int user_record_set_token_pin(UserRecord *h, char **pin, bool prepend);
|
||||
int user_record_set_pkcs11_protected_authentication_path_permitted(UserRecord *h, int b);
|
||||
int user_record_set_fido2_user_presence_permitted(UserRecord *h, int b);
|
||||
int user_record_set_fido2_user_verification_permitted(UserRecord *h, int b);
|
||||
int user_record_set_password_change_now(UserRecord *h, int b);
|
||||
int user_record_merge_secret(UserRecord *h, UserRecord *secret);
|
||||
int user_record_good_authentication(UserRecord *h);
|
||||
|
||||
@ -125,6 +125,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOKEN_PIN_NEEDED, ENOANO),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOKEN_PROTECTED_AUTHENTICATION_PATH_NEEDED, ERFKILL),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED, EMEDIUMTYPE),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOKEN_USER_VERIFICATION_NEEDED, ENOCSI),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOKEN_ACTION_TIMEOUT, ENOSTR),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOKEN_PIN_LOCKED, EOWNERDEAD),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOKEN_BAD_PIN, ENOLCK),
|
||||
|
||||
@ -107,6 +107,8 @@
|
||||
#define BUS_ERROR_TOKEN_PROTECTED_AUTHENTICATION_PATH_NEEDED \
|
||||
"org.freedesktop.home1.TokenProtectedAuthenticationPathNeeded"
|
||||
#define BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED "org.freedesktop.home1.TokenUserPresenceNeeded"
|
||||
#define BUS_ERROR_TOKEN_USER_VERIFICATION_NEEDED \
|
||||
"org.freedesktop.home1.TokenUserVerificationNeeded"
|
||||
#define BUS_ERROR_TOKEN_ACTION_TIMEOUT "org.freedesktop.home1.TokenActionTimeout"
|
||||
#define BUS_ERROR_TOKEN_PIN_LOCKED "org.freedesktop.home1.TokenPinLocked"
|
||||
#define BUS_ERROR_TOKEN_BAD_PIN "org.freedesktop.home1.BadPin"
|
||||
|
||||
@ -141,7 +141,7 @@ static int acquire_user_record(
|
||||
if (!ur)
|
||||
return pam_log_oom(handle);
|
||||
|
||||
r = user_record_load(ur, v, USER_RECORD_LOAD_REFUSE_SECRET);
|
||||
r = user_record_load(ur, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE);
|
||||
if (r < 0) {
|
||||
pam_syslog(handle, LOG_ERR, "Failed to load user record: %s", strerror_safe(r));
|
||||
return PAM_SERVICE_ERR;
|
||||
|
||||
@ -377,14 +377,16 @@ int bind_user_setup(
|
||||
USER_RECORD_STRIP_PRIVILEGED|
|
||||
USER_RECORD_ALLOW_PER_MACHINE|
|
||||
USER_RECORD_ALLOW_BINDING|
|
||||
USER_RECORD_ALLOW_SIGNATURE;
|
||||
USER_RECORD_ALLOW_SIGNATURE|
|
||||
USER_RECORD_PERMISSIVE;
|
||||
static const UserRecordLoadFlags shadow_flags = /* Extracts privileged info */
|
||||
USER_RECORD_STRIP_REGULAR|
|
||||
USER_RECORD_ALLOW_PRIVILEGED|
|
||||
USER_RECORD_STRIP_PER_MACHINE|
|
||||
USER_RECORD_STRIP_BINDING|
|
||||
USER_RECORD_STRIP_SIGNATURE|
|
||||
USER_RECORD_EMPTY_OK;
|
||||
USER_RECORD_EMPTY_OK|
|
||||
USER_RECORD_PERMISSIVE;
|
||||
int r;
|
||||
|
||||
assert(root);
|
||||
|
||||
@ -107,7 +107,7 @@ static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **pa
|
||||
|
||||
assert(keyname);
|
||||
|
||||
if (!(flags & ASK_PASSWORD_PUSH_CACHE))
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_PUSH_CACHE))
|
||||
return 0;
|
||||
if (strv_isempty(passwords))
|
||||
return 0;
|
||||
@ -165,7 +165,7 @@ static int ask_password_keyring(const char *keyname, AskPasswordFlags flags, cha
|
||||
assert(keyname);
|
||||
assert(ret);
|
||||
|
||||
if (!(flags & ASK_PASSWORD_ACCEPT_CACHED))
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED))
|
||||
return -EUNATCH;
|
||||
|
||||
r = lookup_key(keyname, &serial);
|
||||
@ -258,7 +258,7 @@ int ask_password_plymouth(
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (flags & ASK_PASSWORD_ACCEPT_CACHED) {
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED)) {
|
||||
packet = strdup("c");
|
||||
n = 1;
|
||||
} else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0)
|
||||
@ -320,7 +320,7 @@ int ask_password_plymouth(
|
||||
|
||||
if (buffer[0] == 5) {
|
||||
|
||||
if (flags & ASK_PASSWORD_ACCEPT_CACHED) {
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED)) {
|
||||
/* Hmm, first try with cached
|
||||
* passwords failed, so let's retry
|
||||
* with a normal password request */
|
||||
@ -415,16 +415,16 @@ int ask_password_tty(
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (flags & ASK_PASSWORD_NO_TTY)
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_NO_TTY))
|
||||
return -EUNATCH;
|
||||
|
||||
if (!message)
|
||||
message = "Password:";
|
||||
|
||||
if (emoji_enabled())
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_HIDE_EMOJI) && emoji_enabled())
|
||||
message = strjoina(special_glyph(SPECIAL_GLYPH_LOCK_AND_KEY), " ", message);
|
||||
|
||||
if (flag_file || ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname)) {
|
||||
if (flag_file || (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname)) {
|
||||
notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
|
||||
if (notify < 0)
|
||||
return -errno;
|
||||
@ -433,7 +433,7 @@ int ask_password_tty(
|
||||
if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0)
|
||||
return -errno;
|
||||
}
|
||||
if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
|
||||
r = ask_password_keyring(keyname, flags, ret);
|
||||
if (r >= 0)
|
||||
return 0;
|
||||
@ -452,7 +452,7 @@ int ask_password_tty(
|
||||
if (tcgetattr(ttyfd, &old_termios) < 0)
|
||||
return -errno;
|
||||
|
||||
if (flags & ASK_PASSWORD_CONSOLE_COLOR)
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_CONSOLE_COLOR))
|
||||
use_color = dev_console_colors_enabled();
|
||||
else
|
||||
use_color = colors_enabled();
|
||||
@ -463,7 +463,7 @@ int ask_password_tty(
|
||||
(void) loop_write(ttyfd, message, strlen(message), false);
|
||||
(void) loop_write(ttyfd, " ", 1, false);
|
||||
|
||||
if (!(flags & ASK_PASSWORD_SILENT) && !(flags & ASK_PASSWORD_ECHO)) {
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT) && !FLAGS_SET(flags, ASK_PASSWORD_ECHO)) {
|
||||
if (use_color)
|
||||
(void) loop_write(ttyfd, ansi_grey(), strlen(ansi_grey()), false);
|
||||
(void) loop_write(ttyfd, PRESS_TAB, strlen(PRESS_TAB), false);
|
||||
@ -564,7 +564,7 @@ int ask_password_tty(
|
||||
|
||||
if (c == 21) { /* C-u */
|
||||
|
||||
if (!(flags & ASK_PASSWORD_SILENT))
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT))
|
||||
(void) backspace_string(ttyfd, passphrase);
|
||||
|
||||
explicit_bzero_safe(passphrase, sizeof(passphrase));
|
||||
@ -575,7 +575,7 @@ int ask_password_tty(
|
||||
if (p > 0) {
|
||||
size_t q;
|
||||
|
||||
if (!(flags & ASK_PASSWORD_SILENT))
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT))
|
||||
(void) backspace_chars(ttyfd, 1);
|
||||
|
||||
/* Remove a full UTF-8 codepoint from the end. For that, figure out where the
|
||||
@ -599,7 +599,7 @@ int ask_password_tty(
|
||||
p = codepoint = q == SIZE_MAX ? p - 1 : q;
|
||||
explicit_bzero_safe(passphrase + p, sizeof(passphrase) - p);
|
||||
|
||||
} else if (!dirty && !(flags & ASK_PASSWORD_SILENT)) {
|
||||
} else if (!dirty && !FLAGS_SET(flags, ASK_PASSWORD_SILENT)) {
|
||||
|
||||
flags |= ASK_PASSWORD_SILENT;
|
||||
|
||||
@ -612,7 +612,7 @@ int ask_password_tty(
|
||||
} else if (ttyfd >= 0)
|
||||
(void) loop_write(ttyfd, "\a", 1, false);
|
||||
|
||||
} else if (c == '\t' && !(flags & ASK_PASSWORD_SILENT)) {
|
||||
} else if (c == '\t' && !FLAGS_SET(flags, ASK_PASSWORD_SILENT)) {
|
||||
|
||||
(void) backspace_string(ttyfd, passphrase);
|
||||
flags |= ASK_PASSWORD_SILENT;
|
||||
@ -631,11 +631,11 @@ int ask_password_tty(
|
||||
} else {
|
||||
passphrase[p++] = c;
|
||||
|
||||
if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0) {
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT) && ttyfd >= 0) {
|
||||
/* Check if we got a complete UTF-8 character now. If so, let's output one '*'. */
|
||||
n = utf8_encoded_valid_unichar(passphrase + codepoint, SIZE_MAX);
|
||||
if (n >= 0) {
|
||||
if (flags & ASK_PASSWORD_ECHO)
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ECHO))
|
||||
(void) loop_write(ttyfd, passphrase + codepoint, n, false);
|
||||
else
|
||||
(void) loop_write(ttyfd, "*", 1, false);
|
||||
@ -739,7 +739,7 @@ int ask_password_agent(
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (flags & ASK_PASSWORD_NO_AGENT)
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT))
|
||||
return -EUNATCH;
|
||||
|
||||
assert_se(sigemptyset(&mask) >= 0);
|
||||
@ -748,7 +748,7 @@ int ask_password_agent(
|
||||
|
||||
(void) mkdir_p_label("/run/systemd/ask-password", 0755);
|
||||
|
||||
if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
|
||||
r = ask_password_keyring(keyname, flags, ret);
|
||||
if (r >= 0) {
|
||||
r = 0;
|
||||
@ -803,10 +803,10 @@ int ask_password_agent(
|
||||
"Silent=%i\n",
|
||||
getpid_cached(),
|
||||
socket_name,
|
||||
(flags & ASK_PASSWORD_ACCEPT_CACHED) ? 1 : 0,
|
||||
(flags & ASK_PASSWORD_ECHO) ? 1 : 0,
|
||||
FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED),
|
||||
FLAGS_SET(flags, ASK_PASSWORD_ECHO),
|
||||
until,
|
||||
(flags & ASK_PASSWORD_SILENT) ? 1 : 0);
|
||||
FLAGS_SET(flags, ASK_PASSWORD_SILENT));
|
||||
|
||||
if (message)
|
||||
fprintf(f, "Message=%s\n", message);
|
||||
@ -1009,25 +1009,25 @@ int ask_password_auto(
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (!(flags & ASK_PASSWORD_NO_CREDENTIAL) && credential_name) {
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_NO_CREDENTIAL) && credential_name) {
|
||||
r = ask_password_credential(credential_name, flags, ret);
|
||||
if (r != -ENOKEY)
|
||||
return r;
|
||||
}
|
||||
|
||||
if ((flags & ASK_PASSWORD_ACCEPT_CACHED) &&
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) &&
|
||||
key_name &&
|
||||
((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
|
||||
(flags & ASK_PASSWORD_NO_AGENT)) {
|
||||
(FLAGS_SET(flags, ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
|
||||
FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT)) {
|
||||
r = ask_password_keyring(key_name, flags, ret);
|
||||
if (r != -ENOKEY)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
|
||||
return ask_password_tty(-1, message, key_name, until, flags, NULL, ret);
|
||||
|
||||
if (!(flags & ASK_PASSWORD_NO_AGENT))
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT))
|
||||
return ask_password_agent(message, icon, id, key_name, until, flags, ret);
|
||||
|
||||
return -EUNATCH;
|
||||
|
||||
@ -14,6 +14,7 @@ typedef enum AskPasswordFlags {
|
||||
ASK_PASSWORD_NO_AGENT = 1 << 5, /* never ask for password via agent */
|
||||
ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */
|
||||
ASK_PASSWORD_NO_CREDENTIAL = 1 << 7, /* never use $CREDENTIALS_DIRECTORY data */
|
||||
ASK_PASSWORD_HIDE_EMOJI = 1 << 8, /* hide the lock and key emoji */
|
||||
} AskPasswordFlags;
|
||||
|
||||
int ask_password_tty(int tty_fd, const char *message, const char *key_name, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
||||
|
||||
@ -17,23 +17,38 @@ int (*sym_crypt_activate_by_volume_key)(struct crypt_device *cd, const char *nam
|
||||
int (*sym_crypt_deactivate_by_name)(struct crypt_device *cd, const char *name, uint32_t flags);
|
||||
int (*sym_crypt_format)(struct crypt_device *cd, const char *type, const char *cipher, const char *cipher_mode, const char *uuid, const char *volume_key, size_t volume_key_size, void *params);
|
||||
void (*sym_crypt_free)(struct crypt_device *cd);
|
||||
const char *(*sym_crypt_get_cipher)(struct crypt_device *cd);
|
||||
const char *(*sym_crypt_get_cipher_mode)(struct crypt_device *cd);
|
||||
uint64_t (*sym_crypt_get_data_offset)(struct crypt_device *cd);
|
||||
const char *(*sym_crypt_get_device_name)(struct crypt_device *cd);
|
||||
const char *(*sym_crypt_get_dir)(void);
|
||||
const char *(*sym_crypt_get_type)(struct crypt_device *cd);
|
||||
const char *(*sym_crypt_get_uuid)(struct crypt_device *cd);
|
||||
int (*sym_crypt_get_verity_info)(struct crypt_device *cd, struct crypt_params_verity *vp);
|
||||
int (*sym_crypt_get_volume_key_size)(struct crypt_device *cd);
|
||||
int (*sym_crypt_init)(struct crypt_device **cd, const char *device);
|
||||
int (*sym_crypt_init_by_name)(struct crypt_device **cd, const char *name);
|
||||
int (*sym_crypt_keyslot_add_by_volume_key)(struct crypt_device *cd, int keyslot, const char *volume_key, size_t volume_key_size, const char *passphrase, size_t passphrase_size);
|
||||
int (*sym_crypt_keyslot_destroy)(struct crypt_device *cd, int keyslot);
|
||||
int (*sym_crypt_keyslot_max)(const char *type);
|
||||
int (*sym_crypt_load)(struct crypt_device *cd, const char *requested_type, void *params);
|
||||
int (*sym_crypt_resize)(struct crypt_device *cd, const char *name, uint64_t new_size);
|
||||
int (*sym_crypt_resume_by_passphrase)(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size);
|
||||
int (*sym_crypt_set_data_device)(struct crypt_device *cd, const char *device);
|
||||
void (*sym_crypt_set_debug_level)(int level);
|
||||
void (*sym_crypt_set_log_callback)(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr);
|
||||
int (*sym_crypt_set_pbkdf_type)(struct crypt_device *cd, const struct crypt_pbkdf_type *pbkdf) = NULL;
|
||||
int (*sym_crypt_token_json_get)(struct crypt_device *cd, int token, const char **json) = NULL;
|
||||
int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const char *json) = NULL;
|
||||
int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
|
||||
#if HAVE_CRYPT_SET_METADATA_SIZE
|
||||
int (*sym_crypt_set_metadata_size)(struct crypt_device *cd, uint64_t metadata_size, uint64_t keyslots_size);
|
||||
#endif
|
||||
int (*sym_crypt_set_pbkdf_type)(struct crypt_device *cd, const struct crypt_pbkdf_type *pbkdf);
|
||||
int (*sym_crypt_suspend)(struct crypt_device *cd, const char *name);
|
||||
int (*sym_crypt_token_json_get)(struct crypt_device *cd, int token, const char **json);
|
||||
int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const char *json);
|
||||
#if HAVE_CRYPT_TOKEN_MAX
|
||||
int (*sym_crypt_token_max)(const char *type);
|
||||
#endif
|
||||
crypt_token_info (*sym_crypt_token_status)(struct crypt_device *cd, int token, const char **type);
|
||||
int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
|
||||
|
||||
int dlopen_cryptsetup(void) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
@ -58,23 +73,38 @@ int dlopen_cryptsetup(void) {
|
||||
DLSYM_ARG(crypt_deactivate_by_name),
|
||||
DLSYM_ARG(crypt_format),
|
||||
DLSYM_ARG(crypt_free),
|
||||
DLSYM_ARG(crypt_get_cipher),
|
||||
DLSYM_ARG(crypt_get_cipher_mode),
|
||||
DLSYM_ARG(crypt_get_data_offset),
|
||||
DLSYM_ARG(crypt_get_device_name),
|
||||
DLSYM_ARG(crypt_get_dir),
|
||||
DLSYM_ARG(crypt_get_type),
|
||||
DLSYM_ARG(crypt_get_uuid),
|
||||
DLSYM_ARG(crypt_get_verity_info),
|
||||
DLSYM_ARG(crypt_get_volume_key_size),
|
||||
DLSYM_ARG(crypt_init),
|
||||
DLSYM_ARG(crypt_init_by_name),
|
||||
DLSYM_ARG(crypt_keyslot_add_by_volume_key),
|
||||
DLSYM_ARG(crypt_keyslot_destroy),
|
||||
DLSYM_ARG(crypt_keyslot_max),
|
||||
DLSYM_ARG(crypt_load),
|
||||
DLSYM_ARG(crypt_resize),
|
||||
DLSYM_ARG(crypt_resume_by_passphrase),
|
||||
DLSYM_ARG(crypt_set_data_device),
|
||||
DLSYM_ARG(crypt_set_debug_level),
|
||||
DLSYM_ARG(crypt_set_log_callback),
|
||||
#if HAVE_CRYPT_SET_METADATA_SIZE
|
||||
DLSYM_ARG(crypt_set_metadata_size),
|
||||
#endif
|
||||
DLSYM_ARG(crypt_set_pbkdf_type),
|
||||
DLSYM_ARG(crypt_suspend),
|
||||
DLSYM_ARG(crypt_token_json_get),
|
||||
DLSYM_ARG(crypt_token_json_set),
|
||||
DLSYM_ARG(crypt_volume_key_get),
|
||||
#if HAVE_CRYPT_TOKEN_MAX
|
||||
DLSYM_ARG(crypt_token_max),
|
||||
#endif
|
||||
DLSYM_ARG(crypt_token_status),
|
||||
DLSYM_ARG(crypt_volume_key_get),
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -82,6 +112,13 @@ int dlopen_cryptsetup(void) {
|
||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
||||
* was traditionally a regular shared library dependency which lives forever too. */
|
||||
cryptsetup_dl = TAKE_PTR(dl);
|
||||
|
||||
/* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
|
||||
* libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
|
||||
* whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some
|
||||
* other code loaded into this process also changes the global log functions of libcryptsetup, who
|
||||
* knows? And if so, we still want our own objects to log via our own infra, at the very least.) */
|
||||
cryptsetup_enable_logging(NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -109,13 +146,17 @@ static void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
|
||||
}
|
||||
|
||||
void cryptsetup_enable_logging(struct crypt_device *cd) {
|
||||
if (!cd)
|
||||
return;
|
||||
/* It's OK to call this with a NULL parameter, in which case libcryptsetup will set the defaut log
|
||||
* function.
|
||||
*
|
||||
* Note that this is also called from dlopen_cryptsetup(), which we call here too. Sounds like an
|
||||
* endless loop, but isn't because we break it via the check for 'cryptsetup_dl' early in
|
||||
* dlopen_cryptsetup(). */
|
||||
|
||||
if (dlopen_cryptsetup() < 0) /* If this fails, let's gracefully ignore the issue, this is just debug
|
||||
* logging after all, and if this failed we already generated a debug
|
||||
* log message that should help to track things down. */
|
||||
return;
|
||||
if (dlopen_cryptsetup() < 0)
|
||||
return; /* If this fails, let's gracefully ignore the issue, this is just debug logging after
|
||||
* all, and if this failed we already generated a debug log message that should help
|
||||
* to track things down. */
|
||||
|
||||
sym_crypt_set_log_callback(cd, cryptsetup_log_glue, NULL);
|
||||
sym_crypt_set_debug_level(DEBUG_LOGGING ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
|
||||
@ -123,11 +164,15 @@ void cryptsetup_enable_logging(struct crypt_device *cd) {
|
||||
|
||||
int cryptsetup_set_minimal_pbkdf(struct crypt_device *cd) {
|
||||
|
||||
/* With CRYPT_PBKDF_NO_BENCHMARK flag set .time_ms member is ignored
|
||||
* while .iterations must be set at least to recommended minimum value. */
|
||||
|
||||
static const struct crypt_pbkdf_type minimal_pbkdf = {
|
||||
.hash = "sha512",
|
||||
.type = CRYPT_KDF_PBKDF2,
|
||||
.iterations = 1,
|
||||
.time_ms = 1,
|
||||
.iterations = 1000, /* recommended minimum count for pbkdf2
|
||||
* according to NIST SP 800-132, ch. 5.2 */
|
||||
.flags = CRYPT_PBKDF_NO_BENCHMARK
|
||||
};
|
||||
|
||||
int r;
|
||||
|
||||
@ -23,20 +23,33 @@ extern int (*sym_crypt_activate_by_volume_key)(struct crypt_device *cd, const ch
|
||||
extern int (*sym_crypt_deactivate_by_name)(struct crypt_device *cd, const char *name, uint32_t flags);
|
||||
extern int (*sym_crypt_format)(struct crypt_device *cd, const char *type, const char *cipher, const char *cipher_mode, const char *uuid, const char *volume_key, size_t volume_key_size, void *params);
|
||||
extern void (*sym_crypt_free)(struct crypt_device *cd);
|
||||
extern const char *(*sym_crypt_get_cipher)(struct crypt_device *cd);
|
||||
extern const char *(*sym_crypt_get_cipher_mode)(struct crypt_device *cd);
|
||||
extern uint64_t (*sym_crypt_get_data_offset)(struct crypt_device *cd);
|
||||
extern const char *(*sym_crypt_get_device_name)(struct crypt_device *cd);
|
||||
extern const char *(*sym_crypt_get_dir)(void);
|
||||
extern const char *(*sym_crypt_get_type)(struct crypt_device *cd);
|
||||
extern const char *(*sym_crypt_get_uuid)(struct crypt_device *cd);
|
||||
extern int (*sym_crypt_get_verity_info)(struct crypt_device *cd, struct crypt_params_verity *vp);
|
||||
extern int (*sym_crypt_get_volume_key_size)(struct crypt_device *cd);
|
||||
extern int (*sym_crypt_init)(struct crypt_device **cd, const char *device);
|
||||
extern int (*sym_crypt_init_by_name)(struct crypt_device **cd, const char *name);
|
||||
extern int (*sym_crypt_keyslot_add_by_volume_key)(struct crypt_device *cd, int keyslot, const char *volume_key, size_t volume_key_size, const char *passphrase, size_t passphrase_size);
|
||||
extern int (*sym_crypt_keyslot_destroy)(struct crypt_device *cd, int keyslot);
|
||||
extern int (*sym_crypt_keyslot_max)(const char *type);
|
||||
extern int (*sym_crypt_load)(struct crypt_device *cd, const char *requested_type, void *params);
|
||||
extern int (*sym_crypt_resize)(struct crypt_device *cd, const char *name, uint64_t new_size);
|
||||
extern int (*sym_crypt_resume_by_passphrase)(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size);
|
||||
extern int (*sym_crypt_set_data_device)(struct crypt_device *cd, const char *device);
|
||||
extern void (*sym_crypt_set_debug_level)(int level);
|
||||
extern void (*sym_crypt_set_log_callback)(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr);
|
||||
#if HAVE_CRYPT_SET_METADATA_SIZE
|
||||
extern int (*sym_crypt_set_metadata_size)(struct crypt_device *cd, uint64_t metadata_size, uint64_t keyslots_size);
|
||||
#endif
|
||||
extern int (*sym_crypt_set_pbkdf_type)(struct crypt_device *cd, const struct crypt_pbkdf_type *pbkdf);
|
||||
extern int (*sym_crypt_suspend)(struct crypt_device *cd, const char *name);
|
||||
extern int (*sym_crypt_token_json_get)(struct crypt_device *cd, int token, const char **json);
|
||||
extern int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const char *json);
|
||||
extern int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
|
||||
#if HAVE_CRYPT_TOKEN_MAX
|
||||
extern int (*sym_crypt_token_max)(const char *type);
|
||||
#else
|
||||
@ -47,6 +60,8 @@ static inline int sym_crypt_token_max(_unused_ const char *type) {
|
||||
return 32;
|
||||
}
|
||||
#endif
|
||||
extern crypt_token_info (*sym_crypt_token_status)(struct crypt_device *cd, int token, const char **type);
|
||||
extern int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
|
||||
|
||||
int dlopen_cryptsetup(void);
|
||||
|
||||
|
||||
@ -1926,6 +1926,8 @@ static int verity_can_reuse(
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Error opening verity device, crypt_init_by_name failed: %m");
|
||||
|
||||
cryptsetup_enable_logging(cd);
|
||||
|
||||
r = sym_crypt_get_verity_info(cd, &crypt_params);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Error opening verity device, crypt_get_verity_info failed: %m");
|
||||
|
||||
@ -200,6 +200,7 @@ UserRecord* user_record_new(void) {
|
||||
.password_change_now = -1,
|
||||
.pkcs11_protected_authentication_path_permitted = -1,
|
||||
.fido2_user_presence_permitted = -1,
|
||||
.fido2_user_verification_permitted = -1,
|
||||
};
|
||||
|
||||
return h;
|
||||
@ -774,6 +775,7 @@ static int dispatch_secret(const char *name, JsonVariant *variant, JsonDispatchF
|
||||
{ "pkcs11Pin", /* legacy alias */ _JSON_VARIANT_TYPE_INVALID, json_dispatch_strv, offsetof(UserRecord, token_pin), 0 },
|
||||
{ "pkcs11ProtectedAuthenticationPathPermitted", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, pkcs11_protected_authentication_path_permitted), 0 },
|
||||
{ "fido2UserPresencePermitted", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, fido2_user_presence_permitted), 0 },
|
||||
{ "fido2UserVerificationPermitted", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, fido2_user_verification_permitted), 0 },
|
||||
{},
|
||||
};
|
||||
|
||||
@ -1019,6 +1021,9 @@ static int dispatch_fido2_hmac_salt(const char *name, JsonVariant *variant, Json
|
||||
{ "credential", JSON_VARIANT_STRING, dispatch_fido2_hmac_credential, offsetof(Fido2HmacSalt, credential), JSON_MANDATORY },
|
||||
{ "salt", JSON_VARIANT_STRING, dispatch_fido2_hmac_salt_value, 0, JSON_MANDATORY },
|
||||
{ "hashedPassword", JSON_VARIANT_STRING, json_dispatch_string, offsetof(Fido2HmacSalt, hashed_password), JSON_MANDATORY },
|
||||
{ "up", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(Fido2HmacSalt, up), 0 },
|
||||
{ "uv", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(Fido2HmacSalt, uv), 0 },
|
||||
{ "clientPin", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(Fido2HmacSalt, client_pin), 0 },
|
||||
{},
|
||||
};
|
||||
|
||||
@ -1031,7 +1036,11 @@ static int dispatch_fido2_hmac_salt(const char *name, JsonVariant *variant, Json
|
||||
|
||||
h->fido2_hmac_salt = array;
|
||||
k = h->fido2_hmac_salt + h->n_fido2_hmac_salt;
|
||||
*k = (Fido2HmacSalt) {};
|
||||
*k = (Fido2HmacSalt) {
|
||||
.uv = -1,
|
||||
.up = -1,
|
||||
.client_pin = -1,
|
||||
};
|
||||
|
||||
r = json_dispatch(e, fido2_hmac_salt_dispatch_table, NULL, flags, k);
|
||||
if (r < 0) {
|
||||
@ -2105,7 +2114,7 @@ int user_record_masked_equal(UserRecord *a, UserRecord *b, UserRecordMask mask)
|
||||
/* Compares the two records, but ignores anything not listed in the specified mask */
|
||||
|
||||
if ((a->mask & ~mask) != 0) {
|
||||
r = user_record_clone(a, USER_RECORD_ALLOW(mask) | USER_RECORD_STRIP(~mask & _USER_RECORD_MASK_MAX), &x);
|
||||
r = user_record_clone(a, USER_RECORD_ALLOW(mask) | USER_RECORD_STRIP(~mask & _USER_RECORD_MASK_MAX) | USER_RECORD_PERMISSIVE, &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2113,7 +2122,7 @@ int user_record_masked_equal(UserRecord *a, UserRecord *b, UserRecordMask mask)
|
||||
}
|
||||
|
||||
if ((b->mask & ~mask) != 0) {
|
||||
r = user_record_clone(b, USER_RECORD_ALLOW(mask) | USER_RECORD_STRIP(~mask & _USER_RECORD_MASK_MAX), &y);
|
||||
r = user_record_clone(b, USER_RECORD_ALLOW(mask) | USER_RECORD_STRIP(~mask & _USER_RECORD_MASK_MAX) | USER_RECORD_PERMISSIVE, &y);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -236,6 +236,9 @@ typedef struct Fido2HmacSalt {
|
||||
|
||||
/* What to test the hashed salt value against, usually UNIX password hash here. */
|
||||
char *hashed_password;
|
||||
|
||||
/* Whether the 'up', 'uv', 'clientPin' features are enabled. */
|
||||
int uv, up, client_pin;
|
||||
} Fido2HmacSalt;
|
||||
|
||||
typedef struct RecoveryKey {
|
||||
@ -371,6 +374,7 @@ typedef struct UserRecord {
|
||||
Fido2HmacSalt *fido2_hmac_salt;
|
||||
size_t n_fido2_hmac_salt;
|
||||
int fido2_user_presence_permitted;
|
||||
int fido2_user_verification_permitted;
|
||||
|
||||
char **recovery_key_type;
|
||||
RecoveryKey *recovery_key;
|
||||
|
||||
@ -82,7 +82,8 @@ static int load_user(
|
||||
USER_RECORD_ALLOW_PER_MACHINE|
|
||||
USER_RECORD_ALLOW_BINDING|
|
||||
USER_RECORD_ALLOW_SIGNATURE|
|
||||
(have_privileged ? USER_RECORD_ALLOW_PRIVILEGED : 0));
|
||||
(have_privileged ? USER_RECORD_ALLOW_PRIVILEGED : 0)|
|
||||
USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -225,7 +226,8 @@ static int load_group(
|
||||
USER_RECORD_ALLOW_PER_MACHINE|
|
||||
USER_RECORD_ALLOW_BINDING|
|
||||
USER_RECORD_ALLOW_SIGNATURE|
|
||||
(have_privileged ? USER_RECORD_ALLOW_PRIVILEGED : 0));
|
||||
(have_privileged ? USER_RECORD_ALLOW_PRIVILEGED : 0)|
|
||||
USER_RECORD_PERMISSIVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ static int build_user_json(Varlink *link, UserRecord *ur, JsonVariant **ret) {
|
||||
} else
|
||||
trusted = peer_uid == 0 || peer_uid == ur->uid;
|
||||
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE;
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE;
|
||||
if (trusted)
|
||||
flags |= USER_RECORD_ALLOW_PRIVILEGED;
|
||||
else
|
||||
@ -232,7 +232,7 @@ static int build_group_json(Varlink *link, GroupRecord *gr, JsonVariant **ret) {
|
||||
} else
|
||||
trusted = peer_uid == 0;
|
||||
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE;
|
||||
flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE;
|
||||
if (trusted)
|
||||
flags |= USER_RECORD_ALLOW_PRIVILEGED;
|
||||
else
|
||||
|
||||
@ -138,6 +138,8 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
log_setup();
|
||||
|
||||
cryptsetup_enable_logging(NULL);
|
||||
|
||||
umask(0022);
|
||||
|
||||
if (streq(argv[1], "attach")) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user