diff options
Diffstat (limited to 'src/backend/libpq/auth-scram.c')
-rw-r--r-- | src/backend/libpq/auth-scram.c | 113 |
1 files changed, 69 insertions, 44 deletions
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index 0f79b28bb5a..6879a816183 100644 --- a/src/backend/libpq/auth-scram.c +++ b/src/backend/libpq/auth-scram.c @@ -527,8 +527,12 @@ scram_verify_plain_password(const char *username, const char *password, password = prep_password; /* Compute Server Key based on the user-supplied plaintext password */ - scram_SaltedPassword(password, salt, saltlen, iterations, salted_password); - scram_ServerKey(salted_password, computed_key); + if (scram_SaltedPassword(password, salt, saltlen, iterations, + salted_password) < 0 || + scram_ServerKey(salted_password, computed_key) < 0) + { + elog(ERROR, "could not compute server key"); + } if (prep_password) pfree(prep_password); @@ -651,8 +655,17 @@ mock_scram_secret(const char *username, int *iterations, char **salt, char *encoded_salt; int encoded_len; - /* Generate deterministic salt */ + /* + * Generate deterministic salt. + * + * Note that we cannot reveal any information to an attacker here so the + * error messages need to remain generic. This should never fail anyway + * as the salt generated for mock authentication uses the cluster's nonce + * value. + */ raw_salt = scram_mock_salt(username); + if (raw_salt == NULL) + elog(ERROR, "could not encode salt"); encoded_len = pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN); /* don't forget the zero-terminator */ @@ -660,12 +673,6 @@ mock_scram_secret(const char *username, int *iterations, char **salt, encoded_len = pg_b64_encode(raw_salt, SCRAM_DEFAULT_SALT_LEN, encoded_salt, encoded_len); - /* - * Note that we cannot reveal any information to an attacker here so the - * error message needs to remain generic. This should never fail anyway - * as the salt generated for mock authentication uses the cluster's nonce - * value. - */ if (encoded_len < 0) elog(ERROR, "could not encode salt"); encoded_salt[encoded_len] = '\0'; @@ -1084,7 +1091,8 @@ verify_final_nonce(scram_state *state) /* * Verify the client proof contained in the last message received from - * client in an exchange. + * client in an exchange. Returns true if the verification is a success, + * or false for a failure. */ static bool verify_client_proof(scram_state *state) @@ -1095,27 +1103,35 @@ verify_client_proof(scram_state *state) scram_HMAC_ctx ctx; int i; - /* calculate ClientSignature */ - scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN); - scram_HMAC_update(&ctx, - state->client_first_message_bare, - strlen(state->client_first_message_bare)); - scram_HMAC_update(&ctx, ",", 1); - scram_HMAC_update(&ctx, - state->server_first_message, - strlen(state->server_first_message)); - scram_HMAC_update(&ctx, ",", 1); - scram_HMAC_update(&ctx, - state->client_final_message_without_proof, - strlen(state->client_final_message_without_proof)); - scram_HMAC_final(ClientSignature, &ctx); + /* + * Calculate ClientSignature. Note that we don't log directly a failure + * here even when processing the calculations as this could involve a mock + * authentication. + */ + if (scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN) < 0 || + scram_HMAC_update(&ctx, + state->client_first_message_bare, + strlen(state->client_first_message_bare)) < 0 || + scram_HMAC_update(&ctx, ",", 1) < 0 || + scram_HMAC_update(&ctx, + state->server_first_message, + strlen(state->server_first_message)) < 0 || + scram_HMAC_update(&ctx, ",", 1) < 0 || + scram_HMAC_update(&ctx, + state->client_final_message_without_proof, + strlen(state->client_final_message_without_proof)) < 0 || + scram_HMAC_final(ClientSignature, &ctx) < 0) + { + elog(ERROR, "could not calculate client signature"); + } /* Extract the ClientKey that the client calculated from the proof */ for (i = 0; i < SCRAM_KEY_LEN; i++) ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i]; /* Hash it one more time, and compare with StoredKey */ - scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey); + if (scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey) < 0) + elog(ERROR, "could not hash stored key"); if (memcmp(client_StoredKey, state->StoredKey, SCRAM_KEY_LEN) != 0) return false; @@ -1346,19 +1362,22 @@ build_server_final_message(scram_state *state) scram_HMAC_ctx ctx; /* calculate ServerSignature */ - scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN); - scram_HMAC_update(&ctx, - state->client_first_message_bare, - strlen(state->client_first_message_bare)); - scram_HMAC_update(&ctx, ",", 1); - scram_HMAC_update(&ctx, - state->server_first_message, - strlen(state->server_first_message)); - scram_HMAC_update(&ctx, ",", 1); - scram_HMAC_update(&ctx, - state->client_final_message_without_proof, - strlen(state->client_final_message_without_proof)); - scram_HMAC_final(ServerSignature, &ctx); + if (scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN) < 0 || + scram_HMAC_update(&ctx, + state->client_first_message_bare, + strlen(state->client_first_message_bare)) < 0 || + scram_HMAC_update(&ctx, ",", 1) < 0 || + scram_HMAC_update(&ctx, + state->server_first_message, + strlen(state->server_first_message)) < 0 || + scram_HMAC_update(&ctx, ",", 1) < 0 || + scram_HMAC_update(&ctx, + state->client_final_message_without_proof, + strlen(state->client_final_message_without_proof)) < 0 || + scram_HMAC_final(ServerSignature, &ctx) < 0) + { + elog(ERROR, "could not calculate server signature"); + } siglen = pg_b64_enc_len(SCRAM_KEY_LEN); /* don't forget the zero-terminator */ @@ -1388,12 +1407,12 @@ build_server_final_message(scram_state *state) /* * Deterministically generate salt for mock authentication, using a SHA256 * hash based on the username and a cluster-level secret key. Returns a - * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN. + * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN, or NULL. */ static char * scram_mock_salt(const char *username) { - pg_sha256_ctx ctx; + pg_cryptohash_ctx *ctx; static uint8 sha_digest[PG_SHA256_DIGEST_LENGTH]; char *mock_auth_nonce = GetMockAuthenticationNonce(); @@ -1406,10 +1425,16 @@ scram_mock_salt(const char *username) StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >= SCRAM_DEFAULT_SALT_LEN, "salt length greater than SHA256 digest length"); - pg_sha256_init(&ctx); - pg_sha256_update(&ctx, (uint8 *) username, strlen(username)); - pg_sha256_update(&ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN); - pg_sha256_final(&ctx, sha_digest); + ctx = pg_cryptohash_create(PG_SHA256); + if (pg_cryptohash_init(ctx) < 0 || + pg_cryptohash_update(ctx, (uint8 *) username, strlen(username)) < 0 || + pg_cryptohash_update(ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN) < 0 || + pg_cryptohash_final(ctx, sha_digest) < 0) + { + pg_cryptohash_free(ctx); + return NULL; + } + pg_cryptohash_free(ctx); return (char *) sha_digest; } |