Merge pull request #24273 from lnussel/refactor_sysuser_creds

Refactor sysuser creds
This commit is contained in:
Lennart Poettering 2022-08-12 14:32:06 +02:00 committed by GitHub
commit c94887f10d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 38 deletions

View file

@ -266,7 +266,8 @@ services where they are ultimately consumed.
three of these specific switches would set credential `foo` to `bar`.)
Passing credentials via the SMBIOS mechanism is typically preferable over
`fw_cfg` since it is faster and less specific to the chosen VMM
implementation.
implementation. Moreover, `fw_cfg` has a 55 character limitation
on names passed that way. So some settings may not fit.
3. Credentials can also be passed into a system via the kernel command line,
via the `systemd.set-credential=` kernel command line option. Note though

View file

@ -595,21 +595,8 @@ static int prompt_root_password(void) {
if (arg_root_password)
return 0;
r = read_credential("passwd.hashed-password.root", (void**) &arg_root_password, NULL);
if (r == -ENOENT) {
r = read_credential("passwd.plaintext-password.root", (void**) &arg_root_password, NULL);
if (r < 0)
log_debug_errno(r, "Couldn't read credential 'passwd.{hashed|plaintext}-password.root', ignoring: %m");
else {
arg_root_password_is_hashed = false;
return 0;
}
} else if (r < 0)
log_debug_errno(r, "Couldn't read credential 'passwd.hashed-password.root', ignoring: %m");
else {
arg_root_password_is_hashed = true;
if (get_credential_user_password("root", &arg_root_password, &arg_root_password_is_hashed) >= 0)
return 0;
}
if (!arg_prompt_root_password)
return 0;

View file

@ -83,6 +83,38 @@ int read_credential(const char *name, void **ret, size_t *ret_size) {
(char**) ret, ret_size);
}
int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed) {
_cleanup_(erase_and_freep) char *creds_password = NULL;
_cleanup_free_ char *cn = NULL;
int r;
/* Try to pick up the password for this account via the credentials logic */
cn = strjoin("passwd.hashed-password.", username);
if (!cn)
return -ENOMEM;
r = read_credential(cn, (void**) &creds_password, NULL);
if (r == -ENOENT) {
free(cn);
cn = strjoin("passwd.plaintext-password.", username);
if (!cn)
return -ENOMEM;
r = read_credential(cn, (void**) &creds_password, NULL);
if (r < 0)
log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
else
*ret_is_hashed = false;
} else if (r < 0)
log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
else
*ret_is_hashed = true;
*ret_password = TAKE_PTR(creds_password);
return r;
}
#if HAVE_OPENSSL
#define CREDENTIAL_HOST_SECRET_SIZE 4096

View file

@ -44,6 +44,8 @@ typedef enum CredentialSecretFlags {
int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *ret_size);
int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed);
/* The four modes we support: keyed only by on-disk key, only by TPM2 HMAC key, and by the combination of
* both, as well as one with a fixed zero length key if TPM2 is missing (the latter of course provides no
* authenticity or confidentiality, but is still useful for integrity protection, and makes things simpler

View file

@ -581,7 +581,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
ORDERED_HASHMAP_FOREACH(i, todo_uids) {
_cleanup_(erase_and_freep) char *creds_password = NULL;
_cleanup_free_ char *cn = NULL;
bool is_hashed;
struct spwd n = {
.sp_namp = i->name,
@ -595,30 +595,16 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
.sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
};
/* Try to pick up the password for this account via the credentials logic */
cn = strjoin("passwd.hashed-password.", i->name);
if (!cn)
return -ENOMEM;
r = get_credential_user_password(i->name, &creds_password, &is_hashed);
if (r < 0)
log_debug_errno(r, "Couldn't read password credential for user '%s', ignoring: %m", i->name);
r = read_credential(cn, (void**) &creds_password, NULL);
if (r == -ENOENT) {
_cleanup_(erase_and_freep) char *plaintext_password = NULL;
free(cn);
cn = strjoin("passwd.plaintext-password.", i->name);
if (!cn)
return -ENOMEM;
r = read_credential(cn, (void**) &plaintext_password, NULL);
if (creds_password && !is_hashed) {
_cleanup_(erase_and_freep) char* plaintext_password = TAKE_PTR(creds_password);
r = hash_password(plaintext_password, &creds_password);
if (r < 0)
log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
else {
r = hash_password(plaintext_password, &creds_password);
if (r < 0)
return log_debug_errno(r, "Failed to hash password: %m");
}
} else if (r < 0)
log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
return log_debug_errno(r, "Failed to hash password: %m");
}
if (creds_password)
n.sp_pwdp = creds_password;