Skip to content

Commit 44bd012

Browse files
committed
Add more sanity checks in SASL exchanges
The following checks are added, to make the SASL infrastructure more aware of defects when implementing new mechanisms: - Detect that no output is generated by a mechanism if an exchange fails in the backend, failing if there is a message waiting to be sent. - Handle zero-length messages in the frontend. The backend handles that already, and SCRAM would complain if sending empty messages as this is not authorized for this mechanism, but other mechanisms may want this capability (the SASL specification allows that). - Make sure that a mechanism generates a message in the middle of the exchange in the frontend. SCRAM, as implemented, respects all these requirements already, and the recent refactoring of SASL done in 9fd8557 helps in documenting that in a cleaner way. Analyzed-by: Jacob Champion Author: Michael Paquier Reviewed-by: Jacob Champion Discussion: https://postgr.es/m/3d2a6f5d50e741117d6baf83eb67ebf1a8a35a11.camel@vmware.com
1 parent e7fc488 commit 44bd012

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

src/backend/libpq/auth-sasl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass,
171171

172172
if (output)
173173
{
174+
/*
175+
* PG_SASL_EXCHANGE_FAILURE with some output is forbidden by SASL.
176+
* Make sure here that the mechanism used got that right.
177+
*/
178+
if (result == PG_SASL_EXCHANGE_FAILURE)
179+
elog(ERROR, "output message found after SASL exchange failure");
180+
174181
/*
175182
* Negotiation generated data to be sent to the client.
176183
*/

src/interfaces/libpq/fe-auth-sasl.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@ typedef struct pg_fe_sasl_mech
7878
* Output parameters, to be set by the callback function:
7979
*
8080
* output: A malloc'd buffer containing the client's response to
81-
* the server, or NULL if the exchange should be aborted.
82-
* (*success should be set to false in the latter case.)
81+
* the server (can be empty), or NULL if the exchange should
82+
* be aborted. (*success should be set to false in the
83+
* latter case.)
8384
*
84-
* outputlen: The length of the client response buffer, or zero if no
85-
* data should be sent due to an exchange failure
85+
* outputlen: The length (0 or higher) of the client response buffer,
86+
* ignored if output is NULL.
8687
*
8788
* done: Set to true if the SASL exchange should not continue,
8889
* because the exchange is either complete or failed

src/interfaces/libpq/fe-auth.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,22 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
674674
return STATUS_ERROR;
675675
}
676676

677-
if (outputlen != 0)
677+
/*
678+
* If the exchange is not completed yet, we need to make sure that the
679+
* SASL mechanism has generated a message to send back.
680+
*/
681+
if (output == NULL && !done)
682+
{
683+
appendPQExpBufferStr(&conn->errorMessage,
684+
libpq_gettext("no client response found after SASL exchange success\n"));
685+
return STATUS_ERROR;
686+
}
687+
688+
/*
689+
* SASL allows zero-length responses, so this check uses "output" and not
690+
* "outputlen" to allow the case of an empty message.
691+
*/
692+
if (output)
678693
{
679694
/*
680695
* Send the SASL response to the server.

0 commit comments

Comments
 (0)