aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq-oauth/oauth-curl.c
diff options
context:
space:
mode:
authorJacob Champion <jchampion@postgresql.org>2025-05-23 13:05:33 -0700
committerJacob Champion <jchampion@postgresql.org>2025-05-23 13:05:33 -0700
commitcbc8fd0c9aec01f451af5e4eeb0eb2c5d5e47eb2 (patch)
tree643d5d4f0f6c129b81b0647f4531251cd95e66a7 /src/interfaces/libpq-oauth/oauth-curl.c
parent1ca583f6c0f9c178dd2721886c723791ced65520 (diff)
downloadpostgresql-cbc8fd0c9aec01f451af5e4eeb0eb2c5d5e47eb2.tar.gz
postgresql-cbc8fd0c9aec01f451af5e4eeb0eb2c5d5e47eb2.zip
oauth: Limit JSON parsing depth in the client
Check the ctx->nested level as we go, to prevent a server from running the client out of stack space. The limit we choose when communicating with authorization servers can't be overly strict, since those servers will continue to add extensions in their JSON documents which we need to correctly ignore. For the SASL communication, we can be more conservative, since there are no defined extensions (and the peer is probably more Postgres code). Reviewed-by: Aleksander Alekseev <aleksander@timescale.com> Discussion: https://postgr.es/m/CAOYmi%2Bm71aRUEi0oQE9ciBnBS8xVtMn3CifaPu2kmJzUfhOZgA%40mail.gmail.com
Diffstat (limited to 'src/interfaces/libpq-oauth/oauth-curl.c')
-rw-r--r--src/interfaces/libpq-oauth/oauth-curl.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c
index d13b9cbabb4..dba9a684fa8 100644
--- a/src/interfaces/libpq-oauth/oauth-curl.c
+++ b/src/interfaces/libpq-oauth/oauth-curl.c
@@ -83,6 +83,20 @@
#define MAX_OAUTH_RESPONSE_SIZE (256 * 1024)
/*
+ * Similarly, a limit on the maximum JSON nesting level keeps a server from
+ * running us out of stack space. A common nesting level in practice is 2 (for a
+ * top-level object containing arrays of strings). As of May 2025, the maximum
+ * depth for standard server metadata appears to be 6, if the document contains
+ * a full JSON Web Key Set in its "jwks" parameter.
+ *
+ * Since it's easy to nest JSON, and the number of parameters and key types
+ * keeps growing, take a healthy buffer of 16. (If this ever proves to be a
+ * problem in practice, we may want to switch over to the incremental JSON
+ * parser instead of playing with this parameter.)
+ */
+#define MAX_OAUTH_NESTING_LEVEL 16
+
+/*
* Parsed JSON Representations
*
* As a general rule, we parse and cache only the fields we're currently using.
@@ -495,6 +509,12 @@ oauth_json_object_start(void *state)
}
++ctx->nested;
+ if (ctx->nested > MAX_OAUTH_NESTING_LEVEL)
+ {
+ oauth_parse_set_error(ctx, "JSON is too deeply nested");
+ return JSON_SEM_ACTION_FAILED;
+ }
+
return JSON_SUCCESS;
}
@@ -599,6 +619,12 @@ oauth_json_array_start(void *state)
}
++ctx->nested;
+ if (ctx->nested > MAX_OAUTH_NESTING_LEVEL)
+ {
+ oauth_parse_set_error(ctx, "JSON is too deeply nested");
+ return JSON_SEM_ACTION_FAILED;
+ }
+
return JSON_SUCCESS;
}