diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:49:52 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:49:52 +0000 |
commit | 55944e5e40b1be2afc4855d8d2baf4b73d1876b5 (patch) | |
tree | 33f869f55a1b149e9b7c2b7e201867ca5dd52992 /src/cryptenroll/cryptenroll-password.c | |
parent | Initial commit. (diff) | |
download | systemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.tar.xz systemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.zip |
Adding upstream version 255.4.upstream/255.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cryptenroll/cryptenroll-password.c')
-rw-r--r-- | src/cryptenroll/cryptenroll-password.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/cryptenroll/cryptenroll-password.c b/src/cryptenroll/cryptenroll-password.c new file mode 100644 index 0000000..c35b609 --- /dev/null +++ b/src/cryptenroll/cryptenroll-password.c @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "ask-password-api.h" +#include "cryptenroll-password.h" +#include "env-util.h" +#include "errno-util.h" +#include "escape.h" +#include "memory-util.h" +#include "password-quality-util.h" +#include "strv.h" + +int load_volume_key_password( + struct crypt_device *cd, + const char *cd_node, + void *ret_vk, + size_t *ret_vks) { + + _cleanup_(erase_and_freep) char *envpw = NULL; + int r; + + assert_se(cd); + assert_se(cd_node); + assert_se(ret_vk); + assert_se(ret_vks); + + r = getenv_steal_erase("PASSWORD", &envpw); + if (r < 0) + return log_error_errno(r, "Failed to acquire password from environment: %m"); + if (r > 0) { + r = crypt_volume_key_get( + cd, + CRYPT_ANY_SLOT, + ret_vk, + ret_vks, + envpw, + strlen(envpw)); + if (r < 0) + return log_error_errno(r, "Password from environment variable $PASSWORD did not work: %m"); + } else { + AskPasswordFlags ask_password_flags = ASK_PASSWORD_PUSH_CACHE|ASK_PASSWORD_ACCEPT_CACHED; + _cleanup_free_ char *question = NULL, *disk_path = NULL; + unsigned i = 5; + const char *id; + + question = strjoin("Please enter current passphrase for disk ", cd_node, ":"); + if (!question) + return log_oom(); + + disk_path = cescape(cd_node); + if (!disk_path) + return log_oom(); + + id = strjoina("cryptsetup:", disk_path); + + for (;;) { + _cleanup_strv_free_erase_ char **passwords = NULL; + + if (--i == 0) + return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), + "Too many attempts, giving up."); + + r = ask_password_auto( + question, "drive-harddisk", id, "cryptenroll", "cryptenroll.passphrase", USEC_INFINITY, + ask_password_flags, + &passwords); + if (r < 0) + return log_error_errno(r, "Failed to query password: %m"); + + r = -EPERM; + STRV_FOREACH(p, passwords) { + r = crypt_volume_key_get( + cd, + CRYPT_ANY_SLOT, + ret_vk, + ret_vks, + *p, + strlen(*p)); + if (r >= 0) + break; + } + if (r >= 0) + break; + + log_error_errno(r, "Password not correct, please try again: %m"); + ask_password_flags &= ~ASK_PASSWORD_ACCEPT_CACHED; + } + } + + return r; +} + +int enroll_password( + struct crypt_device *cd, + const void *volume_key, + size_t volume_key_size) { + + _cleanup_(erase_and_freep) char *new_password = NULL; + _cleanup_free_ char *error = NULL; + const char *node; + int r, keyslot; + + assert_se(node = crypt_get_device_name(cd)); + + r = getenv_steal_erase("NEWPASSWORD", &new_password); + if (r < 0) + return log_error_errno(r, "Failed to acquire password from environment: %m"); + if (r == 0) { + _cleanup_free_ char *disk_path = NULL; + unsigned i = 5; + const char *id; + + assert_se(node = crypt_get_device_name(cd)); + + (void) suggest_passwords(); + + disk_path = cescape(node); + if (!disk_path) + return log_oom(); + + id = strjoina("cryptsetup:", disk_path); + + for (;;) { + _cleanup_strv_free_erase_ char **passwords = NULL, **passwords2 = NULL; + _cleanup_free_ char *question = NULL; + + if (--i == 0) + return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), + "Too many attempts, giving up."); + + question = strjoin("Please enter new passphrase for disk ", node, ":"); + if (!question) + return log_oom(); + + 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"); + + assert(strv_length(passwords) == 1); + + free(question); + question = strjoin("Please enter new passphrase for disk ", node, " (repeat):"); + if (!question) + return log_oom(); + + 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"); + + assert(strv_length(passwords2) == 1); + + if (strv_equal(passwords, passwords2)) { + new_password = passwords2[0]; + passwords2 = mfree(passwords2); + break; + } + + log_error("Password didn't match, try again."); + } + } + + r = check_password_quality(new_password, /* old */ NULL, /* user */ NULL, &error); + if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) + log_warning("Password quality check is not supported, proceeding anyway."); + else if (r < 0) + return log_error_errno(r, "Failed to check password quality: %m"); + else if (r == 0) + log_warning("Specified password does not pass quality checks (%s), proceeding anyway.", error); + + keyslot = crypt_keyslot_add_by_volume_key( + cd, + CRYPT_ANY_SLOT, + volume_key, + volume_key_size, + new_password, + strlen(new_password)); + if (keyslot < 0) + return log_error_errno(keyslot, "Failed to add new password to %s: %m", node); + + log_info("New password enrolled as key slot %i.", keyslot); + return keyslot; +} |