Skip to content

Commit ea92f3a

Browse files
committed
libpq: Trace frontend authentication challenges
If tracing was enabled during connection startup, these messages would previously be listed in the trace output as something like this: F 54 Unknown message: 70 mismatched message length: consumed 4, expected 54 With this commit their type and contents are now correctly listed: F 36 StartupMessage 3 0 "user" "foo" "database" "alvherre" F 54 SASLInitialResponse "SCRAM-SHA-256" 32 'n,,n=,r=nq5zEPR/VREHEpOAZzH8Rujm' F 108 SASLResponse 'c=biws,r=nq5zEPR/VREHEpOAZzH8RujmVtWZDQ8glcrvy9OMNw7ZqFUn,p=BBwAKe0WjSvigB6RsmmArAC+hwucLeuwJrR5C/HQD5M=' Author: Jelte Fennema-Nio <postgres@jeltef.nl> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/CAGECzQSoPHtZ4xe0raJ6FYSEiPPS+YWXBhOGo+Y1YecLgknF3g@mail.gmail.com
1 parent 12d6c72 commit ea92f3a

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

src/interfaces/libpq/fe-auth.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ pg_GSS_continue(PGconn *conn, int payloadlen)
124124
* first or subsequent packet, just send the same kind of password
125125
* packet.
126126
*/
127+
conn->current_auth_response = AUTH_RESPONSE_GSS;
127128
if (pqPacketSend(conn, PqMsg_GSSResponse,
128129
goutbuf.value, goutbuf.length) != STATUS_OK)
129130
{
@@ -324,6 +325,7 @@ pg_SSPI_continue(PGconn *conn, int payloadlen)
324325
*/
325326
if (outbuf.pBuffers[0].cbBuffer > 0)
326327
{
328+
conn->current_auth_response = AUTH_RESPONSE_GSS;
327329
if (pqPacketSend(conn, PqMsg_GSSResponse,
328330
outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
329331
{
@@ -597,8 +599,10 @@ pg_SASL_init(PGconn *conn, int payloadlen)
597599
if (pqPutnchar(initialresponse, initialresponselen, conn))
598600
goto error;
599601
}
602+
conn->current_auth_response = AUTH_RESPONSE_SASL_INITIAL;
600603
if (pqPutMsgEnd(conn))
601604
goto error;
605+
602606
if (pqFlush(conn))
603607
goto error;
604608

@@ -683,6 +687,7 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
683687
/*
684688
* Send the SASL response to the server.
685689
*/
690+
conn->current_auth_response = AUTH_RESPONSE_SASL;
686691
res = pqPacketSend(conn, PqMsg_SASLResponse, output, outputlen);
687692
free(output);
688693

@@ -754,6 +759,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
754759
default:
755760
return STATUS_ERROR;
756761
}
762+
conn->current_auth_response = AUTH_RESPONSE_PASSWORD;
757763
ret = pqPacketSend(conn, PqMsg_PasswordMessage,
758764
pwd_to_send, strlen(pwd_to_send) + 1);
759765
free(crypt_pwd);

src/interfaces/libpq/fe-trace.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,42 @@ pqTraceOutput_CopyFail(FILE *f, const char *message, int *cursor)
354354
pqTraceOutputString(f, message, cursor, false);
355355
}
356356

357+
static void
358+
pqTraceOutput_GSSResponse(FILE *f, const char *message, int *cursor,
359+
int length, bool regress)
360+
{
361+
fprintf(f, "GSSResponse\t");
362+
pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, regress);
363+
}
364+
365+
static void
366+
pqTraceOutput_PasswordMessage(FILE *f, const char *message, int *cursor)
367+
{
368+
fprintf(f, "PasswordMessage\t");
369+
pqTraceOutputString(f, message, cursor, false);
370+
}
371+
372+
static void
373+
pqTraceOutput_SASLInitialResponse(FILE *f, const char *message, int *cursor,
374+
bool regress)
375+
{
376+
int initialResponse;
377+
378+
fprintf(f, "SASLInitialResponse\t");
379+
pqTraceOutputString(f, message, cursor, false);
380+
initialResponse = pqTraceOutputInt32(f, message, cursor, false);
381+
if (initialResponse != -1)
382+
pqTraceOutputNchar(f, initialResponse, message, cursor, regress);
383+
}
384+
385+
static void
386+
pqTraceOutput_SASLResponse(FILE *f, const char *message, int *cursor,
387+
int length, bool regress)
388+
{
389+
fprintf(f, "SASLResponse\t");
390+
pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, regress);
391+
}
392+
357393
static void
358394
pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regress)
359395
{
@@ -610,6 +646,39 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
610646
case PqMsg_CopyFail:
611647
pqTraceOutput_CopyFail(conn->Pfdebug, message, &logCursor);
612648
break;
649+
case PqMsg_GSSResponse:
650+
Assert(PqMsg_GSSResponse == PqMsg_PasswordMessage);
651+
Assert(PqMsg_GSSResponse == PqMsg_SASLInitialResponse);
652+
Assert(PqMsg_GSSResponse == PqMsg_SASLResponse);
653+
654+
/*
655+
* These messages share a common type byte, so we discriminate by
656+
* having the code store the auth type separately.
657+
*/
658+
switch (conn->current_auth_response)
659+
{
660+
case AUTH_RESPONSE_GSS:
661+
pqTraceOutput_GSSResponse(conn->Pfdebug, message,
662+
&logCursor, length, regress);
663+
break;
664+
case AUTH_RESPONSE_PASSWORD:
665+
pqTraceOutput_PasswordMessage(conn->Pfdebug, message,
666+
&logCursor);
667+
break;
668+
case AUTH_RESPONSE_SASL_INITIAL:
669+
pqTraceOutput_SASLInitialResponse(conn->Pfdebug, message,
670+
&logCursor, regress);
671+
break;
672+
case AUTH_RESPONSE_SASL:
673+
pqTraceOutput_SASLResponse(conn->Pfdebug, message,
674+
&logCursor, length, regress);
675+
break;
676+
default:
677+
fprintf(conn->Pfdebug, "UnknownAuthenticationResponse");
678+
break;
679+
}
680+
conn->current_auth_response = '\0';
681+
break;
613682
case PqMsg_FunctionCall:
614683
pqTraceOutput_FunctionCall(conn->Pfdebug, message, &logCursor, regress);
615684
break;

src/interfaces/libpq/libpq-int.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,18 @@ typedef enum
331331
PGQUERY_CLOSE /* Close Statement or Portal */
332332
} PGQueryClass;
333333

334+
335+
/*
336+
* valid values for pg_conn->current_auth_response. These are just for
337+
* libpq internal use: since authentication response types all use the
338+
* protocol byte 'p', fe-trace.c needs a way to distinguish them in order
339+
* to print them correctly.
340+
*/
341+
#define AUTH_RESPONSE_GSS 'G'
342+
#define AUTH_RESPONSE_PASSWORD 'P'
343+
#define AUTH_RESPONSE_SASL_INITIAL 'I'
344+
#define AUTH_RESPONSE_SASL 'S'
345+
334346
/*
335347
* An entry in the pending command queue.
336348
*/
@@ -490,7 +502,9 @@ struct pg_conn
490502
* codes */
491503
bool client_finished_auth; /* have we finished our half of the
492504
* authentication exchange? */
493-
505+
char current_auth_response; /* used by pqTraceOutputMessage to
506+
* know which auth response we're
507+
* sending */
494508

495509
/* Transient state needed while establishing connection */
496510
PGTargetServerType target_server_type; /* desired session properties */

0 commit comments

Comments
 (0)