mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
libpq: Improve error handling in passwordFromFile()
Previously, passwordFromFile() returned NULL for valid cases (like no matching password found) and actual errors (two out-of-memory paths). This made it impossible for its sole caller, pqConnectOptions2(), to distinguish between these scenarios and fail the connection appropriately should an out-of-memory error occur. This patch extends passwordFromFile() to be able to detect both valid and failure cases, with an error string given back to the caller of the function. Out-of-memory failures unlikely happen in the field, so no backpatch is done. Author: Joshua Shanks <jjshanks@gmail.com> Discussion: https://postgr.es/m/CAOxqWDfihFRmhNVdfu8epYTXQRxkCHSOrg+=-ij2c_X3gW=o3g@mail.gmail.com
This commit is contained in:
@@ -501,8 +501,9 @@ static int parseServiceFile(const char *serviceFile,
|
|||||||
PQExpBuffer errorMessage,
|
PQExpBuffer errorMessage,
|
||||||
bool *group_found);
|
bool *group_found);
|
||||||
static char *pwdfMatchesString(char *buf, const char *token);
|
static char *pwdfMatchesString(char *buf, const char *token);
|
||||||
static char *passwordFromFile(const char *hostname, const char *port, const char *dbname,
|
static char *passwordFromFile(const char *hostname, const char *port,
|
||||||
const char *username, const char *pgpassfile);
|
const char *dbname, const char *username,
|
||||||
|
const char *pgpassfile, const char **errmsg);
|
||||||
static void pgpassfileWarning(PGconn *conn);
|
static void pgpassfileWarning(PGconn *conn);
|
||||||
static void default_threadlock(int acquire);
|
static void default_threadlock(int acquire);
|
||||||
static bool sslVerifyProtocolVersion(const char *version);
|
static bool sslVerifyProtocolVersion(const char *version);
|
||||||
@@ -1454,6 +1455,7 @@ pqConnectOptions2(PGconn *conn)
|
|||||||
* least one of them is guaranteed nonempty by now).
|
* least one of them is guaranteed nonempty by now).
|
||||||
*/
|
*/
|
||||||
const char *pwhost = conn->connhost[i].host;
|
const char *pwhost = conn->connhost[i].host;
|
||||||
|
const char *password_errmsg = NULL;
|
||||||
|
|
||||||
if (pwhost == NULL || pwhost[0] == '\0')
|
if (pwhost == NULL || pwhost[0] == '\0')
|
||||||
pwhost = conn->connhost[i].hostaddr;
|
pwhost = conn->connhost[i].hostaddr;
|
||||||
@@ -1463,7 +1465,15 @@ pqConnectOptions2(PGconn *conn)
|
|||||||
conn->connhost[i].port,
|
conn->connhost[i].port,
|
||||||
conn->dbName,
|
conn->dbName,
|
||||||
conn->pguser,
|
conn->pguser,
|
||||||
conn->pgpassfile);
|
conn->pgpassfile,
|
||||||
|
&password_errmsg);
|
||||||
|
|
||||||
|
if (password_errmsg != NULL)
|
||||||
|
{
|
||||||
|
conn->status = CONNECTION_BAD;
|
||||||
|
libpq_append_conn_error(conn, "%s", password_errmsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7942,10 +7952,16 @@ pwdfMatchesString(char *buf, const char *token)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a password from the password file. Return value is malloc'd. */
|
/*
|
||||||
|
* Get a password from the password file. Return value is malloc'd.
|
||||||
|
*
|
||||||
|
* On failure, *errmsg is set to an error to be returned. It is
|
||||||
|
* left NULL on success, or if no password could be found.
|
||||||
|
*/
|
||||||
static char *
|
static char *
|
||||||
passwordFromFile(const char *hostname, const char *port, const char *dbname,
|
passwordFromFile(const char *hostname, const char *port,
|
||||||
const char *username, const char *pgpassfile)
|
const char *dbname, const char *username,
|
||||||
|
const char *pgpassfile, const char **errmsg)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
@@ -7953,6 +7969,8 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
|
|||||||
#endif
|
#endif
|
||||||
PQExpBufferData buf;
|
PQExpBufferData buf;
|
||||||
|
|
||||||
|
*errmsg = NULL;
|
||||||
|
|
||||||
if (dbname == NULL || dbname[0] == '\0')
|
if (dbname == NULL || dbname[0] == '\0')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -8019,7 +8037,10 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
|
|||||||
{
|
{
|
||||||
/* Make sure there's a reasonable amount of room in the buffer */
|
/* Make sure there's a reasonable amount of room in the buffer */
|
||||||
if (!enlargePQExpBuffer(&buf, 128))
|
if (!enlargePQExpBuffer(&buf, 128))
|
||||||
|
{
|
||||||
|
*errmsg = libpq_gettext("out of memory");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read some data, appending it to what we already have */
|
/* Read some data, appending it to what we already have */
|
||||||
if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
|
if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
|
||||||
@@ -8058,7 +8079,7 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
|
|||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
/* Out of memory. XXX: an error message would be nice. */
|
*errmsg = libpq_gettext("out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user