Skip to content

Commit c46c85d

Browse files
committed
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.
1 parent bfc8068 commit c46c85d

File tree

3 files changed

+20
-28
lines changed

3 files changed

+20
-28
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7495,6 +7495,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
74957495
</para>
74967496
</listitem>
74977497

7498+
<listitem>
7499+
<para>
7500+
<indexterm>
7501+
<primary><envar>PGGSSENCMODE</envar></primary>
7502+
</indexterm>
7503+
<envar>PGGSSENCMODE</envar> behaves the same as the <xref
7504+
linkend="libpq-connect-gssencmode"/> connection parameter.
7505+
</para>
7506+
</listitem>
7507+
74987508
<listitem>
74997509
<para>
75007510
<indexterm>

src/interfaces/libpq/fe-connect.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
308308
* Expose gssencmode similarly to sslmode - we can still handle "disable"
309309
* and "prefer".
310310
*/
311-
{"gssencmode", "PGGSSMODE", DefaultGSSMode, NULL,
311+
{"gssencmode", "PGGSSENCMODE", DefaultGSSMode, NULL,
312312
"GSS-Mode", "", 7, /* sizeof("disable") == 7 */
313313
offsetof(struct pg_conn, gssencmode)},
314314

@@ -1875,7 +1875,7 @@ connectDBStart(PGconn *conn)
18751875
resetPQExpBuffer(&conn->errorMessage);
18761876

18771877
#ifdef ENABLE_GSS
1878-
if (conn->gssencmode[0] == 'd') /* "disable" */
1878+
if (conn->gssencmode[0] == 'd') /* "disable" */
18791879
conn->try_gss = false;
18801880
#endif
18811881

src/interfaces/libpq/fe-secure-gssapi.c

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -459,42 +459,24 @@ pqsecure_open_gss(PGconn *conn)
459459
*
460460
* This is safe to do because we shouldn't ever get a packet over 8192
461461
* and therefore the actual length bytes, being that they are in
462-
* network byte order, for any real packet will be two zero bytes.
462+
* network byte order, for any real packet will start with two zero
463+
* bytes.
463464
*/
464465
if (PqGSSRecvBuffer[0] == 'E')
465466
{
466467
/*
467-
* For an error message, the length is after the E, so read one
468-
* more byte to get the full length
468+
* For an error packet during startup, we don't get a length, so
469+
* simply read as much as we can fit into our buffer (as a string,
470+
* so leave a spot at the end for a NULL byte too) and report that
471+
* back to the caller.
469472
*/
470-
result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, 1, &ret);
473+
result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, PQ_GSS_RECV_BUFFER_SIZE - PqGSSRecvLength - 1, &ret);
471474
if (result != PGRES_POLLING_OK)
472475
return result;
473476

474477
PqGSSRecvLength += ret;
475478

476-
if (PqGSSRecvLength < 1 + sizeof(uint32))
477-
return PGRES_POLLING_READING;
478-
479-
input.length = ntohl(*(uint32 *) PqGSSRecvBuffer + 1);
480-
if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32) - 1)
481-
{
482-
printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Over-size error packet sent by the server."));
483-
return PGRES_POLLING_FAILED;
484-
}
485-
486-
result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, input.length - PqGSSRecvLength - 1 - sizeof(uint32), &ret);
487-
if (result != PGRES_POLLING_OK)
488-
return result;
489-
490-
PqGSSRecvLength += ret;
491-
492-
if (PqGSSRecvLength < 1 + sizeof(uint32) + input.length)
493-
return PGRES_POLLING_READING;
494-
495-
printfPQExpBuffer(&conn->errorMessage,
496-
libpq_gettext("Server error: %s"),
497-
PqGSSRecvBuffer + 1 + sizeof(int32));
479+
printfPQExpBuffer(&conn->errorMessage, "%s", PqGSSRecvBuffer + 1);
498480

499481
return PGRES_POLLING_FAILED;
500482
}

0 commit comments

Comments
 (0)