From cb508c3d78a49bcd24fc54a5649d018c03989525 Mon Sep 17 00:00:00 2001 From: kirill reshke Date: Thu, 9 Dec 2021 12:26:27 +0500 Subject: [PATCH] Fix scram with pg version num >= 140 000 (#383) --- config-examples/odyssey-dev-no-ldap.conf | 28 +++++- sources/scram.c | 109 ++++++++++++----------- sources/scram.h | 22 +++-- 3 files changed, 102 insertions(+), 57 deletions(-) diff --git a/config-examples/odyssey-dev-no-ldap.conf b/config-examples/odyssey-dev-no-ldap.conf index 148781e4..1f33607e 100644 --- a/config-examples/odyssey-dev-no-ldap.conf +++ b/config-examples/odyssey-dev-no-ldap.conf @@ -131,7 +131,33 @@ database "postgres" { quantiles "0.99,0.95,0.5" client_max 107 } - + + user "user_scram" { + authentication "scram-sha-256" + password "12" + + storage "postgres_server" + + pool "transaction" + pool_size 1 + + pool_timeout 0 + pool_ttl 60 + pool_discard no + pool_cancel yes + pool_rollback yes + + client_fwd_error yes + + application_name_add_host yes + reserve_session_server_connection no + server_lifetime 3600 + log_debug no + + quantiles "0.99,0.95,0.5" + client_max 107 + } + user "userstmt" { authentication "none" diff --git a/sources/scram.c b/sources/scram.c index 83359fbe..402ed41a 100644 --- a/sources/scram.c +++ b/sources/scram.c @@ -300,7 +300,7 @@ static int calculate_client_proof(od_scram_state_t *scram_state, if (scram_state->salted_password == NULL) goto error; - od_scram_ctx_t ctx; + od_scram_ctx_t *ctx = od_scram_HMAC_create(); scram_SaltedPassword(prepared_password, salt, strlen(salt), iterations, scram_state->salted_password); @@ -310,23 +310,25 @@ static int calculate_client_proof(od_scram_state_t *scram_state, uint8_t stored_key[SCRAM_KEY_LEN]; scram_H(client_key, SCRAM_KEY_LEN, stored_key); - od_scram_HMAC_init(&ctx, stored_key, SCRAM_KEY_LEN); + od_scram_HMAC_init(ctx, stored_key, SCRAM_KEY_LEN); - od_scram_HMAC_update(&ctx, scram_state->client_first_message, + od_scram_HMAC_update(ctx, scram_state->client_first_message, strlen(scram_state->client_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, scram_state->server_first_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, scram_state->server_first_message, strlen(scram_state->server_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, client_final_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, client_final_message, strlen(client_final_message)); uint8_t client_signature[SCRAM_KEY_LEN]; - od_scram_HMAC_final(client_signature, &ctx); + od_scram_HMAC_final(client_signature, ctx); for (int i = 0; i < SCRAM_KEY_LEN; i++) client_proof[i] = client_key[i] ^ client_signature[i]; + od_scram_HMAC_free(ctx); + free(prepared_password); return 0; @@ -338,20 +340,21 @@ error: static char *calculate_server_signature(od_scram_state_t *scram_state) { - od_scram_ctx_t ctx; + od_scram_ctx_t *ctx = od_scram_HMAC_create(); - od_scram_HMAC_init(&ctx, scram_state->server_key, SCRAM_KEY_LEN); - od_scram_HMAC_update(&ctx, scram_state->client_first_message, + od_scram_HMAC_init(ctx, scram_state->server_key, SCRAM_KEY_LEN); + od_scram_HMAC_update(ctx, scram_state->client_first_message, strlen(scram_state->client_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, scram_state->server_first_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, scram_state->server_first_message, strlen(scram_state->server_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, scram_state->client_final_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, scram_state->client_final_message, strlen(scram_state->client_final_message)); uint8_t server_signature[SCRAM_KEY_LEN]; - od_scram_HMAC_final(server_signature, &ctx); + od_scram_HMAC_final(server_signature, ctx); + od_scram_HMAC_free(ctx); int base64_signature_dst_len = pg_b64_enc_len(SCRAM_KEY_LEN) + 1; char *base64_signature = malloc(base64_signature_dst_len); @@ -464,39 +467,42 @@ error: return -1; } -int od_scram_verify_server_signature(od_scram_state_t *scram_state, - char *auth_data, size_t auth_data_size) +od_retcode_t od_scram_verify_server_signature(od_scram_state_t *scram_state, + char *auth_data, + size_t auth_data_size) { char server_signature[SHA256_DIGEST_LENGTH]; - int rc = read_server_final_message(auth_data, auth_data_size, - server_signature); - if (rc == -1) - return -1; + od_retcode_t rc = read_server_final_message(auth_data, auth_data_size, + server_signature); + if (rc == NOT_OK_RESPONSE) + return NOT_OK_RESPONSE; - od_scram_ctx_t ctx; + od_scram_ctx_t *ctx = od_scram_HMAC_create(); uint8_t server_key[SCRAM_KEY_LEN]; scram_ServerKey(scram_state->salted_password, server_key); - od_scram_HMAC_init(&ctx, server_key, SCRAM_KEY_LEN); + od_scram_HMAC_init(ctx, server_key, SCRAM_KEY_LEN); - od_scram_HMAC_update(&ctx, scram_state->client_first_message, + od_scram_HMAC_update(ctx, scram_state->client_first_message, strlen(scram_state->client_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, scram_state->server_first_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, scram_state->server_first_message, strlen(scram_state->server_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, scram_state->client_final_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, scram_state->client_final_message, strlen(scram_state->client_final_message)); uint8_t expected_server_signature[SHA256_DIGEST_LENGTH]; - od_scram_HMAC_final(expected_server_signature, &ctx); + od_scram_HMAC_final(expected_server_signature, ctx); + + od_scram_HMAC_free(ctx); if (memcmp(expected_server_signature, server_signature, SHA256_DIGEST_LENGTH) != 0) - return -1; + return NOT_OK_RESPONSE; - return 0; + return OK_RESPONSE; } int od_scram_read_client_first_message(od_scram_state_t *scram_state, @@ -710,56 +716,59 @@ error: return NULL; } -int od_scram_verify_final_nonce(od_scram_state_t *scram_state, - char *final_nonce, size_t final_nonce_size) +od_retcode_t od_scram_verify_final_nonce(od_scram_state_t *scram_state, + char *final_nonce, + size_t final_nonce_size) { size_t client_nonce_len = strlen(scram_state->client_nonce); size_t server_nonce_len = strlen(scram_state->server_nonce); if (final_nonce_size != client_nonce_len + server_nonce_len) - return -1; + return NOT_OK_RESPONSE; if (memcmp(final_nonce, scram_state->client_nonce, client_nonce_len) != 0) - return -1; + return NOT_OK_RESPONSE; if (memcmp(final_nonce + client_nonce_len, scram_state->server_nonce, server_nonce_len) != 0) - return -1; + return NOT_OK_RESPONSE; - return 0; + return OK_RESPONSE; } -int od_scram_verify_client_proof(od_scram_state_t *scram_state, - char *client_proof) +od_retcode_t od_scram_verify_client_proof(od_scram_state_t *scram_state, + char *client_proof) { uint8_t client_signature[SCRAM_KEY_LEN]; uint8_t client_key[SCRAM_KEY_LEN]; uint8_t client_stored_key[SCRAM_KEY_LEN]; - od_scram_ctx_t ctx; + od_scram_ctx_t *ctx = od_scram_HMAC_create(); - od_scram_HMAC_init(&ctx, scram_state->stored_key, SCRAM_KEY_LEN); - od_scram_HMAC_update(&ctx, scram_state->client_first_message, + od_scram_HMAC_init(ctx, scram_state->stored_key, SCRAM_KEY_LEN); + od_scram_HMAC_update(ctx, scram_state->client_first_message, strlen(scram_state->client_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, scram_state->server_first_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, scram_state->server_first_message, strlen(scram_state->server_first_message)); - od_scram_HMAC_update(&ctx, ",", 1); - od_scram_HMAC_update(&ctx, scram_state->client_final_message, + od_scram_HMAC_update(ctx, ",", 1); + od_scram_HMAC_update(ctx, scram_state->client_final_message, strlen(scram_state->client_final_message)); - od_scram_HMAC_final(client_signature, &ctx); + od_scram_HMAC_final(client_signature, ctx); for (int i = 0; i < SCRAM_KEY_LEN; i++) client_key[i] = client_proof[i] ^ client_signature[i]; scram_H(client_key, SCRAM_KEY_LEN, client_stored_key); + od_scram_HMAC_free(ctx); + if (memcmp(client_stored_key, scram_state->stored_key, SCRAM_KEY_LEN) != 0) - return -1; + return NOT_OK_RESPONSE; - return 0; + return OK_RESPONSE; } machine_msg_t * diff --git a/sources/scram.h b/sources/scram.h index 925bbafd..32dc76c9 100644 --- a/sources/scram.h +++ b/sources/scram.h @@ -23,24 +23,34 @@ typedef scram_HMAC_ctx od_scram_ctx_t; #define od_scram_HMAC_init scram_HMAC_init +#define od_scram_HMAC_create() malloc(sizeof(od_scram_ctx_t)) #define od_scram_HMAC_update scram_HMAC_update #define od_scram_HMAC_final scram_HMAC_final +#define od_scram_HMAC_free(ctx) free(ctx) #else -struct pg_hmac_ctx { - HMAC_CTX *hmacctx; - pg_cryptohash_type type; -#ifndef FRONTEND - ResourceOwner resowner; -#endif +struct pg_hmac_ctx { + pg_cryptohash_ctx *hash; + pg_cryptohash_type type; + int block_size; + int digest_size; + + /* + * Use the largest block size among supported options. This wastes some + * memory but simplifies the allocation logic. + */ + uint8 k_ipad[PG_SHA512_BLOCK_LENGTH]; + uint8 k_opad[PG_SHA512_BLOCK_LENGTH]; }; typedef struct pg_hmac_ctx od_scram_ctx_t; #define od_scram_HMAC_init pg_hmac_init +#define od_scram_HMAC_create() pg_hmac_create(PG_SHA256) #define od_scram_HMAC_update pg_hmac_update #define od_scram_HMAC_final(dest, ctx) pg_hmac_final(ctx, dest, sizeof(dest)) +#define od_scram_HMAC_free pg_hmac_free #endif