X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Futils_password.c;h=3374e18f53969f6b1dbab105496a7d5dc64d8027;hb=HEAD;hp=55c1343fe7713c0b701cd11466d4c06de21a2af3;hpb=6cd353b6260d3be1b8093534d74ce74f82f0040a;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/src/utils_password.c b/src/utils_password.c index 55c1343..3374e18 100644 --- a/src/utils_password.c +++ b/src/utils_password.c @@ -1,8 +1,8 @@ /* * Password quality check wrapper * - * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2020 Milan Broz + * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2023 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,8 +22,6 @@ #include "cryptsetup.h" #include -int opt_force_password = 0; - #if defined ENABLE_PWQUALITY #include @@ -31,7 +29,7 @@ static int tools_check_pwquality(const char *password) { int r; void *auxerror; - pwquality_settings_t *pwq; + pwquality_settings_t *pwq; log_dbg("Checking new password using default pwquality settings."); pwq = pwquality_default_settings(); @@ -51,10 +49,8 @@ static int tools_check_pwquality(const char *password) log_err(_("Password quality check failed:\n %s"), pwquality_strerror(NULL, 0, r, auxerror)); r = -EPERM; - } else { - log_dbg("New password libpwquality score is %d.", r); + } else r = 0; - } pwquality_free_settings(pwq); return r; @@ -62,55 +58,94 @@ static int tools_check_pwquality(const char *password) #elif defined ENABLE_PASSWDQC #include -static int tools_check_pwquality(const char *password) +static int tools_check_passwdqc(const char *password) { passwdqc_params_t params; - char *parse_reason; + char *parse_reason = NULL; const char *check_reason; const char *config = PASSWDQC_CONFIG_FILE; + int r = -EINVAL; passwdqc_params_reset(¶ms); if (*config && passwdqc_params_load(¶ms, &parse_reason, config)) { log_err(_("Cannot check password quality: %s"), (parse_reason ? parse_reason : "Out of memory")); - free(parse_reason); - return -EINVAL; + goto out; } check_reason = passwdqc_check(¶ms.qc, password, NULL, NULL); if (check_reason) { log_err(_("Password quality check failed: Bad passphrase (%s)"), check_reason); - return -EPERM; - } - - return 0; + r = -EPERM; + } else + r = 0; +out: +#if HAVE_PASSWDQC_PARAMS_FREE + passwdqc_params_free(¶ms); +#endif + free(parse_reason); + return r; } -#else /* !(ENABLE_PWQUALITY || ENABLE_PASSWDQC) */ -static int tools_check_pwquality(const char *password) +#endif /* ENABLE_PWQUALITY || ENABLE_PASSWDQC */ + +/* coverity[ +tainted_string_sanitize_content : arg-0 ] */ +static int tools_check_password(const char *password) { +#if defined ENABLE_PWQUALITY + return tools_check_pwquality(password); +#elif defined ENABLE_PASSWDQC + return tools_check_passwdqc(password); +#else return 0; +#endif } -#endif /* ENABLE_PWQUALITY || ENABLE_PASSWDQC */ /* Password reading helpers */ -static int untimed_read(int fd, char *pass, size_t maxlen) + +/* coverity[ -taint_source : arg-1 ] */ +static ssize_t read_tty_eol(int fd, char *pass, size_t maxlen) +{ + bool eol = false; + size_t read_size = 0; + ssize_t r; + + do { + r = read(fd, pass, maxlen - read_size); + if ((r == -1 && errno != EINTR) || quit) + return -1; + if (r >= 0) { + if (!r || pass[r-1] == '\n') + eol = true; + read_size += (size_t)r; + pass = pass + r; + } + } while (!eol && read_size != maxlen); + + return (ssize_t)read_size; +} + +/* The pass buffer is zeroed and has trailing \0 already " */ +static int untimed_read(int fd, char *pass, size_t maxlen, size_t *realsize) { ssize_t i; - i = read(fd, pass, maxlen); + i = read_tty_eol(fd, pass, maxlen); if (i > 0) { - pass[i-1] = '\0'; + if (pass[i-1] == '\n') { + pass[i-1] = '\0'; + *realsize = i - 1; + } else + *realsize = i; i = 0; - } else if (i == 0) { /* EOF */ - *pass = 0; + } else if (i == 0) /* empty input */ i = -1; - } + return i; } -static int timed_read(int fd, char *pass, size_t maxlen, long timeout) +static int timed_read(int fd, char *pass, size_t maxlen, size_t *realsize, long timeout) { struct timeval t; fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */ @@ -122,7 +157,7 @@ static int timed_read(int fd, char *pass, size_t maxlen, long timeout) t.tv_usec = 0; if (select(fd+1, &fds, NULL, NULL, &t) > 0) - failed = untimed_read(fd, pass, maxlen); + failed = untimed_read(fd, pass, maxlen, realsize); return failed; } @@ -133,6 +168,7 @@ static int interactive_pass(const char *prompt, char *pass, size_t maxlen, struct termios orig, tmp; int failed = -1; int infd, outfd; + size_t realsize = 0; if (maxlen < 1) return failed; @@ -146,24 +182,26 @@ static int interactive_pass(const char *prompt, char *pass, size_t maxlen, outfd = infd; if (tcgetattr(infd, &orig)) - goto out_err; + goto out; memcpy(&tmp, &orig, sizeof(tmp)); tmp.c_lflag &= ~ECHO; if (prompt && write(outfd, prompt, strlen(prompt)) < 0) - goto out_err; + goto out; tcsetattr(infd, TCSAFLUSH, &tmp); if (timeout) - failed = timed_read(infd, pass, maxlen, timeout); + failed = timed_read(infd, pass, maxlen, &realsize, timeout); else - failed = untimed_read(infd, pass, maxlen); + failed = untimed_read(infd, pass, maxlen, &realsize); tcsetattr(infd, TCSAFLUSH, &orig); - -out_err: +out: if (!failed && write(outfd, "\n", 1)) {}; + if (realsize == maxlen) + log_dbg("Read stopped at maximal interactive input length, passphrase can be trimmed."); + if (infd != STDIN_FILENO) close(infd); return failed; @@ -171,8 +209,7 @@ out_err: static int crypt_get_key_tty(const char *prompt, char **key, size_t *key_size, - int timeout, int verify, - struct crypt_device *cd) + int timeout, int verify) { int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX; int r = -EINVAL; @@ -191,35 +228,35 @@ static int crypt_get_key_tty(const char *prompt, if (interactive_pass(prompt, pass, key_size_max, timeout)) { log_err(_("Error reading passphrase from terminal.")); - goto out_err; + goto out; } - pass[key_size_max] = '\0'; if (verify) { - pass_verify = crypt_safe_alloc(key_size_max); + pass_verify = crypt_safe_alloc(key_size_max + 1); if (!pass_verify) { log_err(_("Out of memory while reading passphrase.")); r = -ENOMEM; - goto out_err; + goto out; } if (interactive_pass(_("Verify passphrase: "), pass_verify, key_size_max, timeout)) { log_err(_("Error reading passphrase from terminal.")); - goto out_err; + goto out; } if (strncmp(pass, pass_verify, key_size_max)) { log_err(_("Passphrases do not match.")); r = -EPERM; - goto out_err; + goto out; } } *key = pass; + /* coverity[string_null] (crypt_safe_alloc wipes string with additional \0) */ *key_size = strlen(pass); r = 0; -out_err: +out: crypt_safe_free(pass_verify); if (r) crypt_safe_free(pass); @@ -249,14 +286,18 @@ int tools_get_key(const char *prompt, if (keyfile_offset) { log_err(_("Cannot use offset with terminal input.")); } else { + r = 0; if (!prompt && !crypt_get_device_name(cd)) - snprintf(tmp, sizeof(tmp), _("Enter passphrase: ")); + r = snprintf(tmp, sizeof(tmp), _("Enter passphrase: ")); else if (!prompt) { backing_file = crypt_loop_backing_file(crypt_get_device_name(cd)); - snprintf(tmp, sizeof(tmp), _("Enter passphrase for %s: "), backing_file ?: crypt_get_device_name(cd)); + r = snprintf(tmp, sizeof(tmp), _("Enter passphrase for %s: "), backing_file ?: crypt_get_device_name(cd)); free(backing_file); } - r = crypt_get_key_tty(prompt ?: tmp, key, key_size, timeout, verify, cd); + if (r >= 0) + r = crypt_get_key_tty(prompt ?: tmp, key, key_size, timeout, verify); + else + r = -EINVAL; } } else { log_dbg("STDIN descriptor passphrase entry requested."); @@ -275,8 +316,8 @@ int tools_get_key(const char *prompt, set_int_block(1); /* Check pwquality for password (not keyfile) */ - if (pwquality && !opt_force_password && !key_file && !r) - r = tools_check_pwquality(*key); + if (pwquality && !key_file && !r) + r = tools_check_password(*key); return r; } @@ -288,52 +329,3 @@ void tools_passphrase_msg(int r) else if (r == -ENOENT) log_err(_("No usable keyslot is available.")); } - -int tools_read_mk(const char *file, char **key, int keysize) -{ - int fd; - - if (!keysize || !key) - return -EINVAL; - - *key = crypt_safe_alloc(keysize); - if (!*key) - return -ENOMEM; - - fd = open(file, O_RDONLY); - if (fd == -1) { - log_err(_("Cannot read keyfile %s."), file); - goto fail; - } - - if (read_buffer(fd, *key, keysize) != keysize) { - log_err(_("Cannot read %d bytes from keyfile %s."), keysize, file); - close(fd); - goto fail; - } - close(fd); - return 0; -fail: - crypt_safe_free(*key); - *key = NULL; - return -EINVAL; -} - -int tools_write_mk(const char *file, const char *key, int keysize) -{ - int fd, r = -EINVAL; - - fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR); - if (fd < 0) { - log_err(_("Cannot open keyfile %s for write."), file); - return r; - } - - if (write_buffer(fd, key, keysize) == keysize) - r = 0; - else - log_err(_("Cannot write to keyfile %s."), file); - - close(fd); - return r; -}