mirror of
https://github.com/systemd/systemd.git
synced 2025-02-23 13:57:33 +03:00
ask-password: when querying for a password, try to read from credential store first
This adds generic support for the SetCredential=/LoadCredential= logic to our password querying infrastructure: if a password is requested by a program that has a credential store configured via $CREDENTIALS_DIRECTORY we'll look in it for a password. The "systemd-ask-password" tool is updated with an option to specify the credential to look for.
This commit is contained in:
parent
f6ab6199a2
commit
8806bb4bc7
@ -138,6 +138,17 @@
|
||||
directly. Example: <literal>--keyname=cryptsetup</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--credential=</option></term>
|
||||
<listitem><para>Configure a credential to read the password from – if it exists. This may be used in
|
||||
conjunction with the <varname>LoadCredential=</varname> and <varname>SetCredential=</varname>
|
||||
settings in unit files. See
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
details. If not specified, defaults to <literal>password</literal>. This option has no effect if no
|
||||
credentials directory is passed to the program (i.e. <varname>$CREDENTIALS_DIRECTORY</varname> is not
|
||||
set) or if the no credential of the specified name exists.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--timeout=</option></term>
|
||||
|
||||
|
@ -12,10 +12,12 @@
|
||||
#include "main-func.h"
|
||||
#include "pretty-print.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
|
||||
static const char *arg_icon = NULL;
|
||||
static const char *arg_id = NULL;
|
||||
static const char *arg_keyname = NULL;
|
||||
static const char *arg_id = NULL; /* identifier for 'ask-password' protocol */
|
||||
static const char *arg_key_name = NULL; /* name in kernel keyring */
|
||||
static const char *arg_credential_name = NULL; /* name in $CREDENTIALS_DIRECTORY directory */
|
||||
static char *arg_message = NULL;
|
||||
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
|
||||
static bool arg_multiple = false;
|
||||
@ -32,21 +34,26 @@ static int help(void) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%s [OPTIONS...] MESSAGE\n\n"
|
||||
"Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
|
||||
printf("%1$s [OPTIONS...] MESSAGE\n\n"
|
||||
"%3$sQuery the user for a system passphrase, via the TTY or an UI agent.%4$s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --icon=NAME Icon name\n"
|
||||
" --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
|
||||
" --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
|
||||
" --credential=NAME\n"
|
||||
" Credential name for LoadCredential=/SetCredential=\n"
|
||||
" credentials\n"
|
||||
" --timeout=SEC Timeout in seconds\n"
|
||||
" --echo Do not mask input (useful for usernames)\n"
|
||||
" --no-tty Ask question via agent even on TTY\n"
|
||||
" --accept-cached Accept cached passwords\n"
|
||||
" --multiple List multiple passwords if available\n"
|
||||
" --no-output Do not print password to standard output\n"
|
||||
"\nSee the %s for details.\n",
|
||||
"\nSee the %2$s for details.\n",
|
||||
program_invocation_short_name,
|
||||
link);
|
||||
link,
|
||||
ansi_highlight(),
|
||||
ansi_normal());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -64,6 +71,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_KEYNAME,
|
||||
ARG_NO_OUTPUT,
|
||||
ARG_VERSION,
|
||||
ARG_CREDENTIAL,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -78,6 +86,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "id", required_argument, NULL, ARG_ID },
|
||||
{ "keyname", required_argument, NULL, ARG_KEYNAME },
|
||||
{ "no-output", no_argument, NULL, ARG_NO_OUTPUT },
|
||||
{ "credential", required_argument, NULL, ARG_CREDENTIAL },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -128,13 +137,17 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_KEYNAME:
|
||||
arg_keyname = optarg;
|
||||
arg_key_name = optarg;
|
||||
break;
|
||||
|
||||
case ARG_NO_OUTPUT:
|
||||
arg_no_output = true;
|
||||
break;
|
||||
|
||||
case ARG_CREDENTIAL:
|
||||
arg_credential_name = optarg;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@ -170,7 +183,7 @@ static int run(int argc, char *argv[]) {
|
||||
else
|
||||
timeout = 0;
|
||||
|
||||
r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l);
|
||||
r = ask_password_auto(arg_message, arg_icon, arg_id, arg_key_name, arg_credential_name ?: "password", timeout, arg_flags, &l);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
|
@ -57,7 +57,7 @@ int enroll_password(
|
||||
if (!question)
|
||||
return log_oom();
|
||||
|
||||
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY, 0, &passwords);
|
||||
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
@ -68,7 +68,7 @@ int enroll_password(
|
||||
if (!question)
|
||||
return log_oom();
|
||||
|
||||
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY, 0, &passwords2);
|
||||
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords2);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
|
@ -417,7 +417,7 @@ static int prepare_luks(
|
||||
"Too many attempts, giving up:");
|
||||
|
||||
r = ask_password_auto(
|
||||
question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY,
|
||||
question, "drive-harddisk", id, "cryptenroll", "cryptenroll.passphrase", USEC_INFINITY,
|
||||
ask_password_flags,
|
||||
&passwords);
|
||||
if (r < 0)
|
||||
|
@ -88,7 +88,7 @@ int acquire_fido2_key(
|
||||
|
||||
pins = strv_free_erase(pins);
|
||||
|
||||
r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", until, flags, &pins);
|
||||
r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", "cryptsetup.fido2-pin", until, flags, &pins);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to ask for user password: %m");
|
||||
|
||||
|
@ -70,6 +70,7 @@ static int pkcs11_callback(
|
||||
data->friendly_name,
|
||||
"drive-harddisk",
|
||||
"pkcs11-pin",
|
||||
"cryptsetup.pkcs11-pin",
|
||||
data->until,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
|
@ -545,7 +545,7 @@ static int get_password(
|
||||
|
||||
id = strjoina("cryptsetup:", disk_path);
|
||||
|
||||
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until,
|
||||
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until,
|
||||
ASK_PASSWORD_PUSH_CACHE | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED),
|
||||
&passwords);
|
||||
if (r < 0)
|
||||
@ -561,7 +561,7 @@ static int get_password(
|
||||
|
||||
id = strjoina("cryptsetup-verification:", disk_path);
|
||||
|
||||
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE, &passwords2);
|
||||
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until, ASK_PASSWORD_PUSH_CACHE, &passwords2);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query verification password: %m");
|
||||
|
||||
|
@ -221,7 +221,7 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
|
||||
user_name) < 0)
|
||||
return log_oom();
|
||||
|
||||
r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &password);
|
||||
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.password", USEC_INFINITY, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &password);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire password: %m");
|
||||
|
||||
@ -257,7 +257,7 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
|
||||
return log_oom();
|
||||
|
||||
/* We never cache or use cached PINs, since usually there are only very few attempts allowed before the PIN is blocked */
|
||||
r = ask_password_auto(question, "user-home", NULL, "token-pin", USEC_INFINITY, 0, &pin);
|
||||
r = ask_password_auto(question, "user-home", NULL, "token-pin", "home.token-pin", USEC_INFINITY, 0, &pin);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire security token PIN: %m");
|
||||
|
||||
@ -1010,7 +1010,7 @@ static int acquire_new_password(
|
||||
if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0)
|
||||
return log_oom();
|
||||
|
||||
r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, 0, &first);
|
||||
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.new-password", USEC_INFINITY, 0, &first);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire password: %m");
|
||||
|
||||
@ -1018,7 +1018,7 @@ static int acquire_new_password(
|
||||
if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0)
|
||||
return log_oom();
|
||||
|
||||
r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, 0, &second);
|
||||
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.new-password", USEC_INFINITY, 0, &second);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire password: %m");
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "ask-password-api.h"
|
||||
#include "creds-util.h"
|
||||
#include "def.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@ -971,11 +972,33 @@ finish:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ask_password_credential(const char *credential_name, AskPasswordFlags flags, char ***ret) {
|
||||
_cleanup_(erase_and_freep) char *buffer = NULL;
|
||||
size_t size;
|
||||
char **l;
|
||||
int r;
|
||||
|
||||
assert(credential_name);
|
||||
assert(ret);
|
||||
|
||||
r = read_credential(credential_name, (void**) &buffer, &size);
|
||||
if (IN_SET(r, -ENXIO, -ENOENT)) /* No credentials passed or this credential not defined? */
|
||||
return -ENOKEY;
|
||||
|
||||
l = strv_parse_nulstr(buffer, size);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ask_password_auto(
|
||||
const char *message,
|
||||
const char *icon,
|
||||
const char *id,
|
||||
const char *keyname,
|
||||
const char *id, /* id in "ask-password" protocol */
|
||||
const char *key_name, /* name in kernel keyring */
|
||||
const char *credential_name, /* name in $CREDENTIALS_DIRECTORY directory */
|
||||
usec_t until,
|
||||
AskPasswordFlags flags,
|
||||
char ***ret) {
|
||||
@ -984,20 +1007,26 @@ int ask_password_auto(
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (!(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) &&
|
||||
keyname &&
|
||||
key_name &&
|
||||
((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
|
||||
(flags & ASK_PASSWORD_NO_AGENT)) {
|
||||
r = ask_password_keyring(keyname, flags, ret);
|
||||
r = ask_password_keyring(key_name, flags, ret);
|
||||
if (r != -ENOKEY)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
|
||||
return ask_password_tty(-1, message, keyname, until, flags, NULL, ret);
|
||||
return ask_password_tty(-1, message, key_name, until, flags, NULL, ret);
|
||||
|
||||
if (!(flags & ASK_PASSWORD_NO_AGENT))
|
||||
return ask_password_agent(message, icon, id, keyname, until, flags, ret);
|
||||
return ask_password_agent(message, icon, id, key_name, until, flags, ret);
|
||||
|
||||
return -EUNATCH;
|
||||
}
|
||||
|
@ -6,16 +6,17 @@
|
||||
#include "time-util.h"
|
||||
|
||||
typedef enum AskPasswordFlags {
|
||||
ASK_PASSWORD_ACCEPT_CACHED = 1 << 0,
|
||||
ASK_PASSWORD_PUSH_CACHE = 1 << 1,
|
||||
ASK_PASSWORD_ACCEPT_CACHED = 1 << 0, /* read from kernel keyring */
|
||||
ASK_PASSWORD_PUSH_CACHE = 1 << 1, /* write to kernel keyring after getting password from elsewhere */
|
||||
ASK_PASSWORD_ECHO = 1 << 2, /* show the password literally while reading, instead of "*" */
|
||||
ASK_PASSWORD_SILENT = 1 << 3, /* do no show any password at all while reading */
|
||||
ASK_PASSWORD_NO_TTY = 1 << 4,
|
||||
ASK_PASSWORD_NO_AGENT = 1 << 5,
|
||||
ASK_PASSWORD_NO_TTY = 1 << 4, /* never ask for password on tty */
|
||||
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 */
|
||||
} AskPasswordFlags;
|
||||
|
||||
int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
||||
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);
|
||||
int ask_password_plymouth(const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
||||
int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||
int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||
int ask_password_agent(const char *message, const char *icon, const char *id, const char *key_name, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||
int ask_password_auto(const char *message, const char *icon, const char *id, const char *key_name, const char *credential_name, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||
|
@ -1993,7 +1993,7 @@ int dissected_image_decrypt_interactively(
|
||||
|
||||
z = strv_free(z);
|
||||
|
||||
r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z);
|
||||
r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", "dissect.passphrase", USEC_INFINITY, 0, &z);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query for passphrase: %m");
|
||||
|
||||
|
@ -566,7 +566,7 @@ int fido2_generate_hmac_hash(
|
||||
if (!has_client_pin)
|
||||
log_warning("Weird, device asked for client PIN, but does not advertise it as feature. Ignoring.");
|
||||
|
||||
r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", USEC_INFINITY, 0, &pin);
|
||||
r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", "fido2-pin", USEC_INFINITY, 0, &pin);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire user PIN: %m");
|
||||
|
||||
|
@ -181,7 +181,8 @@ int pkcs11_token_login(
|
||||
const CK_TOKEN_INFO *token_info,
|
||||
const char *friendly_name,
|
||||
const char *icon_name,
|
||||
const char *keyname,
|
||||
const char *key_name,
|
||||
const char *credential_name,
|
||||
usec_t until,
|
||||
char **ret_used_pin) {
|
||||
|
||||
@ -269,7 +270,7 @@ int pkcs11_token_login(
|
||||
return log_oom();
|
||||
|
||||
/* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */
|
||||
r = ask_password_auto(text, icon_name, id, keyname, until, 0, &passwords);
|
||||
r = ask_password_auto(text, icon_name, id, key_name, credential_name, until, 0, &passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label);
|
||||
}
|
||||
@ -959,7 +960,7 @@ static int pkcs11_acquire_certificate_callback(
|
||||
|
||||
/* Called for every token matching our URI */
|
||||
|
||||
r = pkcs11_token_login(m, session, slot_id, token_info, data->askpw_friendly_name, data->askpw_icon_name, "pkcs11-pin", UINT64_MAX, &pin_used);
|
||||
r = pkcs11_token_login(m, session, slot_id, token_info, data->askpw_friendly_name, data->askpw_icon_name, "pkcs11-pin", "pkcs11-pin", UINT64_MAX, &pin_used);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -30,7 +30,7 @@ char *pkcs11_token_label(const CK_TOKEN_INFO *token_info);
|
||||
char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info);
|
||||
char *pkcs11_token_model(const CK_TOKEN_INFO *token_info);
|
||||
|
||||
int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *keyname, usec_t until, char **ret_used_pin);
|
||||
int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, char **ret_used_pin);
|
||||
|
||||
int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
|
||||
#if HAVE_OPENSSL
|
||||
|
Loading…
x
Reference in New Issue
Block a user