diff options
Diffstat (limited to 'src/backend/libpq/crypt.c')
-rw-r--r-- | src/backend/libpq/crypt.c | 108 |
1 files changed, 57 insertions, 51 deletions
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index 35b657adbbe..b4ca17431a2 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -31,11 +31,16 @@ /* * Check given password for given user, and return STATUS_OK or STATUS_ERROR. + * + * 'client_pass' is the password response given by the remote user. If + * 'md5_salt' is not NULL, it is a response to an MD5 authentication + * challenge, with the given salt. Otherwise, it is a plaintext password. + * * In the error case, optionally store a palloc'd string at *logdetail * that will be sent to the postmaster log (but not the client). */ int -md5_crypt_verify(const Port *port, const char *role, char *client_pass, +md5_crypt_verify(const char *role, char *client_pass, char *md5_salt, int md5_salt_len, char **logdetail) { int retval = STATUS_ERROR; @@ -88,63 +93,64 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass, * error is out-of-memory, which is unlikely, and if it did happen adding * a psprintf call would only make things worse.) */ - switch (port->hba->auth_method) + if (md5_salt) { - case uaMD5: - Assert(md5_salt != NULL && md5_salt_len > 0); - crypt_pwd = palloc(MD5_PASSWD_LEN + 1); - if (isMD5(shadow_pass)) + /* MD5 authentication */ + Assert(md5_salt_len > 0); + crypt_pwd = palloc(MD5_PASSWD_LEN + 1); + if (isMD5(shadow_pass)) + { + /* stored password already encrypted, only do salt */ + if (!pg_md5_encrypt(shadow_pass + strlen("md5"), + md5_salt, md5_salt_len, + crypt_pwd)) { - /* stored password already encrypted, only do salt */ - if (!pg_md5_encrypt(shadow_pass + strlen("md5"), - md5_salt, md5_salt_len, - crypt_pwd)) - { - pfree(crypt_pwd); - return STATUS_ERROR; - } + pfree(crypt_pwd); + return STATUS_ERROR; } - else - { - /* stored password is plain, double-encrypt */ - char *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1); + } + else + { + /* stored password is plain, double-encrypt */ + char *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1); - if (!pg_md5_encrypt(shadow_pass, - port->user_name, - strlen(port->user_name), - crypt_pwd2)) - { - pfree(crypt_pwd); - pfree(crypt_pwd2); - return STATUS_ERROR; - } - if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), - md5_salt, md5_salt_len, - crypt_pwd)) - { - pfree(crypt_pwd); - pfree(crypt_pwd2); - return STATUS_ERROR; - } + if (!pg_md5_encrypt(shadow_pass, + role, + strlen(role), + crypt_pwd2)) + { + pfree(crypt_pwd); pfree(crypt_pwd2); + return STATUS_ERROR; } - break; - default: - if (isMD5(shadow_pass)) + if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), + md5_salt, md5_salt_len, + crypt_pwd)) { - /* Encrypt user-supplied password to match stored MD5 */ - crypt_client_pass = palloc(MD5_PASSWD_LEN + 1); - if (!pg_md5_encrypt(client_pass, - port->user_name, - strlen(port->user_name), - crypt_client_pass)) - { - pfree(crypt_client_pass); - return STATUS_ERROR; - } + pfree(crypt_pwd); + pfree(crypt_pwd2); + return STATUS_ERROR; } - crypt_pwd = shadow_pass; - break; + pfree(crypt_pwd2); + } + } + else + { + /* Client sent password in plaintext */ + if (isMD5(shadow_pass)) + { + /* Encrypt user-supplied password to match stored MD5 */ + crypt_client_pass = palloc(MD5_PASSWD_LEN + 1); + if (!pg_md5_encrypt(client_pass, + role, + strlen(role), + crypt_client_pass)) + { + pfree(crypt_client_pass); + return STATUS_ERROR; + } + } + crypt_pwd = shadow_pass; } if (strcmp(crypt_client_pass, crypt_pwd) == 0) @@ -167,7 +173,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass, *logdetail = psprintf(_("Password does not match for user \"%s\"."), role); - if (port->hba->auth_method == uaMD5) + if (crypt_pwd != shadow_pass) pfree(crypt_pwd); if (crypt_client_pass != client_pass) pfree(crypt_client_pass); |