summaryrefslogtreecommitdiff
path: root/src/backend/libpq/auth-scram.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2021-07-07 10:55:15 +0900
committerMichael Paquier <michael@paquier.xyz>2021-07-07 10:55:15 +0900
commit9fd85570d179f10f93344d722005f7086b3c31ca (patch)
treea678636aee49619b4e69f45a67df6f9498d59104 /src/backend/libpq/auth-scram.c
parent955b3e0f9269639fb916cee3dea37aee50b82df0 (diff)
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/backend/libpq/auth-scram.c')
-rw-r--r--src/backend/libpq/auth-scram.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index f9e1026a12c..9df8f178376 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -101,11 +101,25 @@
#include "common/sha2.h"
#include "libpq/auth.h"
#include "libpq/crypt.h"
+#include "libpq/sasl.h"
#include "libpq/scram.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/timestamp.h"
+static void scram_get_mechanisms(Port *port, StringInfo buf);
+static void *scram_init(Port *port, const char *selected_mech,
+ const char *shadow_pass);
+static int scram_exchange(void *opaq, const char *input, int inputlen,
+ char **output, int *outputlen, char **logdetail);
+
+/* Mechanism declaration */
+const pg_be_sasl_mech pg_be_scram_mech = {
+ scram_get_mechanisms,
+ scram_init,
+ scram_exchange
+};
+
/*
* Status data for a SCRAM authentication exchange. This should be kept
* internal to this file.
@@ -170,16 +184,14 @@ static char *sanitize_str(const char *s);
static char *scram_mock_salt(const char *username);
/*
- * pg_be_scram_get_mechanisms
- *
* Get a list of SASL mechanisms that this module supports.
*
* For the convenience of building the FE/BE packet that lists the
* mechanisms, the names are appended to the given StringInfo buffer,
* separated by '\0' bytes.
*/
-void
-pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
+static void
+scram_get_mechanisms(Port *port, StringInfo buf)
{
/*
* Advertise the mechanisms in decreasing order of importance. So the
@@ -199,15 +211,13 @@ pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
}
/*
- * pg_be_scram_init
- *
* Initialize a new SCRAM authentication exchange status tracker. This
* needs to be called before doing any exchange. It will be filled later
* after the beginning of the exchange with authentication information.
*
* 'selected_mech' identifies the SASL mechanism that the client selected.
* It should be one of the mechanisms that we support, as returned by
- * pg_be_scram_get_mechanisms().
+ * scram_get_mechanisms().
*
* 'shadow_pass' is the role's stored secret, from pg_authid.rolpassword.
* The username was provided by the client in the startup message, and is
@@ -215,10 +225,8 @@ pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
* an authentication exchange, but it will fail, as if an incorrect password
* was given.
*/
-void *
-pg_be_scram_init(Port *port,
- const char *selected_mech,
- const char *shadow_pass)
+static void *
+scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
{
scram_state *state;
bool got_secret;
@@ -325,9 +333,9 @@ pg_be_scram_init(Port *port,
* string at *logdetail that will be sent to the postmaster log (but not
* the client).
*/
-int
-pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
- char **output, int *outputlen, char **logdetail)
+static int
+scram_exchange(void *opaq, const char *input, int inputlen,
+ char **output, int *outputlen, char **logdetail)
{
scram_state *state = (scram_state *) opaq;
int result;
@@ -346,7 +354,7 @@ pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
*output = pstrdup("");
*outputlen = 0;
- return SASL_EXCHANGE_CONTINUE;
+ return PG_SASL_EXCHANGE_CONTINUE;
}
/*
@@ -379,7 +387,7 @@ pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
*output = build_server_first_message(state);
state->state = SCRAM_AUTH_SALT_SENT;
- result = SASL_EXCHANGE_CONTINUE;
+ result = PG_SASL_EXCHANGE_CONTINUE;
break;
case SCRAM_AUTH_SALT_SENT:
@@ -408,7 +416,8 @@ pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
* erroring out in an application-specific way. We choose to do
* the latter, so that the error message for invalid password is
* the same for all authentication methods. The caller will call
- * ereport(), when we return SASL_EXCHANGE_FAILURE with no output.
+ * ereport(), when we return PG_SASL_EXCHANGE_FAILURE with no
+ * output.
*
* NB: the order of these checks is intentional. We calculate the
* client proof even in a mock authentication, even though it's
@@ -417,7 +426,7 @@ pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
*/
if (!verify_client_proof(state) || state->doomed)
{
- result = SASL_EXCHANGE_FAILURE;
+ result = PG_SASL_EXCHANGE_FAILURE;
break;
}
@@ -425,16 +434,16 @@ pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
*output = build_server_final_message(state);
/* Success! */
- result = SASL_EXCHANGE_SUCCESS;
+ result = PG_SASL_EXCHANGE_SUCCESS;
state->state = SCRAM_AUTH_FINISHED;
break;
default:
elog(ERROR, "invalid SCRAM exchange state");
- result = SASL_EXCHANGE_FAILURE;
+ result = PG_SASL_EXCHANGE_FAILURE;
}
- if (result == SASL_EXCHANGE_FAILURE && state->logdetail && logdetail)
+ if (result == PG_SASL_EXCHANGE_FAILURE && state->logdetail && logdetail)
*logdetail = state->logdetail;
if (*output)