]> granicus.if.org Git - postgresql/commitdiff
Check channel binding flag at end of SCRAM exchange
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 22 Nov 2017 19:02:57 +0000 (14:02 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 1 Dec 2017 14:53:26 +0000 (09:53 -0500)
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>
src/backend/libpq/auth-scram.c
src/interfaces/libpq/fe-auth-scram.c

index 15c3857f5732996ad14c681a5d58c20c10e3cf67..d52a76345741c7d2fb548253f40ca97df0934872 100644 (file)
@@ -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"))));
index 97db0b1faa8e8192d80b117e3f69fcb9501418cd..5b783bc3136ec33caae327ef2a4cf19495ae09ef 100644 (file)
@@ -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)
        {