From 7e84b5570adeaa027f8c7861caf6af7943edcd0b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 8 Dec 2021 18:12:28 +0100 Subject: [PATCH] fix error handling for very large uploads, fix re-generation of /keys response after Expires expires --- src/exchange/taler-exchange-httpd.c | 30 +++++++++++++++++++ src/exchange/taler-exchange-httpd_keys.c | 5 +++- ...aler-exchange-httpd_management_post_keys.c | 6 ++++ src/include/taler_mhd_lib.h | 6 ++++ src/lib/exchange_api_management_post_keys.c | 4 +++ src/mhd/mhd_parsing.c | 14 +++------ src/mhd/mhd_responses.c | 22 +++----------- 7 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 57c965189..58e9b572a 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -1003,6 +1003,36 @@ handle_mhd_request (void *cls, "illegal incoming correlation ID\n"); correlation_id = NULL; } + + /* Check if upload is in bounds */ + if (0 == strcasecmp (method, + MHD_HTTP_METHOD_POST)) + { + const char *cl; + + /* Maybe check for maximum upload size + and refuse requests if they are just too big. */ + cl = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_CONTENT_LENGTH); + if (NULL != cl) + { + unsigned long long cv; + char dummy; + + if (1 != sscanf (cl, + "%llu%c", + &cv, + &dummy)) + { + /* Not valid HTTP request, just close connection. */ + GNUNET_break_op (0); + return MHD_NO; + } + if (cv > TALER_MHD_REQUEST_BUFFER_MAX) + return TALER_MHD_reply_request_too_large (connection); + } + } } GNUNET_async_scope_enter (&rc->async_scope_id, diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c index fbca5d652..29d964c6b 100644 --- a/src/exchange/taler-exchange-httpd_keys.c +++ b/src/exchange/taler-exchange-httpd_keys.c @@ -1557,7 +1557,7 @@ get_date_string (struct GNUNET_TIME_Absolute at, * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -setup_general_response_headers (const struct TEH_KeyStateHandle *ksh, +setup_general_response_headers (struct TEH_KeyStateHandle *ksh, struct MHD_Response *response) { char dat[128]; @@ -1590,6 +1590,9 @@ setup_general_response_headers (const struct TEH_KeyStateHandle *ksh, MHD_add_response_header (response, MHD_HTTP_HEADER_EXPIRES, dat)); + ksh->signature_expires + = GNUNET_TIME_absolute_min (m, + ksh->signature_expires); } return GNUNET_OK; } diff --git a/src/exchange/taler-exchange-httpd_management_post_keys.c b/src/exchange/taler-exchange-httpd_management_post_keys.c index ad4cd3c04..f0c3f1f39 100644 --- a/src/exchange/taler-exchange-httpd_management_post_keys.c +++ b/src/exchange/taler-exchange-httpd_management_post_keys.c @@ -367,6 +367,8 @@ TEH_handler_management_post_keys ( TALER_EC_GENERIC_PARAMETER_MALFORMED, "array expected for denom_sigs and signkey_sigs"); } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received /management/keys\n"); akc.nd_sigs = json_array_size (denom_sigs); akc.d_sigs = GNUNET_new_array (akc.nd_sigs, struct DenomSig); @@ -404,6 +406,8 @@ TEH_handler_management_post_keys ( { GNUNET_free (akc.d_sigs); GNUNET_JSON_parse_free (spec); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failure to handle /management/keys\n"); return ret; } akc.ns_sigs = json_array_size (signkey_sigs); @@ -440,6 +444,8 @@ TEH_handler_management_post_keys ( } if (! ok) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failure to handle /management/keys\n"); GNUNET_free (akc.d_sigs); GNUNET_free (akc.s_sigs); GNUNET_JSON_parse_free (spec); diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index ba5a072c4..7f38ffcf5 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -30,6 +30,12 @@ #include +/** + * Maximum POST request size. + */ +#define TALER_MHD_REQUEST_BUFFER_MAX (1024 * 1024 * 16) + + /** * Global options for response generation. */ diff --git a/src/lib/exchange_api_management_post_keys.c b/src/lib/exchange_api_management_post_keys.c index e956cfd55..6b040bdaa 100644 --- a/src/lib/exchange_api_management_post_keys.c +++ b/src/lib/exchange_api_management_post_keys.c @@ -99,6 +99,10 @@ handle_post_keys_finished (void *cls, hr.ec = TALER_JSON_get_error_code (json); hr.hint = TALER_JSON_get_error_hint (json); break; + case MHD_HTTP_REQUEST_ENTITY_TOO_LARGE: + hr.ec = TALER_JSON_get_error_code (json); + hr.hint = TALER_JSON_get_error_hint (json); + break; default: /* unexpected response code */ GNUNET_break_op (0); diff --git a/src/mhd/mhd_parsing.c b/src/mhd/mhd_parsing.c index b55a3db32..4415c82a8 100644 --- a/src/mhd/mhd_parsing.c +++ b/src/mhd/mhd_parsing.c @@ -27,12 +27,6 @@ #include "taler_mhd_lib.h" -/** - * Maximum POST request size. - */ -#define REQUEST_BUFFER_MAX (1024 * 1024) - - /** * Process a POST request containing a JSON object. This function * realizes an MHD POST processor that will (incrementally) process @@ -65,7 +59,7 @@ TALER_MHD_parse_post_json (struct MHD_Connection *connection, { enum GNUNET_JSON_PostResult pr; - pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, + pr = GNUNET_JSON_post_parser (TALER_MHD_REQUEST_BUFFER_MAX, connection, con_cls, upload_data, @@ -87,9 +81,9 @@ TALER_MHD_parse_post_json (struct MHD_Connection *connection, return GNUNET_YES; case GNUNET_JSON_PR_REQUEST_TOO_LARGE: GNUNET_break (NULL == *json); - return (MHD_NO == - TALER_MHD_reply_request_too_large - (connection)) ? GNUNET_SYSERR : GNUNET_NO; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Closing connection, upload too large\n"); + return MHD_NO; case GNUNET_JSON_PR_JSON_INVALID: GNUNET_break (NULL == *json); return (MHD_YES == diff --git a/src/mhd/mhd_responses.c b/src/mhd/mhd_responses.c index 5b99dd128..2918440a2 100644 --- a/src/mhd/mhd_responses.c +++ b/src/mhd/mhd_responses.c @@ -419,24 +419,10 @@ TALER_MHD_reply_with_ec (struct MHD_Connection *connection, MHD_RESULT TALER_MHD_reply_request_too_large (struct MHD_Connection *connection) { - struct MHD_Response *response; - - response = MHD_create_response_from_buffer (0, - NULL, - MHD_RESPMEM_PERSISTENT); - if (NULL == response) - return MHD_NO; - TALER_MHD_add_global_headers (response); - - { - MHD_RESULT ret; - - ret = MHD_queue_response (connection, - MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, - response); - MHD_destroy_response (response); - return ret; - } + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, + TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT, + NULL); }