aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/libpq/auth-sasl.c7
-rw-r--r--src/interfaces/libpq/fe-auth-sasl.h9
-rw-r--r--src/interfaces/libpq/fe-auth.c17
3 files changed, 28 insertions, 5 deletions
diff --git a/src/backend/libpq/auth-sasl.c b/src/backend/libpq/auth-sasl.c
index 3e4f763b609..6cfd90fa214 100644
--- a/src/backend/libpq/auth-sasl.c
+++ b/src/backend/libpq/auth-sasl.c
@@ -172,6 +172,13 @@ CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass,
if (output)
{
/*
+ * PG_SASL_EXCHANGE_FAILURE with some output is forbidden by SASL.
+ * Make sure here that the mechanism used got that right.
+ */
+ if (result == PG_SASL_EXCHANGE_FAILURE)
+ elog(ERROR, "output message found after SASL exchange failure");
+
+ /*
* Negotiation generated data to be sent to the client.
*/
elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
diff --git a/src/interfaces/libpq/fe-auth-sasl.h b/src/interfaces/libpq/fe-auth-sasl.h
index 0aec588a9eb..3d7ee576f2a 100644
--- a/src/interfaces/libpq/fe-auth-sasl.h
+++ b/src/interfaces/libpq/fe-auth-sasl.h
@@ -78,11 +78,12 @@ typedef struct pg_fe_sasl_mech
* Output parameters, to be set by the callback function:
*
* output: A malloc'd buffer containing the client's response to
- * the server, or NULL if the exchange should be aborted.
- * (*success should be set to false in the latter case.)
+ * the server (can be empty), or NULL if the exchange should
+ * be aborted. (*success should be set to false in the
+ * latter case.)
*
- * outputlen: The length of the client response buffer, or zero if no
- * data should be sent due to an exchange failure
+ * outputlen: The length (0 or higher) of the client response buffer,
+ * ignored if output is NULL.
*
* done: Set to true if the SASL exchange should not continue,
* because the exchange is either complete or failed
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index eaba0ba56d7..3421ed4685b 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -674,7 +674,22 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
return STATUS_ERROR;
}
- if (outputlen != 0)
+ /*
+ * If the exchange is not completed yet, we need to make sure that the
+ * SASL mechanism has generated a message to send back.
+ */
+ if (output == NULL && !done)
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("no client response found after SASL exchange success\n"));
+ return STATUS_ERROR;
+ }
+
+ /*
+ * SASL allows zero-length responses, so this check uses "output" and not
+ * "outputlen" to allow the case of an empty message.
+ */
+ if (output)
{
/*
* Send the SASL response to the server.