diff options
author | Michael Paquier <michael@paquier.xyz> | 2021-07-07 10:55:15 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2021-07-07 10:55:15 +0900 |
commit | 9fd85570d179f10f93344d722005f7086b3c31ca (patch) | |
tree | a678636aee49619b4e69f45a67df6f9498d59104 /src/interfaces/libpq/fe-auth.c | |
parent | 955b3e0f9269639fb916cee3dea37aee50b82df0 (diff) | |
download | postgresql-9fd85570d179f10f93344d722005f7086b3c31ca.tar.gz postgresql-9fd85570d179f10f93344d722005f7086b3c31ca.zip |
Refactor SASL code with a generic interface for its mechanisms
The code of SCRAM and SASL have been tightly linked together since SCRAM
exists in the core code, making hard to apprehend the addition of new
SASL mechanisms, but these are by design different facilities, with
SCRAM being an option for SASL. This refactors the code related to both
so as the backend and the frontend use a set of callbacks for SASL
mechanisms, documenting while on it what is expected by anybody adding a
new SASL mechanism.
The separation between both layers is neat, using two sets of callbacks
for the frontend and the backend to mark the frontier between both
facilities. The shape of the callbacks is now directly inspired from
the routines used by SCRAM, so the code change is straight-forward, and
the SASL code is moved into its own set of files. These will likely
change depending on how and if new SASL mechanisms get added in the
future.
Author: Jacob Champion
Reviewed-by: Michael Paquier
Discussion: https://postgr.es/m/3d2a6f5d50e741117d6baf83eb67ebf1a8a35a11.camel@vmware.com
Diffstat (limited to 'src/interfaces/libpq/fe-auth.c')
-rw-r--r-- | src/interfaces/libpq/fe-auth.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index e8062647e60..eaba0ba56d7 100644 --- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -41,6 +41,7 @@ #include "common/md5.h" #include "common/scram-common.h" #include "fe-auth.h" +#include "fe-auth-sasl.h" #include "libpq-fe.h" #ifdef ENABLE_GSS @@ -482,7 +483,10 @@ pg_SASL_init(PGconn *conn, int payloadlen) * channel_binding is not disabled. */ if (conn->channel_binding[0] != 'd') /* disable */ + { selected_mechanism = SCRAM_SHA_256_PLUS_NAME; + conn->sasl = &pg_scram_mech; + } #else /* * The client does not support channel binding. If it is @@ -516,7 +520,10 @@ pg_SASL_init(PGconn *conn, int payloadlen) } else if (strcmp(mechanism_buf.data, SCRAM_SHA_256_NAME) == 0 && !selected_mechanism) + { selected_mechanism = SCRAM_SHA_256_NAME; + conn->sasl = &pg_scram_mech; + } } if (!selected_mechanism) @@ -555,20 +562,22 @@ pg_SASL_init(PGconn *conn, int payloadlen) goto error; } + Assert(conn->sasl); + /* * Initialize the SASL state information with all the information gathered * during the initial exchange. * * Note: Only tls-unique is supported for the moment. */ - conn->sasl_state = pg_fe_scram_init(conn, + conn->sasl_state = conn->sasl->init(conn, password, selected_mechanism); if (!conn->sasl_state) goto oom_error; /* Get the mechanism-specific Initial Client Response, if any */ - pg_fe_scram_exchange(conn->sasl_state, + conn->sasl->exchange(conn->sasl_state, NULL, -1, &initialresponse, &initialresponselen, &done, &success); @@ -649,7 +658,7 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final) /* For safety and convenience, ensure the buffer is NULL-terminated. */ challenge[payloadlen] = '\0'; - pg_fe_scram_exchange(conn->sasl_state, + conn->sasl->exchange(conn->sasl_state, challenge, payloadlen, &output, &outputlen, &done, &success); @@ -664,6 +673,7 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final) libpq_gettext("AuthenticationSASLFinal received from server, but SASL authentication was not completed\n")); return STATUS_ERROR; } + if (outputlen != 0) { /* @@ -830,7 +840,7 @@ check_expected_areq(AuthRequest areq, PGconn *conn) case AUTH_REQ_SASL_FIN: break; case AUTH_REQ_OK: - if (!pg_fe_scram_channel_bound(conn->sasl_state)) + if (!conn->sasl || !conn->sasl->channel_bound(conn->sasl_state)) { appendPQExpBufferStr(&conn->errorMessage, libpq_gettext("channel binding required, but server authenticated client without channel binding\n")); |