30 #if defined(_WIN32) && defined(MHD_W32_MUTEX_)
31 #ifndef WIN32_LEAN_AND_MEAN
32 #define WIN32_LEAN_AND_MEAN 1
37 #define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE)
42 #define _BASE "Digest "
47 #define MAX_USERNAME_LENGTH 128
52 #define MAX_REALM_LENGTH 256
57 #define MAX_AUTH_RESPONSE_LENGTH 128
75 for (i = 0; i < len; ++i)
77 j = (bin[i] >> 4) & 0x0f;
78 hex[i * 2] = j <= 9 ? (j +
'0') : (j +
'a' - 10);
80 hex[i * 2 + 1] = j <= 9 ? (j +
'0') : (j +
'a' - 10);
100 const char *username,
102 const char *password,
111 MD5Update (&md5, username, strlen (username));
115 MD5Update (&md5, password, strlen (password));
124 MD5Update (&md5, cnonce, strlen (cnonce));
127 cvthex (ha1,
sizeof (ha1), sessionkey);
147 const char *noncecount,
161 MD5Update (&md5, method, strlen(method));
165 if (0 == strcasecmp(qop,
"auth-int"))
171 MD5Update (&md5, hentity, strlen(hentity));
184 MD5Update (&md5, noncecount, strlen(noncecount));
186 MD5Update (&md5, cnonce, strlen(cnonce));
193 cvthex (resphash,
sizeof (resphash), response);
227 keylen = strlen (key);
231 if (
NULL == (eq = strchr (ptr,
'=')))
238 q2 = strchr (q1,
',');
244 q2 = strchr (q1,
'\"');
252 (eq == &ptr[keylen]) )
256 len = strlen (q1) + 1;
268 if (size > (
size_t) ((q2 - q1) + 1))
269 size = (q2 - q1) + 1;
280 ptr = strchr (qn,
',');
303 unsigned long int nc)
309 mod = connection->
daemon->nonce_nc_size;
317 off = (off << 8) | (*np ^ (off >> 24));
327 (void) MHD_mutex_lock_ (&connection->
daemon->nnc_lock);
330 strcpy(connection->
daemon->nnc[off].nonce,
332 connection->
daemon->nnc[off].nc = 0;
333 (void) MHD_mutex_unlock_ (&connection->
daemon->nnc_lock);
336 if ( (nc <= connection->daemon->nnc[off].nc) ||
337 (0 != strcmp(connection->
daemon->nnc[off].nonce, nonce)) )
339 (void) MHD_mutex_unlock_ (&connection->
daemon->nnc_lock);
341 MHD_DLOG (connection->
daemon,
342 "Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n");
346 connection->
daemon->nnc[off].nc = nc;
347 (void) MHD_mutex_unlock_ (&connection->
daemon->nnc_lock);
371 if (0 != strncmp (header,
_BASE, strlen (
_BASE)))
373 header += strlen (
_BASE);
379 return strdup (user);
406 unsigned char timestamp[4];
408 char timestamphex[
sizeof(timestamp) * 2 + 1];
411 timestamp[0] = (nonce_time & 0xff000000) >> 0x18;
412 timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10;
413 timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08;
414 timestamp[3] = (nonce_time & 0x000000ff);
417 MD5Update (&md5, method, strlen (method));
426 cvthex (tmpnonce,
sizeof (tmpnonce), nonce);
427 cvthex (timestamp, 4, timestamphex);
428 strncat (nonce, timestamphex, 8);
453 if (0 != strcmp (key, pos->
header))
455 if ( (
NULL == value) &&
458 if ( (
NULL == value) ||
460 (0 != strcmp (value, pos->
value)) )
487 unsigned int num_headers;
493 MHD_DLOG(connection->
daemon,
494 "Failed to allocate memory for copy of URI arguments\n");
500 while ( (
NULL != argp) &&
503 equals = strchr (argp,
'=');
517 amper = strchr (equals,
'&');
542 if (0 != num_headers)
564 const char *username,
565 const char *password,
566 unsigned int nonce_timeout)
576 const char *hentity =
NULL;
583 unsigned long int nci;
590 if (0 != strncmp(header,
_BASE, strlen(
_BASE)))
592 header += strlen (
_BASE);
593 left = strlen (header);
602 (0 != strcmp(username, un)) )
604 left -= strlen (
"username") + len;
614 (0 != strcmp(realm, r)) )
616 left -= strlen (
"realm") + len;
623 left -= strlen (
"nonce") + len;
624 if (left > 32 * 1024)
638 uri = malloc(left + 1);
642 MHD_DLOG(connection->
daemon,
643 "Failed to allocate memory for auth header processing\n");
656 nonce_time = strtoul (nonce + len - 8, (
char **)
NULL, 16);
663 if ( (t > nonce_time + nonce_timeout) ||
664 (nonce_time + nonce_timeout < nonce_time) )
669 if (0 != strncmp (uri,
671 strlen (connection->
url)))
674 MHD_DLOG (connection->
daemon,
675 "Authentication failed, URI does not match.\n");
681 const char *args = strchr (uri,
'?');
692 MHD_DLOG (connection->
daemon,
693 "Authentication failed, arguments do not match.\n");
701 connection->
daemon->digest_auth_random,
702 connection->
daemon->digest_auth_rand_size,
716 if (0 != strcmp (nonce, noncehashexp))
723 header,
"cnonce")) ||
725 ( (0 != strcmp (qop,
"auth")) &&
726 (0 != strcmp (qop,
"")) ) ||
731 MHD_DLOG (connection->
daemon,
732 "Authentication failed, invalid format.\n");
737 nci = strtoul (nc, &end, 16);
738 if ( (
'\0' != *end) ||
739 ( (LONG_MAX == nci) &&
740 (ERANGE == errno) ) )
743 MHD_DLOG (connection->
daemon,
744 "Authentication failed, invalid format.\n");
778 return (0 == strcmp(response, respexp))
813 connection->
daemon->digest_auth_random,
814 connection->
daemon->digest_auth_rand_size,
821 MHD_DLOG (connection->
daemon,
822 "Could not register nonce (is the nonce array size zero?).\n");
829 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s",
839 header = malloc(hlen + 1);
843 MHD_DLOG(connection->
daemon,
844 "Failed to allocate memory for auth response header\n");
851 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s",
void * unescape_callback_cls
#define MAX_AUTH_RESPONSE_LENGTH
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
static void cvthex(const unsigned char *bin, size_t len, char *hex)
static int check_nonce_nc(struct MHD_Connection *connection, const char *nonce, unsigned long int nc)
static size_t lookup_sub_value(char *dest, size_t size, const char *data, const char *key)
#define MHD_INVALID_NONCE
_MHD_EXTERN int MHD_digest_auth_check(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout)
static int test_header(struct MHD_Connection *connection, const char *key, const char *value)
struct MHD_Daemon * daemon
static void calculate_nonce(uint32_t nonce_time, const char *method, const char *rnd, size_t rnd_size, const char *uri, const char *realm, char *nonce)
static void digest_calc_ha1(const char *alg, const char *username, const char *realm, const char *password, const char *nonce, const char *cnonce, char *sessionkey)
_MHD_EXTERN int MHD_queue_auth_fail_response(struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale)
internal shared structures
time_t MHD_monotonic_time(void)
_MHD_EXTERN char * MHD_digest_auth_get_username(struct MHD_Connection *connection)
static int check_argument_match(struct MHD_Connection *connection, const char *args)
UnescapeCallback unescape_callback
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
#define MHD_HTTP_UNAUTHORIZED
void MD5Update(struct MD5Context *ctx, const void *data, unsigned len)
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
void MD5Init(struct MD5Context *ctx)
static void digest_calc_response(const char *ha1, const char *nonce, const char *noncecount, const char *cnonce, const char *qop, const char *method, const char *uri, const char *hentity, char *response)
#define MAX_USERNAME_LENGTH
struct MHD_HTTP_Header * headers_received