mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-07 19:47:50 +08:00
Handle errors during GSSAPI startup better
There was some confusion over the format of the error message returned from the server during GSSAPI startup; specifically, it was expected that a length would be returned when, in reality, at this early stage in the startup sequence, no length is returned from the server as part of an error message. Correct the client-side code for dealing with error messages sent by the server during startup by simply reading what's available into our buffer, after we've discovered it's an error message, and then reporting back what was returned. In passing, also add in documentation of the environment variable PGGSSENCMODE which was missed previously, and adjust the code to look for the PGGSSENCMODE variable (the environment variable change was missed in the prior GSSMODE -> GSSENCMODE commit). Error-handling issue discovered by Peter Eisentraut, the rest were items discovered during testing of the error handling.
This commit is contained in:
parent
bfc80683ce
commit
c46c85d459
@ -7495,6 +7495,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<indexterm>
|
||||
<primary><envar>PGGSSENCMODE</envar></primary>
|
||||
</indexterm>
|
||||
<envar>PGGSSENCMODE</envar> behaves the same as the <xref
|
||||
linkend="libpq-connect-gssencmode"/> connection parameter.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<indexterm>
|
||||
|
@ -308,7 +308,7 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
|
||||
* Expose gssencmode similarly to sslmode - we can still handle "disable"
|
||||
* and "prefer".
|
||||
*/
|
||||
{"gssencmode", "PGGSSMODE", DefaultGSSMode, NULL,
|
||||
{"gssencmode", "PGGSSENCMODE", DefaultGSSMode, NULL,
|
||||
"GSS-Mode", "", 7, /* sizeof("disable") == 7 */
|
||||
offsetof(struct pg_conn, gssencmode)},
|
||||
|
||||
@ -1875,7 +1875,7 @@ connectDBStart(PGconn *conn)
|
||||
resetPQExpBuffer(&conn->errorMessage);
|
||||
|
||||
#ifdef ENABLE_GSS
|
||||
if (conn->gssencmode[0] == 'd') /* "disable" */
|
||||
if (conn->gssencmode[0] == 'd') /* "disable" */
|
||||
conn->try_gss = false;
|
||||
#endif
|
||||
|
||||
|
@ -459,42 +459,24 @@ pqsecure_open_gss(PGconn *conn)
|
||||
*
|
||||
* This is safe to do because we shouldn't ever get a packet over 8192
|
||||
* and therefore the actual length bytes, being that they are in
|
||||
* network byte order, for any real packet will be two zero bytes.
|
||||
* network byte order, for any real packet will start with two zero
|
||||
* bytes.
|
||||
*/
|
||||
if (PqGSSRecvBuffer[0] == 'E')
|
||||
{
|
||||
/*
|
||||
* For an error message, the length is after the E, so read one
|
||||
* more byte to get the full length
|
||||
* For an error packet during startup, we don't get a length, so
|
||||
* simply read as much as we can fit into our buffer (as a string,
|
||||
* so leave a spot at the end for a NULL byte too) and report that
|
||||
* back to the caller.
|
||||
*/
|
||||
result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, 1, &ret);
|
||||
result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, PQ_GSS_RECV_BUFFER_SIZE - PqGSSRecvLength - 1, &ret);
|
||||
if (result != PGRES_POLLING_OK)
|
||||
return result;
|
||||
|
||||
PqGSSRecvLength += ret;
|
||||
|
||||
if (PqGSSRecvLength < 1 + sizeof(uint32))
|
||||
return PGRES_POLLING_READING;
|
||||
|
||||
input.length = ntohl(*(uint32 *) PqGSSRecvBuffer + 1);
|
||||
if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32) - 1)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Over-size error packet sent by the server."));
|
||||
return PGRES_POLLING_FAILED;
|
||||
}
|
||||
|
||||
result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, input.length - PqGSSRecvLength - 1 - sizeof(uint32), &ret);
|
||||
if (result != PGRES_POLLING_OK)
|
||||
return result;
|
||||
|
||||
PqGSSRecvLength += ret;
|
||||
|
||||
if (PqGSSRecvLength < 1 + sizeof(uint32) + input.length)
|
||||
return PGRES_POLLING_READING;
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("Server error: %s"),
|
||||
PqGSSRecvBuffer + 1 + sizeof(int32));
|
||||
printfPQExpBuffer(&conn->errorMessage, "%s", PqGSSRecvBuffer + 1);
|
||||
|
||||
return PGRES_POLLING_FAILED;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user