mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 10:13:58 +00:00
- Copy pg-knoe-auth/ wholesale from upstream/knoe-db/20260523 (Task 1 of docs/plans/junie/upstream-knoe-db-20260523-integration.md). - Extension: PG18 OAUTHBEARER JWT validator using libcurl + OpenSSL RS256. - knoe-db/Dockerfile: add libcurl4-openssl-dev to dev deps; COPY src/ and build with make USE_PGXS=1 install after tds_fdw. - NOT enabled in the default database build (absent from 20_create_extensions.sh). To enable: CREATE EXTENSION pg_knoe_auth; (requires pg_hba.conf oauth_issuer). Closes Task 1 of upstream-knoe-db-20260523-integration.md.
104 lines
3.1 KiB
C
104 lines
3.1 KiB
C
/*
|
|
* test_response_bound.c — unit tests for H3: HTTP response size bound.
|
|
*
|
|
* Tests that the curl write callback aborts at MAX_JWKS_BYTES+1 and
|
|
* passes for smaller payloads.
|
|
* See docs/plans/junie/pg_knoe_auth-rename-harden-modularize.md §2.2.3
|
|
*/
|
|
#include "test_helpers.h"
|
|
|
|
#define MAX_JWKS_BYTES (10 * 1024 * 1024)
|
|
|
|
typedef struct {
|
|
char *data;
|
|
size_t len;
|
|
size_t alloc;
|
|
} CurlBuf;
|
|
|
|
/* curl_write_cb — same logic as pg_knoe_auth.c */
|
|
static size_t
|
|
curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
|
|
{
|
|
CurlBuf *buf = (CurlBuf *) userdata;
|
|
size_t new_bytes = size * nmemb;
|
|
|
|
if (buf->len + new_bytes > MAX_JWKS_BYTES) {
|
|
elog(WARNING, "pg_knoe_auth: JWKS response > %d bytes; aborting",
|
|
MAX_JWKS_BYTES);
|
|
return 0;
|
|
}
|
|
|
|
if (buf->len + new_bytes + 1 > buf->alloc) {
|
|
buf->alloc = (buf->len + new_bytes + 1) * 2;
|
|
buf->data = repalloc(buf->data, buf->alloc);
|
|
}
|
|
memcpy(buf->data + buf->len, ptr, new_bytes);
|
|
buf->len += new_bytes;
|
|
buf->data[buf->len] = '\0';
|
|
return new_bytes;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
CurlBuf buf;
|
|
size_t ret;
|
|
char *chunk;
|
|
|
|
/* ── Test 1: small payload passes ──────────────────────────────────── */
|
|
buf.alloc = 8192;
|
|
buf.len = 0;
|
|
buf.data = palloc(buf.alloc);
|
|
buf.data[0] = '\0';
|
|
|
|
chunk = palloc(1024);
|
|
memset(chunk, 'A', 1024);
|
|
ret = curl_write_cb(chunk, 1, 1024, &buf);
|
|
ASSERT(ret == 1024, "1 KB payload: write callback returns 1024");
|
|
ASSERT(buf.len == 1024, "1 KB payload: buf.len is 1024");
|
|
pfree(chunk);
|
|
pfree(buf.data);
|
|
|
|
/* ── Test 2: exactly MAX_JWKS_BYTES passes ──────────────────────────── */
|
|
buf.alloc = MAX_JWKS_BYTES + 16;
|
|
buf.len = 0;
|
|
buf.data = palloc(buf.alloc);
|
|
buf.data[0] = '\0';
|
|
|
|
/* Simulate buf already at MAX_JWKS_BYTES - 1, then write 1 byte */
|
|
buf.len = MAX_JWKS_BYTES - 1;
|
|
chunk = palloc(1);
|
|
chunk[0] = 'X';
|
|
ret = curl_write_cb(chunk, 1, 1, &buf);
|
|
ASSERT(ret == 1, "write of 1 byte when buf.len == MAX-1 passes");
|
|
pfree(chunk);
|
|
pfree(buf.data);
|
|
|
|
/* ── Test 3: MAX_JWKS_BYTES + 1 aborts ─────────────────────────────── */
|
|
buf.alloc = MAX_JWKS_BYTES + 16;
|
|
buf.len = MAX_JWKS_BYTES;
|
|
buf.data = palloc(buf.alloc);
|
|
buf.data[0] = '\0';
|
|
|
|
chunk = palloc(1);
|
|
chunk[0] = 'Y';
|
|
ret = curl_write_cb(chunk, 1, 1, &buf);
|
|
ASSERT(ret == 0, "write of 1 byte when buf.len == MAX aborts (returns 0)");
|
|
pfree(chunk);
|
|
pfree(buf.data);
|
|
|
|
/* ── Test 4: large chunk that would overflow aborts ─────────────────── */
|
|
buf.alloc = 8192;
|
|
buf.len = MAX_JWKS_BYTES - 100;
|
|
buf.data = palloc(buf.alloc);
|
|
buf.data[0] = '\0';
|
|
|
|
chunk = palloc(200);
|
|
memset(chunk, 'Z', 200);
|
|
ret = curl_write_cb(chunk, 1, 200, &buf);
|
|
ASSERT(ret == 0, "200-byte chunk that would exceed MAX aborts");
|
|
pfree(chunk);
|
|
pfree(buf.data);
|
|
|
|
TEST_SUMMARY();
|
|
}
|