aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/libpq/auth-scram.c61
-rw-r--r--src/backend/utils/resowner/resowner.c61
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));
+}