From 86ab28fbd19a6a0742a7f66e69a595b61eb13d00 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 22 Nov 2017 14:02:57 -0500 Subject: [PATCH] Check channel binding flag at end of SCRAM exchange We need to check whether the channel-binding flag encoded in the client-final-message is the same one sent in the client-first-message. Reviewed-by: Michael Paquier --- src/backend/libpq/auth-scram.c | 11 ++++++++--- src/interfaces/libpq/fe-auth-scram.c | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index 15c3857f57..d52a763457 100644 --- a/src/backend/libpq/auth-scram.c +++ b/src/backend/libpq/auth-scram.c @@ -110,6 +110,7 @@ typedef struct const char *username; /* username from startup packet */ + char cbind_flag; bool ssl_in_use; const char *tls_finished_message; size_t tls_finished_len; @@ -788,6 +789,7 @@ read_client_first_message(scram_state *state, char *input) * Read gs2-cbind-flag. (For details see also RFC 5802 Section 6 "Channel * Binding".) */ + state->cbind_flag = *input; switch (*input) { case 'n': @@ -1111,6 +1113,8 @@ read_client_final_message(scram_state *state, char *input) char *b64_message; int b64_message_len; + Assert(state->cbind_flag == 'p'); + /* * Fetch data appropriate for channel binding type */ @@ -1155,10 +1159,11 @@ read_client_final_message(scram_state *state, char *input) /* * If we are not using channel binding, the binding data is expected * to always be "biws", which is "n,," base64-encoded, or "eSws", - * which is "y,,". + * which is "y,,". We also have to check whether the flag is the same + * one that the client originally sent. */ - if (strcmp(channel_binding, "biws") != 0 && - strcmp(channel_binding, "eSws") != 0) + if (!(strcmp(channel_binding, "biws") == 0 && state->cbind_flag == 'n') && + !(strcmp(channel_binding, "eSws") == 0 && state->cbind_flag == 'y')) ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), (errmsg("unexpected SCRAM channel-binding attribute in client-final-message")))); diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c index 97db0b1faa..5b783bc313 100644 --- a/src/interfaces/libpq/fe-auth-scram.c +++ b/src/interfaces/libpq/fe-auth-scram.c @@ -437,6 +437,10 @@ build_client_final_message(fe_scram_state *state, PQExpBuffer errormessage) /* * Construct client-final-message-without-proof. We need to remember it * for verifying the server proof in the final step of authentication. + * + * The channel binding flag handling (p/y/n) must be consistent with + * build_client_first_message(), because the server will check that it's + * the same flag both times. */ if (strcmp(state->sasl_mechanism, SCRAM_SHA256_PLUS_NAME) == 0) { -- 2.40.0