challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

commit d1aae4b76347b31a72b048fcf31ff82d8012f9ca
parent 053e9d37087c4b51628c69eb703289eb0d6e4a2c
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  6 Aug 2026 08:53:44 +0200

do not die on non-UTF-8 input

Diffstat:
Msrc/challenger/challenger-httpd_challenge.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/challenger/meson.build | 1+
2 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/src/challenger/challenger-httpd_challenge.c b/src/challenger/challenger-httpd_challenge.c @@ -94,6 +94,13 @@ struct ChallengeContext char *last_key; /** + * Name of the first uploaded field that could not be represented + * in JSON (because the key or the value was not valid UTF-8), or + * NULL if all fields were fine. + */ + char *bad_key; + + /** * Uploaded data during POST processing. */ char *data; @@ -256,6 +263,7 @@ cleanup_ctx (void *cls) GNUNET_free (bc->data); GNUNET_free (bc->state); GNUNET_free (bc->last_key); + GNUNET_free (bc->bad_key); GNUNET_free (bc->client_redirect_uri); GNUNET_free (bc); } @@ -492,6 +500,54 @@ send_tan (struct ChallengeContext *bc) /** + * Store the value accumulated in @a bc->data under @a bc->last_key in + * the address object of @a bc, and free both. If the key or the value + * is not valid UTF-8 (and thus not representable in JSON), the field is + * dropped and its name is remembered in @a bc->bad_key so that the main + * handler can fail the request with a 400. + * + * Both strings are raw bytes from the client, so failure here must + * never be fatal to the process. + * + * @param[in,out] bc context to update + */ +static void +flush_field (struct ChallengeContext *bc) +{ + json_t *jkey; + json_t *jval; + + /* json_string() returns NULL if the input is not valid UTF-8. */ + jkey = json_string (bc->last_key); + jval = json_string (NULL != bc->data + ? bc->data + : ""); + if ( (NULL == jkey) || + (NULL == jval) ) + { + GNUNET_break_op (0); + if (NULL == bc->bad_key) + bc->bad_key = GNUNET_strdup ( + (NULL != jkey) + ? bc->last_key + : "<field name is not valid UTF-8>"); + } + else + { + GNUNET_assert (0 == + json_object_set (bc->address, + bc->last_key, + jval)); + } + json_decref (jkey); + json_decref (jval); + GNUNET_free (bc->last_key); + GNUNET_free (bc->data); + bc->data_len = 0; +} + + +/** * Iterator over key-value pairs where the value may be made available * in increments and/or may not be zero-terminated. Used for * processing POST data. @@ -532,13 +588,7 @@ post_iter (void *cls, (0 != strcmp (key, bc->last_key)) ) { - GNUNET_assert (0 == - json_object_set_new (bc->address, - bc->last_key, - json_string (bc->data))); - GNUNET_free (bc->data); - bc->data_len = 0; - GNUNET_free (bc->last_key); + flush_field (bc); } if (NULL == bc->last_key) { @@ -818,13 +868,14 @@ CH_handler_challenge (struct CH_HandlerContext *hc, } if (NULL != bc->last_key) { - GNUNET_assert (0 == - json_object_set_new (bc->address, - bc->last_key, - json_string (bc->data))); - GNUNET_free (bc->data); - bc->data_len = 0; - GNUNET_free (bc->last_key); + flush_field (bc); + } + if (NULL != bc->bad_key) + { + return reply_error (bc, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + bc->bad_key); } #if DEBUG { diff --git a/src/challenger/meson.build b/src/challenger/meson.build @@ -11,6 +11,7 @@ check_SCRIPTS = [ 'test-challenger', 'test-challenger-pkce', 'test-challenger-revisit', + 'test-challenger-badutf8', ] test_helper_cat = configure_file(input: 'cat.sh', output: 'cat.sh', copy: true)