diff options
Diffstat (limited to 'src/microhttpd/digestauth.c')
-rw-r--r-- | src/microhttpd/digestauth.c | 178 |
1 files changed, 94 insertions, 84 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c index 77f6e3b1..5cef1cfe 100644 --- a/src/microhttpd/digestauth.c +++ b/src/microhttpd/digestauth.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | 52 | ||
53 | /** | 53 | /** |
54 | * convert bin to hex | 54 | * convert bin to hex |
55 | * | 55 | * |
56 | * @param bin binary data | 56 | * @param bin binary data |
57 | * @param len number of bytes in bin | 57 | * @param len number of bytes in bin |
@@ -64,12 +64,12 @@ cvthex (const unsigned char *bin, | |||
64 | { | 64 | { |
65 | size_t i; | 65 | size_t i; |
66 | unsigned int j; | 66 | unsigned int j; |
67 | 67 | ||
68 | for (i = 0; i < len; ++i) | 68 | for (i = 0; i < len; ++i) |
69 | { | 69 | { |
70 | j = (bin[i] >> 4) & 0x0f; | 70 | j = (bin[i] >> 4) & 0x0f; |
71 | hex[i * 2] = j <= 9 ? (j + '0') : (j + 'a' - 10); | 71 | hex[i * 2] = j <= 9 ? (j + '0') : (j + 'a' - 10); |
72 | j = bin[i] & 0x0f; | 72 | j = bin[i] & 0x0f; |
73 | hex[i * 2 + 1] = j <= 9 ? (j + '0') : (j + 'a' - 10); | 73 | hex[i * 2 + 1] = j <= 9 ? (j + '0') : (j + 'a' - 10); |
74 | } | 74 | } |
75 | hex[len * 2] = '\0'; | 75 | hex[len * 2] = '\0'; |
@@ -99,7 +99,7 @@ digest_calc_ha1 (const char *alg, | |||
99 | { | 99 | { |
100 | struct MD5Context md5; | 100 | struct MD5Context md5; |
101 | unsigned char ha1[MD5_DIGEST_SIZE]; | 101 | unsigned char ha1[MD5_DIGEST_SIZE]; |
102 | 102 | ||
103 | MD5Init (&md5); | 103 | MD5Init (&md5); |
104 | MD5Update (&md5, username, strlen (username)); | 104 | MD5Update (&md5, username, strlen (username)); |
105 | MD5Update (&md5, ":", 1); | 105 | MD5Update (&md5, ":", 1); |
@@ -107,7 +107,7 @@ digest_calc_ha1 (const char *alg, | |||
107 | MD5Update (&md5, ":", 1); | 107 | MD5Update (&md5, ":", 1); |
108 | MD5Update (&md5, password, strlen (password)); | 108 | MD5Update (&md5, password, strlen (password)); |
109 | MD5Final (ha1, &md5); | 109 | MD5Final (ha1, &md5); |
110 | if (0 == strcasecmp (alg, "md5-sess")) | 110 | if (0 == strcasecmp (alg, "md5-sess")) |
111 | { | 111 | { |
112 | MD5Init (&md5); | 112 | MD5Init (&md5); |
113 | MD5Update (&md5, ha1, sizeof (ha1)); | 113 | MD5Update (&md5, ha1, sizeof (ha1)); |
@@ -122,8 +122,8 @@ digest_calc_ha1 (const char *alg, | |||
122 | 122 | ||
123 | 123 | ||
124 | /** | 124 | /** |
125 | * Calculate request-digest/response-digest as per RFC2617 spec | 125 | * Calculate request-digest/response-digest as per RFC2617 spec |
126 | * | 126 | * |
127 | * @param ha1 H(A1) | 127 | * @param ha1 H(A1) |
128 | * @param nonce nonce from server | 128 | * @param nonce nonce from server |
129 | * @param noncecount 8 hex digits | 129 | * @param noncecount 8 hex digits |
@@ -149,11 +149,11 @@ digest_calc_response (const char *ha1, | |||
149 | unsigned char ha2[MD5_DIGEST_SIZE]; | 149 | unsigned char ha2[MD5_DIGEST_SIZE]; |
150 | unsigned char resphash[MD5_DIGEST_SIZE]; | 150 | unsigned char resphash[MD5_DIGEST_SIZE]; |
151 | char ha2hex[HASH_MD5_HEX_LEN + 1]; | 151 | char ha2hex[HASH_MD5_HEX_LEN + 1]; |
152 | 152 | ||
153 | MD5Init (&md5); | 153 | MD5Init (&md5); |
154 | MD5Update (&md5, method, strlen(method)); | 154 | MD5Update (&md5, method, strlen(method)); |
155 | MD5Update (&md5, ":", 1); | 155 | MD5Update (&md5, ":", 1); |
156 | MD5Update (&md5, uri, strlen(uri)); | 156 | MD5Update (&md5, uri, strlen(uri)); |
157 | #if 0 | 157 | #if 0 |
158 | if (0 == strcasecmp(qop, "auth-int")) | 158 | if (0 == strcasecmp(qop, "auth-int")) |
159 | { | 159 | { |
@@ -163,15 +163,15 @@ digest_calc_response (const char *ha1, | |||
163 | if (NULL != hentity) | 163 | if (NULL != hentity) |
164 | MD5Update (&md5, hentity, strlen(hentity)); | 164 | MD5Update (&md5, hentity, strlen(hentity)); |
165 | } | 165 | } |
166 | #endif | 166 | #endif |
167 | MD5Final (ha2, &md5); | 167 | MD5Final (ha2, &md5); |
168 | cvthex (ha2, MD5_DIGEST_SIZE, ha2hex); | 168 | cvthex (ha2, MD5_DIGEST_SIZE, ha2hex); |
169 | MD5Init (&md5); | 169 | MD5Init (&md5); |
170 | /* calculate response */ | 170 | /* calculate response */ |
171 | MD5Update (&md5, ha1, HASH_MD5_HEX_LEN); | 171 | MD5Update (&md5, ha1, HASH_MD5_HEX_LEN); |
172 | MD5Update (&md5, ":", 1); | 172 | MD5Update (&md5, ":", 1); |
173 | MD5Update (&md5, nonce, strlen(nonce)); | 173 | MD5Update (&md5, nonce, strlen(nonce)); |
174 | MD5Update (&md5, ":", 1); | 174 | MD5Update (&md5, ":", 1); |
175 | if ('\0' != *qop) | 175 | if ('\0' != *qop) |
176 | { | 176 | { |
177 | MD5Update (&md5, noncecount, strlen(noncecount)); | 177 | MD5Update (&md5, noncecount, strlen(noncecount)); |
@@ -180,7 +180,7 @@ digest_calc_response (const char *ha1, | |||
180 | MD5Update (&md5, ":", 1); | 180 | MD5Update (&md5, ":", 1); |
181 | MD5Update (&md5, qop, strlen(qop)); | 181 | MD5Update (&md5, qop, strlen(qop)); |
182 | MD5Update (&md5, ":", 1); | 182 | MD5Update (&md5, ":", 1); |
183 | } | 183 | } |
184 | MD5Update (&md5, ha2hex, HASH_MD5_HEX_LEN); | 184 | MD5Update (&md5, ha2hex, HASH_MD5_HEX_LEN); |
185 | MD5Final (resphash, &md5); | 185 | MD5Final (resphash, &md5); |
186 | cvthex (resphash, sizeof (resphash), response); | 186 | cvthex (resphash, sizeof (resphash), response); |
@@ -225,7 +225,7 @@ lookup_sub_value (char *dest, | |||
225 | return 0; | 225 | return 0; |
226 | q1 = eq + 1; | 226 | q1 = eq + 1; |
227 | while (' ' == *q1) | 227 | while (' ' == *q1) |
228 | q1++; | 228 | q1++; |
229 | if ('\"' != *q1) | 229 | if ('\"' != *q1) |
230 | { | 230 | { |
231 | q2 = strchr (q1, ','); | 231 | q2 = strchr (q1, ','); |
@@ -238,7 +238,7 @@ lookup_sub_value (char *dest, | |||
238 | if (NULL == q2) | 238 | if (NULL == q2) |
239 | return 0; /* end quote not found */ | 239 | return 0; /* end quote not found */ |
240 | qn = q2 + 1; | 240 | qn = q2 + 1; |
241 | } | 241 | } |
242 | if ( (0 == strncasecmp (ptr, | 242 | if ( (0 == strncasecmp (ptr, |
243 | key, | 243 | key, |
244 | keylen)) && | 244 | keylen)) && |
@@ -261,7 +261,7 @@ lookup_sub_value (char *dest, | |||
261 | if (size > (q2 - q1) + 1) | 261 | if (size > (q2 - q1) + 1) |
262 | size = (q2 - q1) + 1; | 262 | size = (q2 - q1) + 1; |
263 | size--; | 263 | size--; |
264 | memcpy (dest, | 264 | memcpy (dest, |
265 | q1, | 265 | q1, |
266 | size); | 266 | size); |
267 | dest[size] = '\0'; | 267 | dest[size] = '\0'; |
@@ -316,13 +316,13 @@ check_nonce_nc (struct MHD_Connection *connection, | |||
316 | * nonce counter is less than the current nonce counter by 1, | 316 | * nonce counter is less than the current nonce counter by 1, |
317 | * then only increase the nonce counter by one. | 317 | * then only increase the nonce counter by one. |
318 | */ | 318 | */ |
319 | 319 | ||
320 | (void) pthread_mutex_lock (&connection->daemon->nnc_lock); | 320 | (void) pthread_mutex_lock (&connection->daemon->nnc_lock); |
321 | if (0 == nc) | 321 | if (0 == nc) |
322 | { | 322 | { |
323 | strcpy(connection->daemon->nnc[off].nonce, | 323 | strcpy(connection->daemon->nnc[off].nonce, |
324 | nonce); | 324 | nonce); |
325 | connection->daemon->nnc[off].nc = 0; | 325 | connection->daemon->nnc[off].nc = 0; |
326 | (void) pthread_mutex_unlock (&connection->daemon->nnc_lock); | 326 | (void) pthread_mutex_unlock (&connection->daemon->nnc_lock); |
327 | return MHD_YES; | 327 | return MHD_YES; |
328 | } | 328 | } |
@@ -331,7 +331,7 @@ check_nonce_nc (struct MHD_Connection *connection, | |||
331 | { | 331 | { |
332 | (void) pthread_mutex_unlock (&connection->daemon->nnc_lock); | 332 | (void) pthread_mutex_unlock (&connection->daemon->nnc_lock); |
333 | #if HAVE_MESSAGES | 333 | #if HAVE_MESSAGES |
334 | MHD_DLOG (connection->daemon, | 334 | MHD_DLOG (connection->daemon, |
335 | "Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n"); | 335 | "Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n"); |
336 | #endif | 336 | #endif |
337 | return MHD_NO; | 337 | return MHD_NO; |
@@ -356,9 +356,9 @@ MHD_digest_auth_get_username(struct MHD_Connection *connection) | |||
356 | size_t len; | 356 | size_t len; |
357 | char user[MAX_USERNAME_LENGTH]; | 357 | char user[MAX_USERNAME_LENGTH]; |
358 | const char *header; | 358 | const char *header; |
359 | 359 | ||
360 | if (NULL == (header = MHD_lookup_connection_value (connection, | 360 | if (NULL == (header = MHD_lookup_connection_value (connection, |
361 | MHD_HEADER_KIND, | 361 | MHD_HEADER_KIND, |
362 | MHD_HTTP_HEADER_AUTHORIZATION))) | 362 | MHD_HTTP_HEADER_AUTHORIZATION))) |
363 | return NULL; | 363 | return NULL; |
364 | if (0 != strncmp (header, _BASE, strlen (_BASE))) | 364 | if (0 != strncmp (header, _BASE, strlen (_BASE))) |
@@ -366,7 +366,7 @@ MHD_digest_auth_get_username(struct MHD_Connection *connection) | |||
366 | header += strlen (_BASE); | 366 | header += strlen (_BASE); |
367 | if (0 == (len = lookup_sub_value (user, | 367 | if (0 == (len = lookup_sub_value (user, |
368 | sizeof (user), | 368 | sizeof (user), |
369 | header, | 369 | header, |
370 | "username"))) | 370 | "username"))) |
371 | return NULL; | 371 | return NULL; |
372 | return strdup (user); | 372 | return strdup (user); |
@@ -404,7 +404,7 @@ calculate_nonce (uint32_t nonce_time, | |||
404 | timestamp[0] = (nonce_time & 0xff000000) >> 0x18; | 404 | timestamp[0] = (nonce_time & 0xff000000) >> 0x18; |
405 | timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10; | 405 | timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10; |
406 | timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08; | 406 | timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08; |
407 | timestamp[3] = (nonce_time & 0x000000ff); | 407 | timestamp[3] = (nonce_time & 0x000000ff); |
408 | MD5Update (&md5, timestamp, 4); | 408 | MD5Update (&md5, timestamp, 4); |
409 | MD5Update (&md5, ":", 1); | 409 | MD5Update (&md5, ":", 1); |
410 | MD5Update (&md5, method, strlen(method)); | 410 | MD5Update (&md5, method, strlen(method)); |
@@ -415,8 +415,8 @@ calculate_nonce (uint32_t nonce_time, | |||
415 | MD5Update (&md5, uri, strlen(uri)); | 415 | MD5Update (&md5, uri, strlen(uri)); |
416 | MD5Update (&md5, ":", 1); | 416 | MD5Update (&md5, ":", 1); |
417 | MD5Update (&md5, realm, strlen(realm)); | 417 | MD5Update (&md5, realm, strlen(realm)); |
418 | MD5Final (tmpnonce, &md5); | 418 | MD5Final (tmpnonce, &md5); |
419 | cvthex (tmpnonce, sizeof (tmpnonce), nonce); | 419 | cvthex (tmpnonce, sizeof (tmpnonce), nonce); |
420 | cvthex (timestamp, 4, timestamphex); | 420 | cvthex (timestamp, 4, timestamphex); |
421 | strncat (nonce, timestamphex, 8); | 421 | strncat (nonce, timestamphex, 8); |
422 | } | 422 | } |
@@ -429,7 +429,7 @@ calculate_nonce (uint32_t nonce_time, | |||
429 | * @param connection the connection | 429 | * @param connection the connection |
430 | * @param key the key | 430 | * @param key the key |
431 | * @param value the value, can be NULL | 431 | * @param value the value, can be NULL |
432 | * @return MHD_YES if the key-value pair is in the headers, | 432 | * @return MHD_YES if the key-value pair is in the headers, |
433 | * MHD_NO if not | 433 | * MHD_NO if not |
434 | */ | 434 | */ |
435 | static int | 435 | static int |
@@ -445,14 +445,14 @@ test_header (struct MHD_Connection *connection, | |||
445 | continue; | 445 | continue; |
446 | if (0 != strcmp (key, pos->header)) | 446 | if (0 != strcmp (key, pos->header)) |
447 | continue; | 447 | continue; |
448 | if ( (NULL == value) && | 448 | if ( (NULL == value) && |
449 | (NULL == pos->value) ) | 449 | (NULL == pos->value) ) |
450 | return MHD_YES; | 450 | return MHD_YES; |
451 | if ( (NULL == value) || | 451 | if ( (NULL == value) || |
452 | (NULL == pos->value) || | 452 | (NULL == pos->value) || |
453 | (0 != strcmp (value, pos->value)) ) | 453 | (0 != strcmp (value, pos->value)) ) |
454 | continue; | 454 | continue; |
455 | return MHD_YES; | 455 | return MHD_YES; |
456 | } | 456 | } |
457 | return MHD_NO; | 457 | return MHD_NO; |
458 | } | 458 | } |
@@ -487,8 +487,8 @@ check_argument_match (struct MHD_Connection *connection, | |||
487 | ('\0' != argp[0]) ) | 487 | ('\0' != argp[0]) ) |
488 | { | 488 | { |
489 | equals = strchr (argp, '='); | 489 | equals = strchr (argp, '='); |
490 | if (NULL == equals) | 490 | if (NULL == equals) |
491 | { | 491 | { |
492 | /* add with 'value' NULL */ | 492 | /* add with 'value' NULL */ |
493 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | 493 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, |
494 | connection, | 494 | connection, |
@@ -517,7 +517,7 @@ check_argument_match (struct MHD_Connection *connection, | |||
517 | num_headers++; | 517 | num_headers++; |
518 | argp = amper; | 518 | argp = amper; |
519 | } | 519 | } |
520 | 520 | ||
521 | /* also check that the number of headers matches */ | 521 | /* also check that the number of headers matches */ |
522 | for (pos = connection->headers_received; NULL != pos; pos = pos->next) | 522 | for (pos = connection->headers_received; NULL != pos; pos = pos->next) |
523 | { | 523 | { |
@@ -525,7 +525,7 @@ check_argument_match (struct MHD_Connection *connection, | |||
525 | continue; | 525 | continue; |
526 | num_headers--; | 526 | num_headers--; |
527 | } | 527 | } |
528 | if (0 != num_headers) | 528 | if (0 != num_headers) |
529 | return MHD_NO; | 529 | return MHD_NO; |
530 | return MHD_YES; | 530 | return MHD_YES; |
531 | } | 531 | } |
@@ -570,10 +570,10 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
570 | 570 | ||
571 | header = MHD_lookup_connection_value (connection, | 571 | header = MHD_lookup_connection_value (connection, |
572 | MHD_HEADER_KIND, | 572 | MHD_HEADER_KIND, |
573 | MHD_HTTP_HEADER_AUTHORIZATION); | 573 | MHD_HTTP_HEADER_AUTHORIZATION); |
574 | if (NULL == header) | 574 | if (NULL == header) |
575 | return MHD_NO; | 575 | return MHD_NO; |
576 | if (0 != strncmp(header, _BASE, strlen(_BASE))) | 576 | if (0 != strncmp(header, _BASE, strlen(_BASE))) |
577 | return MHD_NO; | 577 | return MHD_NO; |
578 | header += strlen (_BASE); | 578 | header += strlen (_BASE); |
579 | left = strlen (header); | 579 | left = strlen (header); |
@@ -585,7 +585,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
585 | sizeof (un), | 585 | sizeof (un), |
586 | header, "username"); | 586 | header, "username"); |
587 | if ( (0 == len) || | 587 | if ( (0 == len) || |
588 | (0 != strcmp(username, un)) ) | 588 | (0 != strcmp(username, un)) ) |
589 | return MHD_NO; | 589 | return MHD_NO; |
590 | left -= strlen ("username") + len; | 590 | left -= strlen ("username") + len; |
591 | } | 591 | } |
@@ -593,32 +593,42 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
593 | { | 593 | { |
594 | char r[MAX_REALM_LENGTH]; | 594 | char r[MAX_REALM_LENGTH]; |
595 | 595 | ||
596 | len = lookup_sub_value(r, | 596 | len = lookup_sub_value(r, |
597 | sizeof (r), | 597 | sizeof (r), |
598 | header, "realm"); | 598 | header, "realm"); |
599 | if ( (0 == len) || | 599 | if ( (0 == len) || |
600 | (0 != strcmp(realm, r)) ) | 600 | (0 != strcmp(realm, r)) ) |
601 | return MHD_NO; | 601 | return MHD_NO; |
602 | left -= strlen ("realm") + len; | 602 | left -= strlen ("realm") + len; |
603 | } | 603 | } |
604 | 604 | ||
605 | if (0 == (len = lookup_sub_value (nonce, | 605 | if (0 == (len = lookup_sub_value (nonce, |
606 | sizeof (nonce), | 606 | sizeof (nonce), |
607 | header, "nonce"))) | 607 | header, "nonce"))) |
608 | return MHD_NO; | 608 | return MHD_NO; |
609 | left -= strlen ("nonce") + len; | 609 | left -= strlen ("nonce") + len; |
610 | 610 | if (left > 32 * 1024) | |
611 | { | 611 | { |
612 | char uri[left]; | 612 | /* we do not permit URIs longer than 32k, as we want to |
613 | 613 | make sure to not blow our stack (or per-connection | |
614 | if (0 == lookup_sub_value(uri, | 614 | heap memory limit). Besides, 32k is already insanely |
615 | sizeof (uri), | 615 | large, but of course in theory the |
616 | header, "uri")) | 616 | #MHD_OPTION_CONNECTION_MEMORY_LIMIT might be very large |
617 | and would thus permit sending a >32k authorization | ||
618 | header value. */ | ||
619 | return MHD_NO; | ||
620 | } | ||
621 | { | ||
622 | char uri[left]; | ||
623 | |||
624 | if (0 == lookup_sub_value (uri, | ||
625 | sizeof (uri), | ||
626 | header, "uri")) | ||
617 | return MHD_NO; | 627 | return MHD_NO; |
618 | 628 | ||
619 | /* 8 = 4 hexadecimal numbers for the timestamp */ | 629 | /* 8 = 4 hexadecimal numbers for the timestamp */ |
620 | nonce_time = strtoul(nonce + len - 8, (char **)NULL, 16); | 630 | nonce_time = strtoul (nonce + len - 8, (char **)NULL, 16); |
621 | t = (uint32_t) MHD_monotonic_time(); | 631 | t = (uint32_t) MHD_monotonic_time(); |
622 | /* | 632 | /* |
623 | * First level vetting for the nonce validity if the timestamp | 633 | * First level vetting for the nonce validity if the timestamp |
624 | * attached to the nonce exceeds `nonce_timeout' then the nonce is | 634 | * attached to the nonce exceeds `nonce_timeout' then the nonce is |
@@ -632,7 +642,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
632 | strlen (connection->url))) | 642 | strlen (connection->url))) |
633 | { | 643 | { |
634 | #if HAVE_MESSAGES | 644 | #if HAVE_MESSAGES |
635 | MHD_DLOG (connection->daemon, | 645 | MHD_DLOG (connection->daemon, |
636 | "Authentication failed, URI does not match.\n"); | 646 | "Authentication failed, URI does not match.\n"); |
637 | #endif | 647 | #endif |
638 | return MHD_NO; | 648 | return MHD_NO; |
@@ -646,10 +656,10 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
646 | args++; | 656 | args++; |
647 | if (MHD_YES != | 657 | if (MHD_YES != |
648 | check_argument_match (connection, | 658 | check_argument_match (connection, |
649 | args) ) | 659 | args) ) |
650 | { | 660 | { |
651 | #if HAVE_MESSAGES | 661 | #if HAVE_MESSAGES |
652 | MHD_DLOG (connection->daemon, | 662 | MHD_DLOG (connection->daemon, |
653 | "Authentication failed, arguments do not match.\n"); | 663 | "Authentication failed, arguments do not match.\n"); |
654 | #endif | 664 | #endif |
655 | return MHD_NO; | 665 | return MHD_NO; |
@@ -671,31 +681,31 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
671 | * not, the nonce fabrication process going to be | 681 | * not, the nonce fabrication process going to be |
672 | * very hard to achieve. | 682 | * very hard to achieve. |
673 | */ | 683 | */ |
674 | 684 | ||
675 | if (0 != strcmp (nonce, noncehashexp)) | 685 | if (0 != strcmp (nonce, noncehashexp)) |
676 | return MHD_INVALID_NONCE; | 686 | return MHD_INVALID_NONCE; |
677 | if ( (0 == lookup_sub_value (cnonce, | 687 | if ( (0 == lookup_sub_value (cnonce, |
678 | sizeof (cnonce), | 688 | sizeof (cnonce), |
679 | header, "cnonce")) || | 689 | header, "cnonce")) || |
680 | (0 == lookup_sub_value (qop, sizeof (qop), header, "qop")) || | 690 | (0 == lookup_sub_value (qop, sizeof (qop), header, "qop")) || |
681 | ( (0 != strcmp (qop, "auth")) && | 691 | ( (0 != strcmp (qop, "auth")) && |
682 | (0 != strcmp (qop, "")) ) || | 692 | (0 != strcmp (qop, "")) ) || |
683 | (0 == lookup_sub_value (nc, sizeof (nc), header, "nc")) || | 693 | (0 == lookup_sub_value (nc, sizeof (nc), header, "nc")) || |
684 | (0 == lookup_sub_value (response, sizeof (response), header, "response")) ) | 694 | (0 == lookup_sub_value (response, sizeof (response), header, "response")) ) |
685 | { | 695 | { |
686 | #if HAVE_MESSAGES | 696 | #if HAVE_MESSAGES |
687 | MHD_DLOG (connection->daemon, | 697 | MHD_DLOG (connection->daemon, |
688 | "Authentication failed, invalid format.\n"); | 698 | "Authentication failed, invalid format.\n"); |
689 | #endif | 699 | #endif |
690 | return MHD_NO; | 700 | return MHD_NO; |
691 | } | 701 | } |
692 | nci = strtoul (nc, &end, 16); | 702 | nci = strtoul (nc, &end, 16); |
693 | if ( ('\0' != *end) || | 703 | if ( ('\0' != *end) || |
694 | ( (LONG_MAX == nci) && | 704 | ( (LONG_MAX == nci) && |
695 | (ERANGE == errno) ) ) | 705 | (ERANGE == errno) ) ) |
696 | { | 706 | { |
697 | #if HAVE_MESSAGES | 707 | #if HAVE_MESSAGES |
698 | MHD_DLOG (connection->daemon, | 708 | MHD_DLOG (connection->daemon, |
699 | "Authentication failed, invalid format.\n"); | 709 | "Authentication failed, invalid format.\n"); |
700 | #endif | 710 | #endif |
701 | return MHD_NO; /* invalid nonce format */ | 711 | return MHD_NO; /* invalid nonce format */ |
@@ -705,10 +715,10 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
705 | * and not a replay attack attempt. Also adds the nonce | 715 | * and not a replay attack attempt. Also adds the nonce |
706 | * to the nonce-nc map if it does not exist there. | 716 | * to the nonce-nc map if it does not exist there. |
707 | */ | 717 | */ |
708 | 718 | ||
709 | if (MHD_YES != check_nonce_nc (connection, nonce, nci)) | 719 | if (MHD_YES != check_nonce_nc (connection, nonce, nci)) |
710 | return MHD_NO; | 720 | return MHD_NO; |
711 | 721 | ||
712 | digest_calc_ha1("md5", | 722 | digest_calc_ha1("md5", |
713 | username, | 723 | username, |
714 | realm, | 724 | realm, |
@@ -724,9 +734,9 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
724 | connection->method, | 734 | connection->method, |
725 | uri, | 735 | uri, |
726 | hentity, | 736 | hentity, |
727 | respexp); | 737 | respexp); |
728 | return (0 == strcmp(response, respexp)) | 738 | return (0 == strcmp(response, respexp)) |
729 | ? MHD_YES | 739 | ? MHD_YES |
730 | : MHD_NO; | 740 | : MHD_NO; |
731 | } | 741 | } |
732 | } | 742 | } |
@@ -757,7 +767,7 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection, | |||
757 | size_t hlen; | 767 | size_t hlen; |
758 | char nonce[HASH_MD5_HEX_LEN + 9]; | 768 | char nonce[HASH_MD5_HEX_LEN + 9]; |
759 | 769 | ||
760 | /* Generating the server nonce */ | 770 | /* Generating the server nonce */ |
761 | calculate_nonce ((uint32_t) MHD_monotonic_time(), | 771 | calculate_nonce ((uint32_t) MHD_monotonic_time(), |
762 | connection->method, | 772 | connection->method, |
763 | connection->daemon->digest_auth_random, | 773 | connection->daemon->digest_auth_random, |
@@ -768,20 +778,20 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection, | |||
768 | if (MHD_YES != check_nonce_nc (connection, nonce, 0)) | 778 | if (MHD_YES != check_nonce_nc (connection, nonce, 0)) |
769 | { | 779 | { |
770 | #if HAVE_MESSAGES | 780 | #if HAVE_MESSAGES |
771 | MHD_DLOG (connection->daemon, | 781 | MHD_DLOG (connection->daemon, |
772 | "Could not register nonce (is the nonce array size zero?).\n"); | 782 | "Could not register nonce (is the nonce array size zero?).\n"); |
773 | #endif | 783 | #endif |
774 | return MHD_NO; | 784 | return MHD_NO; |
775 | } | 785 | } |
776 | /* Building the authentication header */ | 786 | /* Building the authentication header */ |
777 | hlen = snprintf (NULL, | 787 | hlen = snprintf (NULL, |
778 | 0, | 788 | 0, |
779 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", | 789 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", |
780 | realm, | 790 | realm, |
781 | nonce, | 791 | nonce, |
782 | opaque, | 792 | opaque, |
783 | signal_stale | 793 | signal_stale |
784 | ? ",stale=\"true\"" | 794 | ? ",stale=\"true\"" |
785 | : ""); | 795 | : ""); |
786 | { | 796 | { |
787 | char header[hlen + 1]; | 797 | char header[hlen + 1]; |
@@ -789,20 +799,20 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection, | |||
789 | snprintf (header, | 799 | snprintf (header, |
790 | sizeof(header), | 800 | sizeof(header), |
791 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", | 801 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", |
792 | realm, | 802 | realm, |
793 | nonce, | 803 | nonce, |
794 | opaque, | 804 | opaque, |
795 | signal_stale | 805 | signal_stale |
796 | ? ",stale=\"true\"" | 806 | ? ",stale=\"true\"" |
797 | : ""); | 807 | : ""); |
798 | ret = MHD_add_response_header(response, | 808 | ret = MHD_add_response_header(response, |
799 | MHD_HTTP_HEADER_WWW_AUTHENTICATE, | 809 | MHD_HTTP_HEADER_WWW_AUTHENTICATE, |
800 | header); | 810 | header); |
801 | } | 811 | } |
802 | if (MHD_YES == ret) | 812 | if (MHD_YES == ret) |
803 | ret = MHD_queue_response(connection, | 813 | ret = MHD_queue_response(connection, |
804 | MHD_HTTP_UNAUTHORIZED, | 814 | MHD_HTTP_UNAUTHORIZED, |
805 | response); | 815 | response); |
806 | return ret; | 816 | return ret; |
807 | } | 817 | } |
808 | 818 | ||