fix error handling for very large uploads, fix re-generation of /keys response after Expires expires

This commit is contained in:
Christian Grothoff 2021-12-08 18:12:28 +01:00
parent ed7379d235
commit 7e84b5570a
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
7 changed files with 58 additions and 29 deletions

View File

@ -1003,6 +1003,36 @@ handle_mhd_request (void *cls,
"illegal incoming correlation ID\n"); "illegal incoming correlation ID\n");
correlation_id = NULL; 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, GNUNET_async_scope_enter (&rc->async_scope_id,

View File

@ -1557,7 +1557,7 @@ get_date_string (struct GNUNET_TIME_Absolute at,
* @return #GNUNET_OK on success * @return #GNUNET_OK on success
*/ */
static enum GNUNET_GenericReturnValue 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) struct MHD_Response *response)
{ {
char dat[128]; char dat[128];
@ -1590,6 +1590,9 @@ setup_general_response_headers (const struct TEH_KeyStateHandle *ksh,
MHD_add_response_header (response, MHD_add_response_header (response,
MHD_HTTP_HEADER_EXPIRES, MHD_HTTP_HEADER_EXPIRES,
dat)); dat));
ksh->signature_expires
= GNUNET_TIME_absolute_min (m,
ksh->signature_expires);
} }
return GNUNET_OK; return GNUNET_OK;
} }

View File

@ -367,6 +367,8 @@ TEH_handler_management_post_keys (
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
"array expected for denom_sigs and signkey_sigs"); "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.nd_sigs = json_array_size (denom_sigs);
akc.d_sigs = GNUNET_new_array (akc.nd_sigs, akc.d_sigs = GNUNET_new_array (akc.nd_sigs,
struct DenomSig); struct DenomSig);
@ -404,6 +406,8 @@ TEH_handler_management_post_keys (
{ {
GNUNET_free (akc.d_sigs); GNUNET_free (akc.d_sigs);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failure to handle /management/keys\n");
return ret; return ret;
} }
akc.ns_sigs = json_array_size (signkey_sigs); akc.ns_sigs = json_array_size (signkey_sigs);
@ -440,6 +444,8 @@ TEH_handler_management_post_keys (
} }
if (! ok) if (! ok)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failure to handle /management/keys\n");
GNUNET_free (akc.d_sigs); GNUNET_free (akc.d_sigs);
GNUNET_free (akc.s_sigs); GNUNET_free (akc.s_sigs);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);

View File

@ -30,6 +30,12 @@
#include <gnunet/gnunet_mhd_compat.h> #include <gnunet/gnunet_mhd_compat.h>
/**
* Maximum POST request size.
*/
#define TALER_MHD_REQUEST_BUFFER_MAX (1024 * 1024 * 16)
/** /**
* Global options for response generation. * Global options for response generation.
*/ */

View File

@ -99,6 +99,10 @@ handle_post_keys_finished (void *cls,
hr.ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json); hr.hint = TALER_JSON_get_error_hint (json);
break; 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: default:
/* unexpected response code */ /* unexpected response code */
GNUNET_break_op (0); GNUNET_break_op (0);

View File

@ -27,12 +27,6 @@
#include "taler_mhd_lib.h" #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 * Process a POST request containing a JSON object. This function
* realizes an MHD POST processor that will (incrementally) process * 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; enum GNUNET_JSON_PostResult pr;
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, pr = GNUNET_JSON_post_parser (TALER_MHD_REQUEST_BUFFER_MAX,
connection, connection,
con_cls, con_cls,
upload_data, upload_data,
@ -87,9 +81,9 @@ TALER_MHD_parse_post_json (struct MHD_Connection *connection,
return GNUNET_YES; return GNUNET_YES;
case GNUNET_JSON_PR_REQUEST_TOO_LARGE: case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
GNUNET_break (NULL == *json); GNUNET_break (NULL == *json);
return (MHD_NO == GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
TALER_MHD_reply_request_too_large "Closing connection, upload too large\n");
(connection)) ? GNUNET_SYSERR : GNUNET_NO; return MHD_NO;
case GNUNET_JSON_PR_JSON_INVALID: case GNUNET_JSON_PR_JSON_INVALID:
GNUNET_break (NULL == *json); GNUNET_break (NULL == *json);
return (MHD_YES == return (MHD_YES ==

View File

@ -419,24 +419,10 @@ TALER_MHD_reply_with_ec (struct MHD_Connection *connection,
MHD_RESULT MHD_RESULT
TALER_MHD_reply_request_too_large (struct MHD_Connection *connection) TALER_MHD_reply_request_too_large (struct MHD_Connection *connection)
{ {
struct MHD_Response *response; return TALER_MHD_reply_with_error (connection,
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, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
response); TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT,
MHD_destroy_response (response); NULL);
return ret;
}
} }