1
0
mirror of https://github.com/systemd/systemd synced 2026-04-26 00:45:09 +02:00

Compare commits

..

No commits in common. "70e723c000e46e2304e54f8063572d7fa0cdad46" and "127927b2c218e594950b8c699d08570c66650234" have entirely different histories.

17 changed files with 85 additions and 238 deletions

5
TODO
View File

@ -78,11 +78,6 @@ Janitorial Clean-ups:
Features: Features:
* Add ConditionCredentialExists= or so, that allows conditionalizing services
depending on whether a specific system credential is set. Usecase: a service
similar to the ssh keygen service that installs any SSH host key supplied via
system credentials into /etc/ssh.
* drop support for kernels that lack ambient capabilities support (i.e. make * drop support for kernels that lack ambient capabilities support (i.e. make
4.3 new baseline). Then drop support for "!!" modifier for ExecStart= which 4.3 new baseline). Then drop support for "!!" modifier for ExecStart= which
is only supported for such old kernels is only supported for such old kernels

View File

@ -53,15 +53,6 @@ boot. For that it's essential to:
[`/etc/machine-info`](https://www.freedesktop.org/software/systemd/man/machine-info.html) [`/etc/machine-info`](https://www.freedesktop.org/software/systemd/man/machine-info.html)
which carry additional identifying information about the OS image. which carry additional identifying information about the OS image.
5. Remove `/var/lib/systemd/credential.secret` which is used for protecting
service credentials, see
[`systemd.exec(5)`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Credentials)
and
[`systemd-creds(1)`](https://www.freedesktop.org/software/systemd/man/systemd-creds.html)
for details. Note that by removing this file access to previously encrypted
credentials from this image is lost. The file is automatically generated if
a new credential is encrypted and the file does not exist yet.
## Boot Menu Entry Identifiers ## Boot Menu Entry Identifiers
The The

View File

@ -233,7 +233,6 @@ evdev:name:Asus WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:*
evdev:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:* evdev:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:*
evdev:name:Asus Laptop extra buttons:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:* evdev:name:Asus Laptop extra buttons:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:*
KEYBOARD_KEY_6b=f21 # Touchpad Toggle KEYBOARD_KEY_6b=f21 # Touchpad Toggle
KEYBOARD_KEY_7c=f20 # Remap micmute to f20
# USB keyboard in Asus FX503VD # USB keyboard in Asus FX503VD
evdev:input:b0003v0B05p1869* evdev:input:b0003v0B05p1869*

View File

@ -453,10 +453,6 @@ sensor:modalias:acpi:SMO8500*:dmi:*:svnHewlett-Packard:pnHPStream8Tablet:*
sensor:modalias:i2c:bmc150_accel:dmi:*:svnHewlett-Packard:pnHPPavilionx2Detachable:*:rn815D:* sensor:modalias:i2c:bmc150_accel:dmi:*:svnHewlett-Packard:pnHPPavilionx2Detachable:*:rn815D:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# HP Pro Tablet 408 G1
sensor:modalias:i2c:bmc150_accel:dmi:*:svnHewlett-Packard:pnHPProTablet408:*:rn8048:*
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
######################################### #########################################
# I.T.Works # I.T.Works
######################################### #########################################

View File

@ -356,19 +356,6 @@
generally do not required that, and work out of the box.</para></listitem> generally do not required that, and work out of the box.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--fido2-credential-algorithm=</option><replaceable>STRING</replaceable></term>
<listitem><para>Specify COSE algorithm used in credential generation. The default value is
<literal>es256</literal>. Supported values are <literal>es256</literal>, <literal>rs256</literal>
and <literal>eddsa</literal>.</para>
<para><literal>es256</literal> denotes ECDSA over NIST P-256 with SHA-256. <literal>rs256</literal>
denotes 2048-bit RSA with PKCS#1.5 padding and SHA-256. <literal>eddsa</literal> denotes
EDDSA over Curve25519 with SHA-512.</para>
<para>Note that your authenticator may not support some algorithms.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--fido2-device=</option><replaceable>PATH</replaceable></term> <term><option>--fido2-device=</option><replaceable>PATH</replaceable></term>

View File

@ -122,19 +122,6 @@
<filename>/etc/crypttab</filename> line.</para></listitem> <filename>/etc/crypttab</filename> line.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--fido2-credential-algorithm=</option><replaceable>STRING</replaceable></term>
<listitem><para>Specify COSE algorithm used in credential generation. The default value is
<literal>es256</literal>. Supported values are <literal>es256</literal>, <literal>rs256</literal>
and <literal>eddsa</literal>.</para>
<para><literal>es256</literal> denotes ECDSA over NIST P-256 with SHA-256. <literal>rs256</literal>
denotes 2048-bit RSA with PKCS#1.5 padding and SHA-256. <literal>eddsa</literal> denotes
EDDSA over Curve25519 with SHA-512.</para>
<para>Note that your authenticator may not support some algorithms.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--fido2-device=</option><replaceable>PATH</replaceable></term> <term><option>--fido2-device=</option><replaceable>PATH</replaceable></term>

View File

@ -2598,9 +2598,7 @@ static int write_credential(
static int load_credential( static int load_credential(
const ExecContext *context, const ExecContext *context,
const ExecParameters *params, const ExecParameters *params,
const char *id, ExecLoadCredential *lc,
const char *path,
bool encrypted,
const char *unit, const char *unit,
int read_dfd, int read_dfd,
int write_dfd, int write_dfd,
@ -2608,6 +2606,12 @@ static int load_credential(
bool ownership_ok, bool ownership_ok,
uint64_t *left) { uint64_t *left) {
assert(context);
assert(lc);
assert(unit);
assert(write_dfd >= 0);
assert(left);
ReadFullFileFlags flags = READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER; ReadFullFileFlags flags = READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER;
_cleanup_(erase_and_freep) char *data = NULL; _cleanup_(erase_and_freep) char *data = NULL;
_cleanup_free_ char *j = NULL, *bindname = NULL; _cleanup_free_ char *j = NULL, *bindname = NULL;
@ -2616,23 +2620,14 @@ static int load_credential(
size_t size, add; size_t size, add;
int r; int r;
assert(context); if (path_is_absolute(lc->path) || read_dfd >= 0) {
assert(params); /* If this is an absolute path, read the data directly from it, and support AF_UNIX sockets */
assert(id); source = lc->path;
assert(path);
assert(unit);
assert(write_dfd >= 0);
assert(left);
if (path_is_absolute(path) || read_dfd >= 0) {
/* If this is an absolute path (or a directory fd is specifier relative which to read), read
* the data directly from it, and support AF_UNIX sockets */
source = path;
flags |= READ_FULL_FILE_CONNECT_SOCKET; flags |= READ_FULL_FILE_CONNECT_SOCKET;
/* Pass some minimal info about the unit and the credential name we are looking to acquire /* Pass some minimal info about the unit and the credential name we are looking to acquire
* via the source socket address in case we read off an AF_UNIX socket. */ * via the source socket address in case we read off an AF_UNIX socket. */
if (asprintf(&bindname, "@%" PRIx64"/unit/%s/%s", random_u64(), unit, id) < 0) if (asprintf(&bindname, "@%" PRIx64"/unit/%s/%s", random_u64(), unit, lc->id) < 0)
return -ENOMEM; return -ENOMEM;
missing_ok = false; missing_ok = false;
@ -2641,7 +2636,7 @@ static int load_credential(
/* If this is a relative path, take it relative to the credentials we received /* If this is a relative path, take it relative to the credentials we received
* ourselves. We don't support the AF_UNIX stuff in this mode, since we are operating * ourselves. We don't support the AF_UNIX stuff in this mode, since we are operating
* on a credential store, i.e. this is guaranteed to be regular files. */ * on a credential store, i.e. this is guaranteed to be regular files. */
j = path_join(params->received_credentials, path); j = path_join(params->received_credentials, lc->path);
if (!j) if (!j)
return -ENOMEM; return -ENOMEM;
@ -2653,14 +2648,14 @@ static int load_credential(
r = read_full_file_full( r = read_full_file_full(
read_dfd, source, read_dfd, source,
UINT64_MAX, UINT64_MAX,
encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX, lc->encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX,
flags | (encrypted ? READ_FULL_FILE_UNBASE64 : 0), flags | (lc->encrypted ? READ_FULL_FILE_UNBASE64 : 0),
bindname, bindname,
&data, &size); &data, &size);
else else
r = -ENOENT; r = -ENOENT;
if (r == -ENOENT && (missing_ok || hashmap_contains(context->set_credentials, id))) { if (r == -ENOENT && (missing_ok || hashmap_contains(context->set_credentials, lc->id))) {
/* Make a missing inherited credential non-fatal, let's just continue. After all apps /* Make a missing inherited credential non-fatal, let's just continue. After all apps
* will get clear errors if we don't pass such a missing credential on as they * will get clear errors if we don't pass such a missing credential on as they
* themselves will get ENOENT when trying to read them, which should not be much * themselves will get ENOENT when trying to read them, which should not be much
@ -2668,17 +2663,17 @@ static int load_credential(
* *
* Also, if the source file doesn't exist, but a fallback is set via SetCredentials= * Also, if the source file doesn't exist, but a fallback is set via SetCredentials=
* we are fine, too. */ * we are fine, too. */
log_debug_errno(r, "Couldn't read inherited credential '%s', skipping: %m", path); log_debug_errno(r, "Couldn't read inherited credential '%s', skipping: %m", lc->path);
return 0; return 0;
} }
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to read credential '%s': %m", path); return log_debug_errno(r, "Failed to read credential '%s': %m", lc->path);
if (encrypted) { if (lc->encrypted) {
_cleanup_free_ void *plaintext = NULL; _cleanup_free_ void *plaintext = NULL;
size_t plaintext_size = 0; size_t plaintext_size = 0;
r = decrypt_credential_and_warn(id, now(CLOCK_REALTIME), NULL, data, size, &plaintext, &plaintext_size); r = decrypt_credential_and_warn(lc->id, now(CLOCK_REALTIME), NULL, data, size, &plaintext, &plaintext_size);
if (r < 0) if (r < 0)
return r; return r;
@ -2686,22 +2681,24 @@ static int load_credential(
size = plaintext_size; size = plaintext_size;
} }
add = strlen(id) + size; add = strlen(lc->id) + size;
if (add > *left) if (add > *left)
return -E2BIG; return -E2BIG;
r = write_credential(write_dfd, id, data, size, uid, ownership_ok); r = write_credential(write_dfd, lc->id, data, size, uid, ownership_ok);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to write credential '%s': %m", id); return r;
*left -= add; *left -= add;
return 0; return 0;
} }
struct load_cred_args { struct load_cred_args {
Set *seen_creds;
const ExecContext *context; const ExecContext *context;
const ExecParameters *params; const ExecParameters *params;
bool encrypted; ExecLoadCredential *parent_local_credential;
const char *unit; const char *unit;
int dfd; int dfd;
uid_t uid; uid_t uid;
@ -2718,8 +2715,8 @@ static int load_cred_recurse_dir_cb(
const struct statx *sx, const struct statx *sx,
void *userdata) { void *userdata) {
struct load_cred_args *args = ASSERT_PTR(userdata); _cleanup_free_ char *credname = NULL, *sub_id = NULL;
_cleanup_free_ char *sub_id = NULL; struct load_cred_args *args = userdata;
int r; int r;
if (event != RECURSE_DIR_ENTRY) if (event != RECURSE_DIR_ENTRY)
@ -2728,32 +2725,32 @@ static int load_cred_recurse_dir_cb(
if (!IN_SET(de->d_type, DT_REG, DT_SOCK)) if (!IN_SET(de->d_type, DT_REG, DT_SOCK))
return RECURSE_DIR_CONTINUE; return RECURSE_DIR_CONTINUE;
sub_id = strreplace(path, "/", "_"); credname = strreplace(path, "/", "_");
if (!credname)
return -ENOMEM;
sub_id = strjoin(args->parent_local_credential->id, "_", credname);
if (!sub_id) if (!sub_id)
return -ENOMEM; return -ENOMEM;
if (!credential_name_valid(sub_id)) if (!credential_name_valid(sub_id))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Credential would get ID %s, which is not valid, refusing", sub_id); return -EINVAL;
if (faccessat(args->dfd, sub_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { if (set_contains(args->seen_creds, sub_id)) {
log_debug("Skipping credential with duplicated ID %s at %s", sub_id, path); log_debug("Skipping credential with duplicated ID %s at %s", sub_id, path);
return RECURSE_DIR_CONTINUE; return RECURSE_DIR_CONTINUE;
} }
if (errno != ENOENT)
return log_debug_errno(errno, "Failed to test if credential %s exists: %m", sub_id);
r = load_credential( r = set_put_strdup(&args->seen_creds, sub_id);
args->context, if (r < 0)
args->params, return r;
sub_id,
de->d_name, r = load_credential(args->context, args->params,
args->encrypted, &(ExecLoadCredential) {
args->unit, .id = sub_id,
dir_fd, .path = (char *) de->d_name,
args->dfd, .encrypted = args->parent_local_credential->encrypted,
args->uid, }, args->unit, dir_fd, args->dfd, args->uid, args->ownership_ok, args->left);
args->ownership_ok,
args->left);
if (r < 0) if (r < 0)
return r; return r;
@ -2770,6 +2767,7 @@ static int acquire_credentials(
uint64_t left = CREDENTIALS_TOTAL_SIZE_MAX; uint64_t left = CREDENTIALS_TOTAL_SIZE_MAX;
_cleanup_close_ int dfd = -1; _cleanup_close_ int dfd = -1;
_cleanup_set_free_ Set *seen_creds = NULL;
ExecLoadCredential *lc; ExecLoadCredential *lc;
ExecSetCredential *sc; ExecSetCredential *sc;
int r; int r;
@ -2781,71 +2779,62 @@ static int acquire_credentials(
if (dfd < 0) if (dfd < 0)
return -errno; return -errno;
seen_creds = set_new(&string_hash_ops_free);
if (!seen_creds)
return -ENOMEM;
/* First, load credentials off disk (or acquire via AF_UNIX socket) */ /* First, load credentials off disk (or acquire via AF_UNIX socket) */
HASHMAP_FOREACH(lc, context->load_credentials) { HASHMAP_FOREACH(lc, context->load_credentials) {
_cleanup_close_ int sub_fd = -1; _cleanup_close_ int sub_fd = -1;
/* If this is an absolute path, then try to open it as a directory. If that works, then we'll /* Skip over credentials with unspecified paths. These are received by the
* recurse into it. If it is an absolute path but it isn't a directory, then we'll open it as * service manager via the $CREDENTIALS_DIRECTORY environment variable. */
* a regular file. Finally, if it's a relative path we will use it as a credential name to if (!is_path(lc->path) && streq(lc->id, lc->path))
* propagate a credential passed to us from further up. */ continue;
if (path_is_absolute(lc->path)) { sub_fd = open(lc->path, O_DIRECTORY|O_CLOEXEC|O_RDONLY);
sub_fd = open(lc->path, O_DIRECTORY|O_CLOEXEC|O_RDONLY); if (sub_fd < 0 && errno != ENOTDIR)
if (sub_fd < 0 && !IN_SET(errno, return -errno;
ENOTDIR, /* Not a directory */
ENOENT)) /* Doesn't exist? */
return log_debug_errno(errno, "Failed to open '%s': %m", lc->path);
}
if (sub_fd < 0) if (sub_fd < 0) {
/* Regular file (incl. a credential passed in from higher up) */ r = set_put_strdup(&seen_creds, lc->id);
r = load_credential( if (r < 0)
context, return r;
params, r = load_credential(context, params, lc, unit, -1, dfd, uid, ownership_ok, &left);
lc->id, if (r < 0)
lc->path, return r;
lc->encrypted,
unit, } else {
-1,
dfd,
uid,
ownership_ok,
&left);
else
/* Directory */
r = recurse_dir( r = recurse_dir(
sub_fd, sub_fd,
/* path= */ lc->id, /* recurse_dir() will suffix the subdir paths from here to the top-level id */ /* path= */ "",
/* statx_mask= */ 0, /* statx_mask= */ 0,
/* n_depth_max= */ UINT_MAX, /* n_depth_max= */ UINT_MAX,
RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE, RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE,
load_cred_recurse_dir_cb, load_cred_recurse_dir_cb,
&(struct load_cred_args) { &(struct load_cred_args) {
.seen_creds = seen_creds,
.context = context, .context = context,
.params = params, .params = params,
.encrypted = lc->encrypted, .parent_local_credential = lc,
.unit = unit, .unit = unit,
.dfd = dfd, .dfd = dfd,
.uid = uid, .uid = uid,
.ownership_ok = ownership_ok, .ownership_ok = ownership_ok,
.left = &left, .left = &left,
}); });
if (r < 0) if (r < 0)
return r; return r;
}
} }
/* Second, we add in literally specified credentials. If the credentials already exist, we'll not add /* First we use the literally specified credentials. Note that they might be overridden again below,
* them, so that they can act as a "default" if the same credential is specified multiple times. */ * and thus act as a "default" if the same credential is specified multiple times */
HASHMAP_FOREACH(sc, context->set_credentials) { HASHMAP_FOREACH(sc, context->set_credentials) {
_cleanup_(erase_and_freep) void *plaintext = NULL; _cleanup_(erase_and_freep) void *plaintext = NULL;
const char *data; const char *data;
size_t size, add; size_t size, add;
/* Note that we check ahead of time here instead of relying on O_EXCL|O_CREAT later to return
* EEXIST if the credential already exists. That's because the TPM2-based decryption is kinda
* slow and involved, hence it's nice to be able to skip that if the credential already
* exists anyway. */
if (faccessat(dfd, sc->id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) if (faccessat(dfd, sc->id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
continue; continue;
if (errno != ENOENT) if (errno != ENOENT)
@ -2870,6 +2859,7 @@ static int acquire_credentials(
if (r < 0) if (r < 0)
return r; return r;
left -= add; left -= add;
} }

View File

@ -12,8 +12,7 @@ int enroll_fido2(
const void *volume_key, const void *volume_key,
size_t volume_key_size, size_t volume_key_size,
const char *device, const char *device,
Fido2EnrollFlags lock_with, Fido2EnrollFlags lock_with) {
int cred_alg) {
_cleanup_(erase_and_freep) void *salt = NULL, *secret = NULL; _cleanup_(erase_and_freep) void *salt = NULL, *secret = NULL;
_cleanup_(erase_and_freep) char *base64_encoded = NULL; _cleanup_(erase_and_freep) char *base64_encoded = NULL;
@ -43,7 +42,6 @@ int enroll_fido2(
/* user_icon_name= */ NULL, /* user_icon_name= */ NULL,
/* askpw_icon_name= */ "drive-harddisk", /* askpw_icon_name= */ "drive-harddisk",
lock_with, lock_with,
cred_alg,
&cid, &cid_size, &cid, &cid_size,
&salt, &salt_size, &salt, &salt_size,
&secret, &secret_size, &secret, &secret_size,

View File

@ -8,9 +8,9 @@
#include "log.h" #include "log.h"
#if HAVE_LIBFIDO2 #if HAVE_LIBFIDO2
int enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with, int cred_alg); int enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with);
#else #else
static inline int enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with, int cred_alg) { static inline int enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"FIDO2 key enrollment not supported."); "FIDO2 key enrollment not supported.");
} }

View File

@ -39,11 +39,6 @@ static size_t arg_n_wipe_slots = 0;
static WipeScope arg_wipe_slots_scope = WIPE_EXPLICIT; static WipeScope arg_wipe_slots_scope = WIPE_EXPLICIT;
static unsigned arg_wipe_slots_mask = 0; /* Bitmask of (1U << EnrollType), for wiping all slots of specific types */ static unsigned arg_wipe_slots_mask = 0; /* Bitmask of (1U << EnrollType), for wiping all slots of specific types */
static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP; static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP;
#if HAVE_LIBFIDO2
static int arg_fido2_cred_alg = COSE_ES256;
#else
static int arg_fido2_cred_alg = 0;
#endif
assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX); assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX);
@ -94,8 +89,6 @@ static int help(void) {
" --recovery-key Enroll a recovery key\n" " --recovery-key Enroll a recovery key\n"
" --pkcs11-token-uri=URI\n" " --pkcs11-token-uri=URI\n"
" Specify PKCS#11 security token URI\n" " Specify PKCS#11 security token URI\n"
" --fido2-credential-algorithm=STRING\n"
" Specify COSE algorithm for FIDO2 credential\n"
" --fido2-device=PATH\n" " --fido2-device=PATH\n"
" Enroll a FIDO2-HMAC security token\n" " Enroll a FIDO2-HMAC security token\n"
" --fido2-with-client-pin=BOOL\n" " --fido2-with-client-pin=BOOL\n"
@ -136,7 +129,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_FIDO2_WITH_PIN, ARG_FIDO2_WITH_PIN,
ARG_FIDO2_WITH_UP, ARG_FIDO2_WITH_UP,
ARG_FIDO2_WITH_UV, ARG_FIDO2_WITH_UV,
ARG_FIDO2_CRED_ALG,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -145,7 +137,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "password", no_argument, NULL, ARG_PASSWORD }, { "password", no_argument, NULL, ARG_PASSWORD },
{ "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY }, { "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY },
{ "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI }, { "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
{ "fido2-credential-algorithm", required_argument, NULL, ARG_FIDO2_CRED_ALG },
{ "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE }, { "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
{ "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN }, { "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-presence", required_argument, NULL, ARG_FIDO2_WITH_UP },
@ -249,12 +240,6 @@ static int parse_argv(int argc, char *argv[]) {
break; break;
} }
case ARG_FIDO2_CRED_ALG:
r = parse_fido2_algorithm(optarg, &arg_fido2_cred_alg);
if (r < 0)
return log_error_errno(r, "Failed to parse COSE algorithm: %s", optarg);
break;
case ARG_FIDO2_DEVICE: { case ARG_FIDO2_DEVICE: {
_cleanup_free_ char *device = NULL; _cleanup_free_ char *device = NULL;
@ -581,7 +566,7 @@ static int run(int argc, char *argv[]) {
break; break;
case ENROLL_FIDO2: case ENROLL_FIDO2:
slot = enroll_fido2(cd, vk, vks, arg_fido2_device, arg_fido2_lock_with, arg_fido2_cred_alg); slot = enroll_fido2(cd, vk, vks, arg_fido2_device, arg_fido2_lock_with);
break; break;
case ENROLL_TPM2: case ENROLL_TPM2:

View File

@ -118,8 +118,7 @@ static int add_fido2_salt(
int identity_add_fido2_parameters( int identity_add_fido2_parameters(
JsonVariant **v, JsonVariant **v,
const char *device, const char *device,
Fido2EnrollFlags lock_with, Fido2EnrollFlags lock_with) {
int cred_alg) {
#if HAVE_LIBFIDO2 #if HAVE_LIBFIDO2
JsonVariant *un, *realm, *rn; JsonVariant *un, *realm, *rn;
@ -166,7 +165,6 @@ int identity_add_fido2_parameters(
/* user_icon_name= */ NULL, /* user_icon_name= */ NULL,
/* askpw_icon_name= */ "user-home", /* askpw_icon_name= */ "user-home",
lock_with, lock_with,
cred_alg,
&cid, &cid_size, &cid, &cid_size,
&salt, &salt_size, &salt, &salt_size,
&secret, &secret_size, &secret, &secret_size,

View File

@ -4,4 +4,4 @@
#include "json.h" #include "json.h"
#include "libfido2-util.h" #include "libfido2-util.h"
int identity_add_fido2_parameters(JsonVariant **v, const char *device, Fido2EnrollFlags lock_with, int cred_alg); int identity_add_fido2_parameters(JsonVariant **v, const char *device, Fido2EnrollFlags lock_with);

View File

@ -61,11 +61,6 @@ static uint64_t arg_disk_size_relative = UINT64_MAX;
static char **arg_pkcs11_token_uri = NULL; static char **arg_pkcs11_token_uri = NULL;
static char **arg_fido2_device = NULL; static char **arg_fido2_device = NULL;
static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP; static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP;
#if HAVE_LIBFIDO2
static int arg_fido2_cred_alg = COSE_ES256;
#else
static int arg_fido2_cred_alg = 0;
#endif
static bool arg_recovery_key = false; static bool arg_recovery_key = false;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static bool arg_and_resize = false; static bool arg_and_resize = false;
@ -1119,7 +1114,7 @@ static int acquire_new_home_record(UserRecord **ret) {
} }
STRV_FOREACH(i, arg_fido2_device) { STRV_FOREACH(i, arg_fido2_device) {
r = identity_add_fido2_parameters(&v, *i, arg_fido2_lock_with, arg_fido2_cred_alg); r = identity_add_fido2_parameters(&v, *i, arg_fido2_lock_with);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -1478,7 +1473,7 @@ static int acquire_updated_home_record(
} }
STRV_FOREACH(i, arg_fido2_device) { STRV_FOREACH(i, arg_fido2_device) {
r = identity_add_fido2_parameters(&json, *i, arg_fido2_lock_with, arg_fido2_cred_alg); r = identity_add_fido2_parameters(&json, *i, arg_fido2_lock_with);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -2392,7 +2387,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_LUKS_EXTRA_MOUNT_OPTIONS, ARG_LUKS_EXTRA_MOUNT_OPTIONS,
ARG_AUTO_RESIZE_MODE, ARG_AUTO_RESIZE_MODE,
ARG_REBALANCE_WEIGHT, ARG_REBALANCE_WEIGHT,
ARG_FIDO2_CRED_ALG,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -2469,7 +2463,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "json", required_argument, NULL, ARG_JSON }, { "json", required_argument, NULL, ARG_JSON },
{ "export-format", required_argument, NULL, ARG_EXPORT_FORMAT }, { "export-format", required_argument, NULL, ARG_EXPORT_FORMAT },
{ "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI }, { "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
{ "fido2-credential-algorithm", required_argument, NULL, ARG_FIDO2_CRED_ALG },
{ "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE }, { "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
{ "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN }, { "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-presence", required_argument, NULL, ARG_FIDO2_WITH_UP },
@ -3492,12 +3485,6 @@ static int parse_argv(int argc, char *argv[]) {
strv_uniq(arg_pkcs11_token_uri); strv_uniq(arg_pkcs11_token_uri);
break; break;
case ARG_FIDO2_CRED_ALG:
r = parse_fido2_algorithm(optarg, &arg_fido2_cred_alg);
if (r < 0)
return log_error_errno(r, "Failed to parse COSE algorithm: %s", optarg);
break;
case ARG_FIDO2_DEVICE: case ARG_FIDO2_DEVICE:
if (streq(optarg, "list")) if (streq(optarg, "list"))
return fido2_list_devices(); return fido2_list_devices();

View File

@ -450,20 +450,6 @@ static int fido2_use_hmac_hash_specific_token(
return 0; return 0;
} }
/* COSE_ECDH_ES256 is not usable with fido_cred_set_type() thus it's not listed here. */
static const char *fido2_algorithm_to_string(int alg) {
switch(alg) {
case COSE_ES256:
return "es256";
case COSE_RS256:
return "rs256";
case COSE_EDDSA:
return "eddsa";
default:
return NULL;
}
}
int fido2_use_hmac_hash( int fido2_use_hmac_hash(
const char *device, const char *device,
const char *rp_id, const char *rp_id,
@ -546,7 +532,6 @@ int fido2_generate_hmac_hash(
const char *user_icon, const char *user_icon,
const char *askpw_icon_name, const char *askpw_icon_name,
Fido2EnrollFlags lock_with, Fido2EnrollFlags lock_with,
int cred_alg,
void **ret_cid, size_t *ret_cid_size, void **ret_cid, size_t *ret_cid_size,
void **ret_salt, size_t *ret_salt_size, void **ret_salt, size_t *ret_salt_size,
void **ret_secret, size_t *ret_secret_size, void **ret_secret, size_t *ret_secret_size,
@ -643,10 +628,10 @@ int fido2_generate_hmac_hash(
return log_error_errno(SYNTHETIC_ERRNO(EIO), return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to set FIDO2 credential relying party ID/name: %s", sym_fido_strerr(r)); "Failed to set FIDO2 credential relying party ID/name: %s", sym_fido_strerr(r));
r = sym_fido_cred_set_type(c, cred_alg); r = sym_fido_cred_set_type(c, COSE_ES256);
if (r != FIDO_OK) if (r != FIDO_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO), return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to set FIDO2 credential type to %s: %s", fido2_algorithm_to_string(cred_alg), sym_fido_strerr(r)); "Failed to set FIDO2 credential type to ES256: %s", sym_fido_strerr(r));
r = sym_fido_cred_set_user( r = sym_fido_cred_set_user(
c, c,
@ -736,9 +721,6 @@ int fido2_generate_hmac_hash(
if (r == FIDO_ERR_ACTION_TIMEOUT) if (r == FIDO_ERR_ACTION_TIMEOUT)
return log_error_errno(SYNTHETIC_ERRNO(ENOSTR), return log_error_errno(SYNTHETIC_ERRNO(ENOSTR),
"Token action timeout. (User didn't interact with token quickly enough.)"); "Token action timeout. (User didn't interact with token quickly enough.)");
if (r == FIDO_ERR_UNSUPPORTED_ALGORITHM)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Token doesn't support credential algorithm %s.", fido2_algorithm_to_string(cred_alg));
if (r != FIDO_OK) if (r != FIDO_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO), return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to generate FIDO2 credential: %s", sym_fido_strerr(r)); "Failed to generate FIDO2 credential: %s", sym_fido_strerr(r));
@ -1142,24 +1124,3 @@ finish:
"FIDO2 tokens not supported on this build."); "FIDO2 tokens not supported on this build.");
#endif #endif
} }
#if HAVE_LIBFIDO2
int parse_fido2_algorithm(const char *s, int *ret) {
int a;
assert(s);
if (streq(s, "es256"))
a = COSE_ES256;
else if (streq(s, "rs256"))
a = COSE_RS256;
else if (streq(s, "eddsa"))
a = COSE_EDDSA;
else
return -EINVAL;
if (ret)
*ret = a;
return 0;
}
#endif

View File

@ -109,18 +109,12 @@ int fido2_generate_hmac_hash(
const char *user_icon, const char *user_icon,
const char *askpw_icon_name, const char *askpw_icon_name,
Fido2EnrollFlags lock_with, Fido2EnrollFlags lock_with,
int cred_alg,
void **ret_cid, size_t *ret_cid_size, void **ret_cid, size_t *ret_cid_size,
void **ret_salt, size_t *ret_salt_size, void **ret_salt, size_t *ret_salt_size,
void **ret_secret, size_t *ret_secret_size, void **ret_secret, size_t *ret_secret_size,
char **ret_usedpin, char **ret_usedpin,
Fido2EnrollFlags *ret_locked_with); Fido2EnrollFlags *ret_locked_with);
int parse_fido2_algorithm(const char *s, int *ret);
#else
static inline int parse_fido2_algorithm(const char *s, int *ret) {
return -EOPNOTSUPP;
}
#endif #endif
int fido2_list_devices(void); int fido2_list_devices(void);

View File

@ -3,7 +3,6 @@
set -e set -e
TEST_DESCRIPTION="test credentials" TEST_DESCRIPTION="test credentials"
NSPAWN_ARGUMENTS="--set-credential=mynspawncredential:strangevalue"
# shellcheck source=test/test-functions # shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions" . "${TEST_BASE_DIR:?}/test-functions"

View File

@ -16,26 +16,6 @@ systemd-run -p LoadCredential=passwd:/etc/passwd \
( cat /etc/passwd /etc/shadow && echo -n wuff ) | cmp /tmp/ts54-concat ( cat /etc/passwd /etc/shadow && echo -n wuff ) | cmp /tmp/ts54-concat
rm /tmp/ts54-concat rm /tmp/ts54-concat
# Test that SetCredential= acts as fallback for LoadCredential=
echo piff > /tmp/ts54-fallback
[ "$(systemd-run -p LoadCredential=paff:/tmp/ts54-fallback -p SetCredential=paff:poff --pipe --wait systemd-creds cat paff)" = "piff" ]
rm /tmp/ts54-fallback
[ "$(systemd-run -p LoadCredential=paff:/tmp/ts54-fallback -p SetCredential=paff:poff --pipe --wait systemd-creds cat paff)" = "poff" ]
if systemd-detect-virt -q -c ; then
# If this test is run in nspawn a credential should have been passed to us. See test/TEST-54-CREDS/test.sh
[ "$(systemd-creds --system cat mynspawncredential)" = "strangevalue" ]
# Test that propagation from system credential to service credential works
[ "$(systemd-run -p LoadCredential=mynspawncredential --pipe --wait systemd-creds cat mynspawncredential)" = "strangevalue" ]
# Check it also works, if we rename it while propagating it
[ "$(systemd-run -p LoadCredential=miau:mynspawncredential --pipe --wait systemd-creds cat miau)" = "strangevalue" ]
# Combine it with a fallback (which should have no effect, given the cred should be passed down)
[ "$(systemd-run -p LoadCredential=mynspawncredential -p SetCredential=mynspawncredential:zzz --pipe --wait systemd-creds cat mynspawncredential)" = "strangevalue" ]
fi
# Verify that the creds are immutable # Verify that the creds are immutable
systemd-run -p LoadCredential=passwd:/etc/passwd \ systemd-run -p LoadCredential=passwd:/etc/passwd \
-p DynamicUser=1 \ -p DynamicUser=1 \