mirror of
https://github.com/systemd/systemd
synced 2025-11-21 09:44:44 +01:00
Compare commits
No commits in common. "1353564b9d7bd11888b7ca068ffce771ce6d8e7e" and "dfb46b906ecd8391c00354f8ef97133ef0eade22" have entirely different histories.
1353564b9d
...
dfb46b906e
13
TODO
13
TODO
@ -128,19 +128,6 @@ Deprecations and removals:
|
||||
|
||||
Features:
|
||||
|
||||
* systemd-repart: add --ghost, that creates file systems, updates the kernel's
|
||||
partition table but does *not* update partition table on disk. This way, we
|
||||
have disk backed file systems that go effectively disappear on reboot. This
|
||||
is useful when booting from a "live" usb stick that is writable, as it means
|
||||
we do not have to place everything in memory. Moreover, we could then migrate
|
||||
the file systems to disk later (using btrfs device replacement), if needed as
|
||||
part of an installer logic.
|
||||
|
||||
* add a concept of overlay directory stacks to image discovery, i.e. have a dir
|
||||
with a name suffix of ".ovl" or so that contains DDIs and plain dirs (and
|
||||
possible .v dirs) that are glued together on use via overlayfs. one special
|
||||
subdir should be used as writable top layer.
|
||||
|
||||
* journald: log pidfid as another field, i.e. _PIDFDID=
|
||||
|
||||
* systemd-nspawn: something like --volatile= but that isn't volatile, but
|
||||
|
||||
@ -175,7 +175,6 @@ method GetUserRecord(
|
||||
dispositionMask: ?[]string,
|
||||
uidMin: ?int,
|
||||
uidMax: ?int,
|
||||
uuid: ?string,
|
||||
service : string
|
||||
) -> (
|
||||
record : object,
|
||||
@ -189,7 +188,6 @@ method GetGroupRecord(
|
||||
dispositionMask: ?[]string,
|
||||
gidMin: ?int,
|
||||
gidMax: ?int,
|
||||
uuid: ?string,
|
||||
service : string
|
||||
) -> (
|
||||
record : object,
|
||||
@ -224,7 +222,7 @@ If neither of the two parameters are set the whole user database is enumerated.
|
||||
In this case the method call needs to be made with `more` set, so that multiple method call replies may be generated as
|
||||
effect, each carrying one user record.
|
||||
|
||||
The `fuzzyNames`, `dispositionMask`, `uidMin`, `uidMax` and `uuid` fields permit
|
||||
The `fuzzyNames`, `dispositionMask`, `uidMin`, `uidMax` fields permit
|
||||
*additional* filtering of the returned set of user records. The `fuzzyNames`
|
||||
parameter shall be one or more strings that shall be searched for in "fuzzy"
|
||||
way. What specifically this means is left for the backend to decide, but
|
||||
@ -234,20 +232,19 @@ carry identifying information for the user. The `dispositionMask` field shall
|
||||
be one of more user record `disposition` strings. If specified only user
|
||||
records matching one of the specified dispositions should be enumerated. The
|
||||
`uidMin` and `uidMax` fields specify a minimum and maximum value for the UID of
|
||||
returned records. The `uuid` field specifies to search for the user record associated
|
||||
with the specified UUID. Inline searching for `uid` and `userName` support for
|
||||
returned records. Inline searching for `uid` and `userName` support for
|
||||
filtering with these four additional parameters is optional, and clients are
|
||||
expected to be able to do client-side filtering in case the parameters are not
|
||||
supported by a service. The service should return the usual `InvalidParameter`
|
||||
error for the relevant parameter if one is passed and it does not support
|
||||
it. If a request is made specifying `uid` or `userName` and a suitable record
|
||||
is found, but the specified filter via `fuzzyNames`, `dispositionMask`,
|
||||
`uidMin`, `uidMax` or `uuid` does not match, a `NonMatchingRecordFound` error should
|
||||
`uidMin`, or `uidMax` does not match, a `NonMatchingRecordFound` error should
|
||||
be returned.
|
||||
|
||||
Or to say this differently: the *primary search keys* are
|
||||
`userName`/`groupName` and `uid`/`gid` and the *secondary search filters* are
|
||||
`fuzzyNames`, `dispositionMask`, `uidMin`, `uidMax`, `uuid`. If no entry matching
|
||||
`fuzzyNames`, `dispositionMask`, `uidMin`, `uidMax`. If no entry matching
|
||||
either of the primary search keys are found `NoRecordFound()` is returned. If
|
||||
one is found that matches one but not the other primary search key
|
||||
`ConflictingRecordFound()` is returned. If an entry is found that matches the
|
||||
|
||||
@ -424,19 +424,11 @@
|
||||
<varlistentry>
|
||||
<term><option>--allow-null</option></term>
|
||||
|
||||
<listitem><para>Allow decrypting credentials that use a null key. By default decryption of credentials encrypted/authenticated with a null key is only allowed if UEFI SecureBoot is off.</para>
|
||||
<listitem><para>Allow decrypting credentials that use an empty key.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--refuse-null</option></term>
|
||||
|
||||
<listitem><para>Refuse decrypting credentials that use a null key, regardless of the UEFI SecureBoot state (see above).</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--quiet</option></term>
|
||||
<term><option>-q</option></term>
|
||||
|
||||
@ -227,15 +227,6 @@
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--uuid=</option></term>
|
||||
|
||||
<listitem><para>When used with the <command>user</command> or <command>group</command> command,
|
||||
filters the output to the record with the specified UUID. If unspecified, no UUID-based filtering is applied.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--boundaries=</option></term>
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ static bool arg_pretty = false;
|
||||
static bool arg_quiet = false;
|
||||
static bool arg_varlink = false;
|
||||
static uid_t arg_uid = UID_INVALID;
|
||||
static CredentialFlags arg_credential_flags = 0;
|
||||
static bool arg_allow_null = false;
|
||||
static bool arg_ask_password = true;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
|
||||
@ -99,7 +99,7 @@ typedef enum CredKeyType {
|
||||
CRED_KEY_TYPE_HOST_TPM2_PUBLIC,
|
||||
CRED_KEY_TYPE_TPM2_PUBLIC_HOST,
|
||||
CRED_KEY_TYPE_NULL,
|
||||
CRED_KEY_TYPE_TPM2_ABSENT,
|
||||
CRED_KEY_TYPE_ABSENT,
|
||||
_CRED_KEY_TYPE_MAX,
|
||||
_CRED_KEY_TYPE_INVALID = -EINVAL,
|
||||
} CredKeyType;
|
||||
@ -115,7 +115,7 @@ static const char* cred_key_type_table[_CRED_KEY_TYPE_MAX] = {
|
||||
[CRED_KEY_TYPE_HOST_TPM2_PUBLIC] = "host+tpm2-with-public-key",
|
||||
[CRED_KEY_TYPE_TPM2_PUBLIC_HOST] = "tpm2-with-public-key+host",
|
||||
[CRED_KEY_TYPE_NULL] = "null",
|
||||
[CRED_KEY_TYPE_TPM2_ABSENT] = "tpm2-absent", /* legacy alias */
|
||||
[CRED_KEY_TYPE_ABSENT] = "tpm2-absent",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(cred_key_type, CredKeyType);
|
||||
@ -131,7 +131,7 @@ static sd_id128_t cred_key_id[_CRED_KEY_TYPE_MAX] = {
|
||||
[CRED_KEY_TYPE_HOST_TPM2_PUBLIC] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK,
|
||||
[CRED_KEY_TYPE_TPM2_PUBLIC_HOST] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK,
|
||||
[CRED_KEY_TYPE_NULL] = CRED_AES256_GCM_BY_NULL,
|
||||
[CRED_KEY_TYPE_TPM2_ABSENT] = CRED_AES256_GCM_BY_NULL,
|
||||
[CRED_KEY_TYPE_ABSENT] = CRED_AES256_GCM_BY_NULL,
|
||||
};
|
||||
|
||||
static int open_credential_directory(
|
||||
@ -526,7 +526,7 @@ static int verb_cat(int argc, char **argv, void *userdata) {
|
||||
timestamp,
|
||||
uid_is_valid(arg_uid) ? arg_uid : getuid(),
|
||||
&IOVEC_MAKE(data, size),
|
||||
arg_credential_flags | CREDENTIAL_ANY_SCOPE,
|
||||
CREDENTIAL_ANY_SCOPE,
|
||||
&plaintext);
|
||||
else
|
||||
r = decrypt_credential_and_warn(
|
||||
@ -536,7 +536,7 @@ static int verb_cat(int argc, char **argv, void *userdata) {
|
||||
arg_tpm2_signature,
|
||||
uid_is_valid(arg_uid) ? arg_uid : getuid(),
|
||||
&IOVEC_MAKE(data, size),
|
||||
arg_credential_flags | CREDENTIAL_ANY_SCOPE,
|
||||
CREDENTIAL_ANY_SCOPE,
|
||||
&plaintext);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -608,7 +608,7 @@ static int verb_encrypt(int argc, char **argv, void *userdata) {
|
||||
arg_not_after,
|
||||
arg_uid,
|
||||
&plaintext,
|
||||
arg_credential_flags,
|
||||
arg_ask_password ? CREDENTIAL_IPC_ALLOW_INTERACTIVE : 0,
|
||||
&output);
|
||||
} else
|
||||
r = encrypt_credential_and_warn(
|
||||
@ -622,7 +622,7 @@ static int verb_encrypt(int argc, char **argv, void *userdata) {
|
||||
arg_tpm2_public_key_pcr_mask,
|
||||
arg_uid,
|
||||
&plaintext,
|
||||
arg_credential_flags,
|
||||
/* flags= */ 0,
|
||||
&output);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -713,7 +713,7 @@ static int verb_decrypt(int argc, char **argv, void *userdata) {
|
||||
timestamp,
|
||||
arg_uid,
|
||||
&input,
|
||||
arg_credential_flags,
|
||||
arg_ask_password ? CREDENTIAL_IPC_ALLOW_INTERACTIVE : 0,
|
||||
&plaintext);
|
||||
} else
|
||||
r = decrypt_credential_and_warn(
|
||||
@ -723,7 +723,7 @@ static int verb_decrypt(int argc, char **argv, void *userdata) {
|
||||
arg_tpm2_signature,
|
||||
arg_uid,
|
||||
&input,
|
||||
arg_credential_flags,
|
||||
arg_allow_null ? CREDENTIAL_ALLOW_NULL : 0,
|
||||
&plaintext);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -815,8 +815,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
|
||||
" Specify signature for public key PCR policy\n"
|
||||
" --user Select user-scoped credential encryption\n"
|
||||
" --uid=UID Select user for scoped credentials\n"
|
||||
" --allow-null Allow decrypting credentials with null key\n"
|
||||
" --refuse-null Refuse decrypting credentials with null key\n"
|
||||
" --allow-null Allow decrypting credentials with empty key\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
@ -850,7 +849,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_USER,
|
||||
ARG_UID,
|
||||
ARG_ALLOW_NULL,
|
||||
ARG_REFUSE_NULL,
|
||||
ARG_NO_ASK_PASSWORD,
|
||||
};
|
||||
|
||||
@ -877,7 +875,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "uid", required_argument, NULL, ARG_UID },
|
||||
{ "allow-null", no_argument, NULL, ARG_ALLOW_NULL },
|
||||
{ "refuse-null", no_argument, NULL, ARG_REFUSE_NULL },
|
||||
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
|
||||
{}
|
||||
};
|
||||
@ -1071,13 +1068,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_ALLOW_NULL:
|
||||
arg_credential_flags &= ~CREDENTIAL_REFUSE_NULL;
|
||||
arg_credential_flags |= CREDENTIAL_ALLOW_NULL;
|
||||
break;
|
||||
|
||||
case ARG_REFUSE_NULL:
|
||||
arg_credential_flags |= CREDENTIAL_REFUSE_NULL;
|
||||
arg_credential_flags &= ~CREDENTIAL_ALLOW_NULL;
|
||||
arg_allow_null = true;
|
||||
break;
|
||||
|
||||
case ARG_NO_ASK_PASSWORD:
|
||||
@ -1096,8 +1087,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
SET_FLAG(arg_credential_flags, CREDENTIAL_IPC_ALLOW_INTERACTIVE, arg_ask_password);
|
||||
|
||||
if (uid_is_valid(arg_uid)) {
|
||||
/* If a UID is specified, then switch to scoped credentials */
|
||||
|
||||
@ -1178,7 +1167,6 @@ typedef struct MethodEncryptParameters {
|
||||
uint64_t timestamp;
|
||||
uint64_t not_after;
|
||||
CredentialScope scope;
|
||||
sd_id128_t with_key;
|
||||
uid_t uid;
|
||||
} MethodEncryptParameters;
|
||||
|
||||
@ -1232,71 +1220,6 @@ static int settle_scope(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool normalize_separator(char c) {
|
||||
if (IN_SET(c, '-', '+', '_'))
|
||||
return '_';
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static bool enum_name_equal(const char *x, const char *y) {
|
||||
if (x == y)
|
||||
return true;
|
||||
if (!x || !y)
|
||||
return false;
|
||||
|
||||
for (;; x++, y++) {
|
||||
char a = normalize_separator(*x), b = normalize_separator(*y);
|
||||
if (a != b)
|
||||
return false;
|
||||
if (a == 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static CredKeyType cred_key_type_from_string_harder(const char *s) {
|
||||
if (!s)
|
||||
return _CRED_KEY_TYPE_INVALID;
|
||||
|
||||
CredKeyType t = cred_key_type_from_string(s);
|
||||
if (t >= 0)
|
||||
return t;
|
||||
|
||||
/* Varlink doesn't like dashes and plusses in enum names. Try to match when considering them equal to underscores */
|
||||
for (t = 0; t < _CRED_KEY_TYPE_MAX; t++)
|
||||
if (enum_name_equal(cred_key_type_table[t], s))
|
||||
return t;
|
||||
|
||||
return _CRED_KEY_TYPE_INVALID;
|
||||
}
|
||||
|
||||
static int dispatch_credential_key_type(
|
||||
const char *name,
|
||||
sd_json_variant *variant,
|
||||
sd_json_dispatch_flags_t flags,
|
||||
void *userdata) {
|
||||
|
||||
sd_id128_t *id = ASSERT_PTR(userdata);
|
||||
|
||||
if (sd_json_variant_is_null(variant)) {
|
||||
*id = SD_ID128_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *s = sd_json_variant_string(variant);
|
||||
if (isempty(s)) {
|
||||
*id = SD_ID128_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CredKeyType t = cred_key_type_from_string_harder(s);
|
||||
if (t < 0)
|
||||
return json_log(variant, flags, t, "JSON field '%s' is not a valid key type.", strna(name));
|
||||
|
||||
*id = cred_key_id[t];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vl_method_encrypt(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
@ -1306,7 +1229,6 @@ static int vl_method_encrypt(sd_varlink *link, sd_json_variant *parameters, sd_v
|
||||
{ "timestamp", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodEncryptParameters, timestamp), 0 },
|
||||
{ "notAfter", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodEncryptParameters, not_after), 0 },
|
||||
{ "scope", SD_JSON_VARIANT_STRING, dispatch_credential_scope, offsetof(MethodEncryptParameters, scope), 0 },
|
||||
{ "withKey", SD_JSON_VARIANT_STRING, dispatch_credential_key_type, offsetof(MethodEncryptParameters, with_key), SD_JSON_NULLABLE },
|
||||
{ "uid", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(MethodEncryptParameters, uid), 0 },
|
||||
VARLINK_DISPATCH_POLKIT_FIELD,
|
||||
{}
|
||||
@ -1367,7 +1289,7 @@ static int vl_method_encrypt(sd_varlink *link, sd_json_variant *parameters, sd_v
|
||||
}
|
||||
|
||||
r = encrypt_credential_and_warn(
|
||||
sd_id128_is_null(p.with_key) ? (p.scope == CREDENTIAL_USER ? _CRED_AUTO_SCOPED : _CRED_AUTO) : p.with_key,
|
||||
p.scope == CREDENTIAL_USER ? _CRED_AUTO_SCOPED : _CRED_AUTO,
|
||||
p.name,
|
||||
p.timestamp,
|
||||
p.not_after,
|
||||
@ -1402,7 +1324,6 @@ typedef struct MethodDecryptParameters {
|
||||
uint64_t timestamp;
|
||||
CredentialScope scope;
|
||||
uid_t uid;
|
||||
int allow_null;
|
||||
} MethodDecryptParameters;
|
||||
|
||||
static void method_decrypt_parameters_done(MethodDecryptParameters *p) {
|
||||
@ -1414,12 +1335,11 @@ static void method_decrypt_parameters_done(MethodDecryptParameters *p) {
|
||||
static int vl_method_decrypt(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodDecryptParameters, name), 0 },
|
||||
{ "blob", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodDecryptParameters, blob), SD_JSON_MANDATORY },
|
||||
{ "timestamp", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodDecryptParameters, timestamp), 0 },
|
||||
{ "scope", SD_JSON_VARIANT_STRING, dispatch_credential_scope, offsetof(MethodDecryptParameters, scope), 0 },
|
||||
{ "uid", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(MethodDecryptParameters, uid), 0 },
|
||||
{ "allowNull", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(MethodDecryptParameters, allow_null), SD_JSON_NULLABLE },
|
||||
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodDecryptParameters, name), 0 },
|
||||
{ "blob", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodDecryptParameters, blob), SD_JSON_MANDATORY },
|
||||
{ "timestamp", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodDecryptParameters, timestamp), 0 },
|
||||
{ "scope", SD_JSON_VARIANT_STRING, dispatch_credential_scope, offsetof(MethodDecryptParameters, scope), 0 },
|
||||
{ "uid", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(MethodDecryptParameters, uid), 0 },
|
||||
VARLINK_DISPATCH_POLKIT_FIELD,
|
||||
{}
|
||||
};
|
||||
@ -1427,7 +1347,6 @@ static int vl_method_decrypt(sd_varlink *link, sd_json_variant *parameters, sd_v
|
||||
.timestamp = UINT64_MAX,
|
||||
.scope = _CREDENTIAL_SCOPE_INVALID,
|
||||
.uid = UID_INVALID,
|
||||
.allow_null = -1,
|
||||
};
|
||||
bool timestamp_fresh, any_scope_after_polkit = false;
|
||||
_cleanup_(iovec_done_erase) struct iovec output = {};
|
||||
@ -1454,11 +1373,6 @@ static int vl_method_decrypt(sd_varlink *link, sd_json_variant *parameters, sd_v
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (p.allow_null > 0)
|
||||
cflags |= CREDENTIAL_ALLOW_NULL;
|
||||
else if (p.allow_null == 0)
|
||||
cflags |= CREDENTIAL_REFUSE_NULL;
|
||||
|
||||
r = sd_varlink_get_peer_uid(link, &peer_uid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -222,9 +222,9 @@ static int context_open_root(Context *c) {
|
||||
if (r > 0)
|
||||
return 0;
|
||||
|
||||
c->rfd = open(arg_root, O_CLOEXEC | O_DIRECTORY | O_PATH);
|
||||
c->rfd = open(empty_to_root(arg_root), O_CLOEXEC | O_DIRECTORY | O_PATH);
|
||||
if (c->rfd < 0)
|
||||
return log_error_errno(errno, "Failed to open root directory '%s': %m", arg_root);
|
||||
return log_error_errno(errno, "Failed to open root directory '%s': %m", empty_to_root(arg_root));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -554,8 +554,8 @@ int json_dispatch_devnum(const char *name, sd_json_variant *variant, sd_json_dis
|
||||
}
|
||||
|
||||
int json_dispatch_strv_environment(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
|
||||
char ***l = ASSERT_PTR(userdata);
|
||||
_cleanup_strv_free_ char **n = NULL;
|
||||
char ***l = userdata;
|
||||
int r;
|
||||
|
||||
if (sd_json_variant_is_null(variant)) {
|
||||
@ -566,19 +566,20 @@ int json_dispatch_strv_environment(const char *name, sd_json_variant *variant, s
|
||||
if (!sd_json_variant_is_array(variant))
|
||||
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array.", strna(name));
|
||||
|
||||
sd_json_variant *i;
|
||||
JSON_VARIANT_ARRAY_FOREACH(i, variant) {
|
||||
const char *e;
|
||||
for (size_t i = 0; i < sd_json_variant_elements(variant); i++) {
|
||||
sd_json_variant *e;
|
||||
const char *a;
|
||||
|
||||
if (!sd_json_variant_is_string(i))
|
||||
e = sd_json_variant_by_index(variant, i);
|
||||
if (!sd_json_variant_is_string(e))
|
||||
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array of strings.", strna(name));
|
||||
|
||||
e = ASSERT_PTR(sd_json_variant_string(i));
|
||||
if (!env_assignment_is_valid(e))
|
||||
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL),
|
||||
"JSON field '%s' contains invalid environment variable assignment.", strna(name));
|
||||
assert_se(a = sd_json_variant_string(e));
|
||||
|
||||
r = strv_env_replace_strdup(&n, e);
|
||||
if (!env_assignment_is_valid(a))
|
||||
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array of environment variables.", strna(name));
|
||||
|
||||
r = strv_env_replace_strdup(&n, a);
|
||||
if (r < 0)
|
||||
return json_log_oom(variant, flags);
|
||||
}
|
||||
|
||||
@ -812,9 +812,6 @@ int encrypt_credential_and_warn(
|
||||
assert(iovec_is_valid(input));
|
||||
assert(ret);
|
||||
|
||||
/* Only one of these two flags may be set at the same time */
|
||||
assert(!FLAGS_SET(flags, CREDENTIAL_ALLOW_NULL) || !FLAGS_SET(flags, CREDENTIAL_REFUSE_NULL));
|
||||
|
||||
if (!sd_id128_in_set(with_key,
|
||||
_CRED_AUTO,
|
||||
_CRED_AUTO_INITRD,
|
||||
@ -1011,12 +1008,8 @@ int encrypt_credential_and_warn(
|
||||
} else
|
||||
id = with_key;
|
||||
|
||||
if (sd_id128_equal(id, CRED_AES256_GCM_BY_NULL)) {
|
||||
if (FLAGS_SET(flags, CREDENTIAL_REFUSE_NULL))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Attempted to encrypt with null key, but this is disallowed.");
|
||||
if (!FLAGS_SET(flags, CREDENTIAL_ALLOW_NULL))
|
||||
log_warning("Using a null key for encryption and signing. Confidentiality or authenticity will not be provided.");
|
||||
}
|
||||
if (sd_id128_equal(id, CRED_AES256_GCM_BY_NULL) && !FLAGS_SET(flags, CREDENTIAL_ALLOW_NULL))
|
||||
log_warning("Using a null key for encryption and signing. Confidentiality or authenticity will not be provided.");
|
||||
|
||||
/* Let's now take the host key and the TPM2 key and hash it together, to use as encryption key for the data */
|
||||
r = sha256_hash_host_and_tpm2_key(&host_key, &tpm2_key, md);
|
||||
@ -1208,15 +1201,12 @@ int decrypt_credential_and_warn(
|
||||
assert(iovec_is_valid(input));
|
||||
assert(ret);
|
||||
|
||||
/* Only one of these two flags may be set at the same time */
|
||||
assert(!FLAGS_SET(flags, CREDENTIAL_ALLOW_NULL) || !FLAGS_SET(flags, CREDENTIAL_REFUSE_NULL));
|
||||
|
||||
/* Relevant error codes:
|
||||
*
|
||||
* -EBADMSG → Corrupted file
|
||||
* -EOPNOTSUPP → Unsupported file type (could be: requires TPM but we have no TPM)
|
||||
* -EHOSTDOWN → Need PCR signature file, but couldn't find it
|
||||
* -EHWPOISON → Attempt to unlock with NULL key and either CREDENTIAL_ALLOW_REFUSE is on, or CREDENTIAL_ALLOW_NULL is off, but the system has a TPM and SecureBoot is on
|
||||
* -EHWPOISON → Attempt to decode NULL key (and CREDENTIAL_ALLOW_NULL is off), but the system has a TPM and SecureBoot is on
|
||||
* -EMEDIUMTYPE → File has unexpected scope, i.e. user-scoped credential is attempted to be unlocked in system scope, or vice versa
|
||||
* -EDESTADDRREQ → Credential is incorrectly named (i.e. the authenticated name does not match the actual name)
|
||||
* -ESTALE → Credential's validity has passed
|
||||
@ -1247,30 +1237,24 @@ int decrypt_credential_and_warn(
|
||||
return log_error_errno(r, "Failed to load PCR signature: %m");
|
||||
}
|
||||
|
||||
if (with_null) {
|
||||
if (FLAGS_SET(flags, CREDENTIAL_REFUSE_NULL))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON),
|
||||
"Credential uses null key, but that's not allowed, refusing.");
|
||||
if (with_null && !FLAGS_SET(flags, CREDENTIAL_ALLOW_NULL)) {
|
||||
/* So this is a credential encrypted with a zero length key. We support this to cover for the
|
||||
* case where neither a host key not a TPM2 are available (specifically: initrd environments
|
||||
* where the host key is not yet accessible and no TPM2 chip exists at all), to minimize
|
||||
* different codeflow for TPM2 and non-TPM2 codepaths. Of course, credentials encoded this
|
||||
* way offer no confidentiality nor authenticity. Because of that it's important we refuse to
|
||||
* use them on systems that actually *do* have a TPM2 chip – if we are in SecureBoot
|
||||
* mode. Otherwise an attacker could hand us credentials like this and we'd use them thinking
|
||||
* they are trusted, even though they are not. */
|
||||
|
||||
if (!FLAGS_SET(flags, CREDENTIAL_ALLOW_NULL)) {
|
||||
/* So this is a credential encrypted with a zero length key. We support this to cover for the
|
||||
* case where neither a host key not a TPM2 are available (specifically: initrd environments
|
||||
* where the host key is not yet accessible and no TPM2 chip exists at all), to minimize
|
||||
* different codeflow for TPM2 and non-TPM2 codepaths. Of course, credentials encoded this
|
||||
* way offer no confidentiality nor authenticity. Because of that it's important we refuse to
|
||||
* use them on systems that actually *do* have a TPM2 chip – if we are in SecureBoot
|
||||
* mode. Otherwise an attacker could hand us credentials like this and we'd use them thinking
|
||||
* they are trusted, even though they are not. */
|
||||
if (efi_has_tpm2()) {
|
||||
if (is_efi_secure_boot())
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON),
|
||||
"Credential uses fixed key for fallback use when TPM2 is absent — but TPM2 is present, and SecureBoot is enabled, refusing.");
|
||||
|
||||
if (efi_has_tpm2()) {
|
||||
if (is_efi_secure_boot())
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON),
|
||||
"Credential uses null key intended for fallback use when TPM2 is absent — but TPM2 is present, and SecureBoot is enabled, refusing.");
|
||||
|
||||
log_warning("Credential uses null key intended for use when TPM2 is absent, but TPM2 is present! Accepting anyway, since SecureBoot is disabled.");
|
||||
} else
|
||||
log_debug("Credential uses null key intended for use when TPM2 is absent, and TPM2 indeed is absent. Accepting.");
|
||||
}
|
||||
log_warning("Credential uses fixed key for use when TPM2 is absent, but TPM2 is present! Accepting anyway, since SecureBoot is disabled.");
|
||||
} else
|
||||
log_debug("Credential uses fixed key for use when TPM2 is absent, and TPM2 indeed is absent. Accepting.");
|
||||
}
|
||||
|
||||
if (with_scope) {
|
||||
@ -1606,7 +1590,6 @@ int ipc_encrypt_credential(const char *name, usec_t timestamp, usec_t not_after,
|
||||
SD_JSON_BUILD_PAIR_CONDITION(not_after != USEC_INFINITY, "notAfter", SD_JSON_BUILD_UNSIGNED(not_after)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!FLAGS_SET(flags, CREDENTIAL_ANY_SCOPE), "scope", SD_JSON_BUILD_STRING(uid_is_valid(uid) ? "user" : "system")),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(uid_is_valid(uid), "uid", SD_JSON_BUILD_UNSIGNED(uid)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION((flags & (CREDENTIAL_ALLOW_NULL|CREDENTIAL_REFUSE_NULL)) != 0, "allowNull", SD_JSON_BUILD_BOOLEAN(flags & CREDENTIAL_ALLOW_NULL)),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("allowInteractiveAuthentication", FLAGS_SET(flags, CREDENTIAL_IPC_ALLOW_INTERACTIVE)));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to call Encrypt() varlink call.");
|
||||
|
||||
@ -54,12 +54,11 @@ int get_credential_host_secret(CredentialSecretFlags flags, struct iovec *ret);
|
||||
int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed);
|
||||
|
||||
typedef enum CredentialFlags {
|
||||
CREDENTIAL_ALLOW_NULL = 1 << 0, /* allow decryption with NULL key, even if TPM is around */
|
||||
CREDENTIAL_REFUSE_NULL = 1 << 1, /* deny decryption with NULL key, even if SecureBoot is off */
|
||||
CREDENTIAL_ANY_SCOPE = 1 << 2, /* allow decryption of both system and user credentials */
|
||||
CREDENTIAL_ALLOW_NULL = 1 << 0, /* allow decryption of NULL key, even if TPM is around */
|
||||
CREDENTIAL_ANY_SCOPE = 1 << 1, /* allow decryption of both system and user credentials */
|
||||
|
||||
/* Only used by ipc_{encrypt,decrypt}_credential */
|
||||
CREDENTIAL_IPC_ALLOW_INTERACTIVE = 1 << 3,
|
||||
CREDENTIAL_IPC_ALLOW_INTERACTIVE = 1 << 2,
|
||||
} CredentialFlags;
|
||||
|
||||
/* The four modes we support: keyed only by on-disk key, only by TPM2 HMAC key, and by the combination of
|
||||
|
||||
@ -2777,8 +2777,7 @@ bool userdb_match_is_set(const UserDBMatch *match) {
|
||||
return !strv_isempty(match->fuzzy_names) ||
|
||||
!FLAGS_SET(match->disposition_mask, USER_DISPOSITION_MASK_ALL) ||
|
||||
match->uid_min > 0 ||
|
||||
match->uid_max < UID_INVALID-1 ||
|
||||
!sd_id128_is_null(match->uuid);
|
||||
match->uid_max < UID_INVALID-1;
|
||||
}
|
||||
|
||||
void userdb_match_done(UserDBMatch *match) {
|
||||
@ -2837,9 +2836,6 @@ bool user_record_match(UserRecord *u, const UserDBMatch *match) {
|
||||
if (!BIT_SET(match->disposition_mask, user_record_disposition(u)))
|
||||
return false;
|
||||
|
||||
if (!sd_id128_is_null(match->uuid) && !sd_id128_equal(match->uuid, u->uuid))
|
||||
return false;
|
||||
|
||||
if (!strv_isempty(match->fuzzy_names)) {
|
||||
|
||||
/* Note this array of names is sparse, i.e. various entries listed in it will be
|
||||
|
||||
@ -513,7 +513,6 @@ typedef struct UserDBMatch {
|
||||
uid_t uid_max;
|
||||
gid_t gid_max;
|
||||
};
|
||||
sd_id128_t uuid;
|
||||
} UserDBMatch;
|
||||
|
||||
#define USER_DISPOSITION_MASK_ALL ((UINT64_C(1) << _USER_DISPOSITION_MAX) - UINT64_C(1))
|
||||
@ -523,7 +522,6 @@ typedef struct UserDBMatch {
|
||||
.disposition_mask = USER_DISPOSITION_MASK_ALL, \
|
||||
.uid_min = 0, \
|
||||
.uid_max = UID_INVALID-1, \
|
||||
.uuid = SD_ID128_NULL, \
|
||||
}
|
||||
|
||||
/* Maybe useful when we want to resolve root and system user/group but want to refuse nobody user/group. */
|
||||
|
||||
@ -799,29 +799,27 @@ nomatch:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int query_append_common(sd_json_variant **query, const UserDBMatch *match) {
|
||||
static int query_append_disposition_mask(sd_json_variant **query, uint64_t mask) {
|
||||
int r;
|
||||
_cleanup_strv_free_ char **dispositions = NULL;
|
||||
|
||||
assert(query);
|
||||
|
||||
uint64_t mask = match->disposition_mask;
|
||||
if (FLAGS_SET(mask, USER_DISPOSITION_MASK_ALL)) {
|
||||
for (UserDisposition d = 0; d < _USER_DISPOSITION_MAX; d++) {
|
||||
if (!BIT_SET(mask, d))
|
||||
continue;
|
||||
if (FLAGS_SET(mask, USER_DISPOSITION_MASK_ALL))
|
||||
return 0;
|
||||
|
||||
r = strv_extend(&dispositions, user_disposition_to_string(d));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
_cleanup_strv_free_ char **dispositions = NULL;
|
||||
for (UserDisposition d = 0; d < _USER_DISPOSITION_MAX; d++) {
|
||||
if (!BITS_SET(mask, d))
|
||||
continue;
|
||||
|
||||
r = strv_extend(&dispositions, user_disposition_to_string(d));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_json_variant_merge_objectbo(
|
||||
query,
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(match->fuzzy_names), "fuzzyNames", SD_JSON_BUILD_STRV(match->fuzzy_names)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(match->uuid), "uuid", SD_JSON_BUILD_UUID(match->uuid)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(dispositions), "dispositionMask", SD_JSON_BUILD_STRV(dispositions)));
|
||||
SD_JSON_BUILD_PAIR_STRV("dispositionMask", dispositions));
|
||||
}
|
||||
|
||||
static int query_append_uid_match(sd_json_variant **query, const UserDBMatch *match) {
|
||||
@ -834,12 +832,13 @@ static int query_append_uid_match(sd_json_variant **query, const UserDBMatch *ma
|
||||
|
||||
r = sd_json_variant_merge_objectbo(
|
||||
query,
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(match->fuzzy_names), "fuzzyNames", SD_JSON_BUILD_STRV(match->fuzzy_names)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(match->uid_min > 0, "uidMin", SD_JSON_BUILD_UNSIGNED(match->uid_min)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(match->uid_max < UID_INVALID-1, "uidMax", SD_JSON_BUILD_UNSIGNED(match->uid_max)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return query_append_common(query, match);
|
||||
return query_append_disposition_mask(query, match->disposition_mask);
|
||||
}
|
||||
|
||||
static int userdb_by_name_fallbacks(
|
||||
@ -1299,13 +1298,13 @@ static int query_append_gid_match(sd_json_variant **query, const UserDBMatch *ma
|
||||
|
||||
r = sd_json_variant_merge_objectbo(
|
||||
query,
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(match->fuzzy_names), "fuzzyNames", SD_JSON_BUILD_STRV(match->fuzzy_names)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(match->gid_min > 0, "gidMin", SD_JSON_BUILD_UNSIGNED(match->gid_min)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(match->gid_max < GID_INVALID-1, "gidMax", SD_JSON_BUILD_UNSIGNED(match->gid_max)));
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return query_append_common(query, match);
|
||||
return query_append_disposition_mask(query, match->disposition_mask);
|
||||
}
|
||||
|
||||
static int groupdb_by_name_fallbacks(
|
||||
|
||||
@ -3,32 +3,6 @@
|
||||
#include "bus-polkit.h"
|
||||
#include "varlink-io.systemd.Credentials.h"
|
||||
|
||||
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||
Scope,
|
||||
SD_VARLINK_FIELD_COMMENT("Generate a system-bound credential"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(system),
|
||||
SD_VARLINK_FIELD_COMMENT("Generate a system and user bound credential"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(user));
|
||||
|
||||
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||
WithKey,
|
||||
SD_VARLINK_FIELD_COMMENT("Automatically pick the key to bind the credential to"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(auto),
|
||||
SD_VARLINK_FIELD_COMMENT("Automatically pick the key to bind the credential to, but ensure it is accessible in the initrd, thus potentially leaving it unencrypted."),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(auto_initrd),
|
||||
SD_VARLINK_FIELD_COMMENT("Bind to the host key only, i.e. not the TPM"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(host),
|
||||
SD_VARLINK_FIELD_COMMENT("Bind to the TPM only, not the host key"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(tpm2),
|
||||
SD_VARLINK_FIELD_COMMENT("Bind to the TPM only (using a public key identifying the UKI), not the host key"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(tpm2_with_public_key),
|
||||
SD_VARLINK_FIELD_COMMENT("Bind to both the TPM and the host key"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(host_tpm2),
|
||||
SD_VARLINK_FIELD_COMMENT("Bind to both the TPM (using a public key identifying the UKI) and the host key"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(host_tpm2_with_public_key),
|
||||
SD_VARLINK_FIELD_COMMENT("Do not bind to either host key nor the TPM, thus using null encryption (this provides no authenticity nor confidentiality guarantees)"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(null));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
Encrypt,
|
||||
SD_VARLINK_FIELD_COMMENT("The name for the encrypted credential, a string suitable for inclusion in a file name. If not specified no name is encoded in the credential. Typically, if this credential is stored on disk, this is how the file should be called, and permits authentication of the filename."),
|
||||
@ -42,9 +16,7 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||
SD_VARLINK_FIELD_COMMENT("Timestamp when to the credential should be considered invalid. In µs since the UNIX epoch. If not specified, the credential remains valid forever."),
|
||||
SD_VARLINK_DEFINE_INPUT(notAfter, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("The intended scope for the credential. One of 'system' or 'user'. If not specified defaults to 'system', unless an uid is specified (see below), in which case it default to 'user'."),
|
||||
SD_VARLINK_DEFINE_INPUT_BY_TYPE(scope, Scope, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Selects the type of key to encrypt this with"),
|
||||
SD_VARLINK_DEFINE_INPUT_BY_TYPE(withKey, WithKey, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_INPUT(scope, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("The numeric UNIX UID of the user the credential shall be scoped to. Only relevant if 'user' scope is selected (see above). If not specified and 'user' scope is selected defaults to the UID of the calling user, if that can be determined."),
|
||||
SD_VARLINK_DEFINE_INPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_POLKIT_INPUT,
|
||||
@ -60,11 +32,9 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||
SD_VARLINK_FIELD_COMMENT("The timestamp to use when validating the credential's time validity range. If not specified the current time is used."),
|
||||
SD_VARLINK_DEFINE_INPUT(timestamp, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("The scope for this credential. If not specified no restrictions on the credential scope are made."),
|
||||
SD_VARLINK_DEFINE_INPUT_BY_TYPE(scope, Scope, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_INPUT(scope, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("If the 'user' scope is selected, specifies the numeric UNIX UID of the user the credential is associated with. If not specified this is automatically derived from the UID of the calling user, if that can be determined."),
|
||||
SD_VARLINK_DEFINE_INPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("If true allows decryption of credentials encrypted with the null key, if false does not allow it, if unset/null the default depends on whether a TPM device exists and SecureBoot is enabled."),
|
||||
SD_VARLINK_DEFINE_INPUT(allowNull, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_POLKIT_INPUT,
|
||||
SD_VARLINK_FIELD_COMMENT("The decrypted plaintext data in Base64 encoding."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(data, SD_VARLINK_STRING, 0));
|
||||
@ -84,10 +54,6 @@ SD_VARLINK_DEFINE_INTERFACE(
|
||||
io_systemd_Credentials,
|
||||
"io.systemd.Credentials",
|
||||
SD_VARLINK_INTERFACE_COMMENT("APIs for encrypting and decrypting service credentials."),
|
||||
SD_VARLINK_SYMBOL_COMMENT("The intended scope for the credential."),
|
||||
&vl_type_Scope,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Selects the key(s) to encrypt the credentials with."),
|
||||
&vl_type_WithKey,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Encrypts some plaintext data, returns an encrypted credential."),
|
||||
&vl_method_Encrypt,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Decrypts an encrypted credential, returns plaintext data."),
|
||||
|
||||
@ -16,21 +16,19 @@
|
||||
#include "varlink-io.systemd.BootControl.h"
|
||||
#include "varlink-io.systemd.Credentials.h"
|
||||
#include "varlink-io.systemd.FactoryReset.h"
|
||||
#include "varlink-io.systemd.Hostname.h"
|
||||
#include "varlink-io.systemd.Import.h"
|
||||
#include "varlink-io.systemd.Journal.h"
|
||||
#include "varlink-io.systemd.Login.h"
|
||||
#include "varlink-io.systemd.Machine.h"
|
||||
#include "varlink-io.systemd.MachineImage.h"
|
||||
#include "varlink-io.systemd.ManagedOOM.h"
|
||||
#include "varlink-io.systemd.Manager.h"
|
||||
#include "varlink-io.systemd.ManagedOOM.h"
|
||||
#include "varlink-io.systemd.MountFileSystem.h"
|
||||
#include "varlink-io.systemd.MuteConsole.h"
|
||||
#include "varlink-io.systemd.NamespaceResource.h"
|
||||
#include "varlink-io.systemd.Network.h"
|
||||
#include "varlink-io.systemd.PCRExtend.h"
|
||||
#include "varlink-io.systemd.PCRLock.h"
|
||||
#include "varlink-io.systemd.Repart.h"
|
||||
#include "varlink-io.systemd.Resolve.h"
|
||||
#include "varlink-io.systemd.Resolve.Monitor.h"
|
||||
#include "varlink-io.systemd.Udev.h"
|
||||
@ -165,46 +163,61 @@ static void test_parse_format_one(const sd_varlink_interface *iface) {
|
||||
}
|
||||
|
||||
TEST(parse_format) {
|
||||
const sd_varlink_interface* const list[] = {
|
||||
&vl_interface_io_systemd,
|
||||
&vl_interface_io_systemd_AskPassword,
|
||||
&vl_interface_io_systemd_BootControl,
|
||||
&vl_interface_io_systemd_Credentials,
|
||||
&vl_interface_io_systemd_FactoryReset,
|
||||
&vl_interface_io_systemd_Hostname,
|
||||
&vl_interface_io_systemd_Import,
|
||||
&vl_interface_io_systemd_Journal,
|
||||
&vl_interface_io_systemd_Login,
|
||||
&vl_interface_io_systemd_Machine,
|
||||
&vl_interface_io_systemd_MachineImage,
|
||||
&vl_interface_io_systemd_ManagedOOM,
|
||||
&vl_interface_io_systemd_Manager,
|
||||
&vl_interface_io_systemd_MountFileSystem,
|
||||
&vl_interface_io_systemd_MuteConsole,
|
||||
&vl_interface_io_systemd_NamespaceResource,
|
||||
&vl_interface_io_systemd_Network,
|
||||
&vl_interface_io_systemd_PCRExtend,
|
||||
&vl_interface_io_systemd_PCRLock,
|
||||
&vl_interface_io_systemd_Repart,
|
||||
&vl_interface_io_systemd_Resolve,
|
||||
&vl_interface_io_systemd_Resolve_Monitor,
|
||||
&vl_interface_io_systemd_Udev,
|
||||
&vl_interface_io_systemd_Unit,
|
||||
&vl_interface_io_systemd_UserDatabase,
|
||||
&vl_interface_io_systemd_oom,
|
||||
&vl_interface_io_systemd_service,
|
||||
&vl_interface_io_systemd_sysext,
|
||||
&vl_interface_org_varlink_service,
|
||||
&vl_interface_xyz_test,
|
||||
};
|
||||
|
||||
bool sep = false;
|
||||
FOREACH_ELEMENT(i, list) {
|
||||
if (sep)
|
||||
print_separator();
|
||||
test_parse_format_one(*i);
|
||||
sep = true;
|
||||
}
|
||||
test_parse_format_one(&vl_interface_org_varlink_service);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_UserDatabase);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_MuteConsole);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_NamespaceResource);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Journal);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Resolve);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Resolve_Monitor);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_ManagedOOM);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_MountFileSystem);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Network);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_oom);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_PCRExtend);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_PCRLock);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_service);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_sysext);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Credentials);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_BootControl);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Import);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Machine);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_MachineImage);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Manager);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_AskPassword);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Udev);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Login);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_FactoryReset);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_Unit);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_xyz_test);
|
||||
}
|
||||
|
||||
TEST(parse) {
|
||||
|
||||
@ -57,7 +57,6 @@ static bool arg_chain = false;
|
||||
static uint64_t arg_disposition_mask = UINT64_MAX;
|
||||
static uid_t arg_uid_min = 0;
|
||||
static uid_t arg_uid_max = UID_INVALID-1;
|
||||
static sd_id128_t arg_uuid = SD_ID128_NULL;
|
||||
static bool arg_fuzzy = false;
|
||||
static bool arg_boundaries = true;
|
||||
static sd_json_variant *arg_from_file = NULL;
|
||||
@ -412,7 +411,7 @@ static int display_user(int argc, char *argv[], void *userdata) {
|
||||
int ret = 0, r;
|
||||
|
||||
if (arg_output < 0)
|
||||
arg_output = arg_from_file || (argc > 1 && !arg_fuzzy) || !sd_id128_is_null(arg_uuid) ? OUTPUT_FRIENDLY : OUTPUT_TABLE;
|
||||
arg_output = arg_from_file || (argc > 1 && !arg_fuzzy) ? OUTPUT_FRIENDLY : OUTPUT_TABLE;
|
||||
|
||||
if (arg_output == OUTPUT_TABLE) {
|
||||
table = table_new(" ", "name", "disposition", "uid", "gid", "realname", "home", "shell", "order");
|
||||
@ -432,7 +431,6 @@ static int display_user(int argc, char *argv[], void *userdata) {
|
||||
.disposition_mask = arg_disposition_mask,
|
||||
.uid_min = arg_uid_min,
|
||||
.uid_max = arg_uid_max,
|
||||
.uuid = arg_uuid,
|
||||
};
|
||||
|
||||
if (arg_from_file) {
|
||||
@ -755,7 +753,7 @@ static int display_group(int argc, char *argv[], void *userdata) {
|
||||
int ret = 0, r;
|
||||
|
||||
if (arg_output < 0)
|
||||
arg_output = arg_from_file || (argc > 1 && !arg_fuzzy) || !sd_id128_is_null(arg_uuid) ? OUTPUT_FRIENDLY : OUTPUT_TABLE;
|
||||
arg_output = arg_from_file || (argc > 1 && !arg_fuzzy) ? OUTPUT_FRIENDLY : OUTPUT_TABLE;
|
||||
|
||||
if (arg_output == OUTPUT_TABLE) {
|
||||
table = table_new(" ", "name", "disposition", "gid", "description", "order");
|
||||
@ -774,7 +772,6 @@ static int display_group(int argc, char *argv[], void *userdata) {
|
||||
.disposition_mask = arg_disposition_mask,
|
||||
.gid_min = arg_uid_min,
|
||||
.gid_max = arg_uid_max,
|
||||
.uuid = arg_uuid,
|
||||
};
|
||||
|
||||
if (arg_from_file) {
|
||||
@ -1591,7 +1588,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_CHAIN,
|
||||
ARG_UID_MIN,
|
||||
ARG_UID_MAX,
|
||||
ARG_UUID,
|
||||
ARG_DISPOSITION,
|
||||
ARG_BOUNDARIES,
|
||||
};
|
||||
@ -1612,7 +1608,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "chain", no_argument, NULL, ARG_CHAIN },
|
||||
{ "uid-min", required_argument, NULL, ARG_UID_MIN },
|
||||
{ "uid-max", required_argument, NULL, ARG_UID_MAX },
|
||||
{ "uuid", required_argument, NULL, ARG_UUID },
|
||||
{ "fuzzy", no_argument, NULL, 'z' },
|
||||
{ "disposition", required_argument, NULL, ARG_DISPOSITION },
|
||||
{ "boundaries", required_argument, NULL, ARG_BOUNDARIES },
|
||||
@ -1796,12 +1791,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(r, "Failed to parse --uid-max= value: %s", optarg);
|
||||
break;
|
||||
|
||||
case ARG_UUID:
|
||||
r = sd_id128_from_string(optarg, &arg_uuid);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse --uuid= value: %s", optarg);
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
arg_fuzzy = true;
|
||||
break;
|
||||
|
||||
@ -149,7 +149,6 @@ static int vl_method_get_user_record(sd_varlink *link, sd_json_variant *paramete
|
||||
{ "dispositionMask", SD_JSON_VARIANT_ARRAY, json_dispatch_dispositions_mask, offsetof(LookupParameters, match.disposition_mask), 0 },
|
||||
{ "uidMin", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.uid_min), 0 },
|
||||
{ "uidMax", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.uid_max), 0 },
|
||||
{ "uuid", SD_JSON_VARIANT_STRING, sd_json_dispatch_id128, offsetof(LookupParameters, match.uuid), 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -294,7 +293,6 @@ static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *paramet
|
||||
{ "dispositionMask", SD_JSON_VARIANT_ARRAY, json_dispatch_dispositions_mask, offsetof(LookupParameters, match.disposition_mask), 0 },
|
||||
{ "gidMin", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.gid_min), 0 },
|
||||
{ "gidMax", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.gid_max), 0 },
|
||||
{ "uuid", SD_JSON_VARIANT_STRING, sd_json_dispatch_id128, offsetof(LookupParameters, match.uuid), 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@ -482,34 +482,14 @@ fi
|
||||
|
||||
# Decrypt/encrypt via varlink
|
||||
|
||||
DATA="Zm9vYmFyCg=="
|
||||
echo "{\"data\":\"$DATA\"}" > /tmp/vlcredsdata
|
||||
echo '{"data":"Zm9vYmFyCg=="}' > /tmp/vlcredsdata
|
||||
|
||||
varlinkctl call /run/systemd/io.systemd.Credentials io.systemd.Credentials.Encrypt "$(cat /tmp/vlcredsdata)" | \
|
||||
varlinkctl call --json=short /run/systemd/io.systemd.Credentials io.systemd.Credentials.Decrypt > /tmp/vlcredsdata2
|
||||
|
||||
cmp /tmp/vlcredsdata /tmp/vlcredsdata2
|
||||
rm /tmp/vlcredsdata2
|
||||
|
||||
# Pick a key type explicitly
|
||||
varlinkctl call /run/systemd/io.systemd.Credentials io.systemd.Credentials.Encrypt "{\"data\":\"$DATA\",\"withKey\":\"host\"}" | \
|
||||
varlinkctl call --json=short /run/systemd/io.systemd.Credentials io.systemd.Credentials.Decrypt > /tmp/vlcredsdata2
|
||||
|
||||
cmp /tmp/vlcredsdata /tmp/vlcredsdata2
|
||||
rm /tmp/vlcredsdata2
|
||||
|
||||
varlinkctl call /run/systemd/io.systemd.Credentials io.systemd.Credentials.Encrypt "{\"data\":\"$DATA\",\"withKey\":\"null\"}" | \
|
||||
jq '.["allowNull"] = true' |
|
||||
varlinkctl call --json=short /run/systemd/io.systemd.Credentials io.systemd.Credentials.Decrypt > /tmp/vlcredsdata2
|
||||
|
||||
cmp /tmp/vlcredsdata /tmp/vlcredsdata2
|
||||
rm /tmp/vlcredsdata /tmp/vlcredsdata2
|
||||
|
||||
# Ensure allowNull works
|
||||
(! varlinkctl call /run/systemd/io.systemd.Credentials io.systemd.Credentials.Encrypt "{\"data\":\"$DATA\",\"withKey\":\"null\"}" | \
|
||||
jq '.["allowNull"] = false' |
|
||||
varlinkctl call --json=short /run/systemd/io.systemd.Credentials io.systemd.Credentials.Decrypt )
|
||||
|
||||
clean_usertest() {
|
||||
rm -f /tmp/usertest.data /tmp/usertest.data /tmp/brummbaer.data
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user