0005-Create-generic-routine-to-fetch-password-and-valid-u.patch
application/x-patch
Filename: 0005-Create-generic-routine-to-fetch-password-and-valid-u.patch
Type: application/x-patch
Part: 4
Patch
Format: format-patch
Series: patch 0005
Subject: Create generic routine to fetch password and valid until values for a role
| File | + | − |
|---|---|---|
| src/backend/libpq/crypt.c | 44 | 15 |
| src/include/libpq/crypt.h | 2 | 0 |
From 65bf1db7dae12f3e3095de73c1449b11437399dc Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Mon, 25 Jul 2016 14:40:15 +0900
Subject: [PATCH 5/8] Create generic routine to fetch password and valid until
values for a role
This is used now for the MD5-encrypted case and the plain text, and this
is going to be used as well for SCRAM-SHA256. That's as well useful for
any new password-based protocols.
---
src/backend/libpq/crypt.c | 59 +++++++++++++++++++++++++++++++++++------------
src/include/libpq/crypt.h | 2 ++
2 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index d84a180..1c41c57 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -1,8 +1,8 @@
/*-------------------------------------------------------------------------
*
* crypt.c
- * Look into the password file and check the encrypted password with
- * the one passed in from the frontend.
+ * Set of routines to look into the password file and check the
+ * encrypted password with the one passed in from the frontend.
*
* Original coding by Todd A. Brandys
*
@@ -30,23 +30,25 @@
/*
- * Check given password for given user, and return STATUS_OK or STATUS_ERROR.
- * In the error case, optionally store a palloc'd string at *logdetail
- * that will be sent to the postmaster log (but not the client).
+ * Fetch information of a given role necessary to check password data,
+ * and return STATUS_OK or STATUS_ERROR. In the case of an error,
+ * 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,
+get_role_details(const char *role,
+ char **password,
+ TimestampTz *vuntil,
+ bool *vuntil_null,
char **logdetail)
{
- int retval = STATUS_ERROR;
- char *shadow_pass,
- *crypt_pwd;
- TimestampTz vuntil = 0;
- char *crypt_client_pass = client_pass;
HeapTuple roleTup;
Datum datum;
bool isnull;
+ *vuntil = 0;
+ *vuntil_null = true;
+
/* Get role info from pg_authid */
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
if (!HeapTupleIsValid(roleTup))
@@ -65,22 +67,49 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
role);
return STATUS_ERROR; /* user has no password */
}
- shadow_pass = TextDatumGetCString(datum);
+ *password = TextDatumGetCString(datum);
datum = SysCacheGetAttr(AUTHNAME, roleTup,
Anum_pg_authid_rolvaliduntil, &isnull);
if (!isnull)
- vuntil = DatumGetTimestampTz(datum);
+ {
+ *vuntil = DatumGetTimestampTz(datum);
+ *vuntil_null = false;
+ }
ReleaseSysCache(roleTup);
- if (*shadow_pass == '\0')
+ if (**password == '\0')
{
*logdetail = psprintf(_("User \"%s\" has an empty password."),
role);
return STATUS_ERROR; /* empty password */
}
+ return STATUS_OK;
+}
+
+/*
+ * Check given password for given user, and return STATUS_OK or STATUS_ERROR.
+ * 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,
+ char **logdetail)
+{
+ int retval = STATUS_ERROR;
+ char *shadow_pass,
+ *crypt_pwd;
+ TimestampTz vuntil;
+ char *crypt_client_pass = client_pass;
+ bool vuntil_null;
+
+ /* fetch details about role needed for password checks */
+ if (get_role_details(role, &shadow_pass, &vuntil, &vuntil_null,
+ logdetail) != STATUS_OK)
+ return STATUS_ERROR;
+
/*
* Compare with the encrypted or plain password depending on the
* authentication method being used for this connection. (We do not
@@ -152,7 +181,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
/*
* Password OK, now check to be sure we are not past rolvaliduntil
*/
- if (isnull)
+ if (vuntil_null)
retval = STATUS_OK;
else if (vuntil < GetCurrentTimestamp())
{
diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h
index 5725bb4..856c451 100644
--- a/src/include/libpq/crypt.h
+++ b/src/include/libpq/crypt.h
@@ -15,6 +15,8 @@
#include "libpq/libpq-be.h"
+extern int get_role_details(const char *role, char **password,
+ TimestampTz *vuntil, bool *vuntil_null, char **logdetail);
extern int md5_crypt_verify(const Port *port, const char *role,
char *client_pass, char **logdetail);
--
2.9.3