diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/libpq/auth-scram.c | 61 | ||||
-rw-r--r-- | src/backend/utils/resowner/resowner.c | 61 |
2 files changed, 94 insertions, 28 deletions
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index b9b6d464a05..f9e1026a12c 100644 --- a/src/backend/libpq/auth-scram.c +++ b/src/backend/libpq/auth-scram.c @@ -95,6 +95,7 @@ #include "catalog/pg_authid.h" #include "catalog/pg_control.h" #include "common/base64.h" +#include "common/hmac.h" #include "common/saslprep.h" #include "common/scram-common.h" #include "common/sha2.h" @@ -1100,7 +1101,7 @@ verify_client_proof(scram_state *state) uint8 ClientSignature[SCRAM_KEY_LEN]; uint8 ClientKey[SCRAM_KEY_LEN]; uint8 client_StoredKey[SCRAM_KEY_LEN]; - scram_HMAC_ctx ctx; + pg_hmac_ctx *ctx = pg_hmac_create(PG_SHA256); int i; /* @@ -1108,23 +1109,25 @@ verify_client_proof(scram_state *state) * 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) + if (pg_hmac_init(ctx, state->StoredKey, SCRAM_KEY_LEN) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->client_first_message_bare, + strlen(state->client_first_message_bare)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->server_first_message, + strlen(state->server_first_message)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->client_final_message_without_proof, + strlen(state->client_final_message_without_proof)) < 0 || + pg_hmac_final(ctx, ClientSignature, sizeof(ClientSignature)) < 0) { elog(ERROR, "could not calculate client signature"); } + pg_hmac_free(ctx); + /* 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]; @@ -1359,26 +1362,28 @@ build_server_final_message(scram_state *state) uint8 ServerSignature[SCRAM_KEY_LEN]; char *server_signature_base64; int siglen; - scram_HMAC_ctx ctx; + pg_hmac_ctx *ctx = pg_hmac_create(PG_SHA256); /* calculate ServerSignature */ - 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) + if (pg_hmac_init(ctx, state->ServerKey, SCRAM_KEY_LEN) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->client_first_message_bare, + strlen(state->client_first_message_bare)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->server_first_message, + strlen(state->server_first_message)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->client_final_message_without_proof, + strlen(state->client_final_message_without_proof)) < 0 || + pg_hmac_final(ctx, ServerSignature, sizeof(ServerSignature)) < 0) { elog(ERROR, "could not calculate server signature"); } + pg_hmac_free(ctx); + siglen = pg_b64_enc_len(SCRAM_KEY_LEN); /* don't forget the zero-terminator */ server_signature_base64 = palloc(siglen + 1); diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index a171df573ce..e24f00f0601 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -22,6 +22,7 @@ #include "common/cryptohash.h" #include "common/hashfn.h" +#include "common/hmac.h" #include "jit/jit.h" #include "storage/bufmgr.h" #include "storage/ipc.h" @@ -130,6 +131,7 @@ typedef struct ResourceOwnerData ResourceArray dsmarr; /* dynamic shmem segments */ ResourceArray jitarr; /* JIT contexts */ ResourceArray cryptohasharr; /* cryptohash contexts */ + ResourceArray hmacarr; /* HMAC contexts */ /* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */ int nlocks; /* number of owned locks */ @@ -178,6 +180,7 @@ static void PrintSnapshotLeakWarning(Snapshot snapshot); static void PrintFileLeakWarning(File file); static void PrintDSMLeakWarning(dsm_segment *seg); static void PrintCryptoHashLeakWarning(Datum handle); +static void PrintHMACLeakWarning(Datum handle); /***************************************************************************** @@ -448,6 +451,7 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name) ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL)); ResourceArrayInit(&(owner->jitarr), PointerGetDatum(NULL)); ResourceArrayInit(&(owner->cryptohasharr), PointerGetDatum(NULL)); + ResourceArrayInit(&(owner->hmacarr), PointerGetDatum(NULL)); return owner; } @@ -568,6 +572,16 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, PrintCryptoHashLeakWarning(foundres); pg_cryptohash_free(context); } + + /* Ditto for HMAC contexts */ + while (ResourceArrayGetAny(&(owner->hmacarr), &foundres)) + { + pg_hmac_ctx *context = (pg_hmac_ctx *) PointerGetDatum(foundres); + + if (isCommit) + PrintHMACLeakWarning(foundres); + pg_hmac_free(context); + } } else if (phase == RESOURCE_RELEASE_LOCKS) { @@ -737,6 +751,7 @@ ResourceOwnerDelete(ResourceOwner owner) Assert(owner->dsmarr.nitems == 0); Assert(owner->jitarr.nitems == 0); Assert(owner->cryptohasharr.nitems == 0); + Assert(owner->hmacarr.nitems == 0); Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1); /* @@ -765,6 +780,7 @@ ResourceOwnerDelete(ResourceOwner owner) ResourceArrayFree(&(owner->dsmarr)); ResourceArrayFree(&(owner->jitarr)); ResourceArrayFree(&(owner->cryptohasharr)); + ResourceArrayFree(&(owner->hmacarr)); pfree(owner); } @@ -1428,3 +1444,48 @@ PrintCryptoHashLeakWarning(Datum handle) elog(WARNING, "cryptohash context reference leak: context %p still referenced", DatumGetPointer(handle)); } + +/* + * Make sure there is room for at least one more entry in a ResourceOwner's + * hmac context reference array. + * + * This is separate from actually inserting an entry because if we run out of + * memory, it's critical to do so *before* acquiring the resource. + */ +void +ResourceOwnerEnlargeHMAC(ResourceOwner owner) +{ + ResourceArrayEnlarge(&(owner->hmacarr)); +} + +/* + * Remember that a HMAC context is owned by a ResourceOwner + * + * Caller must have previously done ResourceOwnerEnlargeHMAC() + */ +void +ResourceOwnerRememberHMAC(ResourceOwner owner, Datum handle) +{ + ResourceArrayAdd(&(owner->hmacarr), handle); +} + +/* + * Forget that a HMAC context is owned by a ResourceOwner + */ +void +ResourceOwnerForgetHMAC(ResourceOwner owner, Datum handle) +{ + if (!ResourceArrayRemove(&(owner->hmacarr), handle)) + elog(ERROR, "HMAC context %p is not owned by resource owner %s", + DatumGetPointer(handle), owner->name); +} + +/* + * Debugging subroutine + */ +static void +PrintHMACLeakWarning(Datum handle) +{ + elog(WARNING, "HMAC context reference leak: context %p still referenced", + DatumGetPointer(handle)); +} |