From: Ludwig Nussel Date: Tue, 9 Aug 2022 09:07:34 +0000 (+0200) Subject: creds: refactor reading user password X-Git-Tag: v252-rc1~462^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ff86850b304f635297829c7d12208b96c10fa48f;p=thirdparty%2Fsystemd.git creds: refactor reading user password Share code between firstboot and sysusers --- diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 0716914b26f..7684c205fb3 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -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; diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 72ec992121f..c1a9d35528d 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -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 diff --git a/src/shared/creds-util.h b/src/shared/creds-util.h index ccbecaf58bd..62e5c888eec 100644 --- a/src/shared/creds-util.h +++ b/src/shared/creds-util.h @@ -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 diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 901e8aaf02e..dfb703f10ec 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -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 = 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 = 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**) &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;