Accept SCRAM channel binding enabled clients
authorPeter Eisentraut
Fri, 8 Dec 2017 15:17:46 +0000 (10:17 -0500)
committerPeter Eisentraut
Fri, 8 Dec 2017 15:17:46 +0000 (10:17 -0500)
Add support to the SCRAM exchange for clients that support channel
binding, such as PostgreSQL version 11 and beyond.  If such a client
encounters a PostgreSQL 10 server that does not support channel binding,
it will send a channel binding flag 'y', meaning the client supports
channel binding but thinks the server does not.  But PostgreSQL 10
erroneously did not accept that flag.  This would cause connections to
fail if a version 11 client connects to a version 10 server with SCRAM
authentication over SSL.

Author: Michael Paquier 

src/backend/libpq/auth-scram.c

index 9161c885e1f1b89f247188e09236fc53c1528065..7cd31ebe8e201d95e0dd8068e3a829273651ccf4 100644 (file)
@@ -112,6 +112,8 @@ typedef struct
 
    const char *username;       /* username from startup packet */
 
+   char        cbind_flag;
+
    int         iterations;
    char       *salt;           /* base64-encoded */
    uint8       StoredKey[SCRAM_KEY_LEN];
@@ -774,6 +776,7 @@ read_client_first_message(scram_state *state, char *input)
     */
 
    /* read gs2-cbind-flag */
+   state->cbind_flag = *input;
    switch (*input)
    {
        case 'n':
@@ -1033,10 +1036,13 @@ read_client_final_message(scram_state *state, char *input)
 
    /*
     * Read channel-binding.  We don't support channel binding, so it's
-    * expected to always be "biws", which is "n,,", base64-encoded.
+    * expected to always be "biws", which is "n,,", base64-encoded, or
+    * "eSws", which is "y,,".  We also have to check whether the flag is
+    * the same one that the client originally sent.
     */
    channel_binding = read_attr_value(&p, 'c');
-   if (strcmp(channel_binding, "biws") != 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"))));