aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-09-11 18:39:46 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-09-11 18:42:18 +0300
commit8318f56ebc0085f1319f29862b74b65304894afe (patch)
treef33a4c735f372bc36234f13a12e6c80cc9349ec8
parent9fa5a3b990f93b94557bc2f52aaff8db241702a7 (diff)
downloadlibmicrohttpd-8318f56ebc0085f1319f29862b74b65304894afe.tar.gz
libmicrohttpd-8318f56ebc0085f1319f29862b74b65304894afe.zip
digestauth: added support for SHA-512/256, made MD5 and SHA-256 optional
Give more flexibility for custom builds: MD5, SHA-256 and SHA-512/256 may be disabled individually.
-rw-r--r--configure.ac72
-rw-r--r--src/include/microhttpd.h47
-rw-r--r--src/microhttpd/Makefile.am20
-rw-r--r--src/microhttpd/daemon.c8
-rw-r--r--src/microhttpd/digestauth.c333
-rw-r--r--src/microhttpd/gen_auth.c30
-rw-r--r--src/microhttpd/internal.h10
-rw-r--r--src/microhttpd/test_dauth_userdigest.c201
-rw-r--r--src/microhttpd/test_dauth_userhash.c233
-rw-r--r--src/testcurl/Makefile.am24
10 files changed, 878 insertions, 100 deletions
diff --git a/configure.ac b/configure.ac
index b8de0798..31ae78ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3082,9 +3082,63 @@ AS_VAR_IF([[enable_cookie]],[["yes"]],
3082AM_CONDITIONAL([ENABLE_COOKIE], [[test "x$enable_cookie" = "xyes"]]) 3082AM_CONDITIONAL([ENABLE_COOKIE], [[test "x$enable_cookie" = "xyes"]])
3083AC_MSG_RESULT([[$enable_cookie]]) 3083AC_MSG_RESULT([[$enable_cookie]])
3084 3084
3085# optional: MD5 support for Digest Auth. Enabled by default.
3086AC_ARG_ENABLE([[md5]],
3087 [AS_HELP_STRING([[--disable-md5]],[disable MD5 hashing support for Digest Authentication])
3088 ],
3089 [
3090 AS_VAR_IF([[enable_md5]],[["yes"]],
3091 [
3092 AS_VAR_IF([enable_dauth],["yes"],[],
3093 [
3094 AC_MSG_WARN([The parameter --enable-md5 is ignored as Digest Authentication is disabled])
3095 enable_md5='no'
3096 ]
3097 )
3098 ],[[enable_md5='no']]
3099 )
3100 ], [[enable_md5="${enable_dauth}"]]
3101)
3102AC_MSG_CHECKING([[whether to support MD5]])
3103AS_VAR_IF([[enable_md5]],[["yes"]],
3104 [
3105 AC_DEFINE([[MHD_MD5_SUPPORT]],[[1]],
3106 [Define to 1 if libmicrohttpd is compiled with MD5 hashing support.])
3107 ]
3108)
3109AM_CONDITIONAL([ENABLE_MD5], [[test "x${enable_md5}" = "xyes"]])
3110AC_MSG_RESULT([[${enable_md5}]])
3111
3112# optional: SHA-256 support for Digest Auth. Enabled by default.
3113AC_ARG_ENABLE([[sha256]],
3114 [AS_HELP_STRING([[--disable-sha256]],[disable SHA-256 hashing support for Digest Authentication])
3115 ],
3116 [
3117 AS_VAR_IF([[enable_sha256]],[["yes"]],
3118 [
3119 AS_VAR_IF([enable_dauth],["yes"],[],
3120 [
3121 AC_MSG_WARN([The parameter --enable-sha256 is ignored as Digest Authentication is disabled])
3122 enable_sha256='no'
3123 ]
3124 )
3125 ],[[enable_sha256='no']]
3126 )
3127 ], [[enable_sha256="${enable_dauth}"]]
3128)
3129AC_MSG_CHECKING([[whether to support SHA-256]])
3130AS_VAR_IF([[enable_sha256]],[["yes"]],
3131 [
3132 AC_DEFINE([[MHD_SHA256_SUPPORT]],[[1]],
3133 [Define to 1 if libmicrohttpd is compiled with SHA-256 hashing support.])
3134 ]
3135)
3136AM_CONDITIONAL([ENABLE_SHA256], [[test "x${enable_sha256}" = "xyes"]])
3137AC_MSG_RESULT([[${enable_sha256}]])
3138
3085# optional: SHA-512/256 support for Digest Auth. Enabled by default. 3139# optional: SHA-512/256 support for Digest Auth. Enabled by default.
3086AC_ARG_ENABLE([[sha512-256]], 3140AC_ARG_ENABLE([[sha512-256]],
3087 [AS_HELP_STRING([[--disable-sha512-256]],[disable SHA-512/256 support for Digest Authentication]) 3141 [AS_HELP_STRING([[--disable-sha512-256]],[disable SHA-512/256 hashing support for Digest Authentication])
3088 ], 3142 ],
3089 [ 3143 [
3090 AS_VAR_IF([[enable_sha512_256]],[["yes"]], 3144 AS_VAR_IF([[enable_sha512_256]],[["yes"]],
@@ -3102,13 +3156,21 @@ AC_ARG_ENABLE([[sha512-256]],
3102AC_MSG_CHECKING([[whether to support SHA-512/256]]) 3156AC_MSG_CHECKING([[whether to support SHA-512/256]])
3103AS_VAR_IF([[enable_sha512_256]],[["yes"]], 3157AS_VAR_IF([[enable_sha512_256]],[["yes"]],
3104 [ 3158 [
3105 AC_DEFINE([[SHA512_256_SUPPORT]],[[1]], 3159 AC_DEFINE([[MHD_SHA512_256_SUPPORT]],[[1]],
3106 [Define to 1 if libmicrohttpd is compiled with SHA-512/256 support.]) 3160 [Define to 1 if libmicrohttpd is compiled with SHA-512/256 hashing support.])
3107 ] 3161 ]
3108) 3162)
3109AM_CONDITIONAL([ENABLE_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]]) 3163AM_CONDITIONAL([ENABLE_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]])
3110AC_MSG_RESULT([[${enable_sha512_256}]]) 3164AC_MSG_RESULT([[${enable_sha512_256}]])
3111 3165
3166AS_IF([test "x$enable_dauth" != "xno"],
3167 [
3168 AS_IF([test "x${enable_md5}" != "xyes" && test "x${enable_sha256}" != "xyes" && test "x${enable_sha512_256}" != "xyes"],
3169 [AC_MSG_ERROR([At least one hashing algorithm must be enabled if Digest Auth is enabled])]
3170 )
3171 ]
3172)
3173
3112 3174
3113AC_CACHE_CHECK([[for calloc()]], [[mhd_cv_have_func_calloc]], 3175AC_CACHE_CHECK([[for calloc()]], [[mhd_cv_have_func_calloc]],
3114 [ 3176 [
@@ -3990,6 +4052,8 @@ AC_MSG_NOTICE([GNU libmicrohttpd ${PACKAGE_VERSION} Configuration Summary:
3990 Messages: ${enable_messages} 4052 Messages: ${enable_messages}
3991 Basic auth.: ${enable_bauth} 4053 Basic auth.: ${enable_bauth}
3992 Digest auth.: ${enable_dauth} 4054 Digest auth.: ${enable_dauth}
4055 MD5: ${enable_md5}
4056 SHA-256: ${enable_sha256}
3993 SHA-512/256: ${enable_sha512_256} 4057 SHA-512/256: ${enable_sha512_256}
3994 HTTP "Upgrade": ${enable_httpupgrade} 4058 HTTP "Upgrade": ${enable_httpupgrade}
3995 Cookie parsing: ${enable_cookie} 4059 Cookie parsing: ${enable_cookie}
@@ -4011,6 +4075,8 @@ AS_IF([test "x$enable_https" = "xyes"],
4011 4075
4012AS_IF([test "x$enable_bauth" != "xyes" || \ 4076AS_IF([test "x$enable_bauth" != "xyes" || \
4013 test "x$enable_dauth" != "xyes" || \ 4077 test "x$enable_dauth" != "xyes" || \
4078 test "x${enable_md5}" != "xyes" || \
4079 test "x${enable_sha256}" != "xyes" || \
4014 test "x${enable_sha512_256}" != "xyes" || \ 4080 test "x${enable_sha512_256}" != "xyes" || \
4015 test "x$enable_httpupgrade" != "xyes" || \ 4081 test "x$enable_httpupgrade" != "xyes" || \
4016 test "x$enable_cookie" != "xyes" || \ 4082 test "x$enable_cookie" != "xyes" || \
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 31d4c648..e5f0abac 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -96,7 +96,7 @@ extern "C"
96 * they are parsed as decimal numbers. 96 * they are parsed as decimal numbers.
97 * Example: 0x01093001 = 1.9.30-1. 97 * Example: 0x01093001 = 1.9.30-1.
98 */ 98 */
99#define MHD_VERSION 0x00097538 99#define MHD_VERSION 0x00097539
100 100
101/* If generic headers don't work on your platform, include headers 101/* If generic headers don't work on your platform, include headers
102 which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t', 102 which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t',
@@ -4430,7 +4430,8 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp);
4430 4430
4431/** 4431/**
4432 * Length of the binary output of the SHA-512/256 hash function. 4432 * Length of the binary output of the SHA-512/256 hash function.
4433 * The value is the same as the #MHD_SHA256_DIGEST_SIZE. 4433 * @warning While this value is the same as the #MHD_SHA256_DIGEST_SIZE,
4434 * the calculated digests for SHA-256 and SHA-512/256 are different.
4434 * @sa #MHD_digest_get_hash_size() 4435 * @sa #MHD_digest_get_hash_size()
4435 * @note Available since #MHD_VERSION 0x00097538 4436 * @note Available since #MHD_VERSION 0x00097538
4436 * @ingroup authentication 4437 * @ingroup authentication
@@ -4465,22 +4466,21 @@ enum MHD_DigestBaseAlgo
4465 4466
4466 /** 4467 /**
4467 * SHA-512/256 hash algorithm. 4468 * SHA-512/256 hash algorithm.
4468 * Not supported for calculations, only supported for parsing of 4469 * As specified by FIPS PUB 180-4
4469 * client's authorisation headers.
4470 */ 4470 */
4471 MHD_DIGEST_BASE_ALGO_SHA512_256 = (1 << 2) 4471 MHD_DIGEST_BASE_ALGO_SHA512_256 = (1 << 2)
4472} _MHD_FIXED_FLAGS_ENUM; 4472} _MHD_FIXED_FLAGS_ENUM;
4473 4473
4474/** 4474/**
4475 * The flag indicating digest calculation types, 4475 * The flag indicating non-session algorithm types,
4476 * like 'MD5' or 'SHA-256'. 4476 * like 'MD5', 'SHA-256' or 'SHA-512-256'.
4477 * @note Available since #MHD_VERSION 0x00097519 4477 * @note Available since #MHD_VERSION 0x00097519
4478 */ 4478 */
4479#define MHD_DIGEST_AUTH_ALGO3_NON_SESSION (1 << 6) 4479#define MHD_DIGEST_AUTH_ALGO3_NON_SESSION (1 << 6)
4480 4480
4481/** 4481/**
4482 * The flag indicating session algorithm types, 4482 * The flag indicating session algorithm types,
4483 * like 'MD5-sess' or 'SHA-256-sess'. 4483 * like 'MD5-sess', 'SHA-256-sess' or 'SHA-512-256-sess'.
4484 * @note Available since #MHD_VERSION 0x00097519 4484 * @note Available since #MHD_VERSION 0x00097519
4485 */ 4485 */
4486#define MHD_DIGEST_AUTH_ALGO3_SESSION (1 << 7) 4486#define MHD_DIGEST_AUTH_ALGO3_SESSION (1 << 7)
@@ -4528,7 +4528,6 @@ enum MHD_DigestAuthAlgo3
4528 4528
4529 /** 4529 /**
4530 * The 'SHA-512-256' (SHA-512/256) algorithm. 4530 * The 'SHA-512-256' (SHA-512/256) algorithm.
4531 * Not supported by MHD for authentication.
4532 */ 4531 */
4533 MHD_DIGEST_AUTH_ALGO3_SHA512_256 = 4532 MHD_DIGEST_AUTH_ALGO3_SHA512_256 =
4534 MHD_DIGEST_BASE_ALGO_SHA512_256 | MHD_DIGEST_AUTH_ALGO3_NON_SESSION, 4533 MHD_DIGEST_BASE_ALGO_SHA512_256 | MHD_DIGEST_AUTH_ALGO3_NON_SESSION,
@@ -4549,8 +4548,8 @@ enum MHD_DigestAuthAlgo3
4549 * and other parameters which size depends on used hash algorithm. 4548 * and other parameters which size depends on used hash algorithm.
4550 * @param algo3 the algorithm to check 4549 * @param algo3 the algorithm to check
4551 * @return the size of the digest (either #MHD_MD5_DIGEST_SIZE or 4550 * @return the size of the digest (either #MHD_MD5_DIGEST_SIZE or
4552 * #MHD_SHA256_DIGEST_SIZE) or zero if the input value is not 4551 * #MHD_SHA256_DIGEST_SIZE/MHD_SHA512_256_DIGEST_SIZE)
4553 * recognised/valid 4552 * or zero if the input value is not supported or not valid
4554 * @sa #MHD_digest_auth_calc_userdigest() 4553 * @sa #MHD_digest_auth_calc_userdigest()
4555 * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex() 4554 * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex()
4556 * @note Available since #MHD_VERSION 0x00097526 4555 * @note Available since #MHD_VERSION 0x00097526
@@ -4601,8 +4600,6 @@ enum MHD_DigestAuthMultiAlgo3
4601 4600
4602 /** 4601 /**
4603 * The 'SHA-512-256' (SHA-512/256) algorithm. 4602 * The 'SHA-512-256' (SHA-512/256) algorithm.
4604 * Not supported by MHD for authentication.
4605 * Reserved value.
4606 */ 4603 */
4607 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 = MHD_DIGEST_AUTH_ALGO3_SHA512_256, 4604 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 = MHD_DIGEST_AUTH_ALGO3_SHA512_256,
4608 4605
@@ -4646,6 +4643,15 @@ enum MHD_DigestAuthMultiAlgo3
4646 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_SESSION, 4643 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_SESSION,
4647 4644
4648 /** 4645 /**
4646 * The 'SHA-512/256' algorithm, session or non-session.
4647 * Not supported by MHD.
4648 * Reserved value.
4649 */
4650 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_ANY =
4651 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256
4652 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_SESSION,
4653
4654 /**
4649 * Any algorithm, MHD will choose. 4655 * Any algorithm, MHD will choose.
4650 */ 4656 */
4651 MHD_DIGEST_AUTH_MULT_ALGO3_ANY = 4657 MHD_DIGEST_AUTH_MULT_ALGO3_ANY =
@@ -5317,7 +5323,8 @@ MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo3 algo3,
5317 * see #MHD_digest_auth_calc_userdigest() 5323 * see #MHD_digest_auth_calc_userdigest()
5318 * @param userdigest_size the size of the @a userdigest in bytes, must match the 5324 * @param userdigest_size the size of the @a userdigest in bytes, must match the
5319 * hashing algorithm (see #MHD_MD5_DIGEST_SIZE, 5325 * hashing algorithm (see #MHD_MD5_DIGEST_SIZE,
5320 * #MHD_SHA256_DIGEST_SIZE, #MHD_digest_get_hash_size()) 5326 * #MHD_SHA256_DIGEST_SIZE, #MHD_SHA512_256_DIGEST_SIZE,
5327 * #MHD_digest_get_hash_size())
5321 * @param nonce_timeout the period of seconds since nonce generation, when 5328 * @param nonce_timeout the period of seconds since nonce generation, when
5322 * the nonce is recognised as valid and not stale. 5329 * the nonce is recognised as valid and not stale.
5323 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc 5330 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
@@ -5327,9 +5334,9 @@ MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo3 algo3,
5327 * @param mqop the QOP to use 5334 * @param mqop the QOP to use
5328 * @param malgo3 digest algorithms allowed to use, fail if algorithm used 5335 * @param malgo3 digest algorithms allowed to use, fail if algorithm used
5329 * by the client is not allowed by this parameter; 5336 * by the client is not allowed by this parameter;
5330 * both MD5-based and SHA-256-based algorithms cannot be used at 5337 * more than one base algorithms (MD5, SHA-256, SHA-512/256)
5331 * the same time for this function as @a userdigest_size must 5338 * cannot be used at the same time for this function
5332 * match specified algorithm 5339 * as @a userdigest must match specified algorithm
5333 * @return #MHD_DAUTH_OK if authenticated, 5340 * @return #MHD_DAUTH_OK if authenticated,
5334 * the error code otherwise 5341 * the error code otherwise
5335 * @sa #MHD_digest_auth_calc_userdigest() 5342 * @sa #MHD_digest_auth_calc_userdigest()
@@ -6085,7 +6092,8 @@ enum MHD_FEATURE
6085 /** 6092 /**
6086 * Get whether the MD5-based hashing algorithms are supported for Digest 6093 * Get whether the MD5-based hashing algorithms are supported for Digest
6087 * Authorization. 6094 * Authorization.
6088 * Currently it is always supported if Digest Auth module is built. 6095 * Currently it is always supported if Digest Auth module is built
6096 * unless manually disabled in a custom build.
6089 * @note Available since #MHD_VERSION 0x00097527 6097 * @note Available since #MHD_VERSION 0x00097527
6090 */ 6098 */
6091 MHD_FEATURE_DIGEST_AUTH_MD5 = 26, 6099 MHD_FEATURE_DIGEST_AUTH_MD5 = 26,
@@ -6094,7 +6102,7 @@ enum MHD_FEATURE
6094 * Get whether the SHA-256-based hashing algorithms are supported for Digest 6102 * Get whether the SHA-256-based hashing algorithms are supported for Digest
6095 * Authorization. 6103 * Authorization.
6096 * It it always supported since #MHD_VERSION 0x00096200 if Digest Auth 6104 * It it always supported since #MHD_VERSION 0x00096200 if Digest Auth
6097 * module is built. 6105 * module is built unless manually disabled in a custom build.
6098 * @note Available since #MHD_VERSION 0x00097527 6106 * @note Available since #MHD_VERSION 0x00097527
6099 */ 6107 */
6100 MHD_FEATURE_DIGEST_AUTH_SHA256 = 27, 6108 MHD_FEATURE_DIGEST_AUTH_SHA256 = 27,
@@ -6102,7 +6110,8 @@ enum MHD_FEATURE
6102 /** 6110 /**
6103 * Get whether the SHA-512/256-based hashing algorithms are supported 6111 * Get whether the SHA-512/256-based hashing algorithms are supported
6104 * for Digest Authorization. 6112 * for Digest Authorization.
6105 * Currently it is always not supported. 6113 * It it always supported since #MHD_VERSION 0x00097539 if Digest Auth
6114 * module is built unless manually disabled in a custom build.
6106 * @note Available since #MHD_VERSION 0x00097536 6115 * @note Available since #MHD_VERSION 0x00097536
6107 */ 6116 */
6108 MHD_FEATURE_DIGEST_AUTH_SHA512_256 = 28, 6117 MHD_FEATURE_DIGEST_AUTH_SHA512_256 = 28,
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index b400d8e6..10a32f59 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -168,9 +168,15 @@ endif
168if ENABLE_DAUTH 168if ENABLE_DAUTH
169libmicrohttpd_la_SOURCES += \ 169libmicrohttpd_la_SOURCES += \
170 digestauth.c digestauth.h \ 170 digestauth.c digestauth.h \
171 mhd_bithelpers.h mhd_byteorder.h mhd_align.h \ 171 mhd_bithelpers.h mhd_byteorder.h mhd_align.h
172 md5.c md5.h \ 172if ENABLE_MD5
173libmicrohttpd_la_SOURCES += \
174 md5.c md5.h
175endif
176if ENABLE_SHA256
177libmicrohttpd_la_SOURCES += \
173 sha256.c sha256.h 178 sha256.c sha256.h
179endif
174if ENABLE_SHA512_256 180if ENABLE_SHA512_256
175libmicrohttpd_la_SOURCES += \ 181libmicrohttpd_la_SOURCES += \
176 sha512_256.c sha512_256.h 182 sha512_256.c sha512_256.h
@@ -197,9 +203,7 @@ check_PROGRAMS = \
197 test_str_pct \ 203 test_str_pct \
198 test_str_bin_hex \ 204 test_str_bin_hex \
199 test_http_reasons \ 205 test_http_reasons \
200 test_md5 \
201 test_sha1 \ 206 test_sha1 \
202 test_sha256 \
203 test_start_stop \ 207 test_start_stop \
204 test_daemon \ 208 test_daemon \
205 test_response_entries \ 209 test_response_entries \
@@ -219,6 +223,14 @@ check_PROGRAMS = \
219 test_options \ 223 test_options \
220 test_set_panic 224 test_set_panic
221 225
226if ENABLE_MD5
227check_PROGRAMS += \
228 test_md5
229endif
230if ENABLE_SHA256
231check_PROGRAMS += \
232 test_sha256
233endif
222if ENABLE_SHA512_256 234if ENABLE_SHA512_256
223check_PROGRAMS += \ 235check_PROGRAMS += \
224 test_sha512_256 236 test_sha512_256
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index fc7d4da3..fc293a1f 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -8430,20 +8430,20 @@ MHD_is_feature_supported (enum MHD_FEATURE feature)
8430 return MHD_NO; 8430 return MHD_NO;
8431#endif 8431#endif
8432 case MHD_FEATURE_DIGEST_AUTH_MD5: 8432 case MHD_FEATURE_DIGEST_AUTH_MD5:
8433#ifdef DAUTH_SUPPORT 8433#if defined(DAUTH_SUPPORT) && defined(MHD_MD5_SUPPORT)
8434 return MHD_YES; 8434 return MHD_YES;
8435#else 8435#else
8436 return MHD_NO; 8436 return MHD_NO;
8437#endif 8437#endif
8438 case MHD_FEATURE_DIGEST_AUTH_SHA256: 8438 case MHD_FEATURE_DIGEST_AUTH_SHA256:
8439#ifdef DAUTH_SUPPORT 8439#if defined(DAUTH_SUPPORT) && defined(MHD_SHA256_SUPPORT)
8440 return MHD_YES; 8440 return MHD_YES;
8441#else 8441#else
8442 return MHD_NO; 8442 return MHD_NO;
8443#endif 8443#endif
8444 case MHD_FEATURE_DIGEST_AUTH_SHA512_256: 8444 case MHD_FEATURE_DIGEST_AUTH_SHA512_256:
8445#ifdef DAUTH_SUPPORT 8445#if defined(DAUTH_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
8446 return MHD_NO; 8446 return MHD_YES;
8447#else 8447#else
8448 return MHD_NO; 8448 return MHD_NO;
8449#endif 8449#endif
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index a6792930..1155e6ff 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -33,8 +33,15 @@
33#include "mhd_limits.h" 33#include "mhd_limits.h"
34#include "internal.h" 34#include "internal.h"
35#include "response.h" 35#include "response.h"
36#include "md5.h" 36#ifdef MHD_MD5_SUPPORT
37#include "sha256.h" 37# include "md5.h"
38#endif /* MHD_MD5_SUPPORT */
39#ifdef MHD_SHA256_SUPPORT
40# include "sha256.h"
41#endif /* MHD_SHA256_SUPPORT */
42#ifdef MHD_SHA512_256_SUPPORT
43# include "sha512_256.h"
44#endif /* MHD_SHA512_256_SUPPORT */
38#include "mhd_locks.h" 45#include "mhd_locks.h"
39#include "mhd_mono_clock.h" 46#include "mhd_mono_clock.h"
40#include "mhd_str.h" 47#include "mhd_str.h"
@@ -86,6 +93,18 @@
86 ((digest_size) * 2 + TIMESTAMP_CHARS_LEN) 93 ((digest_size) * 2 + TIMESTAMP_CHARS_LEN)
87 94
88 95
96#ifdef MHD_SHA512_256_SUPPORT
97/**
98 * Maximum size of any digest hash supported by MHD.
99 * (SHA-512/256 > MD5).
100 */
101#define MAX_DIGEST SHA512_256_DIGEST_SIZE
102
103/**
104 * The common size of SHA-256 digest and SHA-512/256 digest
105 */
106#define SHA256_SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_SIZE
107#elif defined(MHD_SHA256_SUPPORT)
89/** 108/**
90 * Maximum size of any digest hash supported by MHD. 109 * Maximum size of any digest hash supported by MHD.
91 * (SHA-256 > MD5). 110 * (SHA-256 > MD5).
@@ -93,6 +112,20 @@
93#define MAX_DIGEST SHA256_DIGEST_SIZE 112#define MAX_DIGEST SHA256_DIGEST_SIZE
94 113
95/** 114/**
115 * The common size of SHA-256 digest and SHA-512/256 digest
116 */
117#define SHA256_SHA512_256_DIGEST_SIZE SHA256_DIGEST_SIZE
118#elif defined(MHD_MD5_SUPPORT)
119/**
120 * Maximum size of any digest hash supported by MHD.
121 */
122#define MAX_DIGEST MD5_DIGEST_SIZE
123#else /* ! MHD_MD5_SUPPORT */
124#error At least one hashing algorithm must be enabled
125#endif /* ! MHD_MD5_SUPPORT */
126
127
128/**
96 * Macro to avoid using VLAs if the compiler does not support them. 129 * Macro to avoid using VLAs if the compiler does not support them.
97 */ 130 */
98#ifndef HAVE_C_VARARRAYS 131#ifndef HAVE_C_VARARRAYS
@@ -193,26 +226,54 @@ get_base_digest_algo (enum MHD_DigestAuthAlgo3 algo3)
193 * Internal inline version. 226 * Internal inline version.
194 * @param algo3 the algorithm to check 227 * @param algo3 the algorithm to check
195 * @return the size of the digest or zero if the input value is not 228 * @return the size of the digest or zero if the input value is not
196 * recognised/valid 229 * supported/valid
197 */ 230 */
198_MHD_static_inline size_t 231_MHD_static_inline size_t
199digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3) 232digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3)
200{ 233{
234#ifdef MHD_MD5_SUPPORT
201 mhd_assert (MHD_MD5_DIGEST_SIZE == MD5_DIGEST_SIZE); 235 mhd_assert (MHD_MD5_DIGEST_SIZE == MD5_DIGEST_SIZE);
236#endif /* MHD_MD5_SUPPORT */
237#ifdef MHD_SHA256_SUPPORT
202 mhd_assert (MHD_SHA256_DIGEST_SIZE == SHA256_DIGEST_SIZE); 238 mhd_assert (MHD_SHA256_DIGEST_SIZE == SHA256_DIGEST_SIZE);
203 /* Both MD5 and SHA-256 must not be specified at the same time */ 239#endif /* MHD_SHA256_SUPPORT */
204 mhd_assert ( (0 == (((unsigned int) algo3) \ 240#ifdef MHD_SHA512_256_SUPPORT
205 & ((unsigned int) MHD_DIGEST_BASE_ALGO_MD5))) || \ 241 mhd_assert (MHD_SHA512_256_DIGEST_SIZE == SHA512_256_DIGEST_SIZE);
206 (0 == (((unsigned int) algo3) \ 242#ifdef MHD_SHA256_SUPPORT
207 & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256))) ); 243 mhd_assert (SHA256_DIGEST_SIZE == SHA512_256_DIGEST_SIZE);
244#endif /* MHD_SHA256_SUPPORT */
245#endif /* MHD_SHA512_256_SUPPORT */
246 /* Only one algorithm must be specified */
247 mhd_assert (1 == \
248 (((0 != (algo3 & MHD_DIGEST_BASE_ALGO_MD5)) ? 1 : 0) \
249 + ((0 != (algo3 & MHD_DIGEST_BASE_ALGO_SHA256)) ? 1 : 0) \
250 + ((0 != (algo3 & MHD_DIGEST_BASE_ALGO_SHA512_256)) ? 1 : 0)));
251#ifdef MHD_MD5_SUPPORT
208 if (0 != (((unsigned int) algo3) 252 if (0 != (((unsigned int) algo3)
209 & ((unsigned int) MHD_DIGEST_BASE_ALGO_MD5))) 253 & ((unsigned int) MHD_DIGEST_BASE_ALGO_MD5)))
210 return MHD_MD5_DIGEST_SIZE; 254 return MHD_MD5_DIGEST_SIZE;
211 else if (0 != (((unsigned int) algo3) 255 else
212 & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256))) 256#endif /* MHD_MD5_SUPPORT */
257#if defined(MHD_SHA256_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
258 if (0 != (((unsigned int) algo3)
259 & ( ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256)
260 | ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA512_256))))
261 return MHD_SHA256_DIGEST_SIZE; /* The same as SHA512_256_DIGEST_SIZE */
262 else
263#elif defined(MHD_SHA256_SUPPORT)
264 if (0 != (((unsigned int) algo3)
265 & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256)))
213 return MHD_SHA256_DIGEST_SIZE; 266 return MHD_SHA256_DIGEST_SIZE;
267 else
268#elif defined(MHD_SHA512_256_SUPPORT)
269 if (0 != (((unsigned int) algo3)
270 & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA512_256)))
271 return MHD_SHA512_256_DIGEST_SIZE;
272 else
273#endif /* MHD_SHA512_256_SUPPORT */
274 (void) 0; /* Unsupported algorithm */
214 275
215 return 0; /* Wrong input */ 276 return 0; /* Wrong input or unsupported algorithm */
216} 277}
217 278
218 279
@@ -223,8 +284,8 @@ digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3)
223 * and other parameters which size depends on used hash algorithm. 284 * and other parameters which size depends on used hash algorithm.
224 * @param algo3 the algorithm to check 285 * @param algo3 the algorithm to check
225 * @return the size of the digest (either #MHD_MD5_DIGEST_SIZE or 286 * @return the size of the digest (either #MHD_MD5_DIGEST_SIZE or
226 * #MHD_SHA256_DIGEST_SIZE) or zero if the input value is not 287 * #MHD_SHA256_DIGEST_SIZE/MHD_SHA512_256_DIGEST_SIZE)
227 * recognised/valid 288 * or zero if the input value is not supported or not valid
228 * @sa #MHD_digest_auth_calc_userdigest() 289 * @sa #MHD_digest_auth_calc_userdigest()
229 * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex() 290 * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex()
230 * @note Available since #MHD_VERSION 0x00097526 291 * @note Available since #MHD_VERSION 0x00097526
@@ -242,8 +303,15 @@ MHD_digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3)
242 */ 303 */
243union DigestCtx 304union DigestCtx
244{ 305{
306#ifdef MHD_MD5_SUPPORT
245 struct MD5Context md5_ctx; 307 struct MD5Context md5_ctx;
308#endif /* MHD_MD5_SUPPORT */
309#ifdef MHD_SHA256_SUPPORT
246 struct Sha256Ctx sha256_ctx; 310 struct Sha256Ctx sha256_ctx;
311#endif /* MHD_SHA256_SUPPORT */
312#ifdef MHD_SHA512_256_SUPPORT
313 struct Sha512_256Ctx sha512_256_ctx;
314#endif /* MHD_SHA512_256_SUPPORT */
247}; 315};
248 316
249/** 317/**
@@ -282,10 +350,18 @@ _MHD_static_inline unsigned int
282digest_get_size (struct DigestAlgorithm *da) 350digest_get_size (struct DigestAlgorithm *da)
283{ 351{
284 mhd_assert (da->setup); 352 mhd_assert (da->setup);
353#ifdef MHD_MD5_SUPPORT
285 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo) 354 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
286 return MD5_DIGEST_SIZE; 355 return MD5_DIGEST_SIZE;
356#endif /* MHD_MD5_SUPPORT */
357#ifdef MHD_SHA256_SUPPORT
287 if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo) 358 if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
288 return SHA256_DIGEST_SIZE; 359 return SHA256_DIGEST_SIZE;
360#endif /* MHD_SHA256_SUPPORT */
361#ifdef MHD_SHA512_256_SUPPORT
362 if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
363 return SHA512_256_DIGEST_SIZE;
364#endif /* MHD_SHA512_256_SUPPORT */
289 mhd_assert (0); /* May not happen */ 365 mhd_assert (0); /* May not happen */
290 return 0; 366 return 0;
291} 367}
@@ -307,8 +383,17 @@ digest_setup (struct DigestAlgorithm *da,
307 da->inited = false; 383 da->inited = false;
308 da->digest_calculated = false; 384 da->digest_calculated = false;
309#endif /* _DEBUG */ 385#endif /* _DEBUG */
310 if ((MHD_DIGEST_BASE_ALGO_MD5 == algo) || 386 if (false
311 (MHD_DIGEST_BASE_ALGO_SHA256 == algo)) 387#ifdef MHD_MD5_SUPPORT
388 || (MHD_DIGEST_BASE_ALGO_MD5 == algo)
389#endif /* MHD_MD5_SUPPORT */
390#ifdef MHD_SHA256_SUPPORT
391 || (MHD_DIGEST_BASE_ALGO_SHA256 == algo)
392#endif /* MHD_SHA256_SUPPORT */
393#ifdef MHD_SHA512_256_SUPPORT
394 || (MHD_DIGEST_BASE_ALGO_SHA512_256 == algo)
395#endif /* MHD_SHA512_256_SUPPORT */
396 )
312 { 397 {
313 da->algo = algo; 398 da->algo = algo;
314#ifdef _DEBUG 399#ifdef _DEBUG
@@ -316,8 +401,7 @@ digest_setup (struct DigestAlgorithm *da,
316#endif /* _DEBUG */ 401#endif /* _DEBUG */
317 return true; 402 return true;
318 } 403 }
319 mhd_assert (0); /* Bad parameter */ 404 return false; /* Bad or unsupported algorithm */
320 return false;
321} 405}
322 406
323 407
@@ -332,6 +416,7 @@ digest_init (struct DigestAlgorithm *da)
332#ifdef _DEBUG 416#ifdef _DEBUG
333 da->digest_calculated = false; 417 da->digest_calculated = false;
334#endif 418#endif
419#ifdef MHD_MD5_SUPPORT
335 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo) 420 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
336 { 421 {
337 MHD_MD5Init (&da->ctx.md5_ctx); 422 MHD_MD5Init (&da->ctx.md5_ctx);
@@ -339,7 +424,10 @@ digest_init (struct DigestAlgorithm *da)
339 da->inited = true; 424 da->inited = true;
340#endif 425#endif
341 } 426 }
342 else if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo) 427 else
428#endif /* MHD_MD5_SUPPORT */
429#ifdef MHD_SHA256_SUPPORT
430 if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
343 { 431 {
344 MHD_SHA256_init (&da->ctx.sha256_ctx); 432 MHD_SHA256_init (&da->ctx.sha256_ctx);
345#ifdef _DEBUG 433#ifdef _DEBUG
@@ -347,6 +435,17 @@ digest_init (struct DigestAlgorithm *da)
347#endif 435#endif
348 } 436 }
349 else 437 else
438#endif /* MHD_SHA256_SUPPORT */
439#ifdef MHD_SHA512_256_SUPPORT
440 if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
441 {
442 MHD_SHA512_256_init (&da->ctx.sha512_256_ctx);
443#ifdef _DEBUG
444 da->inited = true;
445#endif
446 }
447 else
448#endif /* MHD_SHA512_256_SUPPORT */
350 { 449 {
351#ifdef _DEBUG 450#ifdef _DEBUG
352 da->inited = false; 451 da->inited = false;
@@ -369,12 +468,23 @@ digest_update (struct DigestAlgorithm *da,
369{ 468{
370 mhd_assert (da->inited); 469 mhd_assert (da->inited);
371 mhd_assert (! da->digest_calculated); 470 mhd_assert (! da->digest_calculated);
471#ifdef MHD_MD5_SUPPORT
372 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo) 472 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
373 MHD_MD5Update (&da->ctx.md5_ctx, (const uint8_t *) data, length); 473 MHD_MD5Update (&da->ctx.md5_ctx, (const uint8_t *) data, length);
374 else if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo) 474 else
475#endif /* MHD_MD5_SUPPORT */
476#ifdef MHD_SHA256_SUPPORT
477 if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
375 MHD_SHA256_update (&da->ctx.sha256_ctx, (const uint8_t *) data, length); 478 MHD_SHA256_update (&da->ctx.sha256_ctx, (const uint8_t *) data, length);
376 else 479 else
377 mhd_assert (0); /* May not happen */ 480#endif /* MHD_SHA256_SUPPORT */
481#ifdef MHD_SHA512_256_SUPPORT
482 if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
483 MHD_SHA512_256_update (&da->ctx.sha512_256_ctx,
484 (const uint8_t *) data, length);
485 else
486#endif /* MHD_SHA512_256_SUPPORT */
487 mhd_assert (0); /* May not happen */
378} 488}
379 489
380 490
@@ -416,12 +526,22 @@ digest_calc_hash (struct DigestAlgorithm *da, uint8_t *digest)
416{ 526{
417 mhd_assert (da->inited); 527 mhd_assert (da->inited);
418 mhd_assert (! da->digest_calculated); 528 mhd_assert (! da->digest_calculated);
529#ifdef MHD_MD5_SUPPORT
419 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo) 530 if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
420 MHD_MD5Final (&da->ctx.md5_ctx, digest); 531 MHD_MD5Final (&da->ctx.md5_ctx, digest);
421 else if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo) 532 else
533#endif /* MHD_MD5_SUPPORT */
534#ifdef MHD_SHA256_SUPPORT
535 if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
422 MHD_SHA256_finish (&da->ctx.sha256_ctx, digest); 536 MHD_SHA256_finish (&da->ctx.sha256_ctx, digest);
423 else 537 else
424 mhd_assert (0); /* May not happen */ 538#endif /* MHD_SHA256_SUPPORT */
539#ifdef MHD_SHA512_256_SUPPORT
540 if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
541 MHD_SHA512_256_finish (&da->ctx.sha512_256_ctx, digest);
542 else
543#endif /* MHD_SHA512_256_SUPPORT */
544 mhd_assert (0); /* May not happen */
425#ifdef _DEBUG 545#ifdef _DEBUG
426 da->digest_calculated = true; 546 da->digest_calculated = true;
427#endif 547#endif
@@ -444,8 +564,14 @@ get_nonce_timestamp (const char *const nonce,
444 if (0 == noncelen) 564 if (0 == noncelen)
445 noncelen = strlen (nonce); 565 noncelen = strlen (nonce);
446 566
447 if ( (NONCE_STD_LEN (SHA256_DIGEST_SIZE) != noncelen) && 567 if (true
448 (NONCE_STD_LEN (MD5_DIGEST_SIZE) != noncelen) ) 568#ifdef MHD_MD5_SUPPORT
569 && (NONCE_STD_LEN (MD5_DIGEST_SIZE) != noncelen)
570#endif /* MHD_MD5_SUPPORT */
571#if defined(MHD_SHA256_SUPPORT) || defined(MHD_SHA512_256_SUPPORT)
572 && (NONCE_STD_LEN (SHA256_SHA512_256_DIGEST_SIZE) != noncelen)
573#endif /* MHD_SHA256_SUPPORT */
574 )
449 return false; 575 return false;
450 576
451 if (TIMESTAMP_CHARS_LEN != 577 if (TIMESTAMP_CHARS_LEN !=
@@ -2213,19 +2339,43 @@ digest_auth_check_all_inner (struct MHD_Connection *connection,
2213#endif /* HAVE_MESSAGES */ 2339#endif /* HAVE_MESSAGES */
2214 return MHD_DAUTH_WRONG_ALGO; 2340 return MHD_DAUTH_WRONG_ALGO;
2215 } 2341 }
2342#ifndef MHD_MD5_SUPPORT
2343 if (0 != (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_MD5))
2344 {
2345#ifdef HAVE_MESSAGES
2346 MHD_DLOG (connection->daemon,
2347 _ ("The MD5 algorithm is not supported by this MHD build.\n"));
2348#endif /* HAVE_MESSAGES */
2349 return MHD_DAUTH_WRONG_ALGO;
2350 }
2351#endif /* ! MHD_MD5_SUPPORT */
2352#ifndef MHD_SHA256_SUPPORT
2353 if (0 != (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_SHA256))
2354 {
2355#ifdef HAVE_MESSAGES
2356 MHD_DLOG (connection->daemon,
2357 _ ("The SHA-256 algorithm is not supported by "
2358 "this MHD build.\n"));
2359#endif /* HAVE_MESSAGES */
2360 return MHD_DAUTH_WRONG_ALGO;
2361 }
2362#endif /* ! MHD_SHA256_SUPPORT */
2363#ifndef MHD_SHA512_256_SUPPORT
2216 if (0 != (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_SHA512_256)) 2364 if (0 != (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_SHA512_256))
2217 { 2365 {
2218#ifdef HAVE_MESSAGES 2366#ifdef HAVE_MESSAGES
2219 MHD_DLOG (connection->daemon, 2367 MHD_DLOG (connection->daemon,
2220 _ ("The SHA-512/256 algorithm is not supported.\n")); 2368 _ ("The SHA-512/256 algorithm is not supported by "
2369 "this MHD build.\n"));
2221#endif /* HAVE_MESSAGES */ 2370#endif /* HAVE_MESSAGES */
2222 return MHD_DAUTH_WRONG_ALGO; 2371 return MHD_DAUTH_WRONG_ALGO;
2223 } 2372 }
2373#endif /* ! MHD_SHA512_256_SUPPORT */
2224 if (! digest_setup (&da, get_base_digest_algo (c_algo))) 2374 if (! digest_setup (&da, get_base_digest_algo (c_algo)))
2225 MHD_PANIC (_ ("Wrong 'malgo3' value, API violation")); 2375 MHD_PANIC (_ ("Wrong 'malgo3' value, API violation"));
2226 /* Check 'mqop' value */ 2376 /* Check 'mqop' value */
2227 c_qop = params->qop; 2377 c_qop = params->qop;
2228 /* Check whether client's algorithm is allowed by function parameter */ 2378 /* Check whether client's QOP is allowed by function parameter */
2229 if (((unsigned int) c_qop) != 2379 if (((unsigned int) c_qop) !=
2230 (((unsigned int) c_qop) & ((unsigned int) mqop))) 2380 (((unsigned int) c_qop) & ((unsigned int) mqop)))
2231 return MHD_DAUTH_WRONG_QOP; 2381 return MHD_DAUTH_WRONG_QOP;
@@ -2241,8 +2391,8 @@ digest_auth_check_all_inner (struct MHD_Connection *connection,
2241 if ((MHD_DIGEST_AUTH_QOP_NONE == c_qop) && 2391 if ((MHD_DIGEST_AUTH_QOP_NONE == c_qop) &&
2242 (0 == (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_MD5))) 2392 (0 == (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_MD5)))
2243 MHD_DLOG (connection->daemon, 2393 MHD_DLOG (connection->daemon,
2244 _ ("RFC2069 with SHA-256 algorithm is non-standard " \ 2394 _ ("RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
2245 "extension.\n")); 2395 "non-standard extension.\n"));
2246#endif /* HAVE_MESSAGES */ 2396#endif /* HAVE_MESSAGES */
2247 2397
2248 digest_size = digest_get_size (&da); 2398 digest_size = digest_get_size (&da);
@@ -2776,7 +2926,8 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
2776 * see #MHD_digest_auth_calc_userdigest() 2926 * see #MHD_digest_auth_calc_userdigest()
2777 * @param userdigest_size the size of the @a userdigest in bytes, must match the 2927 * @param userdigest_size the size of the @a userdigest in bytes, must match the
2778 * hashing algorithm (see #MHD_MD5_DIGEST_SIZE, 2928 * hashing algorithm (see #MHD_MD5_DIGEST_SIZE,
2779 * #MHD_SHA256_DIGEST_SIZE, #MHD_digest_get_hash_size()) 2929 * #MHD_SHA256_DIGEST_SIZE, #MHD_SHA512_256_DIGEST_SIZE,
2930 * #MHD_digest_get_hash_size())
2780 * @param nonce_timeout the period of seconds since nonce generation, when 2931 * @param nonce_timeout the period of seconds since nonce generation, when
2781 * the nonce is recognised as valid and not stale. 2932 * the nonce is recognised as valid and not stale.
2782 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc 2933 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
@@ -2786,9 +2937,9 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
2786 * @param mqop the QOP to use 2937 * @param mqop the QOP to use
2787 * @param malgo3 digest algorithms allowed to use, fail if algorithm used 2938 * @param malgo3 digest algorithms allowed to use, fail if algorithm used
2788 * by the client is not allowed by this parameter; 2939 * by the client is not allowed by this parameter;
2789 * both MD5-based and SHA-256-based algorithms cannot be used at 2940 * more than one base algorithms (MD5, SHA-256, SHA-512/256)
2790 * the same time for this function as @a userdigest_size must 2941 * cannot be used at the same time for this function
2791 * match specified algorithm 2942 * as @a userdigest must match specified algorithm
2792 * @return #MHD_DAUTH_OK if authenticated, 2943 * @return #MHD_DAUTH_OK if authenticated,
2793 * the error code otherwise 2944 * the error code otherwise
2794 * @sa #MHD_digest_auth_calc_userdigest() 2945 * @sa #MHD_digest_auth_calc_userdigest()
@@ -2806,13 +2957,46 @@ MHD_digest_auth_check_digest3 (struct MHD_Connection *connection,
2806 enum MHD_DigestAuthMultiQOP mqop, 2957 enum MHD_DigestAuthMultiQOP mqop,
2807 enum MHD_DigestAuthMultiAlgo3 malgo3) 2958 enum MHD_DigestAuthMultiAlgo3 malgo3)
2808{ 2959{
2809 if (((unsigned int) (MHD_DIGEST_BASE_ALGO_MD5 2960 if (1 != (((0 != (malgo3 & MHD_DIGEST_BASE_ALGO_MD5)) ? 1 : 0)
2810 | MHD_DIGEST_BASE_ALGO_SHA256)) == 2961 + ((0 != (malgo3 & MHD_DIGEST_BASE_ALGO_SHA256)) ? 1 : 0)
2811 (((unsigned int) malgo3) & (MHD_DIGEST_BASE_ALGO_MD5 2962 + ((0 != (malgo3 & MHD_DIGEST_BASE_ALGO_SHA512_256)) ? 1 : 0)))
2812 | MHD_DIGEST_BASE_ALGO_SHA256))) 2963 MHD_PANIC (_ ("Wrong 'malgo3' value, only one base hashing algorithm " \
2813 MHD_PANIC (_ ("Wrong 'malgo3' value, both MD5 and SHA-256 specified, " 2964 "(MD5, SHA-256 or SHA-512/256) must be specified, " \
2814 "API violation")); 2965 "API violation"));
2815 2966
2967#ifndef MHD_MD5_SUPPORT
2968 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_MD5))
2969 {
2970#ifdef HAVE_MESSAGES
2971 MHD_DLOG (connection->daemon,
2972 _ ("The MD5 algorithm is not supported by this MHD build.\n"));
2973#endif /* HAVE_MESSAGES */
2974 return MHD_DAUTH_WRONG_ALGO;
2975 }
2976#endif /* ! MHD_MD5_SUPPORT */
2977#ifndef MHD_SHA256_SUPPORT
2978 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA256))
2979 {
2980#ifdef HAVE_MESSAGES
2981 MHD_DLOG (connection->daemon,
2982 _ ("The SHA-256 algorithm is not supported by "
2983 "this MHD build.\n"));
2984#endif /* HAVE_MESSAGES */
2985 return MHD_DAUTH_WRONG_ALGO;
2986 }
2987#endif /* ! MHD_SHA256_SUPPORT */
2988#ifndef MHD_SHA512_256_SUPPORT
2989 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA512_256))
2990 {
2991#ifdef HAVE_MESSAGES
2992 MHD_DLOG (connection->daemon,
2993 _ ("The SHA-512/256 algorithm is not supported by "
2994 "this MHD build.\n"));
2995#endif /* HAVE_MESSAGES */
2996 return MHD_DAUTH_WRONG_ALGO;
2997 }
2998#endif /* ! MHD_SHA512_256_SUPPORT */
2999
2816 if (digest_get_hash_size ((enum MHD_DigestAuthAlgo3) malgo3) != 3000 if (digest_get_hash_size ((enum MHD_DigestAuthAlgo3) malgo3) !=
2817 userdigest_size) 3001 userdigest_size)
2818 MHD_PANIC (_ ("Wrong 'userdigest_size' value, does not match 'malgo3', " 3002 MHD_PANIC (_ ("Wrong 'userdigest_size' value, does not match 'malgo3', "
@@ -3072,12 +3256,45 @@ MHD_queue_auth_required_response3 (struct MHD_Connection *connection,
3072#endif /* HAVE_MESSAGES */ 3256#endif /* HAVE_MESSAGES */
3073 return MHD_NO; 3257 return MHD_NO;
3074 } 3258 }
3259#ifndef MHD_SHA512_256_SUPPORT
3260 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA512_256))
3261 {
3262#ifdef HAVE_MESSAGES
3263 MHD_DLOG (connection->daemon,
3264 _ ("The SHA-512/256 algorithm is not enabled.\n"));
3265#endif /* HAVE_MESSAGES */
3266 return MHD_NO;
3267 }
3268#endif /* ! MHD_SHA512_256_SUPPORT */
3269#ifdef MHD_MD5_SUPPORT
3075 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_MD5)) 3270 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_MD5))
3076 s_algo = MHD_DIGEST_AUTH_ALGO3_MD5; 3271 s_algo = MHD_DIGEST_AUTH_ALGO3_MD5;
3077 else if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA256)) 3272 else
3273#endif /* MHD_MD5_SUPPORT */
3274#ifdef MHD_SHA256_SUPPORT
3275 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA256))
3078 s_algo = MHD_DIGEST_AUTH_ALGO3_SHA256; 3276 s_algo = MHD_DIGEST_AUTH_ALGO3_SHA256;
3079 else 3277 else
3080 MHD_PANIC (_ ("Wrong 'malgo3' value, API violation")); 3278#endif /* MHD_SHA256_SUPPORT */
3279#ifdef MHD_SHA512_256_SUPPORT
3280 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA512_256))
3281 s_algo = MHD_DIGEST_AUTH_ALGO3_SHA512_256;
3282 else
3283#endif /* MHD_SHA512_256_SUPPORT */
3284 {
3285 if (0 == (((unsigned int) malgo3)
3286 & (MHD_DIGEST_BASE_ALGO_MD5 | MHD_DIGEST_BASE_ALGO_SHA512_256
3287 | MHD_DIGEST_BASE_ALGO_SHA512_256)))
3288 MHD_PANIC (_ ("Wrong 'malgo3' value, API violation"));
3289 else
3290 {
3291#ifdef HAVE_MESSAGES
3292 MHD_DLOG (connection->daemon,
3293 _ ("No requested algorithm is supported by this MHD build.\n"));
3294#endif /* HAVE_MESSAGES */
3295 }
3296 return MHD_NO;
3297 }
3081 3298
3082 if (((unsigned int) mqop) != 3299 if (((unsigned int) mqop) !=
3083 (((unsigned int) mqop) & MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT)) 3300 (((unsigned int) mqop) & MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT))
@@ -3095,8 +3312,8 @@ MHD_queue_auth_required_response3 (struct MHD_Connection *connection,
3095 "are not compatible with RFC2069 and ignored.\n")); 3312 "are not compatible with RFC2069 and ignored.\n"));
3096 if (0 == (((unsigned int) s_algo) & MHD_DIGEST_BASE_ALGO_MD5)) 3313 if (0 == (((unsigned int) s_algo) & MHD_DIGEST_BASE_ALGO_MD5))
3097 MHD_DLOG (connection->daemon, 3314 MHD_DLOG (connection->daemon,
3098 _ ("RFC2069 with SHA-256 algorithm is non-standard " \ 3315 _ ("RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
3099 "extension.\n")); 3316 "non-standard extension.\n"));
3100#endif 3317#endif
3101 userhash_support = 0; 3318 userhash_support = 0;
3102 prefer_utf8 = 0; 3319 prefer_utf8 = 0;
@@ -3141,12 +3358,22 @@ MHD_queue_auth_required_response3 (struct MHD_Connection *connection,
3141 (0 == (((unsigned int) s_algo) & MHD_DIGEST_BASE_ALGO_MD5))) 3358 (0 == (((unsigned int) s_algo) & MHD_DIGEST_BASE_ALGO_MD5)))
3142 { 3359 {
3143 buf_size += MHD_STATICSTR_LEN_ (prefix_algo) + 2; /* 2 for ', ' */ 3360 buf_size += MHD_STATICSTR_LEN_ (prefix_algo) + 2; /* 2 for ', ' */
3361#ifdef MHD_MD5_SUPPORT
3144 if (MHD_DIGEST_AUTH_ALGO3_MD5 == s_algo) 3362 if (MHD_DIGEST_AUTH_ALGO3_MD5 == s_algo)
3145 buf_size += MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN); 3363 buf_size += MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN);
3146 else if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo) 3364 else
3365#endif /* MHD_MD5_SUPPORT */
3366#ifdef MHD_SHA256_SUPPORT
3367 if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo)
3147 buf_size += MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN); 3368 buf_size += MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN);
3148 else 3369 else
3149 mhd_assert (0); 3370#endif /* MHD_SHA256_SUPPORT */
3371#ifdef MHD_SHA512_256_SUPPORT
3372 if (MHD_DIGEST_AUTH_ALGO3_SHA512_256 == s_algo)
3373 buf_size += MHD_STATICSTR_LEN_ (_MHD_SHA512_256_TOKEN);
3374 else
3375#endif /* MHD_SHA512_256_SUPPORT */
3376 mhd_assert (0);
3150 } 3377 }
3151 /* 'nonce="xxxx", ' */ 3378 /* 'nonce="xxxx", ' */
3152 buf_size += MHD_STATICSTR_LEN_ (prefix_nonce) + 3; /* 3 for '", ' */ 3379 buf_size += MHD_STATICSTR_LEN_ (prefix_nonce) + 3; /* 3 for '", ' */
@@ -3243,18 +3470,34 @@ MHD_queue_auth_required_response3 (struct MHD_Connection *connection,
3243 memcpy (buf + p, prefix_algo, 3470 memcpy (buf + p, prefix_algo,
3244 MHD_STATICSTR_LEN_ (prefix_algo)); 3471 MHD_STATICSTR_LEN_ (prefix_algo));
3245 p += MHD_STATICSTR_LEN_ (prefix_algo); 3472 p += MHD_STATICSTR_LEN_ (prefix_algo);
3473#ifdef MHD_MD5_SUPPORT
3246 if (MHD_DIGEST_AUTH_ALGO3_MD5 == s_algo) 3474 if (MHD_DIGEST_AUTH_ALGO3_MD5 == s_algo)
3247 { 3475 {
3248 memcpy (buf + p, _MHD_MD5_TOKEN, 3476 memcpy (buf + p, _MHD_MD5_TOKEN,
3249 MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN)); 3477 MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN));
3250 p += MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN); 3478 p += MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN);
3251 } 3479 }
3252 else if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo) 3480 else
3481#endif /* MHD_MD5_SUPPORT */
3482#ifdef MHD_SHA256_SUPPORT
3483 if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo)
3253 { 3484 {
3254 memcpy (buf + p, _MHD_SHA256_TOKEN, 3485 memcpy (buf + p, _MHD_SHA256_TOKEN,
3255 MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN)); 3486 MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN));
3256 p += MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN); 3487 p += MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN);
3257 } 3488 }
3489 else
3490#endif /* MHD_SHA256_SUPPORT */
3491#ifdef MHD_SHA512_256_SUPPORT
3492 if (MHD_DIGEST_AUTH_ALGO3_SHA512_256 == s_algo)
3493 {
3494 memcpy (buf + p, _MHD_SHA512_256_TOKEN,
3495 MHD_STATICSTR_LEN_ (_MHD_SHA512_256_TOKEN));
3496 p += MHD_STATICSTR_LEN_ (_MHD_SHA512_256_TOKEN);
3497 }
3498 else
3499#endif /* MHD_SHA512_256_SUPPORT */
3500 mhd_assert (0);
3258 buf[p++] = ','; 3501 buf[p++] = ',';
3259 buf[p++] = ' '; 3502 buf[p++] = ' ';
3260 } 3503 }
@@ -3382,7 +3625,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
3382 algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_MD5; 3625 algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_MD5;
3383 else if (MHD_DIGEST_ALG_SHA256 == algo) 3626 else if (MHD_DIGEST_ALG_SHA256 == algo)
3384 algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_SHA256; 3627 algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_SHA256;
3385 else if ((MHD_DIGEST_ALG_MD5 == algo) || (MHD_DIGEST_ALG_AUTO == algo)) 3628 else if (MHD_DIGEST_ALG_AUTO == algo)
3386 algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION; 3629 algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION;
3387 else 3630 else
3388 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */ 3631 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
diff --git a/src/microhttpd/gen_auth.c b/src/microhttpd/gen_auth.c
index c86d35ba..c10e4bee 100644
--- a/src/microhttpd/gen_auth.c
+++ b/src/microhttpd/gen_auth.c
@@ -300,23 +300,23 @@ get_rq_dauth_algo (const struct MHD_RqDAuthParam *const algo_param)
300 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \ 300 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
301 algo_param->value.len, \ 301 algo_param->value.len, \
302 _MHD_MD5_TOKEN _MHD_SESS_TOKEN)) 302 _MHD_MD5_TOKEN _MHD_SESS_TOKEN))
303 return MHD_DIGEST_AUTH_ALGO3_MD5_SESSION; 303 return MHD_DIGEST_AUTH_ALGO3_SHA512_256;
304 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \ 304 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
305 algo_param->value.len, \ 305 algo_param->value.len, \
306 _MHD_SHA256_TOKEN \ 306 _MHD_SHA512_256_TOKEN \
307 _MHD_SESS_TOKEN)) 307 _MHD_SESS_TOKEN))
308 return MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION;
309 308
310 /* Algorithms below are not supported by MHD for authentication */ 309 /* Algorithms below are not supported by MHD for authentication */
311 310
311 return MHD_DIGEST_AUTH_ALGO3_MD5_SESSION;
312 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \ 312 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
313 algo_param->value.len, \ 313 algo_param->value.len, \
314 _MHD_SHA512_256_TOKEN)) 314 _MHD_SHA256_TOKEN \
315 return MHD_DIGEST_AUTH_ALGO3_SHA512_256; 315 _MHD_SESS_TOKEN))
316 return MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION;
316 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \ 317 if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
317 algo_param->value.len, \ 318 algo_param->value.len, \
318 _MHD_SHA512_256_TOKEN \ 319 _MHD_SHA512_256_TOKEN))
319 _MHD_SESS_TOKEN))
320 return MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION; 320 return MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION;
321 321
322 /* No known algorithm has been detected */ 322 /* No known algorithm has been detected */
@@ -331,6 +331,13 @@ get_rq_dauth_algo (const struct MHD_RqDAuthParam *const algo_param)
331 algo_param->value.str, \ 331 algo_param->value.str, \
332 algo_param->value.len)) 332 algo_param->value.len))
333 return MHD_DIGEST_AUTH_ALGO3_SHA256; 333 return MHD_DIGEST_AUTH_ALGO3_SHA256;
334 if (MHD_str_equal_caseless_s_bin_n_ (_MHD_SHA512_256_TOKEN, \
335 algo_param->value.str, \
336 algo_param->value.len))
337 return MHD_DIGEST_AUTH_ALGO3_SHA512_256;
338
339 /* Algorithms below are not supported by MHD for authentication */
340
334 if (MHD_str_equal_caseless_s_bin_n_ (_MHD_MD5_TOKEN _MHD_SESS_TOKEN, \ 341 if (MHD_str_equal_caseless_s_bin_n_ (_MHD_MD5_TOKEN _MHD_SESS_TOKEN, \
335 algo_param->value.str, \ 342 algo_param->value.str, \
336 algo_param->value.len)) 343 algo_param->value.len))
@@ -339,13 +346,6 @@ get_rq_dauth_algo (const struct MHD_RqDAuthParam *const algo_param)
339 algo_param->value.str, \ 346 algo_param->value.str, \
340 algo_param->value.len)) 347 algo_param->value.len))
341 return MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION; 348 return MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION;
342
343 /* Algorithms below are not supported by MHD for authentication */
344
345 if (MHD_str_equal_caseless_s_bin_n_ (_MHD_SHA512_256_TOKEN, \
346 algo_param->value.str, \
347 algo_param->value.len))
348 return MHD_DIGEST_AUTH_ALGO3_SHA512_256;
349 if (MHD_str_equal_caseless_s_bin_n_ (_MHD_SHA512_256_TOKEN _MHD_SESS_TOKEN, \ 349 if (MHD_str_equal_caseless_s_bin_n_ (_MHD_SHA512_256_TOKEN _MHD_SESS_TOKEN, \
350 algo_param->value.str, \ 350 algo_param->value.str, \
351 algo_param->value.len)) 351 algo_param->value.len))
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 3fa773a7..adb69b32 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -250,11 +250,15 @@ enum MHD_ConnectionEventLoopInfo
250/** 250/**
251 * The maximum size of MHD-generated nonce when printed with hexadecimal chars. 251 * The maximum size of MHD-generated nonce when printed with hexadecimal chars.
252 * 252 *
253 * This is equal to "(32 bytes for SHA-256 nonce plus 6 bytes for timestamp) 253 * This is equal to "(32 bytes for SHA-256 (or SHA-512/256) nonce plus 6 bytes
254 * multiplied by two hex chars per byte". 254 * for timestamp) multiplied by two hex chars per byte".
255 * Please keep it in sync with digestauth.c 255 * Please keep it in sync with digestauth.c
256 */ 256 */
257#if defined(MHD_SHA256_SUPPORT) || defined(MHD_SHA512_256_SUPPORT)
257#define MAX_DIGEST_NONCE_LENGTH ((32 + 6) * 2) 258#define MAX_DIGEST_NONCE_LENGTH ((32 + 6) * 2)
259#else /* !MHD_SHA256_SUPPORT && !MHD_SHA512_256_SUPPORT */
260#define MAX_DIGEST_NONCE_LENGTH ((16 + 6) * 2)
261#endif /* !MHD_SHA256_SUPPORT && !MHD_SHA512_256_SUPPORT */
258 262
259/** 263/**
260 * A structure representing the internal holder of the 264 * A structure representing the internal holder of the
@@ -280,7 +284,7 @@ struct MHD_NonceNc
280 uint64_t nmask; 284 uint64_t nmask;
281 285
282 /** 286 /**
283 * Nonce value: 287 * Nonce value
284 */ 288 */
285 char nonce[MAX_DIGEST_NONCE_LENGTH + 1]; 289 char nonce[MAX_DIGEST_NONCE_LENGTH + 1];
286 290
diff --git a/src/microhttpd/test_dauth_userdigest.c b/src/microhttpd/test_dauth_userdigest.c
index 10bf0515..6b15a282 100644
--- a/src/microhttpd/test_dauth_userdigest.c
+++ b/src/microhttpd/test_dauth_userdigest.c
@@ -123,6 +123,54 @@ static const struct data_sha256 sha256_tests[] = {
123 0xcb, 0x14, 0x9c, 0x54, 0xf3, 0x7c, 0xff, 0x37}} 123 0xcb, 0x14, 0x9c, 0x54, 0xf3, 0x7c, 0xff, 0x37}}
124}; 124};
125 125
126struct data_sha512_256
127{
128 unsigned int line_num;
129 const char *const username;
130 const char *const realm;
131 const char *const password;
132 const uint8_t hash[MHD_SHA512_256_DIGEST_SIZE];
133};
134
135static const struct data_sha512_256 sha512_256_tests[] = {
136 {__LINE__,
137 "u", "r", "p",
138 {0xd5, 0xe8, 0xe7, 0x3b, 0xa3, 0x47, 0xb9, 0xad, 0xf0, 0xe4, 0x7a, 0x9a,
139 0xce, 0x43, 0xb7, 0x08, 0x2a, 0xbc, 0x8d, 0x27, 0x27, 0x2e, 0x38, 0x7d,
140 0x1d, 0x9c, 0xe2, 0x44, 0x25, 0x68, 0x74, 0x04}},
141 {__LINE__,
142 "testuser", "testrealm", "testpass",
143 {0x41, 0x7d, 0xf9, 0x60, 0x7c, 0xc9, 0x60, 0x28, 0x44, 0x74, 0x75, 0xf7,
144 0x7b, 0x78, 0xe7, 0x60, 0xec, 0x9a, 0xe1, 0x62, 0xd4, 0x95, 0x82, 0x61,
145 0x68, 0xa7, 0x94, 0xe8, 0x3b, 0xdf, 0x8d, 0x59}},
146 {__LINE__, /* Values from testcurl/test_digestauth2.c */
147 "test_user", "TestRealm", "test pass",
148 {0xe7, 0xa1, 0x9e, 0x27, 0xf6, 0x73, 0x88, 0xb2, 0xde, 0xa4, 0xe2, 0x66,
149 0xc5, 0x16, 0x37, 0x17, 0x4d, 0x29, 0xcc, 0xa3, 0xc1, 0xf5, 0xb2, 0x49,
150 0x20, 0xc1, 0x05, 0xc9, 0x20, 0x13, 0x3c, 0x3d}},
151 {__LINE__,
152 "Mufasa", "myhost@testrealm.com", "CircleOfLife",
153 {0x44, 0xbc, 0xd2, 0xb1, 0x1f, 0x6f, 0x7d, 0xd3, 0xae, 0xa6, 0x66, 0x8a,
154 0x24, 0x84, 0x4b, 0x87, 0x7d, 0xe1, 0x80, 0x24, 0x9a, 0x26, 0x6b, 0xe6,
155 0xdb, 0x7f, 0xe3, 0xc8, 0x7a, 0xf9, 0x75, 0x64}},
156 {__LINE__,
157 "Mufasa", "myhost@example.com", "Circle Of Life",
158 {0xd5, 0xf6, 0x25, 0x7c, 0x64, 0xe4, 0x01, 0xd2, 0x87, 0xd5, 0xaa, 0x19,
159 0xae, 0xf0, 0xa2, 0xa2, 0xce, 0x4e, 0x5d, 0xfc, 0x77, 0x70, 0x0b, 0x72,
160 0x90, 0x43, 0x96, 0xd2, 0x95, 0x6e, 0x83, 0x0a}},
161 {__LINE__,
162 "Mufasa", "http-auth@example.org", "Circle of Life",
163 {0xfb, 0x17, 0x4f, 0x5c, 0x3c, 0x78, 0x02, 0x72, 0x15, 0x17, 0xca, 0xe1,
164 0x3b, 0x98, 0xe2, 0xb8, 0xda, 0xe2, 0xe0, 0x11, 0x8c, 0xb7, 0x05, 0xd9,
165 0x4e, 0xe2, 0x99, 0x46, 0x31, 0x92, 0x04, 0xce}},
166 {__LINE__,
167 "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */,
168 "api@example.org", "Secret, or not?",
169 {0x2d, 0x3d, 0x9f, 0x12, 0xc9, 0xf3, 0xd3, 0x00, 0x11, 0x25, 0x9d, 0xc5,
170 0xfe, 0xce, 0xe0, 0x05, 0xae, 0x24, 0xde, 0x40, 0xe3, 0xe1, 0xf6, 0x18,
171 0x06, 0xd0, 0x3e, 0x65, 0xf1, 0xe6, 0x02, 0x4f}}
172};
173
126 174
127/* 175/*
128 * Helper functions 176 * Helper functions
@@ -413,6 +461,156 @@ test_sha256_failure (void)
413} 461}
414 462
415 463
464static unsigned int
465check_sha512_256 (const struct data_sha512_256 *const data)
466{
467 static const enum MHD_DigestAuthAlgo3 algo3 =
468 MHD_DIGEST_AUTH_ALGO3_SHA512_256;
469 uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
470 char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
471 char expected_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
472 const char *func_name;
473 unsigned int failed = 0;
474
475 func_name = "MHD_digest_auth_calc_userdigest";
476 if (MHD_YES != MHD_digest_auth_calc_userdigest (algo3,
477 data->username,
478 data->realm,
479 data->password,
480 hash_bin, sizeof(hash_bin)))
481 {
482 failed++;
483 fprintf (stderr,
484 "FAILED: %s() has not returned MHD_YES.\n",
485 func_name);
486 }
487 else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
488 {
489 failed++;
490 bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
491 bin2hex (data->hash, sizeof(data->hash), expected_hex);
492 fprintf (stderr,
493 "FAILED: %s() produced wrong hash. "
494 "Calculated digest %s, expected digest %s.\n",
495 func_name,
496 hash_hex, expected_hex);
497 }
498
499 if (failed)
500 {
501 fprintf (stderr,
502 "The check failed for data located at line: %u.\n",
503 data->line_num);
504 fflush (stderr);
505 }
506 else if (verbose)
507 {
508 printf ("PASSED: check for data at line: %u.\n",
509 data->line_num);
510 }
511 return failed ? 1 : 0;
512}
513
514
515static unsigned int
516test_sha512_256 (void)
517{
518 unsigned int num_failed = 0;
519 size_t i;
520
521 for (i = 0; i < sizeof(sha512_256_tests) / sizeof(sha512_256_tests[0]); i++)
522 num_failed += check_sha512_256 (sha512_256_tests + i);
523 return num_failed;
524}
525
526
527static unsigned int
528test_sha512_256_failure (void)
529{
530 static const enum MHD_DigestAuthAlgo3 algo3 =
531 MHD_DIGEST_AUTH_ALGO3_SHA512_256;
532 static const enum MHD_FEATURE feature = MHD_FEATURE_DIGEST_AUTH_SHA512_256;
533 uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
534 char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
535 const char *func_name;
536 unsigned int failed = 0;
537
538 func_name = "MHD_digest_auth_calc_userhash";
539 if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
540 "u", "r",
541 hash_bin, sizeof(hash_bin) - 1))
542 {
543 failed++;
544 fprintf (stderr,
545 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
546 func_name, (unsigned) __LINE__);
547 }
548 if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
549 "u", "r",
550 hash_bin, 0))
551 {
552 failed++;
553 fprintf (stderr,
554 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
555 func_name, (unsigned) __LINE__);
556 }
557 if (MHD_NO == MHD_is_feature_supported (feature))
558 {
559 if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
560 "u", "r",
561 hash_bin, sizeof(hash_bin)))
562 {
563 failed++;
564 fprintf (stderr,
565 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
566 func_name, (unsigned) __LINE__);
567 }
568 }
569
570 func_name = "MHD_digest_auth_calc_userhash_hex";
571 if (MHD_NO !=
572 MHD_digest_auth_calc_userhash_hex (algo3,
573 "u", "r",
574 hash_hex, sizeof(hash_hex) - 1))
575 {
576 failed++;
577 fprintf (stderr,
578 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
579 func_name, (unsigned) __LINE__);
580 }
581 if (MHD_NO !=
582 MHD_digest_auth_calc_userhash_hex (algo3,
583 "u", "r",
584 hash_hex, 0))
585 {
586 failed++;
587 fprintf (stderr,
588 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
589 func_name, (unsigned) __LINE__);
590 }
591 if (MHD_NO == MHD_is_feature_supported (feature))
592 {
593 if (MHD_NO !=
594 MHD_digest_auth_calc_userhash_hex (algo3,
595 "u", "r",
596 hash_hex, sizeof(hash_hex)))
597 {
598 failed++;
599 fprintf (stderr,
600 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
601 func_name, (unsigned) __LINE__);
602 }
603 }
604
605 if (! failed && verbose)
606 {
607 printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
608 (unsigned) __LINE__);
609 }
610 return failed ? 1 : 0;
611}
612
613
416int 614int
417main (int argc, char *argv[]) 615main (int argc, char *argv[])
418{ 616{
@@ -427,6 +625,9 @@ main (int argc, char *argv[])
427 if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256)) 625 if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
428 num_failed += test_sha256 (); 626 num_failed += test_sha256 ();
429 num_failed += test_sha256_failure (); 627 num_failed += test_sha256_failure ();
628 if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA512_256))
629 num_failed += test_sha512_256 ();
630 num_failed += test_sha512_256_failure ();
430 631
431 return num_failed ? 1 : 0; 632 return num_failed ? 1 : 0;
432} 633}
diff --git a/src/microhttpd/test_dauth_userhash.c b/src/microhttpd/test_dauth_userhash.c
index 94230acd..633ab4b9 100644
--- a/src/microhttpd/test_dauth_userhash.c
+++ b/src/microhttpd/test_dauth_userhash.c
@@ -119,6 +119,53 @@ static const struct data_sha256 sha256_tests[] = {
119 0xe9, 0x19, 0x1d, 0x8e, 0x94, 0x6f, 0xc4, 0xe7}} 119 0xe9, 0x19, 0x1d, 0x8e, 0x94, 0x6f, 0xc4, 0xe7}}
120}; 120};
121 121
122struct data_sha512_256
123{
124 unsigned int line_num;
125 const char *const username;
126 const char *const realm;
127 const uint8_t hash[MHD_SHA512_256_DIGEST_SIZE];
128};
129
130
131static const struct data_sha512_256 sha512_256_tests[] = {
132 {__LINE__,
133 "u", "r",
134 {0xc7, 0x38, 0xf2, 0xad, 0x40, 0x1b, 0xc8, 0x7a, 0x71, 0xfe, 0x78, 0x09,
135 0x60, 0x15, 0xc9, 0x7b, 0x9a, 0x26, 0xd5, 0x5f, 0x15, 0xe9, 0xf5, 0x0a,
136 0xc3, 0xa6, 0xde, 0x73, 0xdd, 0xcd, 0x3d, 0x08}},
137 {__LINE__,
138 "testuser", "testrealm",
139 {0x4f, 0x69, 0x1e, 0xe9, 0x50, 0x8a, 0xe4, 0x55, 0x21, 0x32, 0x9e, 0xcf,
140 0xd4, 0x91, 0xf7, 0xe2, 0x77, 0x4b, 0x6f, 0xb8, 0x60, 0x2c, 0x14, 0x86,
141 0xad, 0x94, 0x9d, 0x1c, 0x23, 0xd8, 0xa1, 0xf5}},
142 {__LINE__,
143 "test_user", "TestRealm", /* Values from testcurl/test_digestauth2.c */
144 {0x62, 0xe1, 0xac, 0x9f, 0x6c, 0xb1, 0xeb, 0x26, 0xaa, 0x75, 0xeb, 0x5d,
145 0x46, 0xef, 0xcd, 0xc8, 0x9c, 0xcb, 0xa7, 0x81, 0xf0, 0xf9, 0xf7, 0x2f,
146 0x6a, 0xfd, 0xb9, 0x42, 0x65, 0xd9, 0xa7, 0x9a}},
147 {__LINE__,
148 "Mufasa", "myhost@testrealm.com",
149 {0xbd, 0x3e, 0xbc, 0x30, 0x10, 0x0b, 0x7c, 0xf1, 0x61, 0x45, 0x6c, 0xfe,
150 0x64, 0x1c, 0x4c, 0xd2, 0x82, 0xe0, 0x62, 0x6e, 0x2c, 0x5e, 0x09, 0xc2,
151 0x4c, 0x90, 0xb1, 0x60, 0x8a, 0xec, 0x28, 0x64}},
152 {__LINE__,
153 "Mufasa", "myhost@example.com",
154 {0xea, 0x4b, 0x59, 0x37, 0xde, 0x2c, 0x4e, 0x9f, 0x16, 0xf9, 0x9c, 0x31,
155 0x01, 0xb6, 0xdd, 0xf8, 0x8c, 0x85, 0xd7, 0xe8, 0xf1, 0x75, 0x90, 0xd0,
156 0x63, 0x2a, 0x75, 0x75, 0xe4, 0x80, 0x13, 0x69}},
157 {__LINE__,
158 "Mufasa", "http-auth@example.org",
159 {0xe2, 0xdf, 0xab, 0xd1, 0xa9, 0x6d, 0xdf, 0x86, 0x77, 0x10, 0xb6, 0x53,
160 0xb6, 0xe6, 0x85, 0x7d, 0x1f, 0x14, 0x70, 0x86, 0xde, 0x7d, 0x7e, 0xf7,
161 0x9d, 0xcd, 0x24, 0x98, 0x59, 0x87, 0x25, 0x70}},
162 {__LINE__,
163 "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */, "api@example.org",
164 {0x79, 0x32, 0x63, 0xca, 0xab, 0xb7, 0x07, 0xa5, 0x62, 0x11, 0x94, 0x0d,
165 0x90, 0x41, 0x1e, 0xa4, 0xa5, 0x75, 0xad, 0xec, 0xcb, 0x7e, 0x36, 0x0a,
166 0xeb, 0x62, 0x4e, 0xd0, 0x6e, 0xce, 0x9b, 0x0b}}
167};
168
122 169
123/* 170/*
124 * Helper functions 171 * Helper functions
@@ -510,6 +557,189 @@ test_sha256_failure (void)
510} 557}
511 558
512 559
560static unsigned int
561check_sha512_256 (const struct data_sha512_256 *const data)
562{
563 static const enum MHD_DigestAuthAlgo3 algo3 =
564 MHD_DIGEST_AUTH_ALGO3_SHA512_256;
565 uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
566 char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
567 char expected_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
568 const char *func_name;
569 unsigned int failed = 0;
570
571 func_name = "MHD_digest_auth_calc_userhash";
572 if (MHD_YES != MHD_digest_auth_calc_userhash (algo3,
573 data->username, data->realm,
574 hash_bin, sizeof(hash_bin)))
575 {
576 failed++;
577 fprintf (stderr,
578 "FAILED: %s() has not returned MHD_YES.\n",
579 func_name);
580 }
581 else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
582 {
583 failed++;
584 bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
585 bin2hex (data->hash, sizeof(data->hash), expected_hex);
586 fprintf (stderr,
587 "FAILED: %s() produced wrong hash. "
588 "Calculated digest %s, expected digest %s.\n",
589 func_name,
590 hash_hex, expected_hex);
591 }
592
593 func_name = "MHD_digest_auth_calc_userhash_hex";
594 if (MHD_YES !=
595 MHD_digest_auth_calc_userhash_hex (algo3,
596 data->username, data->realm,
597 hash_hex, sizeof(hash_hex)))
598 {
599 failed++;
600 fprintf (stderr,
601 "FAILED: %s() has not returned MHD_YES.\n",
602 func_name);
603 }
604 else if (sizeof(hash_hex) - 1 != strlen (hash_hex))
605 {
606 failed++;
607 fprintf (stderr,
608 "FAILED: %s produced hash with wrong length. "
609 "Calculated length %u, expected digest %u.\n",
610 func_name,
611 (unsigned) strlen (hash_hex),
612 (unsigned) (sizeof(hash_hex) - 1));
613 }
614 else
615 {
616 bin2hex (data->hash, sizeof(data->hash), expected_hex);
617 if (0 != memcmp (hash_hex, expected_hex, sizeof(hash_hex)))
618 {
619 failed++;
620 fprintf (stderr,
621 "FAILED: %s() produced wrong hash. "
622 "Calculated digest %s, expected digest %s.\n",
623 func_name,
624 hash_hex, expected_hex);
625 }
626 }
627
628 if (failed)
629 {
630 fprintf (stderr,
631 "The check failed for data located at line: %u.\n",
632 data->line_num);
633 fflush (stderr);
634 }
635 else if (verbose)
636 {
637 printf ("PASSED: check for data at line: %u.\n",
638 data->line_num);
639 }
640 return failed ? 1 : 0;
641}
642
643
644static unsigned int
645test_sha512_256 (void)
646{
647 unsigned int num_failed = 0;
648 size_t i;
649
650 for (i = 0; i < sizeof(sha512_256_tests) / sizeof(sha512_256_tests[0]); i++)
651 num_failed += check_sha512_256 (sha512_256_tests + i);
652 return num_failed;
653}
654
655
656static unsigned int
657test_sha512_256_failure (void)
658{
659 static const enum MHD_DigestAuthAlgo3 algo3 =
660 MHD_DIGEST_AUTH_ALGO3_SHA512_256;
661 static const enum MHD_FEATURE feature = MHD_FEATURE_DIGEST_AUTH_SHA512_256;
662 uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
663 char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
664 const char *func_name;
665 unsigned int failed = 0;
666
667 func_name = "MHD_digest_auth_calc_userhash";
668 if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
669 "u", "r",
670 hash_bin, sizeof(hash_bin) - 1))
671 {
672 failed++;
673 fprintf (stderr,
674 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
675 func_name, (unsigned) __LINE__);
676 }
677 if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
678 "u", "r",
679 hash_bin, 0))
680 {
681 failed++;
682 fprintf (stderr,
683 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
684 func_name, (unsigned) __LINE__);
685 }
686 if (MHD_NO == MHD_is_feature_supported (feature))
687 {
688 if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
689 "u", "r",
690 hash_bin, sizeof(hash_bin)))
691 {
692 failed++;
693 fprintf (stderr,
694 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
695 func_name, (unsigned) __LINE__);
696 }
697 }
698
699 func_name = "MHD_digest_auth_calc_userhash_hex";
700 if (MHD_NO !=
701 MHD_digest_auth_calc_userhash_hex (algo3,
702 "u", "r",
703 hash_hex, sizeof(hash_hex) - 1))
704 {
705 failed++;
706 fprintf (stderr,
707 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
708 func_name, (unsigned) __LINE__);
709 }
710 if (MHD_NO !=
711 MHD_digest_auth_calc_userhash_hex (algo3,
712 "u", "r",
713 hash_hex, 0))
714 {
715 failed++;
716 fprintf (stderr,
717 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
718 func_name, (unsigned) __LINE__);
719 }
720 if (MHD_NO == MHD_is_feature_supported (feature))
721 {
722 if (MHD_NO !=
723 MHD_digest_auth_calc_userhash_hex (algo3,
724 "u", "r",
725 hash_hex, sizeof(hash_hex)))
726 {
727 failed++;
728 fprintf (stderr,
729 "FAILED: %s() has not returned MHD_NO at line: %u.\n",
730 func_name, (unsigned) __LINE__);
731 }
732 }
733
734 if (! failed && verbose)
735 {
736 printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
737 (unsigned) __LINE__);
738 }
739 return failed ? 1 : 0;
740}
741
742
513int 743int
514main (int argc, char *argv[]) 744main (int argc, char *argv[])
515{ 745{
@@ -524,6 +754,9 @@ main (int argc, char *argv[])
524 if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256)) 754 if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
525 num_failed += test_sha256 (); 755 num_failed += test_sha256 ();
526 num_failed += test_sha256_failure (); 756 num_failed += test_sha256_failure ();
757 if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA512_256))
758 num_failed += test_sha512_256 ();
759 num_failed += test_sha512_256_failure ();
527 760
528 return num_failed ? 1 : 0; 761 return num_failed ? 1 : 0;
529} 762}
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index 0e23f251..a4bc94ef 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -161,12 +161,18 @@ endif
161 161
162 162
163if ENABLE_DAUTH 163if ENABLE_DAUTH
164if ENABLE_MD5
164THREAD_ONLY_TESTS += \ 165THREAD_ONLY_TESTS += \
165 test_digestauth \ 166 test_digestauth \
166 test_digestauth_sha256 \
167 test_digestauth_with_arguments \ 167 test_digestauth_with_arguments \
168 test_digestauth_concurrent 168 test_digestauth_concurrent
169endif
170if ENABLE_SHA256
171THREAD_ONLY_TESTS += \
172 test_digestauth_sha256
173endif
169 174
175if ENABLE_MD5
170check_PROGRAMS += \ 176check_PROGRAMS += \
171 test_digestauth_emu_ext \ 177 test_digestauth_emu_ext \
172 test_digestauth_emu_ext_oldapi \ 178 test_digestauth_emu_ext_oldapi \
@@ -176,21 +182,25 @@ check_PROGRAMS += \
176 test_digestauth2_oldapi1 \ 182 test_digestauth2_oldapi1 \
177 test_digestauth2_oldapi2 \ 183 test_digestauth2_oldapi2 \
178 test_digestauth2_userhash \ 184 test_digestauth2_userhash \
179 test_digestauth2_sha256 \
180 test_digestauth2_sha256_userhash \
181 test_digestauth2_oldapi2_sha256 \
182 test_digestauth2_userdigest \ 185 test_digestauth2_userdigest \
183 test_digestauth2_oldapi1_userdigest \ 186 test_digestauth2_oldapi1_userdigest \
184 test_digestauth2_oldapi2_userdigest \ 187 test_digestauth2_oldapi2_userdigest \
185 test_digestauth2_userhash_userdigest \ 188 test_digestauth2_userhash_userdigest \
186 test_digestauth2_sha256_userdigest \
187 test_digestauth2_oldapi2_sha256_userdigest \
188 test_digestauth2_sha256_userhash_userdigest \
189 test_digestauth2_bind_all \ 189 test_digestauth2_bind_all \
190 test_digestauth2_bind_uri \ 190 test_digestauth2_bind_uri \
191 test_digestauth2_oldapi1_bind_all \ 191 test_digestauth2_oldapi1_bind_all \
192 test_digestauth2_oldapi1_bind_uri 192 test_digestauth2_oldapi1_bind_uri
193endif 193endif
194if ENABLE_SHA256
195check_PROGRAMS += \
196 test_digestauth2_sha256 \
197 test_digestauth2_sha256_userhash \
198 test_digestauth2_oldapi2_sha256 \
199 test_digestauth2_sha256_userdigest \
200 test_digestauth2_oldapi2_sha256_userdigest \
201 test_digestauth2_sha256_userhash_userdigest
202endif
203endif
194 204
195if HEAVY_TESTS 205if HEAVY_TESTS
196if HAVE_FORK_WAITPID 206if HAVE_FORK_WAITPID