aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2017-11-22 14:02:57 -0500
committerPeter Eisentraut <peter_e@gmx.net>2017-12-01 09:53:26 -0500
commit86ab28fbd19a6a0742a7f66e69a595b61eb13d00 (patch)
tree782040f1c7f38de43e86373a40a9e1a0b511abe9
parent143b54d21d37804707c27edebdbd4410891da133 (diff)
downloadpostgresql-86ab28fbd19a6a0742a7f66e69a595b61eb13d00.tar.gz
postgresql-86ab28fbd19a6a0742a7f66e69a595b61eb13d00.zip
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 <michael.paquier@gmail.com>
-rw-r--r--src/backend/libpq/auth-scram.c11
-rw-r--r--src/interfaces/libpq/fe-auth-scram.c4
2 files changed, 12 insertions, 3 deletions
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 15c3857f573..d52a7634574 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 97db0b1faa8..5b783bc3136 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)
{