aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/digestauth.c
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-05-23 17:25:34 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-05-23 17:25:34 +0300
commitd73c6d20e301775597feea322416e475262a9558 (patch)
tree1ef14ba658a5b5f33dbd1c126fc34fc6c42b4f6b /src/microhttpd/digestauth.c
parent4a4d659bac5040c7f7538e28535b4baaa1529ba8 (diff)
downloadlibmicrohttpd-d73c6d20e301775597feea322416e475262a9558.tar.gz
libmicrohttpd-d73c6d20e301775597feea322416e475262a9558.zip
digestauth: reworked support for multiple digest algorithms
Diffstat (limited to 'src/microhttpd/digestauth.c')
-rw-r--r--src/microhttpd/digestauth.c639
1 files changed, 380 insertions, 259 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index a560f2a6..7ac5ad8b 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -175,74 +175,261 @@ enum MHD_CheckNonceNC_
175 175
176 176
177/** 177/**
178 * Context passed to functions that need to calculate 178 * Digest context data
179 * a digest but are orthogonal to the specific
180 * algorithm.
181 */ 179 */
182struct DigestAlgorithm 180union DigestCtx
183{ 181{
184 /** 182 struct MD5Context md5_ctx;
185 * Size of the final digest returned by @e digest. 183 struct Sha256Ctx sha256_ctx;
186 */ 184};
187 unsigned int digest_size; 185
186/**
187 * Digest printed as hex digits.
188 */
189union DigestHex
190{
191 char md5[MD5_DIGEST_STRING_LENGTH];
192 char sha256[SHA256_DIGEST_STRING_SIZE];
193};
194
195/**
196 * Digest in binary form.
197 */
198union DigestBin
199{
200 uint8_t md5[MD5_DIGEST_SIZE];
201 uint8_t sha256[SHA256_DIGEST_SIZE];
202};
188 203
204/**
205 * The digest calculation structure.
206 */
207struct DigestAlgorithm
208{
189 /** 209 /**
190 * A context for the digest algorithm, already initialized to be 210 * A context for the digest algorithm, already initialized to be
191 * useful for @e init, @e update and @e digest. 211 * useful for @e init, @e update and @e digest.
192 */ 212 */
193 void *ctx; 213 union DigestCtx ctx;
194 214
195 /** 215 /**
196 * Name of the algorithm, "MD5" or "SHA-256". 216 * Digest in binary form.
197 * @sa #_MHD_MD5_TOKEN, #_MHD_SHA256_TOKEN
198 */ 217 */
199 const char *alg; 218 union DigestBin digest;
200
201 /** 219 /**
202 * Buffer of @e digest_size * 2 + 1 bytes. 220 * The digest algorithm.
203 */ 221 */
204 char *sessionkey; 222 enum MHD_DigestAuthAlgorithm algo;
205 223
206 /** 224 /**
207 * Call to initialize @e ctx. 225 * Buffer for hex-print of the final digest.
208 */ 226 */
209 void 227 union DigestHex digest_hex;
210 (*init)(void *ctx); 228#if _DEBUG
229 bool setup; /**< The structure was set-up */
230 bool inited; /**< The calculation was initialised */
231 bool digest_calculated; /**< The digest was calculated */
232#endif /* _DEBUG */
233};
211 234
212 /**
213 * Feed more data into the digest function.
214 *
215 * @param ctx context to feed
216 * @param length number of bytes in @a data
217 * @param data data to add
218 */
219 void
220 (*update)(void *ctx,
221 const uint8_t *data,
222 size_t length);
223 235
224 /** 236/**
225 * Compute final @a digest. 237 * Return name of the algorithm as a string.
226 * 238 * @param da the digest calculation structure to identify
227 * @param ctx context to use 239 * @return the name of the @a algo as a string.
228 * @param[out] digest where to write the result, 240 */
229 * must be @e digest_length bytes long 241_MHD_static_inline const char *
230 */ 242digest_get_algo_name (struct DigestAlgorithm *da)
231 void 243{
232 (*digest)(void *ctx, 244 mhd_assert (da->setup);
233 uint8_t *digest); 245 if (MHD_DIGEST_ALG_MD5 == da->algo)
234}; 246 return _MHD_MD5_TOKEN;
247 if (MHD_DIGEST_ALG_SHA256 == da->algo)
248 return _MHD_SHA256_TOKEN;
249 mhd_assert (0); /* May not happen */
250 return "";
251}
252
253
254/**
255 * Return the size of the digest.
256 * @param da the digest calculation structure to identify
257 * @return the size of the digest.
258 */
259_MHD_static_inline unsigned int
260digest_get_size (struct DigestAlgorithm *da)
261{
262 mhd_assert (da->setup);
263 if (MHD_DIGEST_ALG_MD5 == da->algo)
264 return MD5_DIGEST_SIZE;
265 if (MHD_DIGEST_ALG_SHA256 == da->algo)
266 return SHA256_DIGEST_SIZE;
267 mhd_assert (0); /* May not happen */
268 return 0;
269}
270
271
272/**
273 * Set-up the digest calculation structure.
274 * @param da the structure to set-up
275 * @param algo the algorithm to use for digest calculation
276 * @return boolean 'true' if successfully set-up,
277 * false otherwise.
278 */
279_MHD_static_inline bool
280digest_setup (struct DigestAlgorithm *da,
281 enum MHD_DigestAuthAlgorithm algo)
282{
283#ifdef _DEBUG
284 da->setup = false;
285 da->inited = false;
286 da->digest_calculated = false;
287#endif /* _DEBUG */
288 if (MHD_DIGEST_ALG_AUTO == algo)
289 algo = MHD_DIGEST_ALG_SHA256;
290
291 if ((MHD_DIGEST_ALG_MD5 == algo) ||
292 (MHD_DIGEST_ALG_SHA256 == algo))
293 {
294 da->algo = algo;
295#ifdef _DEBUG
296 da->setup = true;
297#endif /* _DEBUG */
298 return true;
299 }
300 mhd_assert (0); /* Bad parameter */
301 return false;
302}
303
304
305/**
306 * Initialise/reset the digest calculation structure.
307 * @param da the structure to initialise/reset
308 */
309_MHD_static_inline void
310digest_init (struct DigestAlgorithm *da)
311{
312 mhd_assert (da->setup);
313#ifdef _DEBUG
314 da->digest_calculated = false;
315#endif
316 if (MHD_DIGEST_ALG_MD5 == da->algo)
317 {
318 MHD_MD5Init (&da->ctx.md5_ctx);
319#ifdef _DEBUG
320 da->inited = true;
321#endif
322 }
323 else if (MHD_DIGEST_ALG_SHA256 == da->algo)
324 {
325 MHD_SHA256_init (&da->ctx.sha256_ctx);
326#ifdef _DEBUG
327 da->inited = true;
328#endif
329 }
330 else
331 {
332#ifdef _DEBUG
333 da->inited = false;
334#endif
335 mhd_assert (0); /* Bad algorithm */
336 }
337}
338
339
340/**
341 * Feed digest calculation with more data.
342 * @param da the digest calculation
343 * @param data the data to process
344 * @param length the size of the @a data in bytes
345 */
346_MHD_static_inline void
347digest_update (struct DigestAlgorithm *da,
348 const uint8_t *data,
349 size_t length)
350{
351 mhd_assert (da->inited);
352 mhd_assert (! da->digest_calculated);
353 if (MHD_DIGEST_ALG_MD5 == da->algo)
354 MHD_MD5Update (&da->ctx.md5_ctx, data, length);
355 else if (MHD_DIGEST_ALG_SHA256 == da->algo)
356 MHD_SHA256_update (&da->ctx.sha256_ctx, data, length);
357 else
358 mhd_assert (0); /* May not happen */
359}
360
361
362/**
363 * Finally calculate hash (the digest).
364 * @param da the digest calculation
365 */
366_MHD_static_inline void
367digest_calc_hash (struct DigestAlgorithm *da)
368{
369 mhd_assert (da->inited);
370 mhd_assert (! da->digest_calculated);
371 if (MHD_DIGEST_ALG_MD5 == da->algo)
372 MHD_MD5Final (&da->ctx.md5_ctx, da->digest.md5);
373 else if (MHD_DIGEST_ALG_SHA256 == da->algo)
374 MHD_SHA256_finish (&da->ctx.sha256_ctx, da->digest.sha256);
375 else
376 mhd_assert (0); /* May not happen */
377#ifdef _DEBUG
378 da->digest_calculated = true;
379#endif
380}
381
382
383/**
384 * Get pointer to the calculated digest in binary form.
385 * @param da the digest calculation
386 * @return the pointer to the calculated digest
387 */
388_MHD_static_inline const uint8_t *
389digest_get_bin (struct DigestAlgorithm *da)
390{
391 mhd_assert (da->inited);
392 mhd_assert (da->digest_calculated);
393 mhd_assert (da->digest.md5 == da->digest.sha256);
394 return da->digest.sha256;
395}
396
397
398/**
399 * Get pointer to the buffer for the printed digest.
400 * @param da the digest calculation
401 * @return the pointer to the buffer
402 */
403_MHD_static_inline char *
404digest_get_hex_buffer (struct DigestAlgorithm *da)
405{
406 return da->digest_hex.sha256;
407}
408
409
410/**
411 * Put calculated digest to the buffer as hex digits.
412 * @param da the digest calculation
413 * @return the pointer to the calculated digest
414 */
415_MHD_static_inline void
416digest_make_hex (struct DigestAlgorithm *da)
417{
418 MHD_bin_to_hex (digest_get_bin (da),
419 digest_get_size (da),
420 digest_get_hex_buffer (da));
421}
235 422
236 423
237/** 424/**
238 * calculate H(A1) from given hash as per RFC2617 spec 425 * calculate H(A1) from given hash as per RFC2617 spec
239 * and store the * result in 'sessionkey'. 426 * and store the result in 'digest_hex'.
240 * 427 *
241 * @param alg The hash algorithm used, can be "MD5" or "MD5-sess" 428 * @param alg The hash algorithm used, can be "MD5" or "MD5-sess"
242 * or "SHA-256" or "SHA-256-sess" 429 * or "SHA-256" or "SHA-256-sess"
243 * Note that the rest of the code does not support the the "-sess" variants! 430 * Note that the rest of the code does not support the the "-sess" variants!
244 * @param[in,out] da digest implementation, must match @a alg; the 431 * @param[in,out] da digest implementation, must match @a alg; the
245 * da->sessionkey will be initialized to the digest in HEX 432 * da->digest_hex will be initialized to the digest in HEX
246 * @param digest An `unsigned char *' pointer to the binary MD5 sum 433 * @param digest An `unsigned char *' pointer to the binary MD5 sum
247 * for the precalculated hash value "username:realm:password" 434 * for the precalculated hash value "username:realm:password"
248 * of #MHD_MD5_DIGEST_SIZE or #SHA256_DIGEST_SIZE bytes 435 * of #MHD_MD5_DIGEST_SIZE or #SHA256_DIGEST_SIZE bytes
@@ -256,49 +443,43 @@ digest_calc_ha1_from_digest (const char *alg,
256 const char *nonce, 443 const char *nonce,
257 const char *cnonce) 444 const char *cnonce)
258{ 445{
259 const unsigned int digest_size = da->digest_size; 446 /* TODO: disable unsupported code paths */
260 if ( (MHD_str_equal_caseless_ (alg, 447 if ( (MHD_str_equal_caseless_ (alg,
261 _MHD_MD5_TOKEN _MHD_SESS_TOKEN)) || 448 _MHD_MD5_TOKEN _MHD_SESS_TOKEN)) ||
262 (MHD_str_equal_caseless_ (alg, 449 (MHD_str_equal_caseless_ (alg,
263 _MHD_SHA256_TOKEN _MHD_SESS_TOKEN)) ) 450 _MHD_SHA256_TOKEN _MHD_SESS_TOKEN)) )
264 { 451 {
265 uint8_t dig[VLA_ARRAY_LEN_DIGEST (digest_size)]; 452 digest_init (da);
266 453 digest_update (da,
267 VLA_CHECK_LEN_DIGEST (digest_size); 454 digest,
268 da->init (da->ctx); 455 digest_get_size (da));
269 da->update (da->ctx, 456 digest_update (da,
270 digest, 457 (const unsigned char *) ":",
271 MHD_MD5_DIGEST_SIZE); 458 1);
272 da->update (da->ctx, 459 digest_update (da,
273 (const unsigned char *) ":", 460 (const unsigned char *) nonce,
274 1); 461 strlen (nonce));
275 da->update (da->ctx, 462 digest_update (da,
276 (const unsigned char *) nonce, 463 (const unsigned char *) ":",
277 strlen (nonce)); 464 1);
278 da->update (da->ctx, 465 digest_update (da,
279 (const unsigned char *) ":", 466 (const unsigned char *) cnonce,
280 1); 467 strlen (cnonce));
281 da->update (da->ctx, 468 digest_calc_hash (da);
282 (const unsigned char *) cnonce, 469 digest_make_hex (da);
283 strlen (cnonce));
284 da->digest (da->ctx,
285 dig);
286 MHD_bin_to_hex (dig,
287 digest_size,
288 da->sessionkey);
289 } 470 }
290 else 471 else
291 { 472 {
292 MHD_bin_to_hex (digest, 473 MHD_bin_to_hex (digest,
293 digest_size, 474 digest_get_size (da),
294 da->sessionkey); 475 digest_get_hex_buffer (da));
295 } 476 }
296} 477}
297 478
298 479
299/** 480/**
300 * calculate H(A1) from username, realm and password as per RFC2617 spec 481 * calculate H(A1) from username, realm and password as per RFC2617 spec
301 * and store the result in 'sessionkey'. 482 * and store the result in 'digest_hex'.
302 * 483 *
303 * @param alg The hash algorithm used, can be "MD5" or "MD5-sess" 484 * @param alg The hash algorithm used, can be "MD5" or "MD5-sess"
304 * or "SHA-256" or "SHA-256-sess" 485 * or "SHA-256" or "SHA-256-sess"
@@ -319,30 +500,26 @@ digest_calc_ha1_from_user (const char *alg,
319 const char *cnonce, 500 const char *cnonce,
320 struct DigestAlgorithm *da) 501 struct DigestAlgorithm *da)
321{ 502{
322 unsigned char ha1[VLA_ARRAY_LEN_DIGEST (da->digest_size)]; 503 digest_init (da);
323 504 digest_update (da,
324 VLA_CHECK_LEN_DIGEST (da->digest_size); 505 (const unsigned char *) username,
325 da->init (da->ctx); 506 strlen (username));
326 da->update (da->ctx, 507 digest_update (da,
327 (const unsigned char *) username, 508 (const unsigned char *) ":",
328 strlen (username)); 509 1);
329 da->update (da->ctx, 510 digest_update (da,
330 (const unsigned char *) ":", 511 (const unsigned char *) realm,
331 1); 512 strlen (realm));
332 da->update (da->ctx, 513 digest_update (da,
333 (const unsigned char *) realm, 514 (const unsigned char *) ":",
334 strlen (realm)); 515 1);
335 da->update (da->ctx, 516 digest_update (da,
336 (const unsigned char *) ":", 517 (const unsigned char *) password,
337 1); 518 strlen (password));
338 da->update (da->ctx, 519 digest_calc_hash (da);
339 (const unsigned char *) password,
340 strlen (password));
341 da->digest (da->ctx,
342 ha1);
343 digest_calc_ha1_from_digest (alg, 520 digest_calc_ha1_from_digest (alg,
344 da, 521 da,
345 ha1, 522 digest_get_bin (da),
346 nonce, 523 nonce,
347 cnonce); 524 cnonce);
348} 525}
@@ -375,85 +552,78 @@ digest_calc_response (const char *ha1,
375 const char *hentity, 552 const char *hentity,
376 struct DigestAlgorithm *da) 553 struct DigestAlgorithm *da)
377{ 554{
378 const unsigned int digest_size = da->digest_size;
379 unsigned char ha2[VLA_ARRAY_LEN_DIGEST (digest_size)];
380 unsigned char resphash[VLA_ARRAY_LEN_DIGEST (digest_size)];
381 (void) hentity; /* Unused. Silence compiler warning. */ 555 (void) hentity; /* Unused. Silence compiler warning. */
382 556
383 VLA_CHECK_LEN_DIGEST (digest_size); 557 /* Calculate h(a2) */
384 da->init (da->ctx); 558 digest_init (da);
385 da->update (da->ctx, 559 digest_update (da,
386 (const unsigned char *) method, 560 (const unsigned char *) method,
387 strlen (method)); 561 strlen (method));
388 da->update (da->ctx, 562 digest_update (da,
389 (const unsigned char *) ":", 563 (const unsigned char *) ":",
390 1); 564 1);
391 da->update (da->ctx, 565 digest_update (da,
392 (const unsigned char *) uri, 566 (const unsigned char *) uri,
393 strlen (uri)); 567 strlen (uri));
394#if 0 568#if 0
395 if (0 == strcasecmp (qop, 569 if (0 == strcasecmp (qop,
396 "auth-int")) 570 "auth-int"))
397 { 571 {
398 /* This is dead code since the rest of this module does 572 /* This is dead code since the rest of this module does
399 not support auth-int. */ 573 not support auth-int. */
400 da->update (da->ctx, 574 digest_update (da,
401 ":", 575 ":",
402 1); 576 1);
403 if (NULL != hentity) 577 if (NULL != hentity)
404 da->update (da->ctx, 578 da->update (da->ctx,
405 hentity, 579 hentity,
406 strlen (hentity)); 580 strlen (hentity));
407 } 581 }
408#endif 582#endif
409 da->digest (da->ctx, 583 digest_calc_hash (da);
410 ha2); 584 digest_make_hex (da);
411 MHD_bin_to_hex (ha2, 585
412 digest_size,
413 da->sessionkey);
414 da->init (da->ctx);
415 /* calculate response */ 586 /* calculate response */
416 da->update (da->ctx, 587 digest_init (da);
417 (const unsigned char *) ha1, 588 digest_update (da,
418 digest_size * 2); 589 (const unsigned char *) ha1,
419 da->update (da->ctx, 590 digest_get_size (da) * 2);
420 (const unsigned char *) ":", 591 digest_update (da,
421 1); 592 (const unsigned char *) ":",
422 da->update (da->ctx, 593 1);
423 (const unsigned char *) nonce, 594 digest_update (da,
424 strlen (nonce)); 595 (const unsigned char *) nonce,
425 da->update (da->ctx, 596 strlen (nonce));
426 (const unsigned char *) ":", 597 digest_update (da,
427 1); 598 (const unsigned char *) ":",
599 1);
428 if ('\0' != *qop) 600 if ('\0' != *qop)
429 { 601 {
430 da->update (da->ctx, 602 digest_update (da,
431 (const unsigned char *) noncecount, 603 (const unsigned char *) noncecount,
432 strlen (noncecount)); 604 strlen (noncecount));
433 da->update (da->ctx, 605 digest_update (da,
434 (const unsigned char *) ":", 606 (const unsigned char *) ":",
435 1); 607 1);
436 da->update (da->ctx, 608 digest_update (da,
437 (const unsigned char *) cnonce, 609 (const unsigned char *) cnonce,
438 strlen (cnonce)); 610 strlen (cnonce));
439 da->update (da->ctx, 611 digest_update (da,
440 (const unsigned char *) ":", 612 (const unsigned char *) ":",
441 1); 613 1);
442 da->update (da->ctx, 614 digest_update (da,
443 (const unsigned char *) qop, 615 (const unsigned char *) qop,
444 strlen (qop)); 616 strlen (qop));
445 da->update (da->ctx, 617 digest_update (da,
446 (const unsigned char *) ":", 618 (const unsigned char *) ":",
447 1); 619 1);
448 } 620 }
449 da->update (da->ctx, 621 digest_update (da,
450 (const unsigned char *) da->sessionkey, 622 (const unsigned char *) digest_get_hex_buffer (da),
451 digest_size * 2); 623 digest_get_size (da) * 2);
452 da->digest (da->ctx, 624
453 resphash); 625 digest_calc_hash (da);
454 MHD_bin_to_hex (resphash, 626 digest_make_hex (da);
455 digest_size,
456 da->sessionkey);
457} 627}
458 628
459 629
@@ -828,13 +998,8 @@ calculate_nonce (uint64_t nonce_time,
828 char *nonce) 998 char *nonce)
829{ 999{
830 uint8_t timestamp[TIMESTAMP_BIN_SIZE]; 1000 uint8_t timestamp[TIMESTAMP_BIN_SIZE];
831 const unsigned int digest_size = da->digest_size;
832 char tmpnonce[VLA_ARRAY_LEN_DIGEST (digest_size)];
833 1001
834 mhd_assert (0 == (digest_size % 2)); 1002 digest_init (da);
835 mhd_assert (0 != digest_size);
836 VLA_CHECK_LEN_DIGEST (digest_size);
837 da->init (da->ctx);
838 /* If the nonce_time is milliseconds, then the same 48 bit value will repeat 1003 /* If the nonce_time is milliseconds, then the same 48 bit value will repeat
839 * every 8 925 years, which is more than enough to mitigate a replay attack */ 1004 * every 8 925 years, which is more than enough to mitigate a replay attack */
840#if TIMESTAMP_BIN_SIZE != 6 1005#if TIMESTAMP_BIN_SIZE != 6
@@ -846,42 +1011,41 @@ calculate_nonce (uint64_t nonce_time,
846 timestamp[3] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 3))); 1011 timestamp[3] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 3)));
847 timestamp[4] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 4))); 1012 timestamp[4] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 4)));
848 timestamp[5] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 5))); 1013 timestamp[5] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 5)));
849 da->update (da->ctx, 1014 digest_update (da,
850 timestamp, 1015 timestamp,
851 sizeof (timestamp)); 1016 sizeof (timestamp));
852 da->update (da->ctx, 1017 digest_update (da,
853 (const unsigned char *) ":", 1018 (const unsigned char *) ":",
854 1); 1019 1);
855 da->update (da->ctx, 1020 digest_update (da,
856 (const unsigned char *) method, 1021 (const unsigned char *) method,
857 strlen (method)); 1022 strlen (method));
858 da->update (da->ctx, 1023 digest_update (da,
859 (const unsigned char *) ":", 1024 (const unsigned char *) ":",
860 1); 1025 1);
861 if (rnd_size > 0) 1026 if (rnd_size > 0)
862 da->update (da->ctx, 1027 digest_update (da,
863 (const unsigned char *) rnd, 1028 (const unsigned char *) rnd,
864 rnd_size); 1029 rnd_size);
865 da->update (da->ctx, 1030 digest_update (da,
866 (const unsigned char *) ":", 1031 (const unsigned char *) ":",
867 1); 1032 1);
868 da->update (da->ctx, 1033 digest_update (da,
869 (const unsigned char *) uri, 1034 (const unsigned char *) uri,
870 strlen (uri)); 1035 strlen (uri));
871 da->update (da->ctx, 1036 digest_update (da,
872 (const unsigned char *) ":", 1037 (const unsigned char *) ":",
873 1); 1038 1);
874 da->update (da->ctx, 1039 digest_update (da,
875 (const unsigned char *) realm, 1040 (const unsigned char *) realm,
876 strlen (realm)); 1041 strlen (realm));
877 da->digest (da->ctx, 1042 digest_calc_hash (da);
878 (uint8_t *) tmpnonce); 1043 MHD_bin_to_hex (digest_get_bin (da),
879 MHD_bin_to_hex (tmpnonce, 1044 digest_get_size (da),
880 digest_size,
881 nonce); 1045 nonce);
882 MHD_bin_to_hex (timestamp, 1046 MHD_bin_to_hex (timestamp,
883 sizeof (timestamp), 1047 sizeof (timestamp),
884 nonce + digest_size * 2); 1048 nonce + digest_get_size (da) * 2);
885} 1049}
886 1050
887 1051
@@ -965,7 +1129,7 @@ calculate_add_nonce (struct MHD_Connection *const connection,
965{ 1129{
966 struct MHD_Daemon *const daemon = MHD_get_master (connection->daemon); 1130 struct MHD_Daemon *const daemon = MHD_get_master (connection->daemon);
967 struct MHD_NonceNc *nn; 1131 struct MHD_NonceNc *nn;
968 const size_t nonce_size = NONCE_STD_LEN (da->digest_size); 1132 const size_t nonce_size = NONCE_STD_LEN (digest_get_size (da));
969 bool ret; 1133 bool ret;
970 1134
971 mhd_assert (MAX_NONCE_LENGTH >= nonce_size); 1135 mhd_assert (MAX_NONCE_LENGTH >= nonce_size);
@@ -1033,7 +1197,7 @@ calculate_add_nonce_with_retry (struct MHD_Connection *const connection,
1033 * 2. Another nonce uses the same slot, and this nonce never has been 1197 * 2. Another nonce uses the same slot, and this nonce never has been
1034 * used by the client and this nonce is still fresh enough. 1198 * used by the client and this nonce is still fresh enough.
1035 */ 1199 */
1036 const size_t digest_size = da->digest_size; 1200 const size_t digest_size = digest_get_size (da);
1037 char nonce2[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (digest_size)) + 1]; 1201 char nonce2[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (digest_size)) + 1];
1038 uint64_t timestamp2; 1202 uint64_t timestamp2;
1039 if (0 == MHD_get_master (connection->daemon)->nonce_nc_size) 1203 if (0 == MHD_get_master (connection->daemon)->nonce_nc_size)
@@ -1216,7 +1380,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1216 char nonce[MAX_NONCE_LENGTH]; 1380 char nonce[MAX_NONCE_LENGTH];
1217 size_t nonce_len; 1381 size_t nonce_len;
1218 char cnonce[MAX_NONCE_LENGTH]; 1382 char cnonce[MAX_NONCE_LENGTH];
1219 const unsigned int digest_size = da->digest_size; 1383 const unsigned int digest_size = digest_get_size (da);
1220 char ha1[VLA_ARRAY_LEN_DIGEST (digest_size) * 2 + 1]; 1384 char ha1[VLA_ARRAY_LEN_DIGEST (digest_size) * 2 + 1];
1221 char qop[15]; /* auth,auth-int */ 1385 char qop[15]; /* auth,auth-int */
1222 char nc[20]; 1386 char nc[20];
@@ -1441,8 +1605,8 @@ digest_auth_check_all (struct MHD_Connection *connection,
1441 } 1605 }
1442 if (NULL != digest) 1606 if (NULL != digest)
1443 { 1607 {
1444 /* This will initialize da->sessionkey (ha1) */ 1608 /* This will initialize da->digest_hex (ha1) */
1445 digest_calc_ha1_from_digest (da->alg, 1609 digest_calc_ha1_from_digest (digest_get_algo_name (da),
1446 da, 1610 da,
1447 digest, 1611 digest,
1448 nonce, 1612 nonce,
@@ -1450,9 +1614,9 @@ digest_auth_check_all (struct MHD_Connection *connection,
1450 } 1614 }
1451 else 1615 else
1452 { 1616 {
1453 /* This will initialize da->sessionkey (ha1) */ 1617 /* This will initialize da->digest_hex (ha1) */
1454 mhd_assert (NULL != password); /* NULL == digest => password != NULL */ 1618 mhd_assert (NULL != password); /* NULL == digest => password != NULL */
1455 digest_calc_ha1_from_user (da->alg, 1619 digest_calc_ha1_from_user (digest_get_algo_name (da),
1456 username, 1620 username,
1457 realm, 1621 realm,
1458 password, 1622 password,
@@ -1461,7 +1625,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1461 da); 1625 da);
1462 } 1626 }
1463 memcpy (ha1, 1627 memcpy (ha1,
1464 da->sessionkey, 1628 digest_get_hex_buffer (da),
1465 digest_size * 2 + 1); 1629 digest_size * 2 + 1);
1466 /* This will initialize da->sessionkey (respexp) */ 1630 /* This will initialize da->sessionkey (respexp) */
1467 digest_calc_response (ha1, 1631 digest_calc_response (ha1,
@@ -1516,7 +1680,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1516 free (uri); 1680 free (uri);
1517 } 1681 }
1518 return (0 == strcmp (response, 1682 return (0 == strcmp (response,
1519 da->sessionkey)) 1683 digest_get_hex_buffer (da)))
1520 ? MHD_DAUTH_OK 1684 ? MHD_DAUTH_OK
1521 : MHD_DAUTH_RESPONSE_WRONG; 1685 : MHD_DAUTH_RESPONSE_WRONG;
1522} 1686}
@@ -1557,55 +1721,6 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
1557 1721
1558 1722
1559/** 1723/**
1560 * Setup digest authentication data structures (on the
1561 * stack, hence must be done inline!). Initializes a
1562 * "struct DigestAlgorithm da" for algorithm @a algo.
1563 *
1564 * @param algo digest algorithm to provide
1565 * @param da data structure to setup
1566 */
1567#define SETUP_DA(algo,da) \
1568 union { \
1569 struct MD5Context md5; \
1570 struct sha256_ctx sha256; \
1571 } ctx; \
1572 union { \
1573 char md5[MD5_DIGEST_SIZE * 2 + 1]; \
1574 char sha256[SHA256_DIGEST_SIZE * 2 + 1]; \
1575 } skey; \
1576 struct DigestAlgorithm da; \
1577 \
1578 do { \
1579 switch (algo) { \
1580 case MHD_DIGEST_ALG_MD5: \
1581 da.digest_size = MD5_DIGEST_SIZE; \
1582 da.ctx = &ctx.md5; \
1583 da.alg = _MHD_MD5_TOKEN; \
1584 da.sessionkey = skey.md5; \
1585 da.init = &MHD_MD5Init; \
1586 da.update = &MHD_MD5Update; \
1587 da.digest = &MHD_MD5Final; \
1588 break; \
1589 case MHD_DIGEST_ALG_AUTO: \
1590 /* auto == SHA256, fall-though thus intentional! */ \
1591 case MHD_DIGEST_ALG_SHA256: \
1592 da.digest_size = SHA256_DIGEST_SIZE; \
1593 da.ctx = &ctx.sha256; \
1594 da.alg = _MHD_SHA256_TOKEN; \
1595 da.sessionkey = skey.sha256; \
1596 da.init = &MHD_SHA256_init; \
1597 da.update = &MHD_SHA256_update; \
1598 da.digest = &MHD_SHA256_finish; \
1599 break; \
1600 default: \
1601 da.digest_size = 0; \
1602 mhd_assert (false); \
1603 break; \
1604 } \
1605 } while (0)
1606
1607
1608/**
1609 * Authenticates the authorization header sent by the client. 1724 * Authenticates the authorization header sent by the client.
1610 * 1725 *
1611 * @param connection the MHD connection structure 1726 * @param connection the MHD connection structure
@@ -1627,10 +1742,11 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
1627 unsigned int nonce_timeout, 1742 unsigned int nonce_timeout,
1628 enum MHD_DigestAuthAlgorithm algo) 1743 enum MHD_DigestAuthAlgorithm algo)
1629{ 1744{
1630 SETUP_DA (algo, da); 1745 struct DigestAlgorithm da;
1631 1746
1632 mhd_assert (NULL != password); 1747 mhd_assert (NULL != password);
1633 if (0 == da.digest_size) 1748
1749 if (! digest_setup (&da, algo))
1634 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */ 1750 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
1635 1751
1636 return digest_auth_check_all (connection, 1752 return digest_auth_check_all (connection,
@@ -1669,10 +1785,13 @@ MHD_digest_auth_check_digest3 (struct MHD_Connection *connection,
1669 unsigned int nonce_timeout, 1785 unsigned int nonce_timeout,
1670 enum MHD_DigestAuthAlgorithm algo) 1786 enum MHD_DigestAuthAlgorithm algo)
1671{ 1787{
1672 SETUP_DA (algo, da); 1788 struct DigestAlgorithm da;
1673 1789
1674 mhd_assert (NULL != digest); 1790 mhd_assert (NULL != digest);
1675 if ((da.digest_size != digest_size) || (0 == digest_size)) 1791 if (! digest_setup (&da, algo))
1792 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
1793
1794 if (digest_get_size (&da) != digest_size)
1676 MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */ 1795 MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */
1677 1796
1678 return digest_auth_check_all (connection, 1797 return digest_auth_check_all (connection,
@@ -1832,9 +1951,10 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1832{ 1951{
1833 int ret; 1952 int ret;
1834 int hlen; 1953 int hlen;
1835 SETUP_DA (algo, da);
1836 1954
1837 if (0 == da.digest_size) 1955 struct DigestAlgorithm da;
1956
1957 if (! digest_setup (&da, algo))
1838 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */ 1958 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
1839 1959
1840 if (NULL == response) 1960 if (NULL == response)
@@ -1851,9 +1971,10 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1851 1971
1852 if (1) 1972 if (1)
1853 { 1973 {
1854 char nonce[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (da.digest_size)) + 1]; 1974 char nonce[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (digest_get_size (&da)))
1975 + 1];
1855 1976
1856 VLA_CHECK_LEN_DIGEST (da.digest_size); 1977 VLA_CHECK_LEN_DIGEST (digest_get_size (&da));
1857 if (! calculate_add_nonce_with_retry (connection, realm, &da, nonce)) 1978 if (! calculate_add_nonce_with_retry (connection, realm, &da, nonce))
1858 { 1979 {
1859#ifdef HAVE_MESSAGES 1980#ifdef HAVE_MESSAGES
@@ -1872,7 +1993,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1872 realm, 1993 realm,
1873 nonce, 1994 nonce,
1874 opaque, 1995 opaque,
1875 da.alg, 1996 digest_get_algo_name (&da),
1876 signal_stale 1997 signal_stale
1877 ? ",stale=\"true\"" 1998 ? ",stale=\"true\""
1878 : ""); 1999 : "");
@@ -1897,7 +2018,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1897 realm, 2018 realm,
1898 nonce, 2019 nonce,
1899 opaque, 2020 opaque,
1900 da.alg, 2021 digest_get_algo_name (&da),
1901 signal_stale 2022 signal_stale
1902 ? ",stale=\"true\"" 2023 ? ",stale=\"true\""
1903 : "") == hlen) 2024 : "") == hlen)