diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/libpq/auth-sasl.c | 7 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-auth-sasl.h | 9 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-auth.c | 17 |
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. |