aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/digestauth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/digestauth.c')
-rw-r--r--src/microhttpd/digestauth.c936
1 files changed, 471 insertions, 465 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index ce7edb79..95aee7b4 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -82,13 +82,15 @@
82/** 82/**
83 * Check that @a n is below #MAX_NONCE 83 * Check that @a n is below #MAX_NONCE
84 */ 84 */
85#define VLA_CHECK_LEN_DIGEST(n) do { if ((n) > MAX_DIGEST) mhd_panic(mhd_panic_cls, __FILE__, __LINE__, "VLA too big"); } while (0) 85#define VLA_CHECK_LEN_DIGEST(n) do { if ((n) > MAX_DIGEST) mhd_panic ( \
86 mhd_panic_cls, __FILE__, __LINE__, \
87 "VLA too big"); } while (0)
86 88
87 89
88/** 90/**
89 * Beginning string for any valid Digest authentication header. 91 * Beginning string for any valid Digest authentication header.
90 */ 92 */
91#define _BASE "Digest " 93#define _BASE "Digest "
92 94
93/** 95/**
94 * Maximum length of a username for digest authentication. 96 * Maximum length of a username for digest authentication.
@@ -149,7 +151,7 @@ struct DigestAlgorithm
149 */ 151 */
150 void 152 void
151 (*update)(void *ctx, 153 (*update)(void *ctx,
152 const uint8_t *data, 154 const uint8_t *data,
153 size_t length); 155 size_t length);
154 156
155 /** 157 /**
@@ -161,7 +163,7 @@ struct DigestAlgorithm
161 */ 163 */
162 void 164 void
163 (*digest)(void *ctx, 165 (*digest)(void *ctx,
164 uint8_t *digest); 166 uint8_t *digest);
165}; 167};
166 168
167 169
@@ -174,19 +176,19 @@ struct DigestAlgorithm
174 */ 176 */
175static void 177static void
176cvthex (const unsigned char *bin, 178cvthex (const unsigned char *bin,
177 size_t len, 179 size_t len,
178 char *hex) 180 char *hex)
179{ 181{
180 size_t i; 182 size_t i;
181 unsigned int j; 183 unsigned int j;
182 184
183 for (i = 0; i < len; ++i) 185 for (i = 0; i < len; ++i)
184 { 186 {
185 j = (bin[i] >> 4) & 0x0f; 187 j = (bin[i] >> 4) & 0x0f;
186 hex[i * 2] = (char)((j <= 9) ? (j + '0') : (j - 10 + 'a')); 188 hex[i * 2] = (char) ((j <= 9) ? (j + '0') : (j - 10 + 'a'));
187 j = bin[i] & 0x0f; 189 j = bin[i] & 0x0f;
188 hex[i * 2 + 1] = (char)((j <= 9) ? (j + '0') : (j - 10 + 'a')); 190 hex[i * 2 + 1] = (char) ((j <= 9) ? (j + '0') : (j - 10 + 'a'));
189 } 191 }
190 hex[len * 2] = '\0'; 192 hex[len * 2] = '\0';
191} 193}
192 194
@@ -201,54 +203,54 @@ cvthex (const unsigned char *bin,
201 * @param[in,out] da digest implementation, must match @a alg; the 203 * @param[in,out] da digest implementation, must match @a alg; the
202 * da->sessionkey will be initialized to the digest in HEX 204 * da->sessionkey will be initialized to the digest in HEX
203 * @param digest An `unsigned char *' pointer to the binary MD5 sum 205 * @param digest An `unsigned char *' pointer to the binary MD5 sum
204 * for the precalculated hash value "username:realm:password" 206 * for the precalculated hash value "username:realm:password"
205 * of #MHD_MD5_DIGEST_SIZE or #MHD_SHA256_DIGEST_SIZE bytes 207 * of #MHD_MD5_DIGEST_SIZE or #MHD_SHA256_DIGEST_SIZE bytes
206 * @param nonce A `char *' pointer to the nonce value 208 * @param nonce A `char *' pointer to the nonce value
207 * @param cnonce A `char *' pointer to the cnonce value 209 * @param cnonce A `char *' pointer to the cnonce value
208 */ 210 */
209static void 211static void
210digest_calc_ha1_from_digest (const char *alg, 212digest_calc_ha1_from_digest (const char *alg,
211 struct DigestAlgorithm *da, 213 struct DigestAlgorithm *da,
212 const uint8_t *digest, 214 const uint8_t *digest,
213 const char *nonce, 215 const char *nonce,
214 const char *cnonce) 216 const char *cnonce)
215{ 217{
216 if ( (MHD_str_equal_caseless_(alg, 218 if ( (MHD_str_equal_caseless_ (alg,
217 "md5-sess")) || 219 "md5-sess")) ||
218 (MHD_str_equal_caseless_(alg, 220 (MHD_str_equal_caseless_ (alg,
219 "sha-256-sess")) ) 221 "sha-256-sess")) )
220 { 222 {
221 uint8_t dig[VLA_ARRAY_LEN_DIGEST(da->digest_size)]; 223 uint8_t dig[VLA_ARRAY_LEN_DIGEST (da->digest_size)];
222 224
223 VLA_CHECK_LEN_DIGEST(da->digest_size); 225 VLA_CHECK_LEN_DIGEST (da->digest_size);
224 da->init (da->ctx); 226 da->init (da->ctx);
225 da->update (da->ctx, 227 da->update (da->ctx,
226 digest, 228 digest,
227 MHD_MD5_DIGEST_SIZE); 229 MHD_MD5_DIGEST_SIZE);
228 da->update (da->ctx, 230 da->update (da->ctx,
229 (const unsigned char *) ":", 231 (const unsigned char *) ":",
230 1); 232 1);
231 da->update (da->ctx, 233 da->update (da->ctx,
232 (const unsigned char *) nonce, 234 (const unsigned char *) nonce,
233 strlen (nonce)); 235 strlen (nonce));
234 da->update (da->ctx, 236 da->update (da->ctx,
235 (const unsigned char *) ":", 237 (const unsigned char *) ":",
236 1); 238 1);
237 da->update (da->ctx, 239 da->update (da->ctx,
238 (const unsigned char *) cnonce, 240 (const unsigned char *) cnonce,
239 strlen (cnonce)); 241 strlen (cnonce));
240 da->digest (da->ctx, 242 da->digest (da->ctx,
241 dig); 243 dig);
242 cvthex (dig, 244 cvthex (dig,
243 sizeof (dig), 245 sizeof (dig),
244 da->sessionkey); 246 da->sessionkey);
245 } 247 }
246 else 248 else
247 { 249 {
248 cvthex (digest, 250 cvthex (digest,
249 da->digest_size, 251 da->digest_size,
250 da->sessionkey); 252 da->sessionkey);
251 } 253 }
252} 254}
253 255
254 256
@@ -268,20 +270,20 @@ digest_calc_ha1_from_digest (const char *alg,
268 */ 270 */
269static void 271static void
270digest_calc_ha1_from_user (const char *alg, 272digest_calc_ha1_from_user (const char *alg,
271 const char *username, 273 const char *username,
272 const char *realm, 274 const char *realm,
273 const char *password, 275 const char *password,
274 const char *nonce, 276 const char *nonce,
275 const char *cnonce, 277 const char *cnonce,
276 struct DigestAlgorithm *da) 278 struct DigestAlgorithm *da)
277{ 279{
278 unsigned char ha1[VLA_ARRAY_LEN_DIGEST(da->digest_size)]; 280 unsigned char ha1[VLA_ARRAY_LEN_DIGEST (da->digest_size)];
279 281
280 VLA_CHECK_LEN_DIGEST(da->digest_size); 282 VLA_CHECK_LEN_DIGEST (da->digest_size);
281 da->init (da->ctx); 283 da->init (da->ctx);
282 da->update (da->ctx, 284 da->update (da->ctx,
283 (const unsigned char *) username, 285 (const unsigned char *) username,
284 strlen (username)); 286 strlen (username));
285 da->update (da->ctx, 287 da->update (da->ctx,
286 (const unsigned char *) ":", 288 (const unsigned char *) ":",
287 1); 289 1);
@@ -322,20 +324,20 @@ digest_calc_ha1_from_user (const char *alg,
322 */ 324 */
323static void 325static void
324digest_calc_response (const char *ha1, 326digest_calc_response (const char *ha1,
325 const char *nonce, 327 const char *nonce,
326 const char *noncecount, 328 const char *noncecount,
327 const char *cnonce, 329 const char *cnonce,
328 const char *qop, 330 const char *qop,
329 const char *method, 331 const char *method,
330 const char *uri, 332 const char *uri,
331 const char *hentity, 333 const char *hentity,
332 struct DigestAlgorithm *da) 334 struct DigestAlgorithm *da)
333{ 335{
334 unsigned char ha2[VLA_ARRAY_LEN_DIGEST(da->digest_size)]; 336 unsigned char ha2[VLA_ARRAY_LEN_DIGEST (da->digest_size)];
335 unsigned char resphash[VLA_ARRAY_LEN_DIGEST(da->digest_size)]; 337 unsigned char resphash[VLA_ARRAY_LEN_DIGEST (da->digest_size)];
336 (void)hentity; /* Unused. Silence compiler warning. */ 338 (void) hentity; /* Unused. Silence compiler warning. */
337 339
338 VLA_CHECK_LEN_DIGEST(da->digest_size); 340 VLA_CHECK_LEN_DIGEST (da->digest_size);
339 da->init (da->ctx); 341 da->init (da->ctx);
340 da->update (da->ctx, 342 da->update (da->ctx,
341 (const unsigned char *) method, 343 (const unsigned char *) method,
@@ -344,22 +346,22 @@ digest_calc_response (const char *ha1,
344 (const unsigned char *) ":", 346 (const unsigned char *) ":",
345 1); 347 1);
346 da->update (da->ctx, 348 da->update (da->ctx,
347 (const unsigned char *) uri, 349 (const unsigned char *) uri,
348 strlen (uri)); 350 strlen (uri));
349#if 0 351#if 0
350 if (0 == strcasecmp (qop, 352 if (0 == strcasecmp (qop,
351 "auth-int")) 353 "auth-int"))
352 { 354 {
353 /* This is dead code since the rest of this module does 355 /* This is dead code since the rest of this module does
354 not support auth-int. */ 356 not support auth-int. */
357 da->update (da->ctx,
358 ":",
359 1);
360 if (NULL != hentity)
355 da->update (da->ctx, 361 da->update (da->ctx,
356 ":", 362 hentity,
357 1); 363 strlen (hentity));
358 if (NULL != hentity) 364 }
359 da->update (da->ctx,
360 hentity,
361 strlen (hentity));
362 }
363#endif 365#endif
364 da->digest (da->ctx, 366 da->digest (da->ctx,
365 ha2); 367 ha2);
@@ -381,26 +383,26 @@ digest_calc_response (const char *ha1,
381 (const unsigned char*) ":", 383 (const unsigned char*) ":",
382 1); 384 1);
383 if ('\0' != *qop) 385 if ('\0' != *qop)
384 { 386 {
385 da->update (da->ctx, 387 da->update (da->ctx,
386 (const unsigned char *) noncecount, 388 (const unsigned char *) noncecount,
387 strlen (noncecount)); 389 strlen (noncecount));
388 da->update (da->ctx, 390 da->update (da->ctx,
389 (const unsigned char *) ":", 391 (const unsigned char *) ":",
390 1); 392 1);
391 da->update (da->ctx, 393 da->update (da->ctx,
392 (const unsigned char *) cnonce, 394 (const unsigned char *) cnonce,
393 strlen (cnonce)); 395 strlen (cnonce));
394 da->update (da->ctx, 396 da->update (da->ctx,
395 (const unsigned char *) ":", 397 (const unsigned char *) ":",
396 1); 398 1);
397 da->update (da->ctx, 399 da->update (da->ctx,
398 (const unsigned char *) qop, 400 (const unsigned char *) qop,
399 strlen (qop)); 401 strlen (qop));
400 da->update (da->ctx, 402 da->update (da->ctx,
401 (const unsigned char *) ":", 403 (const unsigned char *) ":",
402 1); 404 1);
403 } 405 }
404 da->update (da->ctx, 406 da->update (da->ctx,
405 (const unsigned char *) da->sessionkey, 407 (const unsigned char *) da->sessionkey,
406 da->digest_size * 2); 408 da->digest_size * 2);
@@ -428,9 +430,9 @@ digest_calc_response (const char *ha1,
428 */ 430 */
429static size_t 431static size_t
430lookup_sub_value (char *dest, 432lookup_sub_value (char *dest,
431 size_t size, 433 size_t size,
432 const char *data, 434 const char *data,
433 const char *key) 435 const char *key)
434{ 436{
435 size_t keylen; 437 size_t keylen;
436 size_t len; 438 size_t len;
@@ -445,67 +447,67 @@ lookup_sub_value (char *dest,
445 keylen = strlen (key); 447 keylen = strlen (key);
446 ptr = data; 448 ptr = data;
447 while ('\0' != *ptr) 449 while ('\0' != *ptr)
450 {
451 if (NULL == (eq = strchr (ptr,
452 '=')))
453 return 0;
454 q1 = eq + 1;
455 while (' ' == *q1)
456 q1++;
457 if ('\"' != *q1)
458 {
459 q2 = strchr (q1,
460 ',');
461 qn = q2;
462 }
463 else
464 {
465 q1++;
466 q2 = strchr (q1,
467 '\"');
468 if (NULL == q2)
469 return 0; /* end quote not found */
470 qn = q2 + 1;
471 }
472 if ( (MHD_str_equal_caseless_n_ (ptr,
473 key,
474 keylen)) &&
475 (eq == &ptr[keylen]) )
448 { 476 {
449 if (NULL == (eq = strchr (ptr, 477 if (NULL == q2)
450 '='))) 478 {
451 return 0; 479 len = strlen (q1) + 1;
452 q1 = eq + 1; 480 if (size > len)
453 while (' ' == *q1) 481 size = len;
454 q1++; 482 size--;
455 if ('\"' != *q1) 483 strncpy (dest,
456 { 484 q1,
457 q2 = strchr (q1, 485 size);
458 ','); 486 dest[size] = '\0';
459 qn = q2; 487 return size;
460 } 488 }
461 else 489 else
462 { 490 {
463 q1++; 491 if (size > (size_t) ((q2 - q1) + 1))
464 q2 = strchr (q1, 492 size = (q2 - q1) + 1;
465 '\"'); 493 size--;
466 if (NULL == q2) 494 memcpy (dest,
467 return 0; /* end quote not found */ 495 q1,
468 qn = q2 + 1; 496 size);
469 } 497 dest[size] = '\0';
470 if ( (MHD_str_equal_caseless_n_(ptr, 498 return size;
471 key, 499 }
472 keylen)) &&
473 (eq == &ptr[keylen]) )
474 {
475 if (NULL == q2)
476 {
477 len = strlen (q1) + 1;
478 if (size > len)
479 size = len;
480 size--;
481 strncpy (dest,
482 q1,
483 size);
484 dest[size] = '\0';
485 return size;
486 }
487 else
488 {
489 if (size > (size_t) ((q2 - q1) + 1))
490 size = (q2 - q1) + 1;
491 size--;
492 memcpy (dest,
493 q1,
494 size);
495 dest[size] = '\0';
496 return size;
497 }
498 }
499 if (NULL == qn)
500 return 0;
501 ptr = strchr (qn,
502 ',');
503 if (NULL == ptr)
504 return 0;
505 ptr++;
506 while (' ' == *ptr)
507 ptr++;
508 } 500 }
501 if (NULL == qn)
502 return 0;
503 ptr = strchr (qn,
504 ',');
505 if (NULL == ptr)
506 return 0;
507 ptr++;
508 while (' ' == *ptr)
509 ptr++;
510 }
509 return 0; 511 return 0;
510} 512}
511 513
@@ -521,8 +523,8 @@ lookup_sub_value (char *dest,
521 */ 523 */
522static int 524static int
523check_nonce_nc (struct MHD_Connection *connection, 525check_nonce_nc (struct MHD_Connection *connection,
524 const char *nonce, 526 const char *nonce,
525 uint64_t nc) 527 uint64_t nc)
526{ 528{
527 struct MHD_Daemon *daemon = connection->daemon; 529 struct MHD_Daemon *daemon = connection->daemon;
528 struct MHD_NonceNc *nn; 530 struct MHD_NonceNc *nn;
@@ -544,10 +546,10 @@ check_nonce_nc (struct MHD_Connection *connection,
544 off = 0; 546 off = 0;
545 np = nonce; 547 np = nonce;
546 while ('\0' != *np) 548 while ('\0' != *np)
547 { 549 {
548 off = (off << 8) | (*np ^ (off >> 24)); 550 off = (off << 8) | (*np ^ (off >> 24));
549 np++; 551 np++;
550 } 552 }
551 off = off % mod; 553 off = off % mod;
552 /* 554 /*
553 * Look for the nonce, if it does exist and its corresponding 555 * Look for the nonce, if it does exist and its corresponding
@@ -559,47 +561,48 @@ check_nonce_nc (struct MHD_Connection *connection,
559 MHD_mutex_lock_chk_ (&daemon->nnc_lock); 561 MHD_mutex_lock_chk_ (&daemon->nnc_lock);
560#endif 562#endif
561 if (0 == nc) 563 if (0 == nc)
562 { 564 {
563 /* Fresh nonce, reinitialize array */ 565 /* Fresh nonce, reinitialize array */
564 memcpy (nn->nonce, 566 memcpy (nn->nonce,
565 nonce, 567 nonce,
566 noncelen); 568 noncelen);
567 nn->nc = 0; 569 nn->nc = 0;
568 nn->nmask = 0; 570 nn->nmask = 0;
569#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 571#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
570 MHD_mutex_unlock_chk_ (&daemon->nnc_lock); 572 MHD_mutex_unlock_chk_ (&daemon->nnc_lock);
571#endif 573#endif
572 return MHD_YES; 574 return MHD_YES;
573 } 575 }
574 /* Note that we use 64 here, as we do not store the 576 /* Note that we use 64 here, as we do not store the
575 bit for 'nn->nc' itself in 'nn->nmask' */ 577 bit for 'nn->nc' itself in 'nn->nmask' */
576 if ( (nc < nn->nc) && 578 if ( (nc < nn->nc) &&
577 (nc + 64 > nc /* checking for overflow */) && 579 (nc + 64 > nc /* checking for overflow */) &&
578 (nc + 64 >= nn->nc) && 580 (nc + 64 >= nn->nc) &&
579 (0 == ((1LLU << (nn->nc - nc - 1)) & nn->nmask)) ) 581 (0 == ((1LLU << (nn->nc - nc - 1)) & nn->nmask)) )
580 { 582 {
581 /* Out-of-order nonce, but within 64-bit bitmask, set bit */ 583 /* Out-of-order nonce, but within 64-bit bitmask, set bit */
582 nn->nmask |= (1LLU << (nn->nc - nc - 1)); 584 nn->nmask |= (1LLU << (nn->nc - nc - 1));
583#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 585#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
584 MHD_mutex_unlock_chk_ (&daemon->nnc_lock); 586 MHD_mutex_unlock_chk_ (&daemon->nnc_lock);
585#endif 587#endif
586 return MHD_YES; 588 return MHD_YES;
587 } 589 }
588 590
589 if ( (nc <= nn->nc) || 591 if ( (nc <= nn->nc) ||
590 (0 != strcmp (nn->nonce, 592 (0 != strcmp (nn->nonce,
591 nonce)) ) 593 nonce)) )
592 { 594 {
593 /* Nonce does not match, fail */ 595 /* Nonce does not match, fail */
594#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 596#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
595 MHD_mutex_unlock_chk_ (&daemon->nnc_lock); 597 MHD_mutex_unlock_chk_ (&daemon->nnc_lock);
596#endif 598#endif
597#ifdef HAVE_MESSAGES 599#ifdef HAVE_MESSAGES
598 MHD_DLOG (daemon, 600 MHD_DLOG (daemon,
599 _("Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n")); 601 _ (
602 "Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n"));
600#endif 603#endif
601 return MHD_NO; 604 return MHD_NO;
602 } 605 }
603 /* Nonce is larger, shift bitmask and bump limit */ 606 /* Nonce is larger, shift bitmask and bump limit */
604 if (64 > nc - nn->nc) 607 if (64 > nc - nn->nc)
605 nn->nmask <<= (nc - nn->nc); /* small jump, less than mask width */ 608 nn->nmask <<= (nc - nn->nc); /* small jump, less than mask width */
@@ -618,12 +621,12 @@ check_nonce_nc (struct MHD_Connection *connection,
618 * 621 *
619 * @param connection The MHD connection structure 622 * @param connection The MHD connection structure
620 * @return NULL if no username could be found, a pointer 623 * @return NULL if no username could be found, a pointer
621 * to the username if found 624 * to the username if found
622 * @warning Returned value must be freed by #MHD_free(). 625 * @warning Returned value must be freed by #MHD_free().
623 * @ingroup authentication 626 * @ingroup authentication
624 */ 627 */
625char * 628char *
626MHD_digest_auth_get_username(struct MHD_Connection *connection) 629MHD_digest_auth_get_username (struct MHD_Connection *connection)
627{ 630{
628 size_t len; 631 size_t len;
629 char user[MAX_USERNAME_LENGTH]; 632 char user[MAX_USERNAME_LENGTH];
@@ -632,7 +635,8 @@ MHD_digest_auth_get_username(struct MHD_Connection *connection)
632 if (MHD_NO == MHD_lookup_connection_value_n (connection, 635 if (MHD_NO == MHD_lookup_connection_value_n (connection,
633 MHD_HEADER_KIND, 636 MHD_HEADER_KIND,
634 MHD_HTTP_HEADER_AUTHORIZATION, 637 MHD_HTTP_HEADER_AUTHORIZATION,
635 MHD_STATICSTR_LEN_ (MHD_HTTP_HEADER_AUTHORIZATION), 638 MHD_STATICSTR_LEN_ (
639 MHD_HTTP_HEADER_AUTHORIZATION),
636 &header, 640 &header,
637 NULL)) 641 NULL))
638 return NULL; 642 return NULL;
@@ -642,9 +646,9 @@ MHD_digest_auth_get_username(struct MHD_Connection *connection)
642 return NULL; 646 return NULL;
643 header += MHD_STATICSTR_LEN_ (_BASE); 647 header += MHD_STATICSTR_LEN_ (_BASE);
644 if (0 == (len = lookup_sub_value (user, 648 if (0 == (len = lookup_sub_value (user,
645 sizeof (user), 649 sizeof (user),
646 header, 650 header,
647 "username"))) 651 "username")))
648 return NULL; 652 return NULL;
649 return strdup (user); 653 return strdup (user);
650} 654}
@@ -667,24 +671,24 @@ MHD_digest_auth_get_username(struct MHD_Connection *connection)
667 */ 671 */
668static void 672static void
669calculate_nonce (uint32_t nonce_time, 673calculate_nonce (uint32_t nonce_time,
670 const char *method, 674 const char *method,
671 const char *rnd, 675 const char *rnd,
672 size_t rnd_size, 676 size_t rnd_size,
673 const char *uri, 677 const char *uri,
674 const char *realm, 678 const char *realm,
675 struct DigestAlgorithm *da, 679 struct DigestAlgorithm *da,
676 char *nonce) 680 char *nonce)
677{ 681{
678 unsigned char timestamp[TIMESTAMP_BIN_SIZE]; 682 unsigned char timestamp[TIMESTAMP_BIN_SIZE];
679 unsigned char tmpnonce[VLA_ARRAY_LEN_DIGEST(da->digest_size)]; 683 unsigned char tmpnonce[VLA_ARRAY_LEN_DIGEST (da->digest_size)];
680 char timestamphex[TIMESTAMP_BIN_SIZE * 2 + 1]; 684 char timestamphex[TIMESTAMP_BIN_SIZE * 2 + 1];
681 685
682 VLA_CHECK_LEN_DIGEST(da->digest_size); 686 VLA_CHECK_LEN_DIGEST (da->digest_size);
683 da->init (da->ctx); 687 da->init (da->ctx);
684 timestamp[0] = (unsigned char)((nonce_time & 0xff000000) >> 0x18); 688 timestamp[0] = (unsigned char) ((nonce_time & 0xff000000) >> 0x18);
685 timestamp[1] = (unsigned char)((nonce_time & 0x00ff0000) >> 0x10); 689 timestamp[1] = (unsigned char) ((nonce_time & 0x00ff0000) >> 0x10);
686 timestamp[2] = (unsigned char)((nonce_time & 0x0000ff00) >> 0x08); 690 timestamp[2] = (unsigned char) ((nonce_time & 0x0000ff00) >> 0x08);
687 timestamp[3] = (unsigned char)((nonce_time & 0x000000ff)); 691 timestamp[3] = (unsigned char) ((nonce_time & 0x000000ff));
688 da->update (da->ctx, 692 da->update (da->ctx,
689 timestamp, 693 timestamp,
690 sizeof (timestamp)); 694 sizeof (timestamp));
@@ -742,37 +746,37 @@ calculate_nonce (uint32_t nonce_time,
742 */ 746 */
743static int 747static int
744test_header (struct MHD_Connection *connection, 748test_header (struct MHD_Connection *connection,
745 const char *key, 749 const char *key,
746 size_t key_size, 750 size_t key_size,
747 const char *value, 751 const char *value,
748 size_t value_size, 752 size_t value_size,
749 enum MHD_ValueKind kind) 753 enum MHD_ValueKind kind)
750{ 754{
751 struct MHD_HTTP_Header *pos; 755 struct MHD_HTTP_Header *pos;
752 756
753 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 757 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
754 { 758 {
755 if (kind != pos->kind) 759 if (kind != pos->kind)
756 continue; 760 continue;
757 if (key_size != pos->header_size) 761 if (key_size != pos->header_size)
758 continue; 762 continue;
759 if (value_size != pos->value_size) 763 if (value_size != pos->value_size)
760 continue; 764 continue;
761 if (0 != memcmp (key, 765 if (0 != memcmp (key,
762 pos->header, 766 pos->header,
763 key_size)) 767 key_size))
764 continue; 768 continue;
765 if ( (NULL == value) && 769 if ( (NULL == value) &&
766 (NULL == pos->value) ) 770 (NULL == pos->value) )
767 return MHD_YES;
768 if ( (NULL == value) ||
769 (NULL == pos->value) ||
770 (0 != memcmp (value,
771 pos->value,
772 value_size)) )
773 continue;
774 return MHD_YES; 771 return MHD_YES;
775 } 772 if ( (NULL == value) ||
773 (NULL == pos->value) ||
774 (0 != memcmp (value,
775 pos->value,
776 value_size)) )
777 continue;
778 return MHD_YES;
779 }
776 return MHD_NO; 780 return MHD_NO;
777} 781}
778 782
@@ -789,7 +793,7 @@ test_header (struct MHD_Connection *connection,
789 */ 793 */
790static int 794static int
791check_argument_match (struct MHD_Connection *connection, 795check_argument_match (struct MHD_Connection *connection,
792 const char *args) 796 const char *args)
793{ 797{
794 struct MHD_HTTP_Header *pos; 798 struct MHD_HTTP_Header *pos;
795 char *argb; 799 char *argb;
@@ -798,35 +802,35 @@ check_argument_match (struct MHD_Connection *connection,
798 802
799 argb = strdup (args); 803 argb = strdup (args);
800 if (NULL == argb) 804 if (NULL == argb)
801 { 805 {
802#ifdef HAVE_MESSAGES 806#ifdef HAVE_MESSAGES
803 MHD_DLOG (connection->daemon, 807 MHD_DLOG (connection->daemon,
804 _("Failed to allocate memory for copy of URI arguments\n")); 808 _ ("Failed to allocate memory for copy of URI arguments\n"));
805#endif /* HAVE_MESSAGES */ 809#endif /* HAVE_MESSAGES */
806 return MHD_NO; 810 return MHD_NO;
807 } 811 }
808 ret = MHD_parse_arguments_ (connection, 812 ret = MHD_parse_arguments_ (connection,
809 MHD_GET_ARGUMENT_KIND, 813 MHD_GET_ARGUMENT_KIND,
810 argb, 814 argb,
811 &test_header, 815 &test_header,
812 &num_headers); 816 &num_headers);
813 free (argb); 817 free (argb);
814 if (MHD_YES != ret) 818 if (MHD_YES != ret)
815 { 819 {
816 return MHD_NO; 820 return MHD_NO;
817 } 821 }
818 /* also check that the number of headers matches */ 822 /* also check that the number of headers matches */
819 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 823 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
820 { 824 {
821 if (MHD_GET_ARGUMENT_KIND != pos->kind) 825 if (MHD_GET_ARGUMENT_KIND != pos->kind)
822 continue; 826 continue;
823 num_headers--; 827 num_headers--;
824 } 828 }
825 if (0 != num_headers) 829 if (0 != num_headers)
826 { 830 {
827 /* argument count mismatch */ 831 /* argument count mismatch */
828 return MHD_NO; 832 return MHD_NO;
829 } 833 }
830 return MHD_YES; 834 return MHD_YES;
831} 835}
832 836
@@ -842,51 +846,52 @@ check_argument_match (struct MHD_Connection *connection,
842 * @param username The username needs to be authenticated 846 * @param username The username needs to be authenticated
843 * @param password The password used in the authentication 847 * @param password The password used in the authentication
844 * @param digest An optional binary hash 848 * @param digest An optional binary hash
845 * of the precalculated hash value "username:realm:password" 849 * of the precalculated hash value "username:realm:password"
846 * (must contain "da->digest_size" bytes or be NULL) 850 * (must contain "da->digest_size" bytes or be NULL)
847 * @param nonce_timeout The amount of time for a nonce to be 851 * @param nonce_timeout The amount of time for a nonce to be
848 * invalid in seconds 852 * invalid in seconds
849 * @return #MHD_YES if authenticated, #MHD_NO if not, 853 * @return #MHD_YES if authenticated, #MHD_NO if not,
850 * #MHD_INVALID_NONCE if nonce is invalid 854 * #MHD_INVALID_NONCE if nonce is invalid
851 * @ingroup authentication 855 * @ingroup authentication
852 */ 856 */
853static int 857static int
854digest_auth_check_all (struct MHD_Connection *connection, 858digest_auth_check_all (struct MHD_Connection *connection,
855 struct DigestAlgorithm *da, 859 struct DigestAlgorithm *da,
856 const char *realm, 860 const char *realm,
857 const char *username, 861 const char *username,
858 const char *password, 862 const char *password,
859 const uint8_t *digest, 863 const uint8_t *digest,
860 unsigned int nonce_timeout) 864 unsigned int nonce_timeout)
861{ 865{
862 struct MHD_Daemon *daemon = connection->daemon; 866 struct MHD_Daemon *daemon = connection->daemon;
863 size_t len; 867 size_t len;
864 const char *header; 868 const char *header;
865 char nonce[MAX_NONCE_LENGTH]; 869 char nonce[MAX_NONCE_LENGTH];
866 char cnonce[MAX_NONCE_LENGTH]; 870 char cnonce[MAX_NONCE_LENGTH];
867 char ha1[VLA_ARRAY_LEN_DIGEST(da->digest_size) * 2 + 1]; 871 char ha1[VLA_ARRAY_LEN_DIGEST (da->digest_size) * 2 + 1];
868 char qop[15]; /* auth,auth-int */ 872 char qop[15]; /* auth,auth-int */
869 char nc[20]; 873 char nc[20];
870 char response[MAX_AUTH_RESPONSE_LENGTH]; 874 char response[MAX_AUTH_RESPONSE_LENGTH];
871 const char *hentity = NULL; /* "auth-int" is not supported */ 875 const char *hentity = NULL; /* "auth-int" is not supported */
872 char noncehashexp[NONCE_STD_LEN(VLA_ARRAY_LEN_DIGEST(da->digest_size)) + 1]; 876 char noncehashexp[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (da->digest_size)) + 1];
873 uint32_t nonce_time; 877 uint32_t nonce_time;
874 uint32_t t; 878 uint32_t t;
875 size_t left; /* number of characters left in 'header' for 'uri' */ 879 size_t left; /* number of characters left in 'header' for 'uri' */
876 uint64_t nci; 880 uint64_t nci;
877 char *qmark; 881 char *qmark;
878 882
879 VLA_CHECK_LEN_DIGEST(da->digest_size); 883 VLA_CHECK_LEN_DIGEST (da->digest_size);
880 if (MHD_NO == MHD_lookup_connection_value_n (connection, 884 if (MHD_NO == MHD_lookup_connection_value_n (connection,
881 MHD_HEADER_KIND, 885 MHD_HEADER_KIND,
882 MHD_HTTP_HEADER_AUTHORIZATION, 886 MHD_HTTP_HEADER_AUTHORIZATION,
883 MHD_STATICSTR_LEN_ (MHD_HTTP_HEADER_AUTHORIZATION), 887 MHD_STATICSTR_LEN_ (
888 MHD_HTTP_HEADER_AUTHORIZATION),
884 &header, 889 &header,
885 NULL)) 890 NULL))
886 return MHD_NO; 891 return MHD_NO;
887 if (0 != strncmp (header, 892 if (0 != strncmp (header,
888 _BASE, 893 _BASE,
889 MHD_STATICSTR_LEN_(_BASE))) 894 MHD_STATICSTR_LEN_ (_BASE)))
890 return MHD_NO; 895 return MHD_NO;
891 header += MHD_STATICSTR_LEN_ (_BASE); 896 header += MHD_STATICSTR_LEN_ (_BASE);
892 left = strlen (header); 897 left = strlen (header);
@@ -895,11 +900,11 @@ digest_auth_check_all (struct MHD_Connection *connection,
895 char un[MAX_USERNAME_LENGTH]; 900 char un[MAX_USERNAME_LENGTH];
896 901
897 len = lookup_sub_value (un, 902 len = lookup_sub_value (un,
898 sizeof (un), 903 sizeof (un),
899 header, 904 header,
900 "username"); 905 "username");
901 if ( (0 == len) || 906 if ( (0 == len) ||
902 (0 != strcmp (username, 907 (0 != strcmp (username,
903 un)) ) 908 un)) )
904 return MHD_NO; 909 return MHD_NO;
905 left -= strlen ("username") + len; 910 left -= strlen ("username") + len;
@@ -913,15 +918,15 @@ digest_auth_check_all (struct MHD_Connection *connection,
913 header, 918 header,
914 "realm"); 919 "realm");
915 if ( (0 == len) || 920 if ( (0 == len) ||
916 (0 != strcmp (realm, 921 (0 != strcmp (realm,
917 r)) ) 922 r)) )
918 return MHD_NO; 923 return MHD_NO;
919 left -= strlen ("realm") + len; 924 left -= strlen ("realm") + len;
920 } 925 }
921 926
922 if (0 == (len = lookup_sub_value (nonce, 927 if (0 == (len = lookup_sub_value (nonce,
923 sizeof (nonce), 928 sizeof (nonce),
924 header, 929 header,
925 "nonce"))) 930 "nonce")))
926 return MHD_NO; 931 return MHD_NO;
927 left -= strlen ("nonce") + len; 932 left -= strlen ("nonce") + len;
@@ -940,14 +945,14 @@ digest_auth_check_all (struct MHD_Connection *connection,
940 MHD_strx_to_uint32_n_ (nonce + len - TIMESTAMP_BIN_SIZE * 2, 945 MHD_strx_to_uint32_n_ (nonce + len - TIMESTAMP_BIN_SIZE * 2,
941 TIMESTAMP_BIN_SIZE * 2, 946 TIMESTAMP_BIN_SIZE * 2,
942 &nonce_time)) 947 &nonce_time))
943 { 948 {
944#ifdef HAVE_MESSAGES 949#ifdef HAVE_MESSAGES
945 MHD_DLOG (daemon, 950 MHD_DLOG (daemon,
946 _("Authentication failed, invalid timestamp format.\n")); 951 _ ("Authentication failed, invalid timestamp format.\n"));
947#endif 952#endif
948 return MHD_NO; 953 return MHD_NO;
949 } 954 }
950 t = (uint32_t) MHD_monotonic_sec_counter(); 955 t = (uint32_t) MHD_monotonic_sec_counter ();
951 /* 956 /*
952 * First level vetting for the nonce validity: if the timestamp 957 * First level vetting for the nonce validity: if the timestamp
953 * attached to the nonce exceeds `nonce_timeout', then the nonce is 958 * attached to the nonce exceeds `nonce_timeout', then the nonce is
@@ -955,10 +960,10 @@ digest_auth_check_all (struct MHD_Connection *connection,
955 */ 960 */
956 if ( (t > nonce_time + nonce_timeout) || 961 if ( (t > nonce_time + nonce_timeout) ||
957 (nonce_time + nonce_timeout < nonce_time) ) 962 (nonce_time + nonce_timeout < nonce_time) )
958 { 963 {
959 /* too old */ 964 /* too old */
960 return MHD_INVALID_NONCE; 965 return MHD_INVALID_NONCE;
961 } 966 }
962 967
963 calculate_nonce (nonce_time, 968 calculate_nonce (nonce_time,
964 connection->method, 969 connection->method,
@@ -980,9 +985,9 @@ digest_auth_check_all (struct MHD_Connection *connection,
980 985
981 if (0 != strcmp (nonce, 986 if (0 != strcmp (nonce,
982 noncehashexp)) 987 noncehashexp))
983 { 988 {
984 return MHD_INVALID_NONCE; 989 return MHD_INVALID_NONCE;
985 } 990 }
986 if ( (0 == lookup_sub_value (cnonce, 991 if ( (0 == lookup_sub_value (cnonce,
987 sizeof (cnonce), 992 sizeof (cnonce),
988 header, 993 header,
@@ -1003,23 +1008,23 @@ digest_auth_check_all (struct MHD_Connection *connection,
1003 sizeof (response), 1008 sizeof (response),
1004 header, 1009 header,
1005 "response")) ) 1010 "response")) )
1006 { 1011 {
1007#ifdef HAVE_MESSAGES 1012#ifdef HAVE_MESSAGES
1008 MHD_DLOG (daemon, 1013 MHD_DLOG (daemon,
1009 _("Authentication failed, invalid format.\n")); 1014 _ ("Authentication failed, invalid format.\n"));
1010#endif 1015#endif
1011 return MHD_NO; 1016 return MHD_NO;
1012 } 1017 }
1013 if (len != MHD_strx_to_uint64_n_ (nc, 1018 if (len != MHD_strx_to_uint64_n_ (nc,
1014 len, 1019 len,
1015 &nci)) 1020 &nci))
1016 { 1021 {
1017#ifdef HAVE_MESSAGES 1022#ifdef HAVE_MESSAGES
1018 MHD_DLOG (daemon, 1023 MHD_DLOG (daemon,
1019 _("Authentication failed, invalid nc format.\n")); 1024 _ ("Authentication failed, invalid nc format.\n"));
1020#endif 1025#endif
1021 return MHD_NO; /* invalid nonce format */ 1026 return MHD_NO; /* invalid nonce format */
1022 } 1027 }
1023 1028
1024 /* 1029 /*
1025 * Checking if that combination of nonce and nc is sound 1030 * Checking if that combination of nonce and nc is sound
@@ -1030,64 +1035,64 @@ digest_auth_check_all (struct MHD_Connection *connection,
1030 check_nonce_nc (connection, 1035 check_nonce_nc (connection,
1031 nonce, 1036 nonce,
1032 nci)) 1037 nci))
1033 { 1038 {
1034 return MHD_NO; 1039 return MHD_NO;
1035 } 1040 }
1036 1041
1037 { 1042 {
1038 char *uri; 1043 char *uri;
1039 1044
1040 uri = malloc (left + 1); 1045 uri = malloc (left + 1);
1041 if (NULL == uri) 1046 if (NULL == uri)
1042 { 1047 {
1043#ifdef HAVE_MESSAGES 1048#ifdef HAVE_MESSAGES
1044 MHD_DLOG(daemon, 1049 MHD_DLOG (daemon,
1045 _("Failed to allocate memory for auth header processing\n")); 1050 _ ("Failed to allocate memory for auth header processing\n"));
1046#endif /* HAVE_MESSAGES */ 1051#endif /* HAVE_MESSAGES */
1047 return MHD_NO; 1052 return MHD_NO;
1048 } 1053 }
1049 if (0 == lookup_sub_value (uri, 1054 if (0 == lookup_sub_value (uri,
1050 left + 1, 1055 left + 1,
1051 header, 1056 header,
1052 "uri")) 1057 "uri"))
1053 { 1058 {
1054 free (uri); 1059 free (uri);
1055 return MHD_NO; 1060 return MHD_NO;
1056 } 1061 }
1057 if (NULL != digest) 1062 if (NULL != digest)
1058 { 1063 {
1059 /* This will initialize da->sessionkey (ha1) */ 1064 /* This will initialize da->sessionkey (ha1) */
1060 digest_calc_ha1_from_digest (da->alg, 1065 digest_calc_ha1_from_digest (da->alg,
1061 da, 1066 da,
1062 digest, 1067 digest,
1063 nonce, 1068 nonce,
1064 cnonce); 1069 cnonce);
1065 } 1070 }
1066 else 1071 else
1067 { 1072 {
1068 /* This will initialize da->sessionkey (ha1) */ 1073 /* This will initialize da->sessionkey (ha1) */
1069 mhd_assert (NULL != password); /* NULL == digest => password != NULL */ 1074 mhd_assert (NULL != password); /* NULL == digest => password != NULL */
1070 digest_calc_ha1_from_user (da->alg, 1075 digest_calc_ha1_from_user (da->alg,
1071 username, 1076 username,
1072 realm, 1077 realm,
1073 password, 1078 password,
1074 nonce, 1079 nonce,
1075 cnonce, 1080 cnonce,
1076 da); 1081 da);
1077 } 1082 }
1078 memcpy (ha1, 1083 memcpy (ha1,
1079 da->sessionkey, 1084 da->sessionkey,
1080 sizeof (ha1)); 1085 sizeof (ha1));
1081 /* This will initialize da->sessionkey (respexp) */ 1086 /* This will initialize da->sessionkey (respexp) */
1082 digest_calc_response (ha1, 1087 digest_calc_response (ha1,
1083 nonce, 1088 nonce,
1084 nc, 1089 nc,
1085 cnonce, 1090 cnonce,
1086 qop, 1091 qop,
1087 connection->method, 1092 connection->method,
1088 uri, 1093 uri,
1089 hentity, 1094 hentity,
1090 da); 1095 da);
1091 qmark = strchr (uri, 1096 qmark = strchr (uri,
1092 '?'); 1097 '?');
1093 if (NULL != qmark) 1098 if (NULL != qmark)
@@ -1102,7 +1107,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1102 { 1107 {
1103#ifdef HAVE_MESSAGES 1108#ifdef HAVE_MESSAGES
1104 MHD_DLOG (daemon, 1109 MHD_DLOG (daemon,
1105 _("Authentication failed, URI does not match.\n")); 1110 _ ("Authentication failed, URI does not match.\n"));
1106#endif 1111#endif
1107 free (uri); 1112 free (uri);
1108 return MHD_NO; 1113 return MHD_NO;
@@ -1112,26 +1117,26 @@ digest_auth_check_all (struct MHD_Connection *connection,
1112 const char *args = qmark; 1117 const char *args = qmark;
1113 1118
1114 if (NULL == args) 1119 if (NULL == args)
1115 args = ""; 1120 args = "";
1116 else 1121 else
1117 args++; 1122 args++;
1118 if (MHD_YES != 1123 if (MHD_YES !=
1119 check_argument_match (connection, 1124 check_argument_match (connection,
1120 args) ) 1125 args) )
1121 { 1126 {
1122#ifdef HAVE_MESSAGES 1127#ifdef HAVE_MESSAGES
1123 MHD_DLOG (daemon, 1128 MHD_DLOG (daemon,
1124 _("Authentication failed, arguments do not match.\n")); 1129 _ ("Authentication failed, arguments do not match.\n"));
1125#endif 1130#endif
1126 free (uri); 1131 free (uri);
1127 return MHD_NO; 1132 return MHD_NO;
1128 } 1133 }
1129 } 1134 }
1130 free (uri); 1135 free (uri);
1131 return (0 == strcmp (response, 1136 return (0 == strcmp (response,
1132 da->sessionkey)) 1137 da->sessionkey))
1133 ? MHD_YES 1138 ? MHD_YES
1134 : MHD_NO; 1139 : MHD_NO;
1135 } 1140 }
1136} 1141}
1137 1142
@@ -1148,17 +1153,17 @@ digest_auth_check_all (struct MHD_Connection *connection,
1148 * @param username The username needs to be authenticated 1153 * @param username The username needs to be authenticated
1149 * @param password The password used in the authentication 1154 * @param password The password used in the authentication
1150 * @param nonce_timeout The amount of time for a nonce to be 1155 * @param nonce_timeout The amount of time for a nonce to be
1151 * invalid in seconds 1156 * invalid in seconds
1152 * @return #MHD_YES if authenticated, #MHD_NO if not, 1157 * @return #MHD_YES if authenticated, #MHD_NO if not,
1153 * #MHD_INVALID_NONCE if nonce is invalid 1158 * #MHD_INVALID_NONCE if nonce is invalid
1154 * @ingroup authentication 1159 * @ingroup authentication
1155 */ 1160 */
1156_MHD_EXTERN int 1161_MHD_EXTERN int
1157MHD_digest_auth_check (struct MHD_Connection *connection, 1162MHD_digest_auth_check (struct MHD_Connection *connection,
1158 const char *realm, 1163 const char *realm,
1159 const char *username, 1164 const char *username,
1160 const char *password, 1165 const char *password,
1161 unsigned int nonce_timeout) 1166 unsigned int nonce_timeout)
1162{ 1167{
1163 return MHD_digest_auth_check2 (connection, 1168 return MHD_digest_auth_check2 (connection,
1164 realm, 1169 realm,
@@ -1189,29 +1194,29 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
1189 struct DigestAlgorithm da; \ 1194 struct DigestAlgorithm da; \
1190 \ 1195 \
1191 do { \ 1196 do { \
1192 switch (algo) { \ 1197 switch (algo) { \
1193 case MHD_DIGEST_ALG_MD5: \ 1198 case MHD_DIGEST_ALG_MD5: \
1194 da.digest_size = MD5_DIGEST_SIZE; \ 1199 da.digest_size = MD5_DIGEST_SIZE; \
1195 da.ctx = &ctx.md5; \ 1200 da.ctx = &ctx.md5; \
1196 da.alg = "md5"; \ 1201 da.alg = "md5"; \
1197 da.sessionkey = skey.md5; \ 1202 da.sessionkey = skey.md5; \
1198 da.init = &MHD_MD5Init; \ 1203 da.init = &MHD_MD5Init; \
1199 da.update = &MHD_MD5Update; \ 1204 da.update = &MHD_MD5Update; \
1200 da.digest = &MHD_MD5Final; \ 1205 da.digest = &MHD_MD5Final; \
1201 break; \ 1206 break; \
1202 case MHD_DIGEST_ALG_AUTO: \ 1207 case MHD_DIGEST_ALG_AUTO: \
1203 /* auto == SHA256, fall-though thus intentional! */ \ 1208 /* auto == SHA256, fall-though thus intentional! */ \
1204 case MHD_DIGEST_ALG_SHA256: \ 1209 case MHD_DIGEST_ALG_SHA256: \
1205 da.digest_size = SHA256_DIGEST_SIZE; \ 1210 da.digest_size = SHA256_DIGEST_SIZE; \
1206 da.ctx = &ctx.sha256; \ 1211 da.ctx = &ctx.sha256; \
1207 da.alg = "sha-256"; \ 1212 da.alg = "sha-256"; \
1208 da.sessionkey = skey.sha256; \ 1213 da.sessionkey = skey.sha256; \
1209 da.init = &MHD_SHA256_init; \ 1214 da.init = &MHD_SHA256_init; \
1210 da.update = &MHD_SHA256_update; \ 1215 da.update = &MHD_SHA256_update; \
1211 da.digest = &sha256_finish; \ 1216 da.digest = &sha256_finish; \
1212 break; \ 1217 break; \
1213 } \ 1218 } \
1214 } while(0) 1219 } while (0)
1215 1220
1216 1221
1217 1222
@@ -1223,19 +1228,19 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
1223 * @param username The username needs to be authenticated 1228 * @param username The username needs to be authenticated
1224 * @param password The password used in the authentication 1229 * @param password The password used in the authentication
1225 * @param nonce_timeout The amount of time for a nonce to be 1230 * @param nonce_timeout The amount of time for a nonce to be
1226 * invalid in seconds 1231 * invalid in seconds
1227 * @param algo digest algorithms allowed for verification 1232 * @param algo digest algorithms allowed for verification
1228 * @return #MHD_YES if authenticated, #MHD_NO if not, 1233 * @return #MHD_YES if authenticated, #MHD_NO if not,
1229 * #MHD_INVALID_NONCE if nonce is invalid 1234 * #MHD_INVALID_NONCE if nonce is invalid
1230 * @ingroup authentication 1235 * @ingroup authentication
1231 */ 1236 */
1232_MHD_EXTERN int 1237_MHD_EXTERN int
1233MHD_digest_auth_check2 (struct MHD_Connection *connection, 1238MHD_digest_auth_check2 (struct MHD_Connection *connection,
1234 const char *realm, 1239 const char *realm,
1235 const char *username, 1240 const char *username,
1236 const char *password, 1241 const char *password,
1237 unsigned int nonce_timeout, 1242 unsigned int nonce_timeout,
1238 enum MHD_DigestAuthAlgorithm algo) 1243 enum MHD_DigestAuthAlgorithm algo)
1239{ 1244{
1240 SETUP_DA (algo, da); 1245 SETUP_DA (algo, da);
1241 1246
@@ -1256,36 +1261,36 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
1256 * @param realm The realm presented to the client 1261 * @param realm The realm presented to the client
1257 * @param username The username needs to be authenticated 1262 * @param username The username needs to be authenticated
1258 * @param digest An `unsigned char *' pointer to the binary MD5 sum 1263 * @param digest An `unsigned char *' pointer to the binary MD5 sum
1259 * for the precalculated hash value "username:realm:password" 1264 * for the precalculated hash value "username:realm:password"
1260 * of #MHD_MD5_DIGEST_SIZE bytes 1265 * of #MHD_MD5_DIGEST_SIZE bytes
1261 * @param digest_size number of bytes in @a digest 1266 * @param digest_size number of bytes in @a digest
1262 * @param nonce_timeout The amount of time for a nonce to be 1267 * @param nonce_timeout The amount of time for a nonce to be
1263 * invalid in seconds 1268 * invalid in seconds
1264 * @param algo digest algorithms allowed for verification 1269 * @param algo digest algorithms allowed for verification
1265 * @return #MHD_YES if authenticated, #MHD_NO if not, 1270 * @return #MHD_YES if authenticated, #MHD_NO if not,
1266 * #MHD_INVALID_NONCE if nonce is invalid 1271 * #MHD_INVALID_NONCE if nonce is invalid
1267 * @ingroup authentication 1272 * @ingroup authentication
1268 */ 1273 */
1269_MHD_EXTERN int 1274_MHD_EXTERN int
1270MHD_digest_auth_check_digest2 (struct MHD_Connection *connection, 1275MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
1271 const char *realm, 1276 const char *realm,
1272 const char *username, 1277 const char *username,
1273 const uint8_t *digest, 1278 const uint8_t *digest,
1274 size_t digest_size, 1279 size_t digest_size,
1275 unsigned int nonce_timeout, 1280 unsigned int nonce_timeout,
1276 enum MHD_DigestAuthAlgorithm algo) 1281 enum MHD_DigestAuthAlgorithm algo)
1277{ 1282{
1278 SETUP_DA (algo, da); 1283 SETUP_DA (algo, da);
1279 1284
1280 if (da.digest_size != digest_size) 1285 if (da.digest_size != digest_size)
1281 MHD_PANIC (_("digest size missmatch")); /* API violation! */ 1286 MHD_PANIC (_ ("digest size missmatch")); /* API violation! */
1282 return digest_auth_check_all (connection, 1287 return digest_auth_check_all (connection,
1283 &da, 1288 &da,
1284 realm, 1289 realm,
1285 username, 1290 username,
1286 NULL, 1291 NULL,
1287 digest, 1292 digest,
1288 nonce_timeout); 1293 nonce_timeout);
1289} 1294}
1290 1295
1291 1296
@@ -1298,20 +1303,20 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
1298 * @param realm The realm presented to the client 1303 * @param realm The realm presented to the client
1299 * @param username The username needs to be authenticated 1304 * @param username The username needs to be authenticated
1300 * @param digest An `unsigned char *' pointer to the binary digest 1305 * @param digest An `unsigned char *' pointer to the binary digest
1301 * for the precalculated hash value "username:realm:password" 1306 * for the precalculated hash value "username:realm:password"
1302 * of @a digest_size bytes 1307 * of @a digest_size bytes
1303 * @param nonce_timeout The amount of time for a nonce to be 1308 * @param nonce_timeout The amount of time for a nonce to be
1304 * invalid in seconds 1309 * invalid in seconds
1305 * @return #MHD_YES if authenticated, #MHD_NO if not, 1310 * @return #MHD_YES if authenticated, #MHD_NO if not,
1306 * #MHD_INVALID_NONCE if nonce is invalid 1311 * #MHD_INVALID_NONCE if nonce is invalid
1307 * @ingroup authentication 1312 * @ingroup authentication
1308 */ 1313 */
1309_MHD_EXTERN int 1314_MHD_EXTERN int
1310MHD_digest_auth_check_digest (struct MHD_Connection *connection, 1315MHD_digest_auth_check_digest (struct MHD_Connection *connection,
1311 const char *realm, 1316 const char *realm,
1312 const char *username, 1317 const char *username,
1313 const uint8_t digest[MHD_MD5_DIGEST_SIZE], 1318 const uint8_t digest[MHD_MD5_DIGEST_SIZE],
1314 unsigned int nonce_timeout) 1319 unsigned int nonce_timeout)
1315{ 1320{
1316 return MHD_digest_auth_check_digest2 (connection, 1321 return MHD_digest_auth_check_digest2 (connection,
1317 realm, 1322 realm,
@@ -1333,29 +1338,29 @@ MHD_digest_auth_check_digest (struct MHD_Connection *connection,
1333 * body; note that this function will set the "WWW Authenticate" 1338 * body; note that this function will set the "WWW Authenticate"
1334 * header and that the caller should not do this 1339 * header and that the caller should not do this
1335 * @param signal_stale #MHD_YES if the nonce is invalid to add 1340 * @param signal_stale #MHD_YES if the nonce is invalid to add
1336 * 'stale=true' to the authentication header 1341 * 'stale=true' to the authentication header
1337 * @param algo digest algorithm to use 1342 * @param algo digest algorithm to use
1338 * @return #MHD_YES on success, #MHD_NO otherwise 1343 * @return #MHD_YES on success, #MHD_NO otherwise
1339 * @ingroup authentication 1344 * @ingroup authentication
1340 */ 1345 */
1341int 1346int
1342MHD_queue_auth_fail_response2 (struct MHD_Connection *connection, 1347MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1343 const char *realm, 1348 const char *realm,
1344 const char *opaque, 1349 const char *opaque,
1345 struct MHD_Response *response, 1350 struct MHD_Response *response,
1346 int signal_stale, 1351 int signal_stale,
1347 enum MHD_DigestAuthAlgorithm algo) 1352 enum MHD_DigestAuthAlgorithm algo)
1348{ 1353{
1349 int ret; 1354 int ret;
1350 int hlen; 1355 int hlen;
1351 SETUP_DA (algo, da); 1356 SETUP_DA (algo, da);
1352 1357
1353 { 1358 {
1354 char nonce[NONCE_STD_LEN(VLA_ARRAY_LEN_DIGEST (da.digest_size)) + 1]; 1359 char nonce[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (da.digest_size)) + 1];
1355 1360
1356 VLA_CHECK_LEN_DIGEST(da.digest_size); 1361 VLA_CHECK_LEN_DIGEST (da.digest_size);
1357 /* Generating the server nonce */ 1362 /* Generating the server nonce */
1358 calculate_nonce ((uint32_t) MHD_monotonic_sec_counter(), 1363 calculate_nonce ((uint32_t) MHD_monotonic_sec_counter (),
1359 connection->method, 1364 connection->method,
1360 connection->daemon->digest_auth_random, 1365 connection->daemon->digest_auth_random,
1361 connection->daemon->digest_auth_rand_size, 1366 connection->daemon->digest_auth_rand_size,
@@ -1367,13 +1372,14 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1367 check_nonce_nc (connection, 1372 check_nonce_nc (connection,
1368 nonce, 1373 nonce,
1369 0)) 1374 0))
1370 { 1375 {
1371#ifdef HAVE_MESSAGES 1376#ifdef HAVE_MESSAGES
1372 MHD_DLOG (connection->daemon, 1377 MHD_DLOG (connection->daemon,
1373 _("Could not register nonce (is the nonce array size zero?).\n")); 1378 _ (
1379 "Could not register nonce (is the nonce array size zero?).\n"));
1374#endif 1380#endif
1375 return MHD_NO; 1381 return MHD_NO;
1376 } 1382 }
1377 /* Building the authentication header */ 1383 /* Building the authentication header */
1378 hlen = MHD_snprintf_ (NULL, 1384 hlen = MHD_snprintf_ (NULL,
1379 0, 1385 0,
@@ -1386,54 +1392,54 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1386 ? ",stale=\"true\"" 1392 ? ",stale=\"true\""
1387 : ""); 1393 : "");
1388 if (hlen > 0) 1394 if (hlen > 0)
1389 { 1395 {
1390 char *header; 1396 char *header;
1391 1397
1392 header = MHD_calloc_ (1, 1398 header = MHD_calloc_ (1,
1393 hlen + 1); 1399 hlen + 1);
1394 if (NULL == header) 1400 if (NULL == header)
1395 { 1401 {
1396#ifdef HAVE_MESSAGES 1402#ifdef HAVE_MESSAGES
1397 MHD_DLOG(connection->daemon, 1403 MHD_DLOG (connection->daemon,
1398 _("Failed to allocate memory for auth response header\n")); 1404 _ ("Failed to allocate memory for auth response header\n"));
1399#endif /* HAVE_MESSAGES */ 1405#endif /* HAVE_MESSAGES */
1400 return MHD_NO; 1406 return MHD_NO;
1401 }
1402
1403 if (MHD_snprintf_ (header,
1404 hlen + 1,
1405 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
1406 realm,
1407 nonce,
1408 opaque,
1409 da.alg,
1410 signal_stale
1411 ? ",stale=\"true\""
1412 : "") == hlen)
1413 ret = MHD_add_response_header(response,
1414 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
1415 header);
1416 else
1417 ret = MHD_NO;
1418 free (header);
1419 } 1407 }
1408
1409 if (MHD_snprintf_ (header,
1410 hlen + 1,
1411 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
1412 realm,
1413 nonce,
1414 opaque,
1415 da.alg,
1416 signal_stale
1417 ? ",stale=\"true\""
1418 : "") == hlen)
1419 ret = MHD_add_response_header (response,
1420 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
1421 header);
1422 else
1423 ret = MHD_NO;
1424 free (header);
1425 }
1420 else 1426 else
1421 ret = MHD_NO; 1427 ret = MHD_NO;
1422 } 1428 }
1423 1429
1424 if (MHD_YES == ret) 1430 if (MHD_YES == ret)
1425 { 1431 {
1426 ret = MHD_queue_response (connection, 1432 ret = MHD_queue_response (connection,
1427 MHD_HTTP_UNAUTHORIZED, 1433 MHD_HTTP_UNAUTHORIZED,
1428 response); 1434 response);
1429 } 1435 }
1430 else 1436 else
1431 { 1437 {
1432#ifdef HAVE_MESSAGES 1438#ifdef HAVE_MESSAGES
1433 MHD_DLOG (connection->daemon, 1439 MHD_DLOG (connection->daemon,
1434 _("Failed to add Digest auth header\n")); 1440 _ ("Failed to add Digest auth header\n"));
1435#endif /* HAVE_MESSAGES */ 1441#endif /* HAVE_MESSAGES */
1436 } 1442 }
1437 return ret; 1443 return ret;
1438} 1444}
1439 1445
@@ -1450,16 +1456,16 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1450 * body; note that this function will set the "WWW Authenticate" 1456 * body; note that this function will set the "WWW Authenticate"
1451 * header and that the caller should not do this 1457 * header and that the caller should not do this
1452 * @param signal_stale #MHD_YES if the nonce is invalid to add 1458 * @param signal_stale #MHD_YES if the nonce is invalid to add
1453 * 'stale=true' to the authentication header 1459 * 'stale=true' to the authentication header
1454 * @return #MHD_YES on success, #MHD_NO otherwise 1460 * @return #MHD_YES on success, #MHD_NO otherwise
1455 * @ingroup authentication 1461 * @ingroup authentication
1456 */ 1462 */
1457int 1463int
1458MHD_queue_auth_fail_response (struct MHD_Connection *connection, 1464MHD_queue_auth_fail_response (struct MHD_Connection *connection,
1459 const char *realm, 1465 const char *realm,
1460 const char *opaque, 1466 const char *opaque,
1461 struct MHD_Response *response, 1467 struct MHD_Response *response,
1462 int signal_stale) 1468 int signal_stale)
1463{ 1469{
1464 return MHD_queue_auth_fail_response2 (connection, 1470 return MHD_queue_auth_fail_response2 (connection,
1465 realm, 1471 realm,