Explicitly require password for SCRAM exchange
authorDaniel Gustafsson <dgustafsson@postgresql.org>
Thu, 21 Mar 2024 13:45:54 +0000 (14:45 +0100)
committerDaniel Gustafsson <dgustafsson@postgresql.org>
Thu, 21 Mar 2024 13:45:54 +0000 (14:45 +0100)
This refactors the SASL init flow to set password_needed on the two
SCRAM exchanges currently supported. The code already required this
but was set up in such a way that all SASL exchanges required using
a password, a restriction which may not hold for all exchanges (the
example at hand being the proposed OAuthbearer exchange).

This was extracted from a larger patchset to introduce OAuthBearer
authentication and authorization.

Author: Jacob Champion <jacob.champion@enterprisedb.com>
Discussion: https://postgr.es/m/d1b467a78e0e36ed85a09adf979d04cf124a9d4b.camel@vmware.com

src/interfaces/libpq/fe-auth.c

index cf8af4c62e53d6da5a0245ec207dd0a8a75898e7..81ec08485d2e566e25c9ac33839a8935211770dc 100644 (file)
@@ -425,7 +425,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
        int                     initialresponselen;
        const char *selected_mechanism;
        PQExpBufferData mechanism_buf;
-       char       *password;
+       char       *password = NULL;
        SASLStatus      status;
 
        initPQExpBuffer(&mechanism_buf);
@@ -446,8 +446,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
        /*
         * Parse the list of SASL authentication mechanisms in the
         * AuthenticationSASL message, and select the best mechanism that we
-        * support.  SCRAM-SHA-256-PLUS and SCRAM-SHA-256 are the only ones
-        * supported at the moment, listed by order of decreasing importance.
+        * support. Mechanisms are listed by order of decreasing importance.
         */
        selected_mechanism = NULL;
        for (;;)
@@ -487,6 +486,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
                                {
                                        selected_mechanism = SCRAM_SHA_256_PLUS_NAME;
                                        conn->sasl = &pg_scram_mech;
+                                       conn->password_needed = true;
                                }
 #else
                                /*
@@ -522,6 +522,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
                {
                        selected_mechanism = SCRAM_SHA_256_NAME;
                        conn->sasl = &pg_scram_mech;
+                       conn->password_needed = true;
                }
        }
 
@@ -545,18 +546,19 @@ pg_SASL_init(PGconn *conn, int payloadlen)
 
        /*
         * First, select the password to use for the exchange, complaining if
-        * there isn't one.  Currently, all supported SASL mechanisms require a
-        * password, so we can just go ahead here without further distinction.
+        * there isn't one and the selected SASL mechanism needs it.
         */
-       conn->password_needed = true;
-       password = conn->connhost[conn->whichhost].password;
-       if (password == NULL)
-               password = conn->pgpass;
-       if (password == NULL || password[0] == '\0')
+       if (conn->password_needed)
        {
-               appendPQExpBufferStr(&conn->errorMessage,
-                                                        PQnoPasswordSupplied);
-               goto error;
+               password = conn->connhost[conn->whichhost].password;
+               if (password == NULL)
+                       password = conn->pgpass;
+               if (password == NULL || password[0] == '\0')
+               {
+                       appendPQExpBufferStr(&conn->errorMessage,
+                                                                PQnoPasswordSupplied);
+                       goto error;
+               }
        }
 
        Assert(conn->sasl);