diff options
Diffstat (limited to 'src/backend/libpq/crypt.c')
-rw-r--r-- | src/backend/libpq/crypt.c | 83 |
1 files changed, 49 insertions, 34 deletions
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index e230d53577e..77250b40310 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/libpq/crypt.c,v 1.77 2009/01/01 17:23:42 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/libpq/crypt.c,v 1.78 2009/08/29 19:26:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,38 +20,63 @@ #include <crypt.h> #endif +#include "catalog/pg_authid.h" #include "libpq/crypt.h" #include "libpq/md5.h" +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/syscache.h" int md5_crypt_verify(const Port *port, const char *role, char *client_pass) { - char *shadow_pass = NULL, - *valuntil = NULL, - *crypt_pwd; int retval = STATUS_ERROR; - List **line; - ListCell *token; + char *shadow_pass, + *crypt_pwd; + TimestampTz vuntil = 0; char *crypt_client_pass = client_pass; + HeapTuple roleTup; + Datum datum; + bool isnull; + + /* + * Disable immediate interrupts while doing database access. (Note + * we don't bother to turn this back on if we hit one of the failure + * conditions, since we can expect we'll just exit right away anyway.) + */ + ImmediateInterruptOK = false; - if ((line = get_role_line(role)) == NULL) - return STATUS_ERROR; + /* Get role info from pg_authid */ + roleTup = SearchSysCache(AUTHNAME, + PointerGetDatum(role), + 0, 0, 0); + if (!HeapTupleIsValid(roleTup)) + return STATUS_ERROR; /* no such user */ - /* Skip over rolename */ - token = list_head(*line); - if (token) - token = lnext(token); - if (token) + datum = SysCacheGetAttr(AUTHNAME, roleTup, + Anum_pg_authid_rolpassword, &isnull); + if (isnull) { - shadow_pass = (char *) lfirst(token); - token = lnext(token); - if (token) - valuntil = (char *) lfirst(token); + ReleaseSysCache(roleTup); + return STATUS_ERROR; /* user has no password */ } + shadow_pass = TextDatumGetCString(datum); + + datum = SysCacheGetAttr(AUTHNAME, roleTup, + Anum_pg_authid_rolvaliduntil, &isnull); + if (!isnull) + vuntil = DatumGetTimestampTz(datum); - if (shadow_pass == NULL || *shadow_pass == '\0') - return STATUS_ERROR; + ReleaseSysCache(roleTup); + + if (*shadow_pass == '\0') + return STATUS_ERROR; /* empty password */ + + /* Re-enable immediate response to SIGTERM/SIGINT/timeout interrupts */ + ImmediateInterruptOK = true; + /* And don't forget to detect one that already arrived */ + CHECK_FOR_INTERRUPTS(); /* * Compare with the encrypted or plain password depending on the @@ -119,24 +144,14 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass) if (strcmp(crypt_client_pass, crypt_pwd) == 0) { /* - * Password OK, now check to be sure we are not past valuntil + * Password OK, now check to be sure we are not past rolvaliduntil */ - if (valuntil == NULL || *valuntil == '\0') + if (isnull) retval = STATUS_OK; + else if (vuntil < GetCurrentTimestamp()) + retval = STATUS_ERROR; else - { - TimestampTz vuntil; - - vuntil = DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in, - CStringGetDatum(valuntil), - ObjectIdGetDatum(InvalidOid), - Int32GetDatum(-1))); - - if (vuntil < GetCurrentTimestamp()) - retval = STATUS_ERROR; - else - retval = STATUS_OK; - } + retval = STATUS_OK; } if (port->hba->auth_method == uaMD5) |