summaryrefslogtreecommitdiff
path: root/src/backend/libpq/crypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/crypt.c')
-rw-r--r--src/backend/libpq/crypt.c126
1 files changed, 38 insertions, 88 deletions
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index 9fe79b48946..e7a6b04fb5a 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -109,9 +109,8 @@ get_password_type(const char *shadow_pass)
* Given a user-supplied password, convert it into a verifier of
* 'target_type' kind.
*
- * If the password looks like a valid MD5 hash, it is stored as it is.
- * We cannot reverse the hash, so even if the caller requested a plaintext
- * plaintext password, the MD5 hash is returned.
+ * If the password is already in encrypted form, we cannot reverse the
+ * hash, so it is stored as it is regardless of the requested type.
*/
char *
encrypt_password(PasswordType target_type, const char *role,
@@ -120,54 +119,30 @@ encrypt_password(PasswordType target_type, const char *role,
PasswordType guessed_type = get_password_type(password);
char *encrypted_password;
- switch (target_type)
+ if (guessed_type != PASSWORD_TYPE_PLAINTEXT)
{
- case PASSWORD_TYPE_PLAINTEXT:
-
- /*
- * We cannot convert a hashed password back to plaintext, so just
- * store the password as it was, whether it was hashed or not.
- */
- return pstrdup(password);
+ /*
+ * Cannot convert an already-encrypted password from one
+ * format to another, so return it as it is.
+ */
+ return pstrdup(password);
+ }
+ switch (target_type)
+ {
case PASSWORD_TYPE_MD5:
- switch (guessed_type)
- {
- case PASSWORD_TYPE_PLAINTEXT:
- encrypted_password = palloc(MD5_PASSWD_LEN + 1);
-
- if (!pg_md5_encrypt(password, role, strlen(role),
- encrypted_password))
- elog(ERROR, "password encryption failed");
- return encrypted_password;
+ encrypted_password = palloc(MD5_PASSWD_LEN + 1);
- case PASSWORD_TYPE_SCRAM_SHA_256:
-
- /*
- * cannot convert a SCRAM verifier to an MD5 hash, so fall
- * through to save the SCRAM verifier instead.
- */
- case PASSWORD_TYPE_MD5:
- return pstrdup(password);
- }
- break;
+ if (!pg_md5_encrypt(password, role, strlen(role),
+ encrypted_password))
+ elog(ERROR, "password encryption failed");
+ return encrypted_password;
case PASSWORD_TYPE_SCRAM_SHA_256:
- switch (guessed_type)
- {
- case PASSWORD_TYPE_PLAINTEXT:
- return pg_be_scram_build_verifier(password);
-
- case PASSWORD_TYPE_MD5:
+ return pg_be_scram_build_verifier(password);
- /*
- * cannot convert an MD5 hash to a SCRAM verifier, so fall
- * through to save the MD5 hash instead.
- */
- case PASSWORD_TYPE_SCRAM_SHA_256:
- return pstrdup(password);
- }
- break;
+ case PASSWORD_TYPE_PLAINTEXT:
+ elog(ERROR, "cannot encrypt password with 'plaintext'");
}
/*
@@ -197,10 +172,17 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
{
int retval;
char crypt_pwd[MD5_PASSWD_LEN + 1];
- char crypt_pwd2[MD5_PASSWD_LEN + 1];
Assert(md5_salt_len > 0);
+ if (get_password_type(shadow_pass) != PASSWORD_TYPE_MD5)
+ {
+ /* incompatible password hash format. */
+ *logdetail = psprintf(_("User \"%s\" has a password that cannot be used with MD5 authentication."),
+ role);
+ return STATUS_ERROR;
+ }
+
/*
* Compute the correct answer for the MD5 challenge.
*
@@ -208,40 +190,12 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
* below: the only possible error is out-of-memory, which is unlikely, and
* if it did happen adding a psprintf call would only make things worse.
*/
- switch (get_password_type(shadow_pass))
+ /* stored password already encrypted, only do salt */
+ if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
+ md5_salt, md5_salt_len,
+ crypt_pwd))
{
- case PASSWORD_TYPE_MD5:
- /* stored password already encrypted, only do salt */
- if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
- md5_salt, md5_salt_len,
- crypt_pwd))
- {
- return STATUS_ERROR;
- }
- break;
-
- case PASSWORD_TYPE_PLAINTEXT:
- /* stored password is plain, double-encrypt */
- if (!pg_md5_encrypt(shadow_pass,
- role,
- strlen(role),
- crypt_pwd2))
- {
- return STATUS_ERROR;
- }
- if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"),
- md5_salt, md5_salt_len,
- crypt_pwd))
- {
- return STATUS_ERROR;
- }
- break;
-
- default:
- /* unknown password hash format. */
- *logdetail = psprintf(_("User \"%s\" has a password that cannot be used with MD5 authentication."),
- role);
- return STATUS_ERROR;
+ return STATUS_ERROR;
}
if (strcmp(client_pass, crypt_pwd) == 0)
@@ -259,8 +213,8 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
/*
* Check given password for given user, and return STATUS_OK or STATUS_ERROR.
*
- * 'shadow_pass' is the user's correct password or password hash, as stored
- * in pg_authid.rolpassword.
+ * 'shadow_pass' is the user's correct password hash, as stored in
+ * pg_authid.rolpassword.
* 'client_pass' is the password given by the remote user.
*
* In the error case, optionally store a palloc'd string at *logdetail
@@ -320,14 +274,10 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
break;
case PASSWORD_TYPE_PLAINTEXT:
- if (strcmp(client_pass, shadow_pass) == 0)
- return STATUS_OK;
- else
- {
- *logdetail = psprintf(_("Password does not match for user \"%s\"."),
- role);
- return STATUS_ERROR;
- }
+ /*
+ * We never store passwords in plaintext, so this shouldn't
+ * happen.
+ */
break;
}