diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2018-01-04 13:53:09 -0500 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2018-01-04 13:55:12 -0500 |
commit | f3049a603a7950f313b33ab214f11563c66dc069 (patch) | |
tree | f870af0cee87ab890b6925a202c43de7624972fd /src/backend/libpq/auth-scram.c | |
parent | 3ad2afc2e98fc85d5cf9529d84265b70acc0b13d (diff) |
Refactor channel binding code to fetch cbind_data only when necessary
As things stand now, channel binding data is fetched from OpenSSL and
saved into the SCRAM exchange context for any SSL connection attempted
for a SCRAM authentication, resulting in data fetched but not used if no
channel binding is used or if a different channel binding type is used
than what the data is here for.
Refactor the code in such a way that binding data is fetched from the
SSL stack only when a specific channel binding is used for both the
frontend and the backend. In order to achieve that, save the libpq
connection context directly in the SCRAM exchange state, and add a
dependency to SSL in the low-level SCRAM routines.
This makes the interface in charge of initializing the SCRAM context
cleaner as all its data comes from either PGconn* (for frontend) or
Port* (for the backend).
Author: Michael Paquier <michael.paquier@gmail.com>
Diffstat (limited to 'src/backend/libpq/auth-scram.c')
-rw-r--r-- | src/backend/libpq/auth-scram.c | 33 |
1 files changed, 13 insertions, 20 deletions
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index 7068ee5b252..1b07eaebfac 100644 --- a/src/backend/libpq/auth-scram.c +++ b/src/backend/libpq/auth-scram.c @@ -110,10 +110,8 @@ typedef struct const char *username; /* username from startup packet */ + Port *port; char cbind_flag; - bool ssl_in_use; - const char *tls_finished_message; - size_t tls_finished_len; char *channel_binding_type; int iterations; @@ -172,21 +170,15 @@ static char *scram_mock_salt(const char *username); * it will fail, as if an incorrect password was given. */ void * -pg_be_scram_init(const char *username, - const char *shadow_pass, - bool ssl_in_use, - const char *tls_finished_message, - size_t tls_finished_len) +pg_be_scram_init(Port *port, + const char *shadow_pass) { scram_state *state; bool got_verifier; state = (scram_state *) palloc0(sizeof(scram_state)); + state->port = port; state->state = SCRAM_AUTH_INIT; - state->username = username; - state->ssl_in_use = ssl_in_use; - state->tls_finished_message = tls_finished_message; - state->tls_finished_len = tls_finished_len; state->channel_binding_type = NULL; /* @@ -209,7 +201,7 @@ pg_be_scram_init(const char *username, */ ereport(LOG, (errmsg("invalid SCRAM verifier for user \"%s\"", - username))); + state->port->user_name))); got_verifier = false; } } @@ -220,7 +212,7 @@ pg_be_scram_init(const char *username, * authentication with an MD5 hash.) */ state->logdetail = psprintf(_("User \"%s\" does not have a valid SCRAM verifier."), - state->username); + state->port->user_name); got_verifier = false; } } @@ -242,8 +234,8 @@ pg_be_scram_init(const char *username, */ if (!got_verifier) { - mock_scram_verifier(username, &state->iterations, &state->salt, - state->StoredKey, state->ServerKey); + mock_scram_verifier(state->port->user_name, &state->iterations, + &state->salt, state->StoredKey, state->ServerKey); state->doomed = true; } @@ -815,7 +807,7 @@ read_client_first_message(scram_state *state, char *input) * it supports channel binding, which in this implementation is * the case if a connection is using SSL. */ - if (state->ssl_in_use) + if (state->port->ssl_in_use) ereport(ERROR, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("SCRAM channel binding negotiation error"), @@ -839,7 +831,7 @@ read_client_first_message(scram_state *state, char *input) { char *channel_binding_type; - if (!state->ssl_in_use) + if (!state->port->ssl_in_use) { /* * Without SSL, we don't support channel binding. @@ -1120,8 +1112,9 @@ read_client_final_message(scram_state *state, char *input) */ if (strcmp(state->channel_binding_type, SCRAM_CHANNEL_BINDING_TLS_UNIQUE) == 0) { - cbind_data = state->tls_finished_message; - cbind_data_len = state->tls_finished_len; +#ifdef USE_SSL + cbind_data = be_tls_get_peer_finished(state->port, &cbind_data_len); +#endif } else { |