39#ifdef MHD_SHA256_SUPPORT
42#ifdef MHD_SHA512_256_SUPPORT
60#define REUSE_TIMEOUT 30
66#define DAUTH_JUMPBACK_MAX (0x7F)
72#define TIMESTAMP_BIN_SIZE (48 / 8)
78#define TRIM_TO_TIMESTAMP(value) \
79 ((value) & ((UINT64_C (1) << (TIMESTAMP_BIN_SIZE * 8)) - 1))
85#define TIMESTAMP_CHARS_LEN (TIMESTAMP_BIN_SIZE * 2)
93#define NONCE_STD_LEN(digest_size) \
94 ((digest_size) * 2 + TIMESTAMP_CHARS_LEN)
97#ifdef MHD_SHA512_256_SUPPORT
102#define MAX_DIGEST SHA512_256_DIGEST_SIZE
107#define SHA256_SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_SIZE
108#elif defined(MHD_SHA256_SUPPORT)
113#define MAX_DIGEST SHA256_DIGEST_SIZE
118#define SHA256_SHA512_256_DIGEST_SIZE SHA256_DIGEST_SIZE
119#elif defined(MHD_MD5_SUPPORT)
123#define MAX_DIGEST MD5_DIGEST_SIZE
125#error At least one hashing algorithm must be enabled
132#ifndef HAVE_C_VARARRAYS
138#define VLA_ARRAY_LEN_DIGEST(n) (MAX_DIGEST)
146#define VLA_ARRAY_LEN_DIGEST(n) (n)
152#define VLA_CHECK_LEN_DIGEST(n) \
153 do { if ((n) > MAX_DIGEST) MHD_PANIC (_ ("VLA too big.\n")); } while (0)
158#define MAX_USERNAME_LENGTH 128
163#define MAX_REALM_LENGTH 256
168#define MAX_AUTH_RESPONSE_LENGTH (MAX_DIGEST * 2)
173#define MHD_DAUTH_EXT_PARAM_PREFIX "UTF-8'"
178#define MHD_DAUTH_EXT_PARAM_MIN_LEN \
179 MHD_STATICSTR_LEN_ (MHD_DAUTH_EXT_PARAM_PREFIX "'")
213 unsigned int base_algo;
216 ((
unsigned int) algo3)
232_MHD_static_inline
size_t
235#ifdef MHD_MD5_SUPPORT
238#ifdef MHD_SHA256_SUPPORT
241#ifdef MHD_SHA512_256_SUPPORT
243#ifdef MHD_SHA256_SUPPORT
252#ifdef MHD_MD5_SUPPORT
253 if (0 != (((
unsigned int) algo3)
258#if defined(MHD_SHA256_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
259 if (0 != (((
unsigned int) algo3)
264#elif defined(MHD_SHA256_SUPPORT)
265 if (0 != (((
unsigned int) algo3)
269#elif defined(MHD_SHA512_256_SUPPORT)
270 if (0 != (((
unsigned int) algo3)
307#ifdef MHD_MD5_SUPPORT
310#ifdef MHD_SHA256_SUPPORT
313#ifdef MHD_SHA512_256_SUPPORT
321struct DigestAlgorithm
340 bool ready_for_hashing;
351_MHD_static_inline
unsigned int
356#ifdef MHD_MD5_SUPPORT
360#ifdef MHD_SHA256_SUPPORT
364#ifdef MHD_SHA512_256_SUPPORT
373#if defined(MHD_MD5_HAS_DEINIT) || defined(MHD_SHA256_HAS_DEINIT)
377#define MHD_DIGEST_HAS_DEINIT 1
380#ifdef MHD_DIGEST_HAS_DEINIT
388_MHD_static_inline
void
392 da->uninitialised =
false;
393 da->algo_selected =
false;
394 da->ready_for_hashing =
false;
410_MHD_static_inline
void
414#ifdef MHD_MD5_HAS_DEINIT
419#ifdef MHD_SHA256_HAS_DEINIT
430#define digest_setup_zero(da) (void) 0
431#define digest_deinit(da) (void) 0
448_MHD_static_inline
bool
453 da->uninitialised =
false;
454 da->algo_selected =
false;
455 da->ready_for_hashing =
false;
458#ifdef MHD_MD5_SUPPORT
463 da->algo_selected =
true;
467 da->ready_for_hashing =
true;
472#ifdef MHD_SHA256_SUPPORT
477 da->algo_selected =
true;
481 da->ready_for_hashing =
true;
486#ifdef MHD_SHA512_256_SUPPORT
491 da->algo_selected =
true;
495 da->ready_for_hashing =
true;
512_MHD_static_inline
void
520#ifdef MHD_MD5_SUPPORT
525#ifdef MHD_SHA256_SUPPORT
530#ifdef MHD_SHA512_256_SUPPORT
533 (
const uint8_t *)
data, length);
548_MHD_static_inline
void
552 const size_t str_len = strlen (str);
562_MHD_static_inline
void
565 static const uint8_t colon = (uint8_t)
':';
576_MHD_static_inline
void
582#ifdef MHD_MD5_SUPPORT
585#ifdef MHD_MD5_HAS_FINISH
588 da->ready_for_hashing =
false;
593 da->ready_for_hashing =
true;
599#ifdef MHD_SHA256_SUPPORT
602#ifdef MHD_SHA256_HAS_FINISH
605 da->ready_for_hashing =
false;
610 da->ready_for_hashing =
true;
616#ifdef MHD_SHA512_256_SUPPORT
621 da->ready_for_hashing =
false;
638_MHD_static_inline
void
644#ifdef MHD_MD5_SUPPORT
647#ifdef MHD_MD5_HAS_FINISH
654 da->ready_for_hashing =
true;
659#ifdef MHD_SHA256_SUPPORT
662#ifdef MHD_SHA256_HAS_FINISH
669 da->ready_for_hashing =
true;
674#ifdef MHD_SHA512_256_SUPPORT
680 da->ready_for_hashing =
true;
687 da->ready_for_hashing =
false;
694#if defined(MHD_MD5_HAS_EXT_ERROR) || defined(MHD_SHA256_HAS_EXT_ERROR)
698#define MHD_DIGEST_HAS_EXT_ERROR 1
701#ifdef MHD_DIGEST_HAS_EXT_ERROR
711_MHD_static_inline
bool
716#ifdef MHD_MD5_HAS_EXT_ERROR
718 return 0 != da->ctx.md5_ctx.ext_error;
720#ifdef MHD_SHA256_HAS_EXT_ERROR
722 return 0 != da->ctx.sha256_ctx.ext_error;
729#define digest_ext_error(da) (false)
744 uint64_t *
const ptimestamp)
747 noncelen = strlen (nonce);
750#ifdef MHD_MD5_SUPPORT
753#
if defined(MHD_SHA256_SUPPORT) || defined(MHD_SHA512_256_SUPPORT)
754 && (
NONCE_STD_LEN (SHA256_SHA512_256_DIGEST_SIZE) != noncelen)
787 for (i = 1; i < data_size; i++)
851 mod = daemon->nonce_nc_size;
868 if (strlen (nn->
nonce) != noncelen)
870 if (0 == nn->
nonce[0])
881 else if (0 != memcmp (nn->
nonce,
nonce, noncelen))
883 if (0 == nn->
nonce[0])
923 else if (
nc > nn->
nc)
926 const uint32_t jump_size = (uint32_t)
nc - nn->
nc;
930 nn->
nmask <<= jump_size;
932 nn->
nmask |= (UINT64_C (1) << (jump_size - 1));
934 else if (64 == jump_size)
935 nn->
nmask = (UINT64_C (1) << 63);
938 nn->
nc = (uint32_t)
nc;
945 if ( (
nc + 64 >= nn->
nc) &&
946 (0 == ((UINT64_C (1) << (nn->
nc -
nc - 1)) & nn->
nmask)) )
949 nn->
nmask |= (UINT64_C (1) << (nn->
nc -
nc - 1));
976 if (
NULL != params->username.value.str)
978 if (
NULL == params->username_ext.value.str)
979 return params->userhash ?
985 else if (
NULL != params->username_ext.value.str)
987 if (! params->username_ext.quoted && ! params->userhash &&
1005_MHD_static_inline
size_t
1016 s += params->username.value.len + 1;
1018 s += (params->username.value.len + 1) / 2;
1021 s += params->username_ext.value.len
1040 if (! param->quoted)
1042 memcpy (buf, param->value.str, param->value.len);
1043 buf [param->value.len] = 0;
1044 return param->value.len;
1047 len = MHD_str_unquote (param->value.str, param->value.len, buf);
1067 char *buf,
size_t buf_size)
1084 while (r < uname_ext_len &&
'\'' != uname_ext[r])
1086 const char chr = uname_ext[r];
1087 if ((
' ' == chr) || (
'\t' == chr) || (
'\"' == chr) || (
',' == chr) ||
1092 if (r >= uname_ext_len)
1098 if ((0 == w) && (0 != uname_ext_len - r))
1137 uname_info->
username = (
char *) (buf + buf_used);
1153 uname_info->
userhash_bin = (uint8_t *) (buf + buf_used);
1175 params->username_ext.value.len,
1176 (
char *) (buf + buf_used),
1177 buf_size - buf_used);
1182 uname_info->
username = (
char *) (buf + buf_used);
1221 const struct MHD_RqDAuthParam *
const nc_param =
1229 if (
NULL == nc_param->value.str)
1232 if (0 == nc_param->value.len)
1235 if (! nc_param->quoted)
1237 val = nc_param->value.str;
1238 val_len = nc_param->value.len;
1243 if (
sizeof(unq) < params->nc.value.len)
1245 val_len = MHD_str_unquote (nc_param->value.str, nc_param->value.len, unq);
1254 const char f = val[0];
1255 if ( ((
'9' >= f) && (
'0' <= f)) ||
1256 ((
'F' >= f) && (
'A' <= f)) ||
1257 ((
'a' <= f) && (
'f' >= f)) )
1266 *nc = (uint32_t) nc_val;
1284 const struct MHD_RqDAuth *params;
1287 size_t unif_buf_size;
1288 uint8_t *unif_buf_ptr;
1289 size_t unif_buf_used;
1292 params = MHD_get_rq_dauth_params_ (connection);
1302 if (
NULL != params->opaque.value.str)
1303 unif_buf_size += params->opaque.value.len + 1;
1304 if (
NULL != params->realm.value.str)
1305 unif_buf_size += params->realm.value.len + 1;
1310 unif_buf_ptr = (uint8_t *) (info + 1);
1313 info->
algo3 = params->algo3;
1320 unif_buf_ptr + unif_buf_used,
1321 unif_buf_size - unif_buf_used);
1325 if (
NULL != params->opaque.value.str)
1327 info->
opaque = (
char *) (unif_buf_ptr + unif_buf_used);
1332 if (
NULL != params->realm.value.str)
1334 info->
realm = (
char *) (unif_buf_ptr + unif_buf_used);
1342 info->
qop = params->qop;
1344 if (
NULL != params->cnonce.value.str)
1374 const struct MHD_RqDAuth *params;
1377 size_t unif_buf_size;
1378 uint8_t *unif_buf_ptr;
1379 size_t unif_buf_used;
1381 params = MHD_get_rq_dauth_params_ (connection);
1395 if (
NULL == uname_info)
1397 unif_buf_ptr = (uint8_t *) (uname_info + 1);
1401 (void) unif_buf_used;
1410 uname_info->
algo3 = params->algo3;
1434 const struct MHD_RqDAuth *params;
1439 params = MHD_get_rq_dauth_params_ (connection);
1454 if (
NULL == username)
1462 memset (&uname_strct, 0,
sizeof(uname_strct));
1508 const struct sockaddr_storage *saddr,
1515 unsigned int bind_options,
1516 struct DigestAlgorithm *da,
1526#if TIMESTAMP_BIN_SIZE != 6
1527#error The code needs to be updated here
1540 sizeof (timestamp));
1565 if (AF_INET == saddr->ss_family)
1567 &((
const struct sockaddr_in *) saddr)->sin_addr,
1568 sizeof(((
const struct sockaddr_in *) saddr)->sin_addr));
1570 else if (AF_INET6 == saddr->ss_family)
1572 &((
const struct sockaddr_in6 *) saddr)->sin6_addr,
1573 sizeof(((
const struct sockaddr_in6 *) saddr)->sin6_addr));
1583 uint8_t mthd_for_hash;
1585 mthd_for_hash = (uint8_t) mthd_e;
1590 sizeof(mthd_for_hash));
1611 for (h = first_header;
NULL != h; h = h->
next)
1634 uint8_t hash[MAX_DIGEST];
1661 const char *
const new_nonce,
1662 size_t new_nonce_len)
1665 bool timestamp_valid;
1668 if (0 == nn->
nonce[0])
1671 if (0 == memcmp (nn->
nonce, new_nonce, new_nonce_len))
1689 if (! timestamp_valid)
1719 struct DigestAlgorithm *da,
1734 daemon->digest_auth_random,
1735 daemon->digest_auth_rand_size,
1743 daemon->dauth_bind_type,
1747#ifdef MHD_DIGEST_HAS_EXT_ERROR
1752 if (0 == daemon->nonce_nc_size)
1768 nn->
nonce[nonce_size] = 0;
1797 struct DigestAlgorithm *da,
1801 const size_t realm_len = strlen (realm);
1806 MHD_DLOG (connection->
daemon,
1807 _ (
"Random value was not initialised by " \
1808 "MHD_OPTION_DIGEST_AUTH_RANDOM or " \
1809 "MHD_OPTION_DIGEST_AUTH_RANDOM_COPY, generated nonces " \
1810 "are predictable.\n"));
1825 uint64_t timestamp2;
1826#ifdef MHD_DIGEST_HAS_EXT_ERROR
1834 if (timestamp1 == timestamp2)
1845 base1 = ((uint64_t) random ()) ^ UINT64_C (0x54a5acff5be47e63);
1847#elif defined(HAVE_RAND)
1848 base1 = ((uint64_t) rand ()) ^ UINT64_C (0xc4bcf553b12f3965);
1853 base1 = ((uint64_t) (uintptr_t) nonce2) ^ UINT64_C (0xf2e1b21bc6c92655);
1854 base2 = ((uint32_t) (base1 >> 32)) ^ ((uint32_t) base1);
1856 base3 = ((uint16_t) (base2 >> 16)) ^ ((uint16_t) base2);
1857 base4 = ((uint8_t) (base3 >> 8)) ^ ((uint8_t) base3);
1859 ^ UINT64_C (0xccab93f72cf5b15);
1861 base2 = ((uint32_t) (base1 >> 32)) ^ ((uint32_t) base1);
1862 base2 =
_MHD_ROTL32 (base2, (((base4 >> 4) ^ base4) % 32));
1863 base3 = ((uint16_t) (base2 >> 16)) ^ ((uint16_t) base2);
1864 base4 = ((uint8_t) (base3 >> 8)) ^ ((uint8_t) base3);
1867 if (timestamp1 == timestamp2)
1904_MHD_static_inline
void
1906 const char *username,
const size_t username_len,
1907 const char *realm,
const size_t realm_len,
1908 const char *password,
1956 const char *username,
1958 const char *password,
1959 void *userdigest_bin,
1960 size_t bin_buf_size)
1962 struct DigestAlgorithm da;
1980#ifdef MHD_DIGEST_HAS_EXT_ERROR
2004_MHD_static_inline
void
2006 const char *username,
const size_t username_len,
2007 const char *realm,
const size_t realm_len,
2008 uint8_t *digest_bin)
2061 const char *username,
2064 size_t bin_buf_size)
2066 struct DigestAlgorithm da;
2083#ifdef MHD_DIGEST_HAS_EXT_ERROR
2136 const char *username,
2139 size_t hex_buf_size)
2141 uint8_t userhash_bin[MAX_DIGEST];
2145 if (digest_size * 2 + 1 > hex_buf_size)
2148 userhash_bin, MAX_DIGEST))
2156struct test_header_param
2183 struct test_header_param *
const param = (
struct test_header_param *) cls;
2188 param->num_headers++;
2194 if (++i == param->num_headers)
2204 if (0 != memcmp (key,
2213 if (0 != memcmp (
value,
2242 struct test_header_param param;
2244 param.connection = connection;
2245 param.num_headers = 0;
2260 param.num_headers--;
2262 if (0 != param.num_headers)
2291 qmark = memchr (uri,
2301 if ((uri_len != connection->
rq.
url_len) ||
2302 (0 != memcmp (uri, connection->
rq.
url, uri_len)))
2306 _ (
"Authentication failed, URI does not match.\n"));
2311 args = (
NULL != qmark) ? (qmark + 1) : uri + uri_len;
2318 _ (
"Authentication failed, arguments do not match.\n"));
2329#define _MHD_STATIC_UNQ_BUFFER_SIZE 128
2345 size_t required_size)
2355 if (required_size <= *ptmp2_size)
2362 *ptmp2 = (
char *) malloc (required_size);
2366 *ptmp2_size = required_size;
2402 if (! param->quoted)
2404 unquoted->
str = param->value.str;
2405 unquoted->
len = param->value.len;
2414 len = MHD_str_unquote (param->value.str, param->value.len, str);
2415 unquoted->
str = str;
2416 unquoted->
len = len;
2452 if (! param->quoted)
2454 memcpy (unquoted->
str, param->value.str, param->value.len);
2455 unquoted->
len = param->value.len;
2460 MHD_str_unquote (param->value.str, param->value.len, unquoted->
str);
2475_MHD_static_inline
bool
2477 const char *
const str,
2478 const size_t str_len)
2483 return MHD_str_equal_quoted_bin_n (param->value.str, param->value.len,
2485 return (str_len == param->value.len) &&
2486 (0 == memcmp (str, param->value.str, str_len));
2499_MHD_static_inline
bool
2501 const char *
const str,
2502 const size_t str_len)
2507 return MHD_str_equal_caseless_quoted_bin_n (param->value.str,
2511 return (str_len == param->value.len) &&
2557 const char *username,
2558 const char *password,
2559 const uint8_t *userdigest,
2560 unsigned int nonce_timeout,
2565 struct DigestAlgorithm *da)
2570 unsigned int digest_size;
2571 uint8_t hash1_bin[MAX_DIGEST];
2572 uint8_t hash2_bin[MAX_DIGEST];
2574 const char *hentity =
NULL;
2576 uint64_t nonce_time;
2578 const struct MHD_RqDAuth *params;
2583 char **
const ptmp2 = pbuf;
2588 size_t username_len;
2596 params = MHD_get_rq_dauth_params_ (connection);
2602 c_algo = params->algo3;
2604 if (((
unsigned int) c_algo) !=
2605 (((
unsigned int) c_algo) & ((
unsigned int) malgo3)))
2613 MHD_DLOG (connection->
daemon,
2614 _ (
"The 'session' algorithms are not supported.\n"));
2618#ifndef MHD_MD5_SUPPORT
2622 MHD_DLOG (connection->
daemon,
2623 _ (
"The MD5 algorithm is not supported by this MHD build.\n"));
2628#ifndef MHD_SHA256_SUPPORT
2632 MHD_DLOG (connection->
daemon,
2633 _ (
"The SHA-256 algorithm is not supported by "
2634 "this MHD build.\n"));
2639#ifndef MHD_SHA512_256_SUPPORT
2643 MHD_DLOG (connection->
daemon,
2644 _ (
"The SHA-512/256 algorithm is not supported by "
2645 "this MHD build.\n"));
2651 MHD_PANIC (
_ (
"Wrong 'malgo3' value, API violation"));
2653 c_qop = params->qop;
2655 if (((
unsigned int) c_qop) !=
2656 (((
unsigned int) c_qop) & ((
unsigned int) mqop)))
2665 MHD_DLOG (connection->
daemon,
2666 _ (
"The 'auth-int' QOP is not supported.\n"));
2673 MHD_DLOG (connection->
daemon,
2674 _ (
"RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
2675 "non-standard extension.\n"));
2682 if ((
NULL == params->username.value.str) &&
2683 (
NULL == params->username_ext.value.str))
2685 else if ((
NULL != params->username.value.str) &&
2686 (
NULL != params->username_ext.value.str))
2688 else if ((
NULL != params->username.value.str) &&
2689 (0 == params->username.value.len))
2691 else if ((
NULL != params->username_ext.value.str) &&
2694 else if (params->userhash && (
NULL == params->username.value.str))
2696 else if (params->userhash && (digest_size * 2 > params->username.value.len))
2698 else if (params->userhash && (digest_size * 4 < params->username.value.len))
2701 if (
NULL == params->realm.value.str)
2703 else if (0 == params->realm.value.len)
2705 else if (((
NULL == userdigest) || params->userhash) &&
2711 if (
NULL == params->nc.value.str)
2713 else if (0 == params->nc.value.len)
2715 else if (4 * 8 < params->nc.value.len)
2718 if (
NULL == params->cnonce.value.str)
2720 else if (0 == params->cnonce.value.len)
2728 if (
NULL == params->uri.value.str)
2730 else if (0 == params->uri.value.len)
2735 if (
NULL == params->nonce.value.str)
2737 else if (0 == params->nonce.value.len)
2739 else if (
NONCE_STD_LEN (digest_size) * 2 < params->nonce.value.len)
2742 if (
NULL == params->response.value.str)
2744 else if (0 == params->response.value.len)
2746 else if (digest_size * 4 < params->response.value.len)
2760 realm_len = strlen (realm);
2766 username_len = strlen (username);
2767 if (! params->userhash)
2769 if (
NULL != params->username.value.str)
2771 if (!
is_param_equal (¶ms->username, username, username_len))
2777 size_t buf_size = params->username_ext.value.len;
2785 if (
NULL == r_uname)
2789 params->username_ext.value.len,
2793 if ((username_len != (
size_t) res) ||
2794 (0 != memcmp (username, r_uname, username_len)))
2801 calc_userhash (da, username, username_len, realm, realm_len, hash1_bin);
2802#ifdef MHD_DIGEST_HAS_EXT_ERROR
2810 (2 * digest_size) <= sizeof (tmp1),
2838 _ (
"Authentication failed, invalid nc format.\n"));
2846 _ (
"Authentication failed, invalid 'nc' value.\n"));
2850 if ((0 != max_nc) && (max_nc < nci))
2868 _ (
"Authentication failed, invalid nonce format.\n"));
2904 _ (
"Stale nonce received. If this happens a lot, you should "
2905 "probably increase the size of the nonce array.\n"));
2908 _ (
"Stale nonce received. This is expected when client " \
2909 "uses RFC2069-compatible mode and makes more than one " \
2918 _ (
"Received nonce that was not "
2919 "generated by MHD. This may indicate an attack attempt.\n"));
2949#ifdef MHD_DIGEST_HAS_EXT_ERROR
2955 if (
NULL == userdigest)
2960 username, username_len,
2966#ifdef MHD_DIGEST_HAS_EXT_ERROR
2978 (digest_size * 2) <= sizeof (tmp1),
2980 if (
NULL == userdigest)
2984 digest_update (da, (
const uint8_t *) tmp1, digest_size * 2);
3042 (
const uint8_t *) tmp1,
3048#ifdef MHD_DIGEST_HAS_EXT_ERROR
3053 if (0 != memcmp (hash1_bin,
3068 daemon->digest_auth_random,
3069 daemon->digest_auth_rand_size,
3077 daemon->dauth_bind_type,
3081#ifdef MHD_DIGEST_HAS_EXT_ERROR
3133 const char *username,
3134 const char *password,
3135 const uint8_t *userdigest,
3136 unsigned int nonce_timeout,
3143 struct DigestAlgorithm da;
3147 if (0 == nonce_timeout)
3148 nonce_timeout = connection->
daemon->dauth_def_nonce_timeout;
3150 max_nc = connection->
daemon->dauth_def_max_nc;
3154 max_nc, mqop, malgo3,
3185 const char *username,
3186 const char *password,
3187 unsigned int nonce_timeout)
3232 const char *username,
3233 const char *password,
3234 unsigned int nonce_timeout,
3298 const char *username,
3299 const void *userdigest,
3300 size_t userdigest_size,
3301 unsigned int nonce_timeout,
3309 MHD_PANIC (
_ (
"Wrong 'malgo3' value, only one base hashing algorithm " \
3310 "(MD5, SHA-256 or SHA-512/256) must be specified, " \
3313#ifndef MHD_MD5_SUPPORT
3317 MHD_DLOG (connection->
daemon,
3318 _ (
"The MD5 algorithm is not supported by this MHD build.\n"));
3323#ifndef MHD_SHA256_SUPPORT
3327 MHD_DLOG (connection->
daemon,
3328 _ (
"The SHA-256 algorithm is not supported by "
3329 "this MHD build.\n"));
3334#ifndef MHD_SHA512_256_SUPPORT
3338 MHD_DLOG (connection->
daemon,
3339 _ (
"The SHA-512/256 algorithm is not supported by "
3340 "this MHD build.\n"));
3348 MHD_PANIC (
_ (
"Wrong 'userdigest_size' value, does not match 'malgo3', "
3355 (
const uint8_t *) userdigest,
3382 const char *username,
3383 const char *password,
3384 unsigned int nonce_timeout,
3397 MHD_PANIC (
_ (
"Wrong 'algo' value, API violation"));
3441 const char *username,
3442 const uint8_t *digest,
3444 unsigned int nonce_timeout,
3461 MHD_DLOG (connection->
daemon,
3462 _ (
"MHD_DIGEST_ALG_AUTO cannot be used with a " \
3463 "pre-calculated digest: exactly one algorithm must be " \
3464 "named, as the digest was produced by one.\n"));
3473 MHD_PANIC (
_ (
"Wrong 'algo' value, API violation"));
3514 const char *username,
3516 unsigned int nonce_timeout)
3586 int userhash_support,
3589 struct DigestAlgorithm *da)
3591 static const char prefix_realm[] =
"realm=\"";
3592 static const char prefix_qop[] =
"qop=\"";
3593 static const char prefix_algo[] =
"algorithm=";
3594 static const char prefix_nonce[] =
"nonce=\"";
3595 static const char prefix_opaque[] =
"opaque=\"";
3596 static const char prefix_domain[] =
"domain=\"";
3597 static const char str_charset[] =
"charset=UTF-8";
3598 static const char str_userhash[] =
"userhash=true";
3599 static const char str_stale[] =
"stale=true";
3613 MHD_DLOG (connection->
daemon,
3614 _ (
"Only non-'session' algorithms are supported.\n"));
3622#ifdef MHD_MD5_SUPPORT
3627#ifdef MHD_SHA256_SUPPORT
3632#ifdef MHD_SHA512_256_SUPPORT
3638 if (0 == (((
unsigned int) malgo3)
3641 MHD_PANIC (
_ (
"Wrong 'malgo3' value, API violation"));
3645 MHD_DLOG (connection->
daemon,
3646 _ (
"No requested algorithm is supported by this MHD build.\n"));
3653 MHD_PANIC (
_ (
"Wrong 'mqop' value, API violation"));
3660 MHD_PANIC (
_ (
"Wrong 'algo' value, API violation"));
3665 if ((0 != userhash_support) || (0 != prefer_utf8))
3666 MHD_DLOG (connection->
daemon,
3667 _ (
"The 'userhash' and 'charset' ('prefer_utf8') parameters " \
3668 "are not compatible with RFC2069 and ignored.\n"));
3670 MHD_DLOG (connection->
daemon,
3671 _ (
"RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
3672 "non-standard extension.\n"));
3674 userhash_support = 0;
3681 MHD_DLOG (connection->
daemon,
3682 _ (
"The nonce array size is zero.\n"));
3693 realm_len = strlen (realm);
3697 MHD_DLOG (connection->
daemon,
3698 _ (
"The 'realm' is too large.\n"));
3702 if ((
NULL != memchr (realm,
'\r', realm_len)) ||
3703 (
NULL != memchr (realm,
'\n', realm_len)))
3706 buf_size += realm_len * 2;
3718#ifdef MHD_MD5_SUPPORT
3723#ifdef MHD_SHA256_SUPPORT
3728#ifdef MHD_SHA512_256_SUPPORT
3742 opaque_len = strlen (opaque);
3743 if ((
NULL != memchr (opaque,
'\r', opaque_len)) ||
3744 (
NULL != memchr (opaque,
'\n', opaque_len)))
3747 buf_size += opaque_len * 2;
3755 domain_len = strlen (domain);
3756 if ((
NULL != memchr (domain,
'\r', domain_len)) ||
3757 (
NULL != memchr (domain,
'\n', domain_len)))
3760 buf_size += domain_len * 2;
3765 if (
MHD_NO != prefer_utf8)
3768 if (
MHD_NO != userhash_support)
3771 if (
MHD_NO != signal_stale)
3778 buf = malloc (buf_size);
3791 memcpy (buf + p, prefix_realm,
3794 mhd_assert ((buf_size - p) >= (realm_len * 2));
3798 quoted_size = MHD_str_quote (realm, realm_len, buf + p, buf_size - p);
3802 MHD_DLOG (connection->
daemon,
3803 _ (
"The 'realm' is too large after 'quoting'.\n"));
3815 memcpy (buf + p, prefix_qop,
3829 memcpy (buf + p, prefix_algo,
3832#ifdef MHD_MD5_SUPPORT
3841#ifdef MHD_SHA256_SUPPORT
3850#ifdef MHD_SHA512_256_SUPPORT
3864 memcpy (buf + p, prefix_nonce,
3870#ifdef MHD_DIGEST_HAS_EXT_ERROR
3874 MHD_DLOG (connection->
daemon,
3875 _ (
"TLS library reported hash calculation error, nonce could "
3876 "not be generated.\n"));
3882 MHD_DLOG (connection->
daemon,
3883 _ (
"Could not register nonce. Client's requests with this "
3884 "nonce will be always 'stale'. Probably clients' requests "
3885 "are too intensive.\n"));
3896 memcpy (buf + p, prefix_opaque,
3899 mhd_assert ((buf_size - p) >= (opaque_len * 2));
3900 p += MHD_str_quote (opaque, opaque_len, buf + p, buf_size - p);
3908 memcpy (buf + p, prefix_domain,
3911 mhd_assert ((buf_size - p) >= (domain_len * 2));
3912 p += MHD_str_quote (domain, domain_len, buf + p, buf_size - p);
3918 if (
MHD_NO != prefer_utf8)
3920 memcpy (buf + p, str_charset,
3927 if (
MHD_NO != userhash_support)
3929 memcpy (buf + p, str_userhash,
3936 if (
MHD_NO != signal_stale)
3938 memcpy (buf + p, str_stale,
3950 if (
NULL != hdr_name)
3966 MHD_DLOG (connection->
daemon,
3967 _ (
"Failed to add Digest auth header.\n"));
4047 int userhash_support,
4050 struct DigestAlgorithm da;
4069 if (
NULL != buf_ptr)
4111 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)
#define MAX_AUTH_RESPONSE_LENGTH
_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)
enum MHD_Result MHD_parse_arguments_(struct MHD_Connection *connection, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, void *cls)
MHD internal shared structures.
#define MAX_DIGEST_NONCE_LENGTH
_MHD_static_inline struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *const daemon)
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)
#define mhd_assert(ignore)
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)
macros for MHD_CHECK_(), always-compiled memory-safety invariants
#define MHD_CHECK_(daemon, expr, fail_stmt)
void * MHD_calloc_(size_t nelem, size_t elsize)
Header for platform missing functions.
limits values definitions
Header for platform-independent locks abstraction.
#define MHD_mutex_unlock_chk_(ignore)
#define MHD_mutex_lock_chk_(ignore)
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)
uint64_t MHD_monotonic_msec_counter(void)
internal monotonic clock functions implementations
#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)
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)
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
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.
#define MHD_STATICSTR_LEN_(macro)
@ 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_INVALID
@ MHD_DIGEST_AUTH_ALGO3_SHA512_256
@ MHD_DIGEST_AUTH_QOP_INVALID
@ 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
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)
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 MHD_Daemon * daemon
struct sockaddr_storage * addr
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_Req_Header * headers_received
enum MHD_HTTP_Method http_mthd