Commit fe7bdf0b authored by Heikki Linnakangas's avatar Heikki Linnakangas

Clean up password authentication code a bit.

Commit fe0a0b59, which moved code to do MD5 authentication to a separate
CheckMD5Auth() function, left behind a comment that really belongs inside
the function, too. Also move the check for db_user_namespace inside the
function, seems clearer that way.

Now that the md5 salt is passed as argument to md5_crypt_verify, it's a bit
silly that it peeks into the Port struct to see if MD5 authentication was
used. Seems more straightforward to treat it as an MD5 authentication, if
the md5 salt argument is given. And after that, md5_crypt_verify only used
the Port argument to look at port->user_name, but that is redundant,
because it is also passed as a separate 'role' argument. So remove the Port
argument altogether.
parent f7d54f4f
...@@ -544,11 +544,6 @@ ClientAuthentication(Port *port) ...@@ -544,11 +544,6 @@ ClientAuthentication(Port *port)
break; break;
case uaMD5: case uaMD5:
if (Db_user_namespace)
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
/* include the salt to use for computing the response */
status = CheckMD5Auth(port, &logdetail); status = CheckMD5Auth(port, &logdetail);
break; break;
...@@ -714,6 +709,12 @@ CheckMD5Auth(Port *port, char **logdetail) ...@@ -714,6 +709,12 @@ CheckMD5Auth(Port *port, char **logdetail)
char *passwd; char *passwd;
int result; int result;
if (Db_user_namespace)
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
/* include the salt to use for computing the response */
pg_backend_random(md5Salt, 4); pg_backend_random(md5Salt, 4);
sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4); sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
...@@ -723,7 +724,7 @@ CheckMD5Auth(Port *port, char **logdetail) ...@@ -723,7 +724,7 @@ CheckMD5Auth(Port *port, char **logdetail)
if (passwd == NULL) if (passwd == NULL)
return STATUS_EOF; /* client wouldn't send password */ return STATUS_EOF; /* client wouldn't send password */
result = md5_crypt_verify(port, port->user_name, passwd, md5Salt, 4, logdetail); result = md5_crypt_verify(port->user_name, passwd, md5Salt, 4, logdetail);
pfree(passwd); pfree(passwd);
...@@ -748,7 +749,7 @@ CheckPasswordAuth(Port *port, char **logdetail) ...@@ -748,7 +749,7 @@ CheckPasswordAuth(Port *port, char **logdetail)
if (passwd == NULL) if (passwd == NULL)
return STATUS_EOF; /* client wouldn't send password */ return STATUS_EOF; /* client wouldn't send password */
result = md5_crypt_verify(port, port->user_name, passwd, NULL, 0, logdetail); result = md5_crypt_verify(port->user_name, passwd, NULL, 0, logdetail);
pfree(passwd); pfree(passwd);
......
...@@ -31,11 +31,16 @@ ...@@ -31,11 +31,16 @@
/* /*
* Check given password for given user, and return STATUS_OK or STATUS_ERROR. * 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 * In the error case, optionally store a palloc'd string at *logdetail
* that will be sent to the postmaster log (but not the client). * that will be sent to the postmaster log (but not the client).
*/ */
int 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) char *md5_salt, int md5_salt_len, char **logdetail)
{ {
int retval = STATUS_ERROR; int retval = STATUS_ERROR;
...@@ -88,10 +93,10 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass, ...@@ -88,10 +93,10 @@ 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 * error is out-of-memory, which is unlikely, and if it did happen adding
* a psprintf call would only make things worse.) * a psprintf call would only make things worse.)
*/ */
switch (port->hba->auth_method) if (md5_salt)
{ {
case uaMD5: /* MD5 authentication */
Assert(md5_salt != NULL && md5_salt_len > 0); Assert(md5_salt_len > 0);
crypt_pwd = palloc(MD5_PASSWD_LEN + 1); crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
if (isMD5(shadow_pass)) if (isMD5(shadow_pass))
{ {
...@@ -110,8 +115,8 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass, ...@@ -110,8 +115,8 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
char *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1); char *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);
if (!pg_md5_encrypt(shadow_pass, if (!pg_md5_encrypt(shadow_pass,
port->user_name, role,
strlen(port->user_name), strlen(role),
crypt_pwd2)) crypt_pwd2))
{ {
pfree(crypt_pwd); pfree(crypt_pwd);
...@@ -128,15 +133,17 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass, ...@@ -128,15 +133,17 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
} }
pfree(crypt_pwd2); pfree(crypt_pwd2);
} }
break; }
default: else
{
/* Client sent password in plaintext */
if (isMD5(shadow_pass)) if (isMD5(shadow_pass))
{ {
/* Encrypt user-supplied password to match stored MD5 */ /* Encrypt user-supplied password to match stored MD5 */
crypt_client_pass = palloc(MD5_PASSWD_LEN + 1); crypt_client_pass = palloc(MD5_PASSWD_LEN + 1);
if (!pg_md5_encrypt(client_pass, if (!pg_md5_encrypt(client_pass,
port->user_name, role,
strlen(port->user_name), strlen(role),
crypt_client_pass)) crypt_client_pass))
{ {
pfree(crypt_client_pass); pfree(crypt_client_pass);
...@@ -144,7 +151,6 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass, ...@@ -144,7 +151,6 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
} }
} }
crypt_pwd = shadow_pass; crypt_pwd = shadow_pass;
break;
} }
if (strcmp(crypt_client_pass, crypt_pwd) == 0) if (strcmp(crypt_client_pass, crypt_pwd) == 0)
...@@ -167,7 +173,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass, ...@@ -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\"."), *logdetail = psprintf(_("Password does not match for user \"%s\"."),
role); role);
if (port->hba->auth_method == uaMD5) if (crypt_pwd != shadow_pass)
pfree(crypt_pwd); pfree(crypt_pwd);
if (crypt_client_pass != client_pass) if (crypt_client_pass != client_pass)
pfree(crypt_client_pass); pfree(crypt_client_pass);
......
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
#ifndef PG_CRYPT_H #ifndef PG_CRYPT_H
#define PG_CRYPT_H #define PG_CRYPT_H
#include "libpq/libpq-be.h" #include "datatype/timestamp.h"
extern int md5_crypt_verify(const Port *port, const char *role, extern int md5_crypt_verify(const char *role, char *client_pass,
char *client_pass, char *md5_salt, int md5_salt_len, char **logdetail); char *md5_salt, int md5_salt_len, char **logdetail);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment