add convenience function for content-length limiation

This commit is contained in:
Christian Grothoff 2023-05-06 19:43:17 +02:00
parent 737b3338ed
commit 1f9427e1d9
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 96 additions and 36 deletions

@ -1 +1 @@
Subproject commit 85736484cb0da26aded705ebb1e944e8bb1b8504
Subproject commit 4654d82b143cd69dfe7a7bf2f816f6f91f6052e2

View File

@ -1617,33 +1617,8 @@ handle_mhd_request (void *cls,
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)
{
GNUNET_break_op (0);
return TALER_MHD_reply_request_too_large (connection);
}
}
TALER_MHD_check_content_length (connection,
TALER_MHD_REQUEST_BUFFER_MAX);
}
}

View File

@ -596,14 +596,14 @@ TALER_MHD_parse_request_header_data (struct MHD_Connection *connection,
bool p; \
switch (TALER_MHD_parse_request_header_data (connection, name, \
val, sizeof (*val), &p)) \
{ \
case GNUNET_SYSERR: \
GNUNET_break (0); \
return MHD_NO; \
case GNUNET_NO: \
GNUNET_break_op (0); \
return MHD_YES; \
case GNUNET_OK: \
{ \
case GNUNET_SYSERR: \
GNUNET_break (0); \
return MHD_NO; \
case GNUNET_NO: \
GNUNET_break_op (0); \
return MHD_YES; \
case GNUNET_OK: \
if (required & (! p)) \
return TALER_MHD_reply_with_error ( \
connection, \
@ -634,6 +634,49 @@ TALER_MHD_parse_request_header_data (struct MHD_Connection *connection,
} while (0)
/**
* Check that the 'Content-Length' header is giving
* a length below @a max_len. If not, return an
* appropriate error response and return the
* correct #MHD_YES/#MHD_NO value from this function.
*
* @param connection the MHD connection
* @param max_len maximum allowed content length
* @return
* #GNUNET_YES if the the argument is present
* #GNUNET_NO if the argument is absent or malformed
* #GNUNET_SYSERR on internal error (error response could not be sent)
*/
enum GNUNET_GenericReturnValue
TALER_MHD_check_content_length_ (struct MHD_Connection *connection,
unsigned long long max_len);
/**
* Check that the 'Content-Length' header is giving
* a length below @a max_len. If not, return an
* appropriate error response and return the
* correct #MHD_YES/#MHD_NO value from this function.
*
* @param connection the MHD connection
* @param max_len maximum allowed content length
*/
#define TALER_MHD_check_content_length(connection,max_len) \
do { \
switch (TALER_MHD_check_content_length_ (connection, max_len)) \
{ \
case GNUNET_SYSERR: \
GNUNET_break (0); \
return MHD_NO; \
case GNUNET_NO: \
GNUNET_break_op (0); \
return MHD_YES; \
case GNUNET_OK: \
break; \
} \
} while (0)
/**
* Parse the configuration to determine on which port
* or UNIX domain path we should run an HTTP service.

View File

@ -350,4 +350,46 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection,
}
enum GNUNET_GenericReturnValue
TALER_MHD_check_content_length_ (struct MHD_Connection *connection,
unsigned long long max_len)
{
const char *cl;
unsigned long long cv;
char dummy;
/* 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)
return GNUNET_OK;
if (1 != sscanf (cl,
"%llu%c",
&cv,
&dummy))
{
/* Not valid HTTP request, just close connection. */
GNUNET_break_op (0);
return (MHD_YES ==
TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
MHD_HTTP_HEADER_CONTENT_LENGTH))
? GNUNET_NO
: GNUNET_SYSERR;
}
if (cv > TALER_MHD_REQUEST_BUFFER_MAX)
{
GNUNET_break_op (0);
return (MHD_YES ==
TALER_MHD_reply_request_too_large (connection))
? GNUNET_NO
: GNUNET_SYSERR;
}
return GNUNET_OK;
}
/* end of mhd_parsing.c */