[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r30983 - in libmicrohttpd: . src/microhttpd
From: |
gnunet |
Subject: |
[GNUnet-SVN] r30983 - in libmicrohttpd: . src/microhttpd |
Date: |
Fri, 29 Nov 2013 20:18:51 +0100 |
Author: grothoff
Date: 2013-11-29 20:18:51 +0100 (Fri, 29 Nov 2013)
New Revision: 30983
Modified:
libmicrohttpd/ChangeLog
libmicrohttpd/src/microhttpd/digestauth.c
Log:
eliminate theoretical stack overflow
Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog 2013-11-29 18:12:52 UTC (rev 30982)
+++ libmicrohttpd/ChangeLog 2013-11-29 19:18:51 UTC (rev 30983)
@@ -1,3 +1,10 @@
+Fri Nov 29 20:17:03 CET 2013
+ Eliminating theoretical stack overflow by limiting length
+ of URIs in authentication headers to 32k (only applicable
+ if the application explicitly raised the memroy limits,
+ and only applies to MHD_digest_auth_check). Issue was
+ reported by Florian Weimer. -CG
+
Tue Nov 26 01:26:15 CET 2013
Fix race on shutdown signal with thread pool on non-Linux
systems by signalling n times for n threads. -CG
Modified: libmicrohttpd/src/microhttpd/digestauth.c
===================================================================
--- libmicrohttpd/src/microhttpd/digestauth.c 2013-11-29 18:12:52 UTC (rev
30982)
+++ libmicrohttpd/src/microhttpd/digestauth.c 2013-11-29 19:18:51 UTC (rev
30983)
@@ -51,7 +51,7 @@
/**
- * convert bin to hex
+ * convert bin to hex
*
* @param bin binary data
* @param len number of bytes in bin
@@ -64,12 +64,12 @@
{
size_t i;
unsigned int j;
-
- for (i = 0; i < len; ++i)
+
+ for (i = 0; i < len; ++i)
{
- j = (bin[i] >> 4) & 0x0f;
- hex[i * 2] = j <= 9 ? (j + '0') : (j + 'a' - 10);
- j = bin[i] & 0x0f;
+ j = (bin[i] >> 4) & 0x0f;
+ hex[i * 2] = j <= 9 ? (j + '0') : (j + 'a' - 10);
+ j = bin[i] & 0x0f;
hex[i * 2 + 1] = j <= 9 ? (j + '0') : (j + 'a' - 10);
}
hex[len * 2] = '\0';
@@ -99,7 +99,7 @@
{
struct MD5Context md5;
unsigned char ha1[MD5_DIGEST_SIZE];
-
+
MD5Init (&md5);
MD5Update (&md5, username, strlen (username));
MD5Update (&md5, ":", 1);
@@ -107,7 +107,7 @@
MD5Update (&md5, ":", 1);
MD5Update (&md5, password, strlen (password));
MD5Final (ha1, &md5);
- if (0 == strcasecmp (alg, "md5-sess"))
+ if (0 == strcasecmp (alg, "md5-sess"))
{
MD5Init (&md5);
MD5Update (&md5, ha1, sizeof (ha1));
@@ -122,8 +122,8 @@
/**
- * Calculate request-digest/response-digest as per RFC2617 spec
- *
+ * Calculate request-digest/response-digest as per RFC2617 spec
+ *
* @param ha1 H(A1)
* @param nonce nonce from server
* @param noncecount 8 hex digits
@@ -149,11 +149,11 @@
unsigned char ha2[MD5_DIGEST_SIZE];
unsigned char resphash[MD5_DIGEST_SIZE];
char ha2hex[HASH_MD5_HEX_LEN + 1];
-
+
MD5Init (&md5);
MD5Update (&md5, method, strlen(method));
MD5Update (&md5, ":", 1);
- MD5Update (&md5, uri, strlen(uri));
+ MD5Update (&md5, uri, strlen(uri));
#if 0
if (0 == strcasecmp(qop, "auth-int"))
{
@@ -163,15 +163,15 @@
if (NULL != hentity)
MD5Update (&md5, hentity, strlen(hentity));
}
-#endif
+#endif
MD5Final (ha2, &md5);
cvthex (ha2, MD5_DIGEST_SIZE, ha2hex);
- MD5Init (&md5);
- /* calculate response */
+ MD5Init (&md5);
+ /* calculate response */
MD5Update (&md5, ha1, HASH_MD5_HEX_LEN);
MD5Update (&md5, ":", 1);
MD5Update (&md5, nonce, strlen(nonce));
- MD5Update (&md5, ":", 1);
+ MD5Update (&md5, ":", 1);
if ('\0' != *qop)
{
MD5Update (&md5, noncecount, strlen(noncecount));
@@ -180,7 +180,7 @@
MD5Update (&md5, ":", 1);
MD5Update (&md5, qop, strlen(qop));
MD5Update (&md5, ":", 1);
- }
+ }
MD5Update (&md5, ha2hex, HASH_MD5_HEX_LEN);
MD5Final (resphash, &md5);
cvthex (resphash, sizeof (resphash), response);
@@ -225,7 +225,7 @@
return 0;
q1 = eq + 1;
while (' ' == *q1)
- q1++;
+ q1++;
if ('\"' != *q1)
{
q2 = strchr (q1, ',');
@@ -238,7 +238,7 @@
if (NULL == q2)
return 0; /* end quote not found */
qn = q2 + 1;
- }
+ }
if ( (0 == strncasecmp (ptr,
key,
keylen)) &&
@@ -261,7 +261,7 @@
if (size > (q2 - q1) + 1)
size = (q2 - q1) + 1;
size--;
- memcpy (dest,
+ memcpy (dest,
q1,
size);
dest[size] = '\0';
@@ -316,13 +316,13 @@
* nonce counter is less than the current nonce counter by 1,
* then only increase the nonce counter by one.
*/
-
+
(void) pthread_mutex_lock (&connection->daemon->nnc_lock);
if (0 == nc)
{
- strcpy(connection->daemon->nnc[off].nonce,
+ strcpy(connection->daemon->nnc[off].nonce,
nonce);
- connection->daemon->nnc[off].nc = 0;
+ connection->daemon->nnc[off].nc = 0;
(void) pthread_mutex_unlock (&connection->daemon->nnc_lock);
return MHD_YES;
}
@@ -331,7 +331,7 @@
{
(void) pthread_mutex_unlock (&connection->daemon->nnc_lock);
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon,
+ MHD_DLOG (connection->daemon,
"Stale nonce received. If this happens a lot, you should
probably increase the size of the nonce array.\n");
#endif
return MHD_NO;
@@ -356,9 +356,9 @@
size_t len;
char user[MAX_USERNAME_LENGTH];
const char *header;
-
+
if (NULL == (header = MHD_lookup_connection_value (connection,
- MHD_HEADER_KIND,
+ MHD_HEADER_KIND,
MHD_HTTP_HEADER_AUTHORIZATION)))
return NULL;
if (0 != strncmp (header, _BASE, strlen (_BASE)))
@@ -366,7 +366,7 @@
header += strlen (_BASE);
if (0 == (len = lookup_sub_value (user,
sizeof (user),
- header,
+ header,
"username")))
return NULL;
return strdup (user);
@@ -404,7 +404,7 @@
timestamp[0] = (nonce_time & 0xff000000) >> 0x18;
timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10;
timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08;
- timestamp[3] = (nonce_time & 0x000000ff);
+ timestamp[3] = (nonce_time & 0x000000ff);
MD5Update (&md5, timestamp, 4);
MD5Update (&md5, ":", 1);
MD5Update (&md5, method, strlen(method));
@@ -415,8 +415,8 @@
MD5Update (&md5, uri, strlen(uri));
MD5Update (&md5, ":", 1);
MD5Update (&md5, realm, strlen(realm));
- MD5Final (tmpnonce, &md5);
- cvthex (tmpnonce, sizeof (tmpnonce), nonce);
+ MD5Final (tmpnonce, &md5);
+ cvthex (tmpnonce, sizeof (tmpnonce), nonce);
cvthex (timestamp, 4, timestamphex);
strncat (nonce, timestamphex, 8);
}
@@ -429,7 +429,7 @@
* @param connection the connection
* @param key the key
* @param value the value, can be NULL
- * @return MHD_YES if the key-value pair is in the headers,
+ * @return MHD_YES if the key-value pair is in the headers,
* MHD_NO if not
*/
static int
@@ -445,14 +445,14 @@
continue;
if (0 != strcmp (key, pos->header))
continue;
- if ( (NULL == value) &&
+ if ( (NULL == value) &&
(NULL == pos->value) )
return MHD_YES;
- if ( (NULL == value) ||
+ if ( (NULL == value) ||
(NULL == pos->value) ||
(0 != strcmp (value, pos->value)) )
continue;
- return MHD_YES;
+ return MHD_YES;
}
return MHD_NO;
}
@@ -487,8 +487,8 @@
('\0' != argp[0]) )
{
equals = strchr (argp, '=');
- if (NULL == equals)
- {
+ if (NULL == equals)
+ {
/* add with 'value' NULL */
connection->daemon->unescape_callback
(connection->daemon->unescape_callback_cls,
connection,
@@ -517,7 +517,7 @@
num_headers++;
argp = amper;
}
-
+
/* also check that the number of headers matches */
for (pos = connection->headers_received; NULL != pos; pos = pos->next)
{
@@ -525,7 +525,7 @@
continue;
num_headers--;
}
- if (0 != num_headers)
+ if (0 != num_headers)
return MHD_NO;
return MHD_YES;
}
@@ -570,10 +570,10 @@
header = MHD_lookup_connection_value (connection,
MHD_HEADER_KIND,
- MHD_HTTP_HEADER_AUTHORIZATION);
- if (NULL == header)
+ MHD_HTTP_HEADER_AUTHORIZATION);
+ if (NULL == header)
return MHD_NO;
- if (0 != strncmp(header, _BASE, strlen(_BASE)))
+ if (0 != strncmp(header, _BASE, strlen(_BASE)))
return MHD_NO;
header += strlen (_BASE);
left = strlen (header);
@@ -585,7 +585,7 @@
sizeof (un),
header, "username");
if ( (0 == len) ||
- (0 != strcmp(username, un)) )
+ (0 != strcmp(username, un)) )
return MHD_NO;
left -= strlen ("username") + len;
}
@@ -593,32 +593,42 @@
{
char r[MAX_REALM_LENGTH];
- len = lookup_sub_value(r,
+ len = lookup_sub_value(r,
sizeof (r),
- header, "realm");
- if ( (0 == len) ||
+ header, "realm");
+ if ( (0 == len) ||
(0 != strcmp(realm, r)) )
return MHD_NO;
left -= strlen ("realm") + len;
}
- if (0 == (len = lookup_sub_value (nonce,
+ if (0 == (len = lookup_sub_value (nonce,
sizeof (nonce),
header, "nonce")))
return MHD_NO;
left -= strlen ("nonce") + len;
+ if (left > 32 * 1024)
+ {
+ /* we do not permit URIs longer than 32k, as we want to
+ make sure to not blow our stack (or per-connection
+ heap memory limit). Besides, 32k is already insanely
+ large, but of course in theory the
+ #MHD_OPTION_CONNECTION_MEMORY_LIMIT might be very large
+ and would thus permit sending a >32k authorization
+ header value. */
+ return MHD_NO;
+ }
+ {
+ char uri[left];
- {
- char uri[left];
-
- if (0 == lookup_sub_value(uri,
- sizeof (uri),
- header, "uri"))
+ if (0 == lookup_sub_value (uri,
+ sizeof (uri),
+ header, "uri"))
return MHD_NO;
-
- /* 8 = 4 hexadecimal numbers for the timestamp */
- nonce_time = strtoul(nonce + len - 8, (char **)NULL, 16);
- t = (uint32_t) MHD_monotonic_time();
+
+ /* 8 = 4 hexadecimal numbers for the timestamp */
+ nonce_time = strtoul (nonce + len - 8, (char **)NULL, 16);
+ t = (uint32_t) MHD_monotonic_time();
/*
* First level vetting for the nonce validity if the timestamp
* attached to the nonce exceeds `nonce_timeout' then the nonce is
@@ -632,7 +642,7 @@
strlen (connection->url)))
{
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon,
+ MHD_DLOG (connection->daemon,
"Authentication failed, URI does not match.\n");
#endif
return MHD_NO;
@@ -646,10 +656,10 @@
args++;
if (MHD_YES !=
check_argument_match (connection,
- args) )
+ args) )
{
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon,
+ MHD_DLOG (connection->daemon,
"Authentication failed, arguments do not match.\n");
#endif
return MHD_NO;
@@ -671,31 +681,31 @@
* not, the nonce fabrication process going to be
* very hard to achieve.
*/
-
+
if (0 != strcmp (nonce, noncehashexp))
return MHD_INVALID_NONCE;
if ( (0 == lookup_sub_value (cnonce,
- sizeof (cnonce),
+ sizeof (cnonce),
header, "cnonce")) ||
(0 == lookup_sub_value (qop, sizeof (qop), header, "qop")) ||
- ( (0 != strcmp (qop, "auth")) &&
+ ( (0 != strcmp (qop, "auth")) &&
(0 != strcmp (qop, "")) ) ||
(0 == lookup_sub_value (nc, sizeof (nc), header, "nc")) ||
(0 == lookup_sub_value (response, sizeof (response), header,
"response")) )
{
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon,
+ MHD_DLOG (connection->daemon,
"Authentication failed, invalid format.\n");
#endif
return MHD_NO;
}
nci = strtoul (nc, &end, 16);
if ( ('\0' != *end) ||
- ( (LONG_MAX == nci) &&
+ ( (LONG_MAX == nci) &&
(ERANGE == errno) ) )
{
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon,
+ MHD_DLOG (connection->daemon,
"Authentication failed, invalid format.\n");
#endif
return MHD_NO; /* invalid nonce format */
@@ -705,10 +715,10 @@
* and not a replay attack attempt. Also adds the nonce
* to the nonce-nc map if it does not exist there.
*/
-
+
if (MHD_YES != check_nonce_nc (connection, nonce, nci))
return MHD_NO;
-
+
digest_calc_ha1("md5",
username,
realm,
@@ -724,9 +734,9 @@
connection->method,
uri,
hentity,
- respexp);
- return (0 == strcmp(response, respexp))
- ? MHD_YES
+ respexp);
+ return (0 == strcmp(response, respexp))
+ ? MHD_YES
: MHD_NO;
}
}
@@ -757,7 +767,7 @@
size_t hlen;
char nonce[HASH_MD5_HEX_LEN + 9];
- /* Generating the server nonce */
+ /* Generating the server nonce */
calculate_nonce ((uint32_t) MHD_monotonic_time(),
connection->method,
connection->daemon->digest_auth_random,
@@ -768,20 +778,20 @@
if (MHD_YES != check_nonce_nc (connection, nonce, 0))
{
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon,
+ MHD_DLOG (connection->daemon,
"Could not register nonce (is the nonce array size zero?).\n");
#endif
- return MHD_NO;
+ return MHD_NO;
}
/* Building the authentication header */
hlen = snprintf (NULL,
0,
"Digest
realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s",
- realm,
+ realm,
nonce,
opaque,
- signal_stale
- ? ",stale=\"true\""
+ signal_stale
+ ? ",stale=\"true\""
: "");
{
char header[hlen + 1];
@@ -789,20 +799,20 @@
snprintf (header,
sizeof(header),
"Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s",
- realm,
+ realm,
nonce,
opaque,
- signal_stale
- ? ",stale=\"true\""
+ signal_stale
+ ? ",stale=\"true\""
: "");
ret = MHD_add_response_header(response,
- MHD_HTTP_HEADER_WWW_AUTHENTICATE,
+ MHD_HTTP_HEADER_WWW_AUTHENTICATE,
header);
}
- if (MHD_YES == ret)
- ret = MHD_queue_response(connection,
- MHD_HTTP_UNAUTHORIZED,
- response);
+ if (MHD_YES == ret)
+ ret = MHD_queue_response(connection,
+ MHD_HTTP_UNAUTHORIZED,
+ response);
return ret;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r30983 - in libmicrohttpd: . src/microhttpd,
gnunet <=