From bcfb09a15e3b46a7b2f3a19324be9b5f8d81740c Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Fri, 14 Feb 2025 14:36:54 -0800 Subject: [PATCH v50 3/4] fixup! changes to sanitize_char et al --- src/backend/libpq/auth-oauth.c | 55 +++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/backend/libpq/auth-oauth.c b/src/backend/libpq/auth-oauth.c index 27f7af7be00..e4aa6f357b5 100644 --- a/src/backend/libpq/auth-oauth.c +++ b/src/backend/libpq/auth-oauth.c @@ -70,7 +70,7 @@ struct oauth_ctx const char *scope; }; -static char *sanitize_char(char c); +static void sanitize_char(char c, char *buf, size_t buflen); static char *parse_kvpairs_for_auth(char **input); static void generate_error_response(struct oauth_ctx *ctx, char **output, int *outputlen); static bool validate(Port *port, const char *auth); @@ -139,6 +139,7 @@ oauth_exchange(void *opaq, const char *input, int inputlen, char cbind_flag; char *auth; int status; + char errmsgbuf[5]; struct oauth_ctx *ctx = opaq; @@ -162,6 +163,7 @@ oauth_exchange(void *opaq, const char *input, int inputlen, /* * Check that the input length agrees with the string length of the input. + * Possible reasons for discrepancies include embedded nulls in the string. */ if (inputlen == 0) ereport(ERROR, @@ -223,22 +225,29 @@ oauth_exchange(void *opaq, const char *input, int inputlen, case 'y': /* fall through */ case 'n': - p++; + if (!*(++p)) + goto endofmessage; + if (*p != ',') + { + sanitize_char(*p, errmsgbuf, sizeof(errmsgbuf)); ereport(ERROR, errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("malformed OAUTHBEARER message"), errdetail("Comma expected, but found character \"%s\".", - sanitize_char(*p))); - p++; + errmsgbuf)); + } + if (!*(++p)) + goto endofmessage; break; default: + sanitize_char(*p, errmsgbuf, sizeof(errmsgbuf)); ereport(ERROR, errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("malformed OAUTHBEARER message"), errdetail("Unexpected channel-binding flag \"%s\".", - sanitize_char(cbind_flag))); + errmsgbuf)); } /* @@ -249,21 +258,29 @@ oauth_exchange(void *opaq, const char *input, int inputlen, errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("client uses authorization identity, but it is not supported")); if (*p != ',') + { + sanitize_char(*p, errmsgbuf, sizeof(errmsgbuf)); ereport(ERROR, errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("malformed OAUTHBEARER message"), errdetail("Unexpected attribute \"%s\" in client-first-message.", - sanitize_char(*p))); - p++; + errmsgbuf)); + } + if (!*(++p)) + goto endofmessage; /* All remaining fields are separated by the RFC's kvsep (\x01). */ if (*p != KVSEP) + { + sanitize_char(*p, errmsgbuf, sizeof(errmsgbuf)); ereport(ERROR, errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("malformed OAUTHBEARER message"), errdetail("Key-value separator expected, but found character \"%s\".", - sanitize_char(*p))); - p++; + errmsgbuf)); + } + if (!*(++p)) + goto endofmessage; auth = parse_kvpairs_for_auth(&p); if (!auth) @@ -296,6 +313,13 @@ oauth_exchange(void *opaq, const char *input, int inputlen, explicit_bzero(input_copy, inputlen); return status; + +endofmessage: + explicit_bzero(input_copy, inputlen); + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message")); + pg_unreachable(); } /* @@ -303,19 +327,14 @@ oauth_exchange(void *opaq, const char *input, int inputlen, * * If it's a printable ASCII character, print it as a single character. * otherwise, print it in hex. - * - * The returned pointer points to a static buffer. */ -static char * -sanitize_char(char c) +static void +sanitize_char(char c, char *buf, size_t buflen) { - static char buf[5]; - if (c >= 0x21 && c <= 0x7E) - snprintf(buf, sizeof(buf), "'%c'", c); + snprintf(buf, buflen, "'%c'", c); else - snprintf(buf, sizeof(buf), "0x%02x", (unsigned char) c); - return buf; + snprintf(buf, buflen, "0x%02x", (unsigned char) c); } /* -- 2.34.1