mirror of
https://github.com/postgres/postgres.git
synced 2025-08-18 12:22:09 +03:00
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>
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
Reference in New Issue
Block a user