31 #if defined(_WIN32) && defined(MHD_W32_MUTEX_) 32 #ifndef WIN32_LEAN_AND_MEAN 33 #define WIN32_LEAN_AND_MEAN 1 38 #define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE) 40 #define TIMESTAMP_BIN_SIZE 4 41 #define TIMESTAMP_HEX_LEN (2 * TIMESTAMP_BIN_SIZE) 44 #define NONCE_STD_LEN (HASH_MD5_HEX_LEN + TIMESTAMP_HEX_LEN) 49 #define _BASE "Digest " 54 #define MAX_USERNAME_LENGTH 128 59 #define MAX_REALM_LENGTH 256 64 #define MAX_AUTH_RESPONSE_LENGTH 128 82 for (i = 0; i < len; ++i)
84 j = (bin[i] >> 4) & 0x0f;
85 hex[i * 2] = (char)((j <= 9) ? (j +
'0') : (j - 10 +
'a'));
87 hex[i * 2 + 1] = (char)((j <= 9) ? (j +
'0') : (j - 10 +
'a'));
107 const char *username,
109 const char *password,
118 MD5Update (&md5, (
const unsigned char*)username, strlen (username));
119 MD5Update (&md5, (
const unsigned char*)
":", 1);
120 MD5Update (&md5, (
const unsigned char*)realm, strlen (realm));
121 MD5Update (&md5, (
const unsigned char*)
":", 1);
122 MD5Update (&md5, (
const unsigned char*)password, strlen (password));
127 MD5Update (&md5, (
const unsigned char*)ha1,
sizeof (ha1));
128 MD5Update (&md5, (
const unsigned char*)
":", 1);
129 MD5Update (&md5, (
const unsigned char*)nonce, strlen (nonce));
130 MD5Update (&md5, (
const unsigned char*)
":", 1);
131 MD5Update (&md5, (
const unsigned char*)cnonce, strlen (cnonce));
134 cvthex (ha1,
sizeof (ha1), sessionkey);
154 const char *noncecount,
168 MD5Update (&md5, (
const unsigned char*)method, strlen(method));
169 MD5Update (&md5, (
const unsigned char*)
":", 1);
170 MD5Update (&md5, (
const unsigned char*)uri, strlen(uri));
172 if (0 == strcasecmp(qop,
"auth-int"))
178 MD5Update (&md5, hentity, strlen(hentity));
186 MD5Update (&md5, (
const unsigned char*)
":", 1);
187 MD5Update (&md5, (
const unsigned char*)nonce, strlen(nonce));
188 MD5Update (&md5, (
const unsigned char*)
":", 1);
191 MD5Update (&md5, (
const unsigned char*)noncecount, strlen(noncecount));
192 MD5Update (&md5, (
const unsigned char*)
":", 1);
193 MD5Update (&md5, (
const unsigned char*)cnonce, strlen(cnonce));
194 MD5Update (&md5, (
const unsigned char*)
":", 1);
195 MD5Update (&md5, (
const unsigned char*)qop, strlen(qop));
196 MD5Update (&md5, (
const unsigned char*)
":", 1);
200 cvthex (resphash,
sizeof(resphash), response);
234 keylen = strlen (key);
238 if (
NULL == (eq = strchr (ptr,
'=')))
245 q2 = strchr (q1,
',');
251 q2 = strchr (q1,
'\"');
259 (eq == &ptr[keylen]) )
263 len = strlen (q1) + 1;
275 if (size > (
size_t) ((q2 - q1) + 1))
276 size = (q2 - q1) + 1;
287 ptr = strchr (qn,
',');
310 unsigned long int nc)
316 mod = connection->
daemon->nonce_nc_size;
324 off = (off << 8) | (*np ^ (off >> 24));
334 (void) MHD_mutex_lock_ (&connection->
daemon->nnc_lock);
337 strcpy(connection->
daemon->nnc[off].nonce,
339 connection->
daemon->nnc[off].nc = 0;
340 (void) MHD_mutex_unlock_ (&connection->
daemon->nnc_lock);
343 if ( (nc <= connection->daemon->nnc[off].nc) ||
344 (0 != strcmp(connection->
daemon->nnc[off].nonce, nonce)) )
346 (void) MHD_mutex_unlock_ (&connection->
daemon->nnc_lock);
348 MHD_DLOG (connection->
daemon,
349 "Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n");
353 connection->
daemon->nnc[off].nc = nc;
354 (void) MHD_mutex_unlock_ (&connection->
daemon->nnc_lock);
378 if (0 != strncmp (header,
_BASE, strlen (
_BASE)))
380 header += strlen (
_BASE);
386 return strdup (user);
418 timestamp[0] = (
unsigned char)((nonce_time & 0xff000000) >> 0x18);
419 timestamp[1] = (
unsigned char)((nonce_time & 0x00ff0000) >> 0x10);
420 timestamp[2] = (
unsigned char)((nonce_time & 0x0000ff00) >> 0x08);
421 timestamp[3] = (
unsigned char)((nonce_time & 0x000000ff));
422 MD5Update (&md5, timestamp,
sizeof(timestamp));
423 MD5Update (&md5, (
const unsigned char*)
":", 1);
424 MD5Update (&md5, (
const unsigned char*)method, strlen (method));
425 MD5Update (&md5, (
const unsigned char*)
":", 1);
427 MD5Update (&md5, (
const unsigned char*)rnd, rnd_size);
428 MD5Update (&md5, (
const unsigned char*)
":", 1);
429 MD5Update (&md5, (
const unsigned char*)uri, strlen (uri));
430 MD5Update (&md5, (
const unsigned char*)
":", 1);
431 MD5Update (&md5, (
const unsigned char*)realm, strlen (realm));
433 cvthex (tmpnonce,
sizeof (tmpnonce), nonce);
434 cvthex (timestamp,
sizeof(timestamp), timestamphex);
435 strncat (nonce, timestamphex, 8);
460 if (kind != pos->
kind)
462 if (0 != strcmp (key, pos->
header))
464 if ( (
NULL == value) &&
467 if ( (
NULL == value) ||
469 (0 != strcmp (value, pos->
value)) )
493 unsigned int num_headers;
496 argb = strdup (args);
500 MHD_DLOG (connection->
daemon,
501 "Failed to allocate memory for copy of URI arguments\n");
520 if (0 != num_headers)
545 const char *username,
546 const char *password,
547 unsigned int nonce_timeout)
557 const char *hentity =
NULL;
564 unsigned long int nci;
571 if (0 != strncmp(header,
_BASE, strlen(
_BASE)))
573 header += strlen (
_BASE);
574 left = strlen (header);
583 (0 != strcmp(username, un)) )
585 left -= strlen (
"username") + len;
595 (0 != strcmp(realm, r)) )
597 left -= strlen (
"realm") + len;
604 left -= strlen (
"nonce") + len;
605 if (left > 32 * 1024)
623 if ( (t > nonce_time + nonce_timeout) ||
624 (nonce_time + nonce_timeout < nonce_time) )
632 connection->
daemon->digest_auth_random,
633 connection->
daemon->digest_auth_rand_size,
647 if (0 != strcmp (nonce, noncehashexp))
653 header,
"cnonce")) ||
655 ( (0 != strcmp (qop,
"auth")) &&
656 (0 != strcmp (qop,
"")) ) ||
661 MHD_DLOG (connection->
daemon,
662 "Authentication failed, invalid format.\n");
666 nci = strtoul (nc, &end, 16);
667 if ( (
'\0' != *end) ||
669 (ERANGE == errno) ) )
672 MHD_DLOG (connection->
daemon,
673 "Authentication failed, invalid format.\n");
691 uri = malloc (left + 1);
695 MHD_DLOG(connection->
daemon,
696 "Failed to allocate memory for auth header processing\n");
729 if (0 != strncmp (uri,
731 strlen (connection->
url)))
734 MHD_DLOG (connection->
daemon,
735 "Authentication failed, URI does not match.\n");
742 const char *args = strchr (uri,
'?');
753 MHD_DLOG (connection->
daemon,
754 "Authentication failed, arguments do not match.\n");
761 return (0 == strcmp(response, respexp))
796 connection->
daemon->digest_auth_random,
797 connection->
daemon->digest_auth_rand_size,
804 MHD_DLOG (connection->
daemon,
805 "Could not register nonce (is the nonce array size zero?).\n");
812 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s",
822 header = malloc(hlen + 1);
826 MHD_DLOG(connection->
daemon,
827 "Failed to allocate memory for auth response header\n");
834 "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)
static void digest_calc_response(const char ha1[HASH_MD5_HEX_LEN+1], const char *nonce, const char *noncecount, const char *cnonce, const char *qop, const char *method, const char *uri, const char *hentity, char response[HASH_MD5_HEX_LEN+1])
_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 TIMESTAMP_BIN_SIZE
#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)
struct MHD_Daemon * daemon
void MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len)
int MHD_parse_arguments_(struct MHD_Connection *connection, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
_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
static int test_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
_MHD_EXTERN char * MHD_digest_auth_get_username(struct MHD_Connection *connection)
static int check_argument_match(struct MHD_Connection *connection, const char *args)
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[HASH_MD5_HEX_LEN+1])
UnescapeCallback unescape_callback
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
internal monotonic clock functions implementations
#define MHD_HTTP_UNAUTHORIZED
void MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx)
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[NONCE_STD_LEN+1])
void MD5Init(struct MD5Context *ctx)
time_t MHD_monotonic_sec_counter(void)
#define MAX_USERNAME_LENGTH
#define TIMESTAMP_HEX_LEN
struct MHD_HTTP_Header * headers_received