39#ifdef MHD_SHA256_SUPPORT
42#ifdef MHD_SHA512_256_SUPPORT
59#define REUSE_TIMEOUT 30
65#define DAUTH_JUMPBACK_MAX (0x7F)
71#define TIMESTAMP_BIN_SIZE (48 / 8)
77#define TRIM_TO_TIMESTAMP(value) \
78 ((value) & ((UINT64_C (1) << (TIMESTAMP_BIN_SIZE * 8)) - 1))
84#define TIMESTAMP_CHARS_LEN (TIMESTAMP_BIN_SIZE * 2)
92#define NONCE_STD_LEN(digest_size) \
93 ((digest_size) * 2 + TIMESTAMP_CHARS_LEN)
96#ifdef MHD_SHA512_256_SUPPORT
101#define MAX_DIGEST SHA512_256_DIGEST_SIZE
106#define SHA256_SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_SIZE
107#elif defined(MHD_SHA256_SUPPORT)
112#define MAX_DIGEST SHA256_DIGEST_SIZE
117#define SHA256_SHA512_256_DIGEST_SIZE SHA256_DIGEST_SIZE
118#elif defined(MHD_MD5_SUPPORT)
122#define MAX_DIGEST MD5_DIGEST_SIZE
124#error At least one hashing algorithm must be enabled
131#ifndef HAVE_C_VARARRAYS
137#define VLA_ARRAY_LEN_DIGEST(n) (MAX_DIGEST)
145#define VLA_ARRAY_LEN_DIGEST(n) (n)
151#define VLA_CHECK_LEN_DIGEST(n) \
152 do { if ((n) > MAX_DIGEST) MHD_PANIC (_ ("VLA too big.\n")); } while (0)
157#define MAX_USERNAME_LENGTH 128
162#define MAX_REALM_LENGTH 256
167#define MAX_AUTH_RESPONSE_LENGTH (MAX_DIGEST * 2)
172#define MHD_DAUTH_EXT_PARAM_PREFIX "UTF-8'"
177#define MHD_DAUTH_EXT_PARAM_MIN_LEN \
178 MHD_STATICSTR_LEN_ (MHD_DAUTH_EXT_PARAM_PREFIX "'")
212 unsigned int base_algo;
215 ((
unsigned int) algo3)
231_MHD_static_inline
size_t
234#ifdef MHD_MD5_SUPPORT
237#ifdef MHD_SHA256_SUPPORT
240#ifdef MHD_SHA512_256_SUPPORT
242#ifdef MHD_SHA256_SUPPORT
251#ifdef MHD_MD5_SUPPORT
252 if (0 != (((
unsigned int) algo3)
257#if defined(MHD_SHA256_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
258 if (0 != (((
unsigned int) algo3)
263#elif defined(MHD_SHA256_SUPPORT)
264 if (0 != (((
unsigned int) algo3)
268#elif defined(MHD_SHA512_256_SUPPORT)
269 if (0 != (((
unsigned int) algo3)
306#ifdef MHD_MD5_SUPPORT
309#ifdef MHD_SHA256_SUPPORT
312#ifdef MHD_SHA512_256_SUPPORT
320struct DigestAlgorithm
339 bool ready_for_hashing;
350_MHD_static_inline
unsigned int
355#ifdef MHD_MD5_SUPPORT
359#ifdef MHD_SHA256_SUPPORT
363#ifdef MHD_SHA512_256_SUPPORT
372#if defined(MHD_MD5_HAS_DEINIT) || defined(MHD_SHA256_HAS_DEINIT)
376#define MHD_DIGEST_HAS_DEINIT 1
379#ifdef MHD_DIGEST_HAS_DEINIT
387_MHD_static_inline
void
391 da->uninitialised =
false;
392 da->algo_selected =
false;
393 da->ready_for_hashing =
false;
409_MHD_static_inline
void
413#ifdef MHD_MD5_HAS_DEINIT
418#ifdef MHD_SHA256_HAS_DEINIT
429#define digest_setup_zero(da) (void)0
430#define digest_deinit(da) (void)0
447_MHD_static_inline
bool
452 da->uninitialised =
false;
453 da->algo_selected =
false;
454 da->ready_for_hashing =
false;
457#ifdef MHD_MD5_SUPPORT
462 da->algo_selected =
true;
466 da->ready_for_hashing =
true;
471#ifdef MHD_SHA256_SUPPORT
476 da->algo_selected =
true;
480 da->ready_for_hashing =
true;
485#ifdef MHD_SHA512_256_SUPPORT
490 da->algo_selected =
true;
494 da->ready_for_hashing =
true;
511_MHD_static_inline
void
519#ifdef MHD_MD5_SUPPORT
524#ifdef MHD_SHA256_SUPPORT
529#ifdef MHD_SHA512_256_SUPPORT
532 (
const uint8_t *)
data, length);
547_MHD_static_inline
void
551 const size_t str_len = strlen (str);
561_MHD_static_inline
void
564 static const uint8_t colon = (uint8_t)
':';
575_MHD_static_inline
void
581#ifdef MHD_MD5_SUPPORT
584#ifdef MHD_MD5_HAS_FINISH
587 da->ready_for_hashing =
false;
592 da->ready_for_hashing =
true;
598#ifdef MHD_SHA256_SUPPORT
601#ifdef MHD_SHA256_HAS_FINISH
604 da->ready_for_hashing =
false;
609 da->ready_for_hashing =
true;
615#ifdef MHD_SHA512_256_SUPPORT
620 da->ready_for_hashing =
false;
637_MHD_static_inline
void
643#ifdef MHD_MD5_SUPPORT
646#ifdef MHD_MD5_HAS_FINISH
653 da->ready_for_hashing =
true;
658#ifdef MHD_SHA256_SUPPORT
661#ifdef MHD_SHA256_HAS_FINISH
668 da->ready_for_hashing =
true;
673#ifdef MHD_SHA512_256_SUPPORT
679 da->ready_for_hashing =
true;
686 da->ready_for_hashing =
false;
693#if defined(MHD_MD5_HAS_EXT_ERROR) || defined(MHD_SHA256_HAS_EXT_ERROR)
697#define MHD_DIGEST_HAS_EXT_ERROR 1
700#ifdef MHD_DIGEST_HAS_EXT_ERROR
710_MHD_static_inline
bool
715#ifdef MHD_MD5_HAS_EXT_ERROR
717 return 0 != da->ctx.md5_ctx.ext_error;
719#ifdef MHD_SHA256_HAS_EXT_ERROR
721 return 0 != da->ctx.sha256_ctx.ext_error;
728#define digest_ext_error(da) (false)
743 uint64_t *
const ptimestamp)
746 noncelen = strlen (nonce);
749#ifdef MHD_MD5_SUPPORT
752#
if defined(MHD_SHA256_SUPPORT) || defined(MHD_SHA512_256_SUPPORT)
753 && (
NONCE_STD_LEN (SHA256_SHA512_256_DIGEST_SIZE) != noncelen)
786 for (i = 1; i < data_size; i++)
850 mod = daemon->nonce_nc_size;
862 if ( (0 != memcmp (nn->
nonce,
nonce, noncelen)) ||
863 (0 != nn->
nonce[noncelen]) )
865 if (0 == nn->
nonce[0])
870 else if (0 != nn->
nonce[noncelen])
909 else if (
nc > nn->
nc)
912 const uint32_t jump_size = (uint32_t)
nc - nn->
nc;
916 nn->
nmask <<= jump_size;
918 nn->
nmask |= (UINT64_C (1) << (jump_size - 1));
920 else if (64 == jump_size)
921 nn->
nmask = (UINT64_C (1) << 63);
924 nn->
nc = (uint32_t)
nc;
927 else if (nc < nn->
nc)
931 if ( (
nc + 64 >= nn->
nc) &&
932 (0 == ((UINT64_C (1) << (nn->
nc -
nc - 1)) & nn->
nmask)) )
935 nn->
nmask |= (UINT64_C (1) << (nn->
nc -
nc - 1));
962 if (
NULL != params->username.value.str)
964 if (
NULL == params->username_ext.value.str)
965 return params->userhash ?
971 else if (
NULL != params->username_ext.value.str)
973 if (! params->username_ext.quoted && ! params->userhash &&
974 (MHD_DAUTH_EXT_PARAM_MIN_LEN <= params->username_ext.value.len) )
991_MHD_static_inline
size_t
1002 s += params->username.value.len + 1;
1004 s += (params->username.value.len + 1) / 2;
1007 s += params->username_ext.value.len
1026 if (! param->quoted)
1028 memcpy (buf, param->value.str, param->value.len);
1029 buf [param->value.len] = 0;
1030 return param->value.len;
1033 len = MHD_str_unquote (param->value.str, param->value.len, buf);
1053 char *buf,
size_t buf_size)
1070 while (r < uname_ext_len &&
'\'' != uname_ext[r])
1072 const char chr = uname_ext[r];
1073 if ((
' ' == chr) || (
'\t' == chr) || (
'\"' == chr) || (
',' == chr) ||
1078 if (r >= uname_ext_len)
1084 if ((0 == w) && (0 != uname_ext_len - r))
1123 uname_info->
username = (
char *) (buf + buf_used);
1139 uname_info->
userhash_bin = (uint8_t *) (buf + buf_used);
1161 params->username_ext.value.len,
1162 (
char *) (buf + buf_used),
1163 buf_size - buf_used);
1168 uname_info->
username = (
char *) (buf + buf_used);
1207 const struct MHD_RqDAuthParam *
const nc_param =
1215 if (
NULL == nc_param->value.str)
1218 if (0 == nc_param->value.len)
1221 if (! nc_param->quoted)
1223 val = nc_param->value.str;
1224 val_len = nc_param->value.len;
1229 if (
sizeof(unq) < params->nc.value.len)
1231 val_len = MHD_str_unquote (nc_param->value.str, nc_param->value.len, unq);
1240 const char f = val[0];
1241 if ( ((
'9' >= f) && (
'0' <= f)) ||
1242 ((
'F' >= f) && (
'A' <= f)) ||
1243 ((
'a' <= f) && (
'f' >= f)) )
1252 *nc = (uint32_t) nc_val;
1270 const struct MHD_RqDAuth *params;
1273 size_t unif_buf_size;
1274 uint8_t *unif_buf_ptr;
1275 size_t unif_buf_used;
1278 params = MHD_get_rq_dauth_params_ (connection);
1288 if (
NULL != params->opaque.value.str)
1289 unif_buf_size += params->opaque.value.len + 1;
1290 if (
NULL != params->realm.value.str)
1291 unif_buf_size += params->realm.value.len + 1;
1294 unif_buf_ptr = (uint8_t *) (info + 1);
1297 info->
algo3 = params->algo3;
1304 unif_buf_ptr + unif_buf_used,
1305 unif_buf_size - unif_buf_used);
1309 if (
NULL != params->opaque.value.str)
1311 info->
opaque = (
char *) (unif_buf_ptr + unif_buf_used);
1316 if (
NULL != params->realm.value.str)
1318 info->
realm = (
char *) (unif_buf_ptr + unif_buf_used);
1326 info->
qop = params->qop;
1328 if (
NULL != params->cnonce.value.str)
1358 const struct MHD_RqDAuth *params;
1361 size_t unif_buf_size;
1362 uint8_t *unif_buf_ptr;
1363 size_t unif_buf_used;
1365 params = MHD_get_rq_dauth_params_ (connection);
1379 unif_buf_ptr = (uint8_t *) (uname_info + 1);
1383 (void) unif_buf_used;
1392 uname_info->
algo3 = params->algo3;
1416 const struct MHD_RqDAuth *params;
1421 params = MHD_get_rq_dauth_params_ (connection);
1436 if (
NULL == username)
1444 memset (&uname_strct, 0,
sizeof(uname_strct));
1490 const struct sockaddr_storage *saddr,
1497 unsigned int bind_options,
1498 struct DigestAlgorithm *da,
1508#if TIMESTAMP_BIN_SIZE != 6
1509#error The code needs to be updated here
1522 sizeof (timestamp));
1547 if (AF_INET == saddr->ss_family)
1549 &((
const struct sockaddr_in *) saddr)->sin_addr,
1550 sizeof(((
const struct sockaddr_in *) saddr)->sin_addr));
1552 else if (AF_INET6 == saddr->ss_family)
1554 &((
const struct sockaddr_in6 *) saddr)->sin6_addr,
1555 sizeof(((
const struct sockaddr_in6 *) saddr)->sin6_addr));
1565 uint8_t mthd_for_hash;
1567 mthd_for_hash = (uint8_t) mthd_e;
1572 sizeof(mthd_for_hash));
1593 for (h = first_header;
NULL != h; h = h->
next)
1616 uint8_t hash[MAX_DIGEST];
1643 const char *
const new_nonce,
1644 size_t new_nonce_len)
1647 bool timestamp_valid;
1650 if (0 == nn->
nonce[0])
1653 if (0 == memcmp (nn->
nonce, new_nonce, new_nonce_len))
1671 if (! timestamp_valid)
1701 struct DigestAlgorithm *da,
1716 daemon->digest_auth_random,
1717 daemon->digest_auth_rand_size,
1725 daemon->dauth_bind_type,
1729#ifdef MHD_DIGEST_HAS_EXT_ERROR
1734 if (0 == daemon->nonce_nc_size)
1750 nn->
nonce[nonce_size] = 0;
1779 struct DigestAlgorithm *da,
1783 const size_t realm_len = strlen (realm);
1788 MHD_DLOG (connection->
daemon,
1789 _ (
"Random value was not initialised by " \
1790 "MHD_OPTION_DIGEST_AUTH_RANDOM or " \
1791 "MHD_OPTION_DIGEST_AUTH_RANDOM_COPY, generated nonces " \
1792 "are predictable.\n"));
1807 uint64_t timestamp2;
1808#ifdef MHD_DIGEST_HAS_EXT_ERROR
1816 if (timestamp1 == timestamp2)
1827 base1 = ((uint64_t) random ()) ^ UINT64_C (0x54a5acff5be47e63);
1829#elif defined(HAVE_RAND)
1830 base1 = ((uint64_t) rand ()) ^ UINT64_C (0xc4bcf553b12f3965);
1835 base1 = ((uint64_t) (uintptr_t) nonce2) ^ UINT64_C (0xf2e1b21bc6c92655);
1836 base2 = ((uint32_t) (base1 >> 32)) ^ ((uint32_t) base1);
1838 base3 = ((uint16_t) (base2 >> 16)) ^ ((uint16_t) base2);
1839 base4 = ((uint8_t) (base3 >> 8)) ^ ((uint8_t) base3);
1841 ^ UINT64_C (0xccab93f72cf5b15);
1843 base2 = ((uint32_t) (base1 >> 32)) ^ ((uint32_t) base1);
1844 base2 =
_MHD_ROTL32 (base2, (((base4 >> 4) ^ base4) % 32));
1845 base3 = ((uint16_t) (base2 >> 16)) ^ ((uint16_t) base2);
1846 base4 = ((uint8_t) (base3 >> 8)) ^ ((uint8_t) base3);
1849 if (timestamp1 == timestamp2)
1886_MHD_static_inline
void
1888 const char *username,
const size_t username_len,
1889 const char *realm,
const size_t realm_len,
1890 const char *password,
1938 const char *username,
1940 const char *password,
1941 void *userdigest_bin,
1942 size_t bin_buf_size)
1944 struct DigestAlgorithm da;
1962#ifdef MHD_DIGEST_HAS_EXT_ERROR
1986_MHD_static_inline
void
1988 const char *username,
const size_t username_len,
1989 const char *realm,
const size_t realm_len,
1990 uint8_t *digest_bin)
2043 const char *username,
2046 size_t bin_buf_size)
2048 struct DigestAlgorithm da;
2065#ifdef MHD_DIGEST_HAS_EXT_ERROR
2118 const char *username,
2121 size_t hex_buf_size)
2123 uint8_t userhash_bin[MAX_DIGEST];
2127 if (digest_size * 2 + 1 > hex_buf_size)
2130 userhash_bin, MAX_DIGEST))
2138struct test_header_param
2165 struct test_header_param *
const param = (
struct test_header_param *) cls;
2170 param->num_headers++;
2176 if (++i == param->num_headers)
2186 if (0 != memcmp (key,
2195 if (0 != memcmp (
value,
2224 struct test_header_param param;
2226 param.connection = connection;
2227 param.num_headers = 0;
2242 param.num_headers--;
2244 if (0 != param.num_headers)
2273 qmark = memchr (uri,
2283 if ((uri_len != connection->
rq.
url_len) ||
2284 (0 != memcmp (uri, connection->
rq.
url, uri_len)))
2288 _ (
"Authentication failed, URI does not match.\n"));
2293 args = (
NULL != qmark) ? (qmark + 1) : uri + uri_len;
2300 _ (
"Authentication failed, arguments do not match.\n"));
2311#define _MHD_STATIC_UNQ_BUFFER_SIZE 128
2327 size_t required_size)
2337 if (required_size <= *ptmp2_size)
2344 *ptmp2 = (
char *) malloc (required_size);
2348 *ptmp2_size = required_size;
2384 if (! param->quoted)
2386 unquoted->
str = param->value.str;
2387 unquoted->
len = param->value.len;
2396 len = MHD_str_unquote (param->value.str, param->value.len, str);
2397 unquoted->
str = str;
2398 unquoted->
len = len;
2434 if (! param->quoted)
2436 memcpy (unquoted->
str, param->value.str, param->value.len);
2437 unquoted->
len = param->value.len;
2442 MHD_str_unquote (param->value.str, param->value.len, unquoted->
str);
2457_MHD_static_inline
bool
2459 const char *
const str,
2460 const size_t str_len)
2465 return MHD_str_equal_quoted_bin_n (param->value.str, param->value.len,
2467 return (str_len == param->value.len) &&
2468 (0 == memcmp (str, param->value.str, str_len));
2481_MHD_static_inline
bool
2483 const char *
const str,
2484 const size_t str_len)
2489 return MHD_str_equal_quoted_bin_n (param->value.str, param->value.len,
2491 return (str_len == param->value.len) &&
2492 (0 == memcmp (str, param->value.str, str_len));
2536 const char *username,
2537 const char *password,
2538 const uint8_t *userdigest,
2539 unsigned int nonce_timeout,
2544 struct DigestAlgorithm *da)
2549 unsigned int digest_size;
2550 uint8_t hash1_bin[MAX_DIGEST];
2551 uint8_t hash2_bin[MAX_DIGEST];
2553 const char *hentity =
NULL;
2555 uint64_t nonce_time;
2557 const struct MHD_RqDAuth *params;
2562 char **
const ptmp2 = pbuf;
2567 size_t username_len;
2575 params = MHD_get_rq_dauth_params_ (connection);
2581 c_algo = params->algo3;
2583 if (((
unsigned int) c_algo) !=
2584 (((
unsigned int) c_algo) & ((
unsigned int) malgo3)))
2590 MHD_DLOG (connection->
daemon,
2591 _ (
"The 'session' algorithms are not supported.\n"));
2595#ifndef MHD_MD5_SUPPORT
2599 MHD_DLOG (connection->
daemon,
2600 _ (
"The MD5 algorithm is not supported by this MHD build.\n"));
2605#ifndef MHD_SHA256_SUPPORT
2609 MHD_DLOG (connection->
daemon,
2610 _ (
"The SHA-256 algorithm is not supported by "
2611 "this MHD build.\n"));
2616#ifndef MHD_SHA512_256_SUPPORT
2620 MHD_DLOG (connection->
daemon,
2621 _ (
"The SHA-512/256 algorithm is not supported by "
2622 "this MHD build.\n"));
2628 MHD_PANIC (
_ (
"Wrong 'malgo3' value, API violation"));
2630 c_qop = params->qop;
2632 if (((
unsigned int) c_qop) !=
2633 (((
unsigned int) c_qop) & ((
unsigned int) mqop)))
2638 MHD_DLOG (connection->
daemon,
2639 _ (
"The 'auth-int' QOP is not supported.\n"));
2646 MHD_DLOG (connection->
daemon,
2647 _ (
"RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
2648 "non-standard extension.\n"));
2655 if ((
NULL == params->username.value.str) &&
2656 (
NULL == params->username_ext.value.str))
2658 else if ((
NULL != params->username.value.str) &&
2659 (
NULL != params->username_ext.value.str))
2661 else if ((
NULL != params->username_ext.value.str) &&
2664 else if (params->userhash && (
NULL == params->username.value.str))
2666 else if (params->userhash && (digest_size * 2 > params->username.value.len))
2668 else if (params->userhash && (digest_size * 4 < params->username.value.len))
2671 if (
NULL == params->realm.value.str)
2673 else if (((
NULL == userdigest) || params->userhash) &&
2674 (_MHD_AUTH_DIGEST_MAX_PARAM_SIZE < params->realm.value.len))
2679 if (
NULL == params->nc.value.str)
2681 else if (0 == params->nc.value.len)
2683 else if (4 * 8 < params->nc.value.len)
2686 if (
NULL == params->cnonce.value.str)
2688 else if (0 == params->cnonce.value.len)
2690 else if (_MHD_AUTH_DIGEST_MAX_PARAM_SIZE < params->cnonce.value.len)
2696 if (
NULL == params->uri.value.str)
2698 else if (0 == params->uri.value.len)
2700 else if (_MHD_AUTH_DIGEST_MAX_PARAM_SIZE < params->uri.value.len)
2703 if (
NULL == params->nonce.value.str)
2705 else if (0 == params->nonce.value.len)
2707 else if (
NONCE_STD_LEN (digest_size) * 2 < params->nonce.value.len)
2710 if (
NULL == params->response.value.str)
2712 else if (0 == params->response.value.len)
2714 else if (digest_size * 4 < params->response.value.len)
2728 realm_len = strlen (realm);
2734 username_len = strlen (username);
2735 if (! params->userhash)
2737 if (
NULL != params->username.value.str)
2739 if (!
is_param_equal (¶ms->username, username, username_len))
2745 size_t buf_size = params->username_ext.value.len;
2753 if (
NULL == r_uname)
2757 params->username_ext.value.len,
2761 if ((username_len != (
size_t) res) ||
2762 (0 != memcmp (username, r_uname, username_len)))
2769 calc_userhash (da, username, username_len, realm, realm_len, hash1_bin);
2770#ifdef MHD_DIGEST_HAS_EXT_ERROR
2774 mhd_assert (
sizeof (tmp1) >= (2 * digest_size));
2801 _ (
"Authentication failed, invalid nc format.\n"));
2809 _ (
"Authentication failed, invalid 'nc' value.\n"));
2813 if ((0 != max_nc) && (max_nc < nci))
2831 _ (
"Authentication failed, invalid nonce format.\n"));
2867 _ (
"Stale nonce received. If this happens a lot, you should "
2868 "probably increase the size of the nonce array.\n"));
2871 _ (
"Stale nonce received. This is expected when client " \
2872 "uses RFC2069-compatible mode and makes more than one " \
2881 _ (
"Received nonce that was not "
2882 "generated by MHD. This may indicate an attack attempt.\n"));
2912#ifdef MHD_DIGEST_HAS_EXT_ERROR
2918 if (
NULL == userdigest)
2923 username, username_len,
2929#ifdef MHD_DIGEST_HAS_EXT_ERROR
2940 mhd_assert (
sizeof (tmp1) >= (digest_size * 2));
2941 if (
NULL == userdigest)
2945 digest_update (da, (
const uint8_t *) tmp1, digest_size * 2);
2995 digest_update (da, (
const uint8_t *) tmp1, digest_size * 2);
3000#ifdef MHD_DIGEST_HAS_EXT_ERROR
3005 if (0 != memcmp (hash1_bin, hash2_bin, digest_size))
3018 daemon->digest_auth_random,
3019 daemon->digest_auth_rand_size,
3027 daemon->dauth_bind_type,
3031#ifdef MHD_DIGEST_HAS_EXT_ERROR
3083 const char *username,
3084 const char *password,
3085 const uint8_t *userdigest,
3086 unsigned int nonce_timeout,
3093 struct DigestAlgorithm da;
3097 if (0 == nonce_timeout)
3098 nonce_timeout = connection->
daemon->dauth_def_nonce_timeout;
3100 max_nc = connection->
daemon->dauth_def_max_nc;
3104 max_nc, mqop, malgo3,
3135 const char *username,
3136 const char *password,
3137 unsigned int nonce_timeout)
3182 const char *username,
3183 const char *password,
3184 unsigned int nonce_timeout,
3248 const char *username,
3249 const void *userdigest,
3250 size_t userdigest_size,
3251 unsigned int nonce_timeout,
3259 MHD_PANIC (
_ (
"Wrong 'malgo3' value, only one base hashing algorithm " \
3260 "(MD5, SHA-256 or SHA-512/256) must be specified, " \
3263#ifndef MHD_MD5_SUPPORT
3267 MHD_DLOG (connection->
daemon,
3268 _ (
"The MD5 algorithm is not supported by this MHD build.\n"));
3273#ifndef MHD_SHA256_SUPPORT
3277 MHD_DLOG (connection->
daemon,
3278 _ (
"The SHA-256 algorithm is not supported by "
3279 "this MHD build.\n"));
3284#ifndef MHD_SHA512_256_SUPPORT
3288 MHD_DLOG (connection->
daemon,
3289 _ (
"The SHA-512/256 algorithm is not supported by "
3290 "this MHD build.\n"));
3298 MHD_PANIC (
_ (
"Wrong 'userdigest_size' value, does not match 'malgo3', "
3305 (
const uint8_t *) userdigest,
3332 const char *username,
3333 const char *password,
3334 unsigned int nonce_timeout,
3347 MHD_PANIC (
_ (
"Wrong 'algo' value, API violation"));
3388 const char *username,
3389 const uint8_t *digest,
3391 unsigned int nonce_timeout,
3404 MHD_PANIC (
_ (
"Wrong 'algo' value, API violation"));
3445 const char *username,
3447 unsigned int nonce_timeout)
3517 int userhash_support,
3520 struct DigestAlgorithm *da)
3522 static const char prefix_realm[] =
"realm=\"";
3523 static const char prefix_qop[] =
"qop=\"";
3524 static const char prefix_algo[] =
"algorithm=";
3525 static const char prefix_nonce[] =
"nonce=\"";
3526 static const char prefix_opaque[] =
"opaque=\"";
3527 static const char prefix_domain[] =
"domain=\"";
3528 static const char str_charset[] =
"charset=UTF-8";
3529 static const char str_userhash[] =
"userhash=true";
3530 static const char str_stale[] =
"stale=true";
3543 MHD_DLOG (connection->
daemon,
3544 _ (
"Only non-'session' algorithms are supported.\n"));
3551#ifdef MHD_MD5_SUPPORT
3556#ifdef MHD_SHA256_SUPPORT
3561#ifdef MHD_SHA512_256_SUPPORT
3567 if (0 == (((
unsigned int) malgo3)
3570 MHD_PANIC (
_ (
"Wrong 'malgo3' value, API violation"));
3574 MHD_DLOG (connection->
daemon,
3575 _ (
"No requested algorithm is supported by this MHD build.\n"));
3582 MHD_PANIC (
_ (
"Wrong 'mqop' value, API violation"));
3587 MHD_PANIC (
_ (
"Wrong 'algo' value, API violation"));
3592 if ((0 != userhash_support) || (0 != prefer_utf8))
3593 MHD_DLOG (connection->
daemon,
3594 _ (
"The 'userhash' and 'charset' ('prefer_utf8') parameters " \
3595 "are not compatible with RFC2069 and ignored.\n"));
3597 MHD_DLOG (connection->
daemon,
3598 _ (
"RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
3599 "non-standard extension.\n"));
3601 userhash_support = 0;
3608 MHD_DLOG (connection->
daemon,
3609 _ (
"The nonce array size is zero.\n"));
3620 realm_len = strlen (realm);
3624 MHD_DLOG (connection->
daemon,
3625 _ (
"The 'realm' is too large.\n"));
3629 if ((
NULL != memchr (realm,
'\r', realm_len)) ||
3630 (
NULL != memchr (realm,
'\n', realm_len)))
3633 buf_size += realm_len * 2;
3645#ifdef MHD_MD5_SUPPORT
3650#ifdef MHD_SHA256_SUPPORT
3655#ifdef MHD_SHA512_256_SUPPORT
3669 opaque_len = strlen (opaque);
3670 if ((
NULL != memchr (opaque,
'\r', opaque_len)) ||
3671 (
NULL != memchr (opaque,
'\n', opaque_len)))
3674 buf_size += opaque_len * 2;
3682 domain_len = strlen (domain);
3683 if ((
NULL != memchr (domain,
'\r', domain_len)) ||
3684 (
NULL != memchr (domain,
'\n', domain_len)))
3687 buf_size += domain_len * 2;
3692 if (
MHD_NO != prefer_utf8)
3695 if (
MHD_NO != userhash_support)
3698 if (
MHD_NO != signal_stale)
3705 buf = malloc (buf_size);
3718 memcpy (buf + p, prefix_realm,
3721 mhd_assert ((buf_size - p) >= (realm_len * 2));
3725 quoted_size = MHD_str_quote (realm, realm_len, buf + p, buf_size - p);
3729 MHD_DLOG (connection->
daemon,
3730 _ (
"The 'realm' is too large after 'quoting'.\n"));
3742 memcpy (buf + p, prefix_qop,
3756 memcpy (buf + p, prefix_algo,
3759#ifdef MHD_MD5_SUPPORT
3768#ifdef MHD_SHA256_SUPPORT
3777#ifdef MHD_SHA512_256_SUPPORT
3791 memcpy (buf + p, prefix_nonce,
3797#ifdef MHD_DIGEST_HAS_EXT_ERROR
3801 MHD_DLOG (connection->
daemon,
3802 _ (
"TLS library reported hash calculation error, nonce could "
3803 "not be generated.\n"));
3809 MHD_DLOG (connection->
daemon,
3810 _ (
"Could not register nonce. Client's requests with this "
3811 "nonce will be always 'stale'. Probably clients' requests "
3812 "are too intensive.\n"));
3823 memcpy (buf + p, prefix_opaque,
3826 mhd_assert ((buf_size - p) >= (opaque_len * 2));
3827 p += MHD_str_quote (opaque, opaque_len, buf + p, buf_size - p);
3835 memcpy (buf + p, prefix_domain,
3838 mhd_assert ((buf_size - p) >= (domain_len * 2));
3839 p += MHD_str_quote (domain, domain_len, buf + p, buf_size - p);
3845 if (
MHD_NO != prefer_utf8)
3847 memcpy (buf + p, str_charset,
3854 if (
MHD_NO != userhash_support)
3856 memcpy (buf + p, str_userhash,
3863 if (
MHD_NO != signal_stale)
3865 memcpy (buf + p, str_stale,
3877 if (
NULL != hdr_name)
3893 MHD_DLOG (connection->
daemon,
3894 _ (
"Failed to add Digest auth header.\n"));
3974 int userhash_support,
3977 struct DigestAlgorithm da;
3996 if (
NULL != buf_ptr)
4038 NULL, response, signal_stale,
_MHD_static_inline enum MHD_DigestBaseAlgo get_base_digest_algo(enum MHD_DigestAuthAlgo3 algo3)
#define digest_deinit(da)
_MHD_static_inline void calc_userhash(struct DigestAlgorithm *da, const char *username, const size_t username_len, const char *realm, const size_t realm_len, uint8_t *digest_bin)
@ MHD_CHECK_NONCENC_STALE
@ MHD_CHECK_NONCENC_WRONG
#define TRIM_TO_TIMESTAMP(value)
static enum MHD_Result test_header(void *cls, const char *key, size_t key_size, const char *value, size_t value_size, enum MHD_ValueKind kind)
static bool check_uri_match(struct MHD_Connection *connection, char *uri, size_t uri_len)
#define TIMESTAMP_CHARS_LEN
static enum MHD_GetRqNCResult get_rq_nc(const struct MHD_RqDAuth *params, uint32_t *nc)
static MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_ bool calculate_add_nonce_with_retry(struct MHD_Connection *const connection, const char *realm, struct DigestAlgorithm *da, char *nonce)
static MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_ size_t get_nonce_nc_idx(size_t arr_size, const char *nonce, size_t noncelen)
_MHD_static_inline void digest_update_with_colon(struct DigestAlgorithm *da)
#define NONCE_STD_LEN(digest_size)
_MHD_static_inline void digest_reset(struct DigestAlgorithm *da)
#define TIMESTAMP_BIN_SIZE
@ MHD_GET_RQ_NC_TOO_LARGE
static size_t get_rq_param_unquoted_copy_z(const struct MHD_RqDAuthParam *param, char *buf)
static ssize_t get_rq_extended_uname_copy_z(const char *uname_ext, size_t uname_ext_len, char *buf, size_t buf_size)
#define digest_ext_error(da)
_MHD_static_inline bool is_param_equal(const struct MHD_RqDAuthParam *param, const char *const str, const size_t str_len)
static void calculate_nonce(uint64_t nonce_time, enum MHD_HTTP_Method mthd_e, const char *method, const char *rnd, size_t rnd_size, const struct sockaddr_storage *saddr, size_t saddr_size, const char *uri, size_t uri_len, const struct MHD_HTTP_Req_Header *first_header, const char *realm, size_t realm_len, unsigned int bind_options, struct DigestAlgorithm *da, char *nonce)
static size_t get_rq_uname(const struct MHD_RqDAuth *params, enum MHD_DigestAuthUsernameType uname_type, struct MHD_DigestAuthUsernameInfo *uname_info, uint8_t *buf, size_t buf_size)
static enum _MHD_GetUnqResult get_unquoted_param_copy(const struct MHD_RqDAuthParam *param, char tmp1[_MHD_STATIC_UNQ_BUFFER_SIZE], char **ptmp2, size_t *ptmp2_size, struct _MHD_mstr_w_len *unquoted)
static bool calculate_add_nonce(struct MHD_Connection *const connection, uint64_t timestamp, const char *realm, size_t realm_len, struct DigestAlgorithm *da, char *nonce)
_MHD_static_inline size_t digest_get_hash_size(enum MHD_DigestAuthAlgo3 algo3)
#define MHD_DAUTH_EXT_PARAM_PREFIX
static enum _MHD_GetUnqResult get_unquoted_param(const struct MHD_RqDAuthParam *param, char tmp1[_MHD_STATIC_UNQ_BUFFER_SIZE], char **ptmp2, size_t *ptmp2_size, struct _MHD_str_w_len *unquoted)
static enum MHD_CheckNonceNC_ check_nonce_nc(struct MHD_Connection *connection, const char *nonce, size_t noncelen, uint64_t nonce_time, uint64_t nc)
static char * get_buffer_for_size(char tmp1[_MHD_STATIC_UNQ_BUFFER_SIZE], char **ptmp2, size_t *ptmp2_size, size_t required_size)
_MHD_static_inline size_t get_rq_unames_size(const struct MHD_RqDAuth *params, enum MHD_DigestAuthUsernameType uname_type)
#define DAUTH_JUMPBACK_MAX
_MHD_static_inline enum MHD_DigestAuthUsernameType get_rq_uname_type(const struct MHD_RqDAuth *params)
#define _MHD_STATIC_UNQ_BUFFER_SIZE
MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_ _MHD_static_inline void calc_userdigest(struct DigestAlgorithm *da, const char *username, const size_t username_len, const char *realm, const size_t realm_len, const char *password, uint8_t *ha1_bin)
_MHD_static_inline void digest_update(struct DigestAlgorithm *da, const void *data, size_t length)
_MHD_static_inline bool is_param_equal_caseless(const struct MHD_RqDAuthParam *param, const char *const str, const size_t str_len)
static bool get_nonce_timestamp(const char *const nonce, size_t noncelen, uint64_t *const ptimestamp)
_MHD_static_inline void digest_calc_hash(struct DigestAlgorithm *da, uint8_t *digest)
_MHD_static_inline void digest_update_str(struct DigestAlgorithm *da, const char *str)
static MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_ uint32_t fast_simple_hash(const uint8_t *data, size_t data_size)
_MHD_static_inline bool digest_init_one_time(struct DigestAlgorithm *da, enum MHD_DigestBaseAlgo algo)
_MHD_static_inline unsigned int digest_get_size(struct DigestAlgorithm *da)
static bool check_argument_match(struct MHD_Connection *connection, char *args)
#define digest_setup_zero(da)
#define MHD_DAUTH_EXT_PARAM_MIN_LEN
static bool is_slot_available(const struct MHD_NonceNc *const nn, const uint64_t now, const char *const new_nonce, size_t new_nonce_len)
#define _MHD_SHA256_TOKEN
#define _MHD_SHA512_256_TOKEN
#define _MHD_AUTH_DIGEST_BASE
#define _MHD_AUTH_DIGEST_MAX_PARAM_SIZE
Declarations for HTTP authorisation general functions.
_MHD_EXTERN enum MHD_Result MHD_digest_auth_calc_userdigest(enum MHD_DigestAuthAlgo3 algo3, const char *username, const char *realm, const char *password, void *userdigest_bin, size_t bin_buf_size)
static enum MHD_DigestAuthResult digest_auth_check_all_inner(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, const uint8_t *userdigest, unsigned int nonce_timeout, uint32_t max_nc, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo3 malgo3, char **pbuf, struct DigestAlgorithm *da)
#define MHD_SHA512_256_DIGEST_SIZE
static enum MHD_DigestAuthResult digest_auth_check_all(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, const uint8_t *userdigest, unsigned int nonce_timeout, uint32_t max_nc, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo3 malgo3)
_MHD_EXTERN enum MHD_Result MHD_queue_auth_fail_response(struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale)
_MHD_EXTERN int MHD_digest_auth_check2(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout, enum MHD_DigestAuthAlgorithm algo)
_MHD_EXTERN enum MHD_Result MHD_queue_auth_required_response3(struct MHD_Connection *connection, const char *realm, const char *opaque, const char *domain, struct MHD_Response *response, int signal_stale, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo3 algo, int userhash_support, int prefer_utf8)
_MHD_EXTERN int MHD_digest_auth_check_digest2(struct MHD_Connection *connection, const char *realm, const char *username, const uint8_t *digest, size_t digest_size, unsigned int nonce_timeout, enum MHD_DigestAuthAlgorithm algo)
_MHD_EXTERN enum MHD_Result MHD_digest_auth_calc_userhash_hex(enum MHD_DigestAuthAlgo3 algo3, const char *username, const char *realm, char *userhash_hex, size_t hex_buf_size)
_MHD_EXTERN enum MHD_DigestAuthResult MHD_digest_auth_check_digest3(struct MHD_Connection *connection, const char *realm, const char *username, const void *userdigest, size_t userdigest_size, unsigned int nonce_timeout, uint32_t max_nc, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo3 malgo3)
_MHD_EXTERN enum MHD_Result MHD_queue_auth_fail_response2(struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale, enum MHD_DigestAuthAlgorithm algo)
_MHD_EXTERN struct MHD_DigestAuthInfo * MHD_digest_auth_get_request_info3(struct MHD_Connection *connection)
_MHD_EXTERN size_t MHD_digest_get_hash_size(enum MHD_DigestAuthAlgo3 algo3)
_MHD_EXTERN int MHD_digest_auth_check_digest(struct MHD_Connection *connection, const char *realm, const char *username, const uint8_t digest[MHD_MD5_DIGEST_SIZE], unsigned int nonce_timeout)
_MHD_EXTERN char * MHD_digest_auth_get_username(struct MHD_Connection *connection)
_MHD_EXTERN int MHD_digest_auth_check(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout)
#define MHD_INVALID_NONCE
static enum MHD_Result queue_auth_required_response3_inner(struct MHD_Connection *connection, const char *realm, const char *opaque, const char *domain, struct MHD_Response *response, int signal_stale, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo3 malgo3, int userhash_support, int prefer_utf8, char **buf_ptr, struct DigestAlgorithm *da)
#define MHD_SHA256_DIGEST_SIZE
_MHD_EXTERN enum MHD_DigestAuthResult MHD_digest_auth_check3(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout, uint32_t max_nc, enum MHD_DigestAuthMultiQOP mqop, enum MHD_DigestAuthMultiAlgo3 malgo3)
_MHD_EXTERN enum MHD_Result MHD_digest_auth_calc_userhash(enum MHD_DigestAuthAlgo3 algo3, const char *username, const char *realm, void *userhash_bin, size_t bin_buf_size)
_MHD_EXTERN struct MHD_DigestAuthUsernameInfo * MHD_digest_auth_get_username3(struct MHD_Connection *connection)
#define MHD_MD5_DIGEST_SIZE
#define MHD_HTTP_UNAUTHORIZED
_MHD_EXTERN enum MHD_Result MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
void * MHD_calloc_(size_t nelem, size_t elsize)
#define MHD_mutex_unlock_chk_(pmutex)
#define MHD_mutex_lock_chk_(pmutex)
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
#define MHD_STATICSTR_LEN_(macro)
void MHD_MD5_finish(struct Md5Ctx *ctx, uint8_t digest[MD5_DIGEST_SIZE])
void MHD_MD5_update(struct Md5Ctx *ctx, const uint8_t *data, size_t length)
macros for bits manipulations
_MHD_static_inline uint32_t _MHD_ROTR32(uint32_t value32, int bits)
_MHD_static_inline uint32_t _MHD_ROTL32(uint32_t value32, int bits)
Simple wrapper for selection of built-in/external MD5 implementation.
#define MHD_MD5_finish_reset(ctx, digest)
#define MHD_MD5_deinit(ignore)
#define MHD_MD5_reset(ctx)
#define MHD_MD5_init_one_time(ctx)
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_
Simple wrapper for selection of built-in/external SHA-256 implementation.
#define MHD_SHA256_deinit(ignore)
#define MHD_SHA256_init_one_time(ctx)
#define MHD_SHA256_reset(ctx)
#define MHD_SHA256_finish_reset(ctx, digest)
MHD internal shared structures.
#define MAX_DIGEST_NONCE_LENGTH
_MHD_static_inline struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *const daemon)
Header for platform missing functions.
limits values definitions
Header for platform-independent locks abstraction.
uint64_t MHD_monotonic_msec_counter(void)
internal monotonic clock functions implementations
size_t MHD_bin_to_hex(const void *bin, size_t size, char *hex)
size_t MHD_str_pct_decode_strict_n_(const char *pct_encoded, size_t pct_encoded_len, char *decoded, size_t buf_size)
size_t MHD_bin_to_hex_z(const void *bin, size_t size, char *hex)
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
size_t MHD_hex_to_bin(const char *hex, size_t len, void *bin)
Header for string manipulating helpers.
bool MHD_add_response_entry_no_alloc_(struct MHD_Response *response, enum MHD_ValueKind kind, char *header, size_t header_len, char *content, size_t content_len)
@ MHD_DAUTH_RESPONSE_WRONG
@ MHD_DAUTH_NONCE_OTHER_COND
@ MHD_DAUTH_WRONG_USERNAME
#define MHD_DIGEST_AUTH_ALGO3_SESSION
#define MHD_DIGEST_AUTH_ALGO3_NON_SESSION
@ MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT
@ MHD_DIGEST_AUTH_MULT_QOP_AUTH
@ MHD_DIGEST_AUTH_MULT_QOP_NONE
@ MHD_DIGEST_BASE_ALGO_INVALID
@ MHD_DIGEST_BASE_ALGO_SHA256
@ MHD_DIGEST_BASE_ALGO_SHA512_256
@ MHD_DIGEST_BASE_ALGO_MD5
@ MHD_DIGEST_AUTH_ALGO3_MD5
@ MHD_DIGEST_AUTH_ALGO3_SHA256
@ MHD_DIGEST_AUTH_ALGO3_SHA512_256
@ MHD_DIGEST_AUTH_QOP_NONE
@ MHD_DIGEST_AUTH_QOP_AUTH_INT
MHD_DigestAuthUsernameType
@ MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD
@ MHD_DIGEST_AUTH_UNAME_TYPE_MISSING
@ MHD_DIGEST_AUTH_UNAME_TYPE_INVALID
@ MHD_DIGEST_AUTH_UNAME_TYPE_EXTENDED
@ MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH
#define MHD_DIGEST_AUTH_INVALID_NC_VALUE
@ MHD_DIGEST_AUTH_MULT_ALGO3_SHA256
@ MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION
@ MHD_DIGEST_AUTH_MULT_ALGO3_MD5
@ MHD_DAUTH_BIND_NONCE_NONE
@ MHD_DAUTH_BIND_NONCE_URI
@ MHD_DAUTH_BIND_NONCE_URI_PARAMS
@ MHD_DAUTH_BIND_NONCE_REALM
@ MHD_DAUTH_BIND_NONCE_CLIENT_IP
Methods for managing response objects.
void MHD_SHA256_update(struct Sha256Ctx *ctx, const uint8_t *data, size_t length)
void MHD_SHA256_finish(struct Sha256Ctx *ctx, uint8_t digest[SHA256_DIGEST_SIZE])
#define SHA256_DIGEST_SIZE
void MHD_SHA512_256_finish(struct Sha512_256Ctx *ctx, uint8_t digest[SHA512_256_DIGEST_SIZE])
void MHD_SHA512_256_init(struct Sha512_256Ctx *ctx)
void MHD_SHA512_256_update(struct Sha512_256Ctx *ctx, const uint8_t *data, size_t length)
Calculation of SHA-512/256 digest.
#define SHA512_256_DIGEST_SIZE
struct sockaddr_storage addr
struct MHD_Daemon * daemon
void * unescape_callback_cls
UnescapeCallback unescape_callback
enum MHD_DigestAuthQOP qop
enum MHD_DigestAuthUsernameType uname_type
enum MHD_DigestAuthAlgo3 algo3
enum MHD_DigestAuthAlgo3 algo3
enum MHD_DigestAuthUsernameType uname_type
char nonce[MAX_DIGEST_NONCE_LENGTH+1]
struct MHD_HTTP_Header * headers_received
enum MHD_HTTP_Method http_mthd