diff --git a/man/systemd-creds.xml b/man/systemd-creds.xml index 55c5064b65a..fc3d753ac1f 100644 --- a/man/systemd-creds.xml +++ b/man/systemd-creds.xml @@ -177,6 +177,7 @@ + diff --git a/shell-completion/bash/systemd-creds b/shell-completion/bash/systemd-creds index c16619e94f0..3142954625b 100644 --- a/shell-completion/bash/systemd-creds +++ b/shell-completion/bash/systemd-creds @@ -41,7 +41,7 @@ _systemd_creds() { local verb comps mode i local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword local -A OPTS=( - [STANDALONE]='-h --help --version --no-pager --no-legend + [STANDALONE]='-h --help --version --no-pager --no-legend --no-ask-password -H -T --system --user -p --pretty --allow-null' [ARG]='--tpm2-device --tpm2-device-key @@ -77,6 +77,7 @@ _systemd_creds() { --version --no-pager --no-legend + --no-ask-password --uid --with-key -H @@ -94,6 +95,7 @@ _systemd_creds() { --version --no-pager --no-legend + --no-ask-password --uid --tpm2-device --tpm2-pcrs diff --git a/src/creds/creds.c b/src/creds/creds.c index b10c36e66f4..cd53c90ce35 100644 --- a/src/creds/creds.c +++ b/src/creds/creds.c @@ -65,6 +65,7 @@ static bool arg_quiet = false; static bool arg_varlink = false; static uid_t arg_uid = UID_INVALID; static bool arg_allow_null = false; +static bool arg_ask_password = true; STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep); STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep); @@ -586,16 +587,18 @@ static int verb_encrypt(int argc, char **argv, void *userdata) { if (arg_not_after != USEC_INFINITY && arg_not_after < timestamp) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential is invalidated before it is valid."); - if (geteuid() != 0) + if (geteuid() != 0) { + (void) polkit_agent_open_if_enabled(BUS_TRANSPORT_LOCAL, arg_ask_password); + r = ipc_encrypt_credential( name, timestamp, arg_not_after, arg_uid, &plaintext, - /* flags= */ 0, + arg_ask_password ? CREDENTIAL_IPC_ALLOW_INTERACTIVE : 0, &output); - else + } else r = encrypt_credential_and_warn( arg_with_key, name, @@ -690,15 +693,17 @@ static int verb_decrypt(int argc, char **argv, void *userdata) { timestamp = arg_timestamp != USEC_INFINITY ? arg_timestamp : now(CLOCK_REALTIME); - if (geteuid() != 0) + if (geteuid() != 0) { + (void) polkit_agent_open_if_enabled(BUS_TRANSPORT_LOCAL, arg_ask_password); + r = ipc_decrypt_credential( name, timestamp, arg_uid, &input, - /* flags= */ 0, + arg_ask_password ? CREDENTIAL_IPC_ALLOW_INTERACTIVE : 0, &plaintext); - else + } else r = decrypt_credential_and_warn( name, timestamp, @@ -832,6 +837,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_USER, ARG_UID, ARG_ALLOW_NULL, + ARG_NO_ASK_PASSWORD, }; static const struct option options[] = { @@ -857,6 +863,7 @@ 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 }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, {} }; @@ -1052,6 +1059,10 @@ static int parse_argv(int argc, char *argv[]) { arg_allow_null = true; break; + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + case 'q': arg_quiet = true; break; diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 5156c63fd3f..0f840ff61ae 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1572,7 +1572,8 @@ int ipc_encrypt_credential(const char *name, usec_t timestamp, usec_t not_after, SD_JSON_BUILD_PAIR_CONDITION(timestamp != USEC_INFINITY, "timestamp", SD_JSON_BUILD_UNSIGNED(timestamp)), 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(uid_is_valid(uid), "uid", SD_JSON_BUILD_UNSIGNED(uid)), + 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."); if (!isempty(error_id)) { @@ -1629,7 +1630,8 @@ int ipc_decrypt_credential(const char *validate_name, usec_t validate_timestamp, SD_JSON_BUILD_PAIR("blob", SD_JSON_BUILD_VARIANT(jinput)), SD_JSON_BUILD_PAIR_CONDITION(validate_timestamp != USEC_INFINITY, "timestamp", SD_JSON_BUILD_UNSIGNED(validate_timestamp)), 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(uid_is_valid(uid), "uid", SD_JSON_BUILD_UNSIGNED(uid)), + SD_JSON_BUILD_PAIR_BOOLEAN("allowInteractiveAuthentication", FLAGS_SET(flags, CREDENTIAL_IPC_ALLOW_INTERACTIVE))); if (r < 0) return log_error_errno(r, "Failed to call Decrypt() varlink call."); if (!isempty(error_id)) { diff --git a/src/shared/creds-util.h b/src/shared/creds-util.h index e096b6d4d41..3b9580850cc 100644 --- a/src/shared/creds-util.h +++ b/src/shared/creds-util.h @@ -58,8 +58,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 of NULL key, even if TPM is around */ - CREDENTIAL_ANY_SCOPE = 1 << 1, /* 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 << 2, } CredentialFlags; /* The four modes we support: keyed only by on-disk key, only by TPM2 HMAC key, and by the combination of