[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r12805 - libmicrohttpd/src/daemon
From: |
gnunet |
Subject: |
[GNUnet-SVN] r12805 - libmicrohttpd/src/daemon |
Date: |
Wed, 1 Sep 2010 21:20:01 +0200 |
Author: grothoff
Date: 2010-09-01 21:20:01 +0200 (Wed, 01 Sep 2010)
New Revision: 12805
Modified:
libmicrohttpd/src/daemon/digestauth.c
Log:
fixing authentication header parser
Modified: libmicrohttpd/src/daemon/digestauth.c
===================================================================
--- libmicrohttpd/src/daemon/digestauth.c 2010-09-01 15:49:33 UTC (rev
12804)
+++ libmicrohttpd/src/daemon/digestauth.c 2010-09-01 19:20:01 UTC (rev
12805)
@@ -28,9 +28,32 @@
#define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE)
+/**
+ * Beginning string for any valid Digest authentication header.
+ */
#define _BASE "Digest "
/**
+ * Maximum length of a username for digest authentication.
+ */
+#define MAX_USERNAME_LENGTH 128
+
+/**
+ * Maximum length of a realm for digest authentication.
+ */
+#define MAX_REALM_LENGTH 256
+
+/**
+ * Maximum length of a nonce in digest authentication.
+ */
+#define MAX_NONCE_LENGTH 128
+
+/**
+ * Maximum length of the response in digest authentication.
+ */
+#define MAX_AUTH_RESPONSE_LENGTH 128
+
+/**
* convert bin to hex
*
* @param bin binary data
@@ -59,6 +82,12 @@
* calculate H(A1) as per RFC2617 spec and store the
* result in 'sessionkey'.
*
+ * @param alg FIXME: document
+ * @param username FIXME: document
+ * @param realm FIXME: document
+ * @param password FIXME: document
+ * @param nonce FIXME: document
+ * @param cnonce FIXME: document
* @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes
*/
static void
@@ -156,49 +185,81 @@
/**
- * Lookup subvalue off of the HTTP Authorization header
+ * Lookup subvalue off of the HTTP Authorization header.
*
- * @param dest A pointer to char * to store the result
- * @param size The size of dst
- * @param data A pointer to char * of the Authorization header
- * @param key A pointer to char * of the key in the header
+ * A description of the input format for 'data' is at
+ * http://en.wikipedia.org/wiki/Digest_access_authentication
+ *
+ *
+ * @param dest where to store the result (possibly truncated if
+ * the buffer is not big enough).
+ * @param size size of dest
+ * @param data pointer to the Authorization header
+ * @param key key to look up in data
* @return size of the located value, 0 if otherwise
*/
static int
lookup_sub_value(char *dest,
- size_t size,
- const char *data,
- const char *key)
+ size_t size,
+ const char *data,
+ const char *key)
{
size_t keylen = strlen(key);
const char *ptr = data;
- char field[size];
- char fmt[24 + keylen + 1];
- int items_read;
-
- ptr += strstr(ptr, key) - ptr;
-
- if (*(ptr + keylen) != ' ' && *(ptr + keylen) != '=')
- {
- ++ptr;
- ptr += strstr(ptr, key) - ptr;
- }
- if (!ptr)
+ const char *eq;
+ const char *q1;
+ const char *q2;
+
+ if (0 == size)
return 0;
-
- snprintf(fmt,
- sizeof (fmt),
- "%s%%*[ =\"]%%%u[^, \"]",
- key,
- (unsigned int) size - 1);
-
- items_read = sscanf(ptr, fmt, field);
-
- if (items_read == 1)
+ while ('\0' != *ptr)
{
- strcpy(dest, field);
- return strlen(dest);
- }
+ if (NULL == (eq = strstr (ptr, "=")))
+ return 0;
+ q1 = strstr (eq, "\"");
+ if (q1 == NULL)
+ {
+ q1 = eq + 1;
+ q2 = strstr (q1, ",");
+ }
+ else
+ {
+ q2 = strstr (q1 + 1, "\"");
+ if (NULL == q2)
+ return 0; /* end quote not found */
+ }
+ if (0 == strncasecmp (ptr,
+ key,
+ keylen))
+ {
+ if (q2 == NULL)
+ {
+ strncpy (dest,
+ q1 + 1,
+ size - 1);
+ dest[size-1] = '\0';
+ return strlen (dest);
+ }
+ else
+ {
+ if (size >= q2 - q1)
+ size = (q2 - q1) - 1;
+ memcpy (dest,
+ q1 + 1,
+ size);
+ dest[size] = '\0';
+ return size;
+ }
+ }
+ if (NULL == q2)
+ return 0;
+ ptr = strstr (q2, ",");
+ if (NULL == ptr)
+ return 0;
+ ptr++;
+ while (' ' == *ptr)
+ ptr++;
+ }
return 0;
}
@@ -214,7 +275,7 @@
MHD_digest_auth_get_username(struct MHD_Connection *connection)
{
size_t len;
- char user[50];
+ char user[MAX_USERNAME_LENGTH];
const char *header;
header = MHD_lookup_connection_value(connection,
@@ -234,6 +295,17 @@
return strdup(user);
}
+
+/**
+ * FIXME: document
+ *
+ * @param nonce_time FIXME: document
+ * @param method FIXME: document
+ * @param rnd FIXME: document
+ * @param uri FIXME: document
+ * @param realm FIXME: document
+ * @param nonce FIXME: document
+ */
static void
calculate_nonce (uint32_t nonce_time,
const char *method,
@@ -287,24 +359,21 @@
const char *password,
unsigned int nonce_timeout)
{
- int auth;
size_t len;
const char *header;
- const char *rnd;
- char ret[60];
- char nonce[50];
- char cnonce[50];
- char uri[100];
-/*char qop[15]; // Uncomment when supporting "auth-int" */
- char qop[] = "auth"; /* "auth-int" is not supported */
- char nc[10];
- char response[35];
- char *hentity = NULL; /* "auth-int" is not supported */
+ char nonce[MAX_NONCE_LENGTH];
+ char cnonce[MAX_NONCE_LENGTH];
+ /* char qop[15]; // Uncomment when supporting "auth-int" */
+ const char * qop = "auth"; /* "auth-int" is not supported */
+ char nc[20];
+ char response[MAX_AUTH_RESPONSE_LENGTH];
+ const char *hentity = NULL; /* "auth-int" is not supported */
char ha1[HASH_MD5_HEX_LEN + 1];
char respexp[HASH_MD5_HEX_LEN + 1];
char noncehashexp[HASH_MD5_HEX_LEN + 9];
uint32_t nonce_time;
uint32_t t;
+ size_t left; /* number of characters left in 'header' for 'uri' */
header = MHD_lookup_connection_value(connection,
MHD_HEADER_KIND,
@@ -313,86 +382,100 @@
return MHD_NO;
if (strncmp(header, _BASE, strlen(_BASE)) != 0)
return MHD_NO;
+ header += strlen (_BASE);
+ left = strlen (header);
- rnd = connection->daemon->digest_auth_random;
-
- len = lookup_sub_value(ret,
- sizeof (ret),
- header, "username");
- if ( (!len) ||
- (strcmp(username, ret) != 0) )
+ {
+ char un[MAX_USERNAME_LENGTH];
+ len = lookup_sub_value(un,
+ sizeof (un),
+ header, "username");
+ if ( (!len) ||
+ (strcmp(username, un) != 0) )
+ return MHD_NO;
+ left -= strlen ("username") + len;
+ }
+
+ {
+ char r[MAX_REALM_LENGTH];
+ len = lookup_sub_value(r,
+ sizeof (r),
+ header, "realm");
+ if ( (!len) ||
+ (strcmp(realm, r) != 0) )
+ return MHD_NO;
+ left -= strlen ("realm") + len;
+ }
+
+ if (0 == (len = lookup_sub_value(nonce,
+ sizeof (nonce),
+ header, "nonce")))
return MHD_NO;
- len = lookup_sub_value(ret,
- sizeof (ret),
- header, "realm");
- if ( (!len) ||
- (strcmp(realm, ret) != 0) )
- return MHD_NO;
- if ( (0 == lookup_sub_value(uri,
- sizeof (uri),
- header, "uri")) ||
- (0 == (len = lookup_sub_value(nonce,
- sizeof (nonce),
- header, "nonce"))) )
- return MHD_NO;
-
- /* 8 = 4 hexadecimal numbers for the timestamp */
- nonce_time = strtoul(nonce + len - 8, 0, 16);
- t = (uint32_t) time(NULL);
- /*
- * First level vetting for the nonce validity
- * if the timestamp attached to the nonce
- * exceeds `nonce_timeout' then the nonce is
- * invalid.
- */
- if (t > nonce_time + nonce_timeout)
- return MHD_INVALID_NONCE;
- calculate_nonce (nonce_time,
- connection->method,
- rnd,
- uri,
- realm,
- noncehashexp);
- /*
- * Second level vetting for the nonce validity
- * if the timestamp attached to the nonce is valid
- * and possibility fabricated (in case of an attack)
- * the attacker must also know the password to be
- * able to generate a "sane" nonce, which if he does
- * 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),
- header, "cnonce")) ||
- /* (0 == lookup_sub_value(qop, sizeof (qop), header, "qop")) ||
// Uncomment when supporting "auth-int" */
- (0 == lookup_sub_value(nc, sizeof (nc), header, "nc")) ||
- (0 == lookup_sub_value(response, sizeof (response), header,
"response")) )
- return MHD_NO;
+ left -= strlen ("nonce") + len;
- digest_calc_ha1("md5",
- username,
- realm,
- password,
- nonce,
- cnonce,
- ha1);
- digest_calc_response(ha1,
- nonce,
- nc,
- cnonce,
- qop,
- connection->method,
- uri,
- hentity,
- respexp);
+ {
+ char uri[left];
- auth = strcmp(response, respexp) == 0 ? MHD_YES : MHD_NO;
-
- return auth;
+ 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, 0, 16);
+ t = (uint32_t) time(NULL);
+ /*
+ * First level vetting for the nonce validity
+ * if the timestamp attached to the nonce
+ * exceeds `nonce_timeout' then the nonce is
+ * invalid.
+ */
+ if (t > nonce_time + nonce_timeout)
+ return MHD_INVALID_NONCE;
+ calculate_nonce (nonce_time,
+ connection->method,
+ connection->daemon->digest_auth_random,
+ uri,
+ realm,
+ noncehashexp);
+ /*
+ * Second level vetting for the nonce validity
+ * if the timestamp attached to the nonce is valid
+ * and possibility fabricated (in case of an attack)
+ * the attacker must also know the password to be
+ * able to generate a "sane" nonce, which if he does
+ * 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),
+ header, "cnonce")) ||
+ /* (0 == lookup_sub_value(qop, sizeof (qop), header, "qop")) ||
// Uncomment when supporting "auth-int" */
+ (0 == lookup_sub_value(nc, sizeof (nc), header, "nc")) ||
+ (0 == lookup_sub_value(response, sizeof (response), header,
"response")) )
+ return MHD_NO;
+
+ digest_calc_ha1("md5",
+ username,
+ realm,
+ password,
+ nonce,
+ cnonce,
+ ha1);
+ digest_calc_response(ha1,
+ nonce,
+ nc,
+ cnonce,
+ qop,
+ connection->method,
+ uri,
+ hentity,
+ respexp);
+ return strcmp(response, respexp) == 0 ? MHD_YES : MHD_NO;
+ }
}
@@ -414,20 +497,17 @@
{
int ret;
size_t hlen;
- const char *rnd;
char nonce[HASH_MD5_HEX_LEN + 9];
struct MHD_Response *response;
response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO);
if (NULL == response)
return MHD_NO;
-
- rnd = connection->daemon->digest_auth_random;
/* Generating the server nonce */
calculate_nonce ((uint32_t) time(NULL),
connection->method,
- rnd,
+ connection->daemon->digest_auth_random,
connection->url,
realm,
nonce);
@@ -439,7 +519,7 @@
realm,
nonce,
opaque,
- signal_stale ? ",stale=true" : "");
+ signal_stale ? ",stale=\"true\"" : "");
{
char header[hlen + 1];
snprintf(header,
@@ -448,7 +528,7 @@
realm,
nonce,
opaque,
- signal_stale ? ",stale=true" : "");
+ signal_stale ? ",stale=\"true\"" : "");
ret = MHD_add_response_header(response,
MHD_HTTP_HEADER_WWW_AUTHENTICATE,
header);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r12805 - libmicrohttpd/src/daemon,
gnunet <=