Commit 61bf96ca authored by Heikki Linnakangas's avatar Heikki Linnakangas

Refactor libpq authentication request processing.

Move the responsibility of reading the data from the authentication request
message from PQconnectPoll() to pg_fe_sendauth(). This way, PQconnectPoll()
doesn't need to know about all the different authentication request types,
and we don't need the extra fields in the pg_conn struct to pass the data
from PQconnectPoll() to pg_fe_sendauth() anymore.

Reviewed by Michael Paquier.

Discussion: https://www.postgresql.org/message-id/6490b975-5ee1-6280-ac1d-af975b19fb9a%40iki.fi
parent 5e39f06c
This diff is collapsed.
......@@ -19,7 +19,7 @@
/* Prototypes for functions in fe-auth.c */
extern int pg_fe_sendauth(AuthRequest areq, PGconn *conn);
extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn);
extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
/* Prototypes for functions in fe-auth-scram.c */
......
......@@ -2483,6 +2483,7 @@ keep_going: /* We will come back to here until there is
int msgLength;
int avail;
AuthRequest areq;
int res;
/*
* Scan the message from current point (note that if we find
......@@ -2672,116 +2673,50 @@ keep_going: /* We will come back to here until there is
/* We'll come back when there are more data */
return PGRES_POLLING_READING;
}
/* Get the password salt if there is one. */
if (areq == AUTH_REQ_MD5)
{
if (pqGetnchar(conn->md5Salt,
sizeof(conn->md5Salt), conn))
{
/* We'll come back when there are more data */
return PGRES_POLLING_READING;
}
}
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
msgLength -= 4;
/*
* Continue GSSAPI/SSPI authentication
* Ensure the password salt is in the input buffer, if it's an
* MD5 request. All the other authentication methods that
* contain extra data in the authentication request are only
* supported in protocol version 3, in which case we already
* read the whole message above.
*/
if (areq == AUTH_REQ_GSS_CONT)
{
int llen = msgLength - 4;
/*
* We can be called repeatedly for the same buffer. Avoid
* re-allocating the buffer in this case - just re-use the
* old buffer.
*/
if (llen != conn->ginbuf.length)
{
if (conn->ginbuf.value)
free(conn->ginbuf.value);
conn->ginbuf.length = llen;
conn->ginbuf.value = malloc(llen);
if (!conn->ginbuf.value)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating GSSAPI buffer (%d)"),
llen);
goto error_return;
}
}
if (pqGetnchar(conn->ginbuf.value, llen, conn))
{
/* We'll come back when there is more data. */
return PGRES_POLLING_READING;
}
}
#endif
/* Get additional payload for SASL, if any */
if ((areq == AUTH_REQ_SASL ||
areq == AUTH_REQ_SASL_CONT) &&
msgLength > 4)
if (areq == AUTH_REQ_MD5 && PG_PROTOCOL_MAJOR(conn->pversion) < 3)
{
int llen = msgLength - 4;
msgLength += 4;
/*
* We can be called repeatedly for the same buffer. Avoid
* re-allocating the buffer in this case - just re-use the
* old buffer.
*/
if (llen != conn->auth_req_inlen)
avail = conn->inEnd - conn->inCursor;
if (avail < 4)
{
if (conn->auth_req_inbuf)
{
free(conn->auth_req_inbuf);
conn->auth_req_inbuf = NULL;
}
conn->auth_req_inlen = llen;
conn->auth_req_inbuf = malloc(llen + 1);
if (!conn->auth_req_inbuf)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating SASL buffer (%d)"),
llen);
/*
* Before returning, try to enlarge the input buffer
* if needed to hold the whole message; see notes in
* pqParseInput3.
*/
if (pqCheckInBufferSpace(conn->inCursor + (size_t) 4,
conn))
goto error_return;
}
}
if (pqGetnchar(conn->auth_req_inbuf, llen, conn))
{
/* We'll come back when there is more data. */
/* We'll come back when there is more data */
return PGRES_POLLING_READING;
}
/*
* For safety and convenience, always ensure the in-buffer
* is NULL-terminated.
*/
conn->auth_req_inbuf[llen] = '\0';
}
/*
* OK, we successfully read the message; mark data consumed
*/
conn->inStart = conn->inCursor;
/* Respond to the request if necessary. */
/*
* Process the rest of the authentication request message, and
* respond to it if necessary.
*
* Note that conn->pghost must be non-NULL if we are going to
* avoid the Kerberos code doing a hostname look-up.
*/
res = pg_fe_sendauth(areq, msgLength, conn);
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (pg_fe_sendauth(areq, conn) != STATUS_OK)
{
conn->errorMessage.len = strlen(conn->errorMessage.data);
/* OK, we have processed the message; mark data consumed */
conn->inStart = conn->inCursor;
if (res != STATUS_OK)
goto error_return;
}
conn->errorMessage.len = strlen(conn->errorMessage.data);
/*
* Just make sure that any data sent by pg_fe_sendauth is
......@@ -3522,17 +3457,9 @@ closePGconn(PGconn *conn)
gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
if (conn->gtarg_nam)
gss_release_name(&min_s, &conn->gtarg_nam);
if (conn->ginbuf.length)
gss_release_buffer(&min_s, &conn->ginbuf);
if (conn->goutbuf.length)
gss_release_buffer(&min_s, &conn->goutbuf);
}
#endif
#ifdef ENABLE_SSPI
if (conn->ginbuf.length)
free(conn->ginbuf.value);
conn->ginbuf.length = 0;
conn->ginbuf.value = NULL;
if (conn->sspitarget)
free(conn->sspitarget);
conn->sspitarget = NULL;
......
......@@ -419,7 +419,6 @@ struct pg_conn
/* Miscellaneous stuff */
int be_pid; /* PID of backend --- needed for cancels */
int be_key; /* key of backend --- needed for cancels */
char md5Salt[4]; /* password salt received from backend */
pgParameterStatus *pstatus; /* ParameterStatus data */
int client_encoding; /* encoding id */
bool std_strings; /* standard_conforming_strings */
......@@ -452,10 +451,6 @@ struct pg_conn
PGresult *result; /* result being constructed */
PGresult *next_result; /* next result (used in single-row mode) */
/* Buffer to hold incoming authentication request data */
char *auth_req_inbuf;
int auth_req_inlen;
/* Assorted state for SASL, SSL, GSS, etc */
void *sasl_state;
......@@ -479,14 +474,10 @@ struct pg_conn
#ifdef ENABLE_GSS
gss_ctx_id_t gctx; /* GSS context */
gss_name_t gtarg_nam; /* GSS target name */
gss_buffer_desc ginbuf; /* GSS input token */
gss_buffer_desc goutbuf; /* GSS output token */
#endif
#ifdef ENABLE_SSPI
#ifndef ENABLE_GSS
gss_buffer_desc ginbuf; /* GSS input token */
#else
#ifdef ENABLE_GSS
char *gsslib; /* What GSS library to use ("gssapi" or
* "sspi") */
#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