libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit f2bce4c656228718793871f2b2141ba93e0599b0
parent 94c16f349dac04636da8fe94277d53c344e958c5
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 25 Sep 2015 07:51:21 +0000

fix digest auth when used with more complex arguments being passed to GET, i.e. keys without missing values at the beginning and certain other constellations

Diffstat:
MChangeLog | 5+++++
Msrc/include/microhttpd.h | 2+-
Msrc/microhttpd/connection.c | 12+++++-------
Msrc/microhttpd/digestauth.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
4 files changed, 88 insertions(+), 34 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,8 @@ +Fri Sep 25 09:49:10 CEST 2015 + Fix digest authentication with URL arguments where + value-less keys are given before the last argument. + Thanks to MA for reporting. -CG + Tue Sep 22 19:17:54 CEST 2015 Do not use shutdown() on listen socket if MHD_USE_PIPE_FOR_SHUTDOWN is set. -CG diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -130,7 +130,7 @@ typedef intptr_t ssize_t; * Current version of the library. * 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00094301 +#define MHD_VERSION 0x00094302 /** * MHD-internal return code for "YES". diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -1,5 +1,5 @@ /* - This file is part of libmicrohttpd + This file is part of libmicrohttpd Copyright (C) 2007-2015 Daniel Pittman and Christian Grothoff This library is free software; you can redistribute it and/or @@ -17,7 +17,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - /** * @file connection.c * @brief Methods for managing connections @@ -301,7 +300,7 @@ connection_close_error (struct MHD_Connection *connection, if (NULL != emsg) MHD_DLOG (connection->daemon, emsg); #endif - MHD_connection_close (connection, + MHD_connection_close (connection, MHD_REQUEST_TERMINATED_WITH_ERROR); } @@ -369,7 +368,7 @@ try_ready_normal_body (struct MHD_Connection *connection) if (NULL != response->crc) (void) MHD_mutex_unlock_ (&response->mutex); if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret) - MHD_connection_close (connection, + MHD_connection_close (connection, MHD_REQUEST_TERMINATED_COMPLETED_OK); else CONNECTION_CLOSE_ERROR (connection, @@ -1264,7 +1263,6 @@ parse_arguments (enum MHD_ValueKind kind, /* continue with 'bar' */ args = amper; continue; - } /* equals and amper are non-NULL here, and equals < amper, so we got regular 'foo=value&bar...'-kind of argument */ @@ -2597,12 +2595,12 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) connection->client_aware = MHD_NO; } end = - MHD_lookup_connection_value (connection, + MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONNECTION); if ( (MHD_YES == connection->read_closed) || (client_close) || - ( (NULL != end) && + ( (NULL != end) && (MHD_str_equal_caseless_ (end, "close")) ) ) { connection->read_closed = MHD_YES; diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c @@ -493,12 +493,12 @@ check_argument_match (struct MHD_Connection *connection, char *amper; unsigned int num_headers; - argb = strdup(args); + argb = strdup (args); if (NULL == argb) { #if HAVE_MESSAGES - MHD_DLOG(connection->daemon, - "Failed to allocate memory for copy of URI arguments\n"); + MHD_DLOG (connection->daemon, + "Failed to allocate memory for copy of URI arguments\n"); #endif /* HAVE_MESSAGES */ return MHD_NO; } @@ -508,45 +508,93 @@ check_argument_match (struct MHD_Connection *connection, ('\0' != argp[0]) ) { equals = strchr (argp, '='); - if (NULL == equals) + amper = strchr (argp, '&'); + if (NULL == amper) { + /* last argument */ + if (NULL == equals) + { + /* last argument, without '=' */ + MHD_unescape_plus (argp); + if (MHD_YES != test_header (connection, + argp, + NULL)) + { + free (argb); + return MHD_NO; + } + num_headers++; + break; + } + /* got 'foo=bar' */ + equals[0] = '\0'; + equals++; + MHD_unescape_plus (argp); /* add with 'value' NULL */ connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, connection, argp); - if (MHD_YES != test_header (connection, argp, NULL)) - { - free(argb); - return MHD_NO; - } + MHD_unescape_plus (equals); + /* add with 'value' NULL */ + connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, + connection, + equals); + if (MHD_YES != test_header (connection, + argp, + equals)) + { + free (argb); + return MHD_NO; + } num_headers++; break; } - equals[0] = '\0'; - equals++; - amper = strchr (equals, '&'); - if (NULL != amper) + /* amper is non-NULL here */ + amper[0] = '\0'; + amper++; + if ( (NULL == equals) || + (equals >= amper) ) { - amper[0] = '\0'; - amper++; + /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */ + MHD_unescape_plus (argp); + connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, + connection, + argp); + if (MHD_YES != + test_header (connection, + argp, + NULL)) + { + free (argb); + return MHD_NO; + } + /* continue with 'bar' */ + num_headers++; + args = amper; + continue; } + equals[0] = '\0'; + equals++; + MHD_unescape_plus (argp); connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, connection, argp); + MHD_unescape_plus (equals); connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, connection, equals); - if (! test_header (connection, argp, equals)) - { - free(argb); + if (MHD_YES != + test_header (connection, + argp, + equals)) + { + free (argb); return MHD_NO; - } - + } num_headers++; argp = amper; } - - free(argb); + free (argb); /* also check that the number of headers matches */ for (pos = connection->headers_received; NULL != pos; pos = pos->next) @@ -556,7 +604,10 @@ check_argument_match (struct MHD_Connection *connection, num_headers--; } if (0 != num_headers) - return MHD_NO; + { + /* argument count mismatch */ + return MHD_NO; + } return MHD_YES; } @@ -623,9 +674,9 @@ MHD_digest_auth_check (struct MHD_Connection *connection, { char r[MAX_REALM_LENGTH]; - len = lookup_sub_value(r, - sizeof (r), - header, "realm"); + len = lookup_sub_value (r, + sizeof (r), + header, "realm"); if ( (0 == len) || (0 != strcmp(realm, r)) ) return MHD_NO;