35 #if defined(MHD_W32_MUTEX_) 36 #ifndef WIN32_LEAN_AND_MEAN 37 #define WIN32_LEAN_AND_MEAN 1 45 #define TIMESTAMP_BIN_SIZE 4 52 #define NONCE_STD_LEN(digest_size) \ 53 ((digest_size) * 2 + TIMESTAMP_BIN_SIZE * 2) 60 #define MAX_DIGEST SHA256_DIGEST_SIZE 71 #define VLA_ARRAY_LEN_DIGEST(n) (MAX_DIGEST) 79 #define VLA_ARRAY_LEN_DIGEST(n) (n) 85 #define VLA_CHECK_LEN_DIGEST(n) do { if ((n) > MAX_DIGEST) mhd_panic ( \ 86 mhd_panic_cls, __FILE__, __LINE__, \ 87 "VLA too big.\n"); } while (0) 93 #define _BASE "Digest " 98 #define MAX_USERNAME_LENGTH 128 103 #define MAX_REALM_LENGTH 256 108 #define MAX_AUTH_RESPONSE_LENGTH 256 116 struct DigestAlgorithm
121 unsigned int digest_size;
185 for (i = 0; i < len; ++i)
187 j = (bin[i] >> 4) & 0x0f;
188 hex[i * 2] = (char) ((j <= 9) ? (j +
'0') : (j - 10 +
'a'));
190 hex[i * 2 + 1] = (char) ((j <= 9) ? (j +
'0') : (j - 10 +
'a'));
213 struct DigestAlgorithm *da,
214 const uint8_t *digest,
231 (
const unsigned char *)
":",
234 (
const unsigned char *) nonce,
237 (
const unsigned char *)
":",
240 (
const unsigned char *) cnonce,
273 const char *username,
275 const char *password,
278 struct DigestAlgorithm *da)
285 (
const unsigned char *) username,
288 (
const unsigned char *)
":",
291 (
const unsigned char *) realm,
294 (
const unsigned char *)
":",
297 (
const unsigned char *) password,
328 const char *noncecount,
334 struct DigestAlgorithm *da)
343 (
const unsigned char *) method,
346 (
const unsigned char *)
":",
349 (
const unsigned char *) uri,
352 if (0 == strcasecmp (qop,
374 (
const unsigned char *) ha1,
375 da->digest_size * 2);
377 (
const unsigned char *)
":",
380 (
const unsigned char *) nonce,
383 (
const unsigned char*)
":",
388 (
const unsigned char *) noncecount,
389 strlen (noncecount));
391 (
const unsigned char *)
":",
394 (
const unsigned char *) cnonce,
397 (
const unsigned char *)
":",
400 (
const unsigned char *) qop,
403 (
const unsigned char *)
":",
407 (
const unsigned char *) da->sessionkey,
408 da->digest_size * 2);
447 keylen = strlen (key);
451 if (
NULL == (eq = strchr (ptr,
475 (eq == &ptr[keylen]) )
479 len = strlen (q1) + 1;
491 if (size > (
size_t) ((q2 - q1) + 1))
492 size = (q2 - q1) + 1;
536 noncelen = strlen (
nonce) + 1;
542 mod = daemon->nonce_nc_size;
550 off = (off << 8) | (*np ^ (off >> 24));
558 nn = &daemon->nnc[off];
559 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 570 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 577 if ( (nc < nn->
nc) &&
579 (
nc + 64 >= nn->
nc) &&
580 (0 == ((1LLU << (nn->
nc -
nc - 1)) & nn->
nmask)) )
583 nn->
nmask |= (1LLU << (nn->
nc -
nc - 1));
584 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 590 if ( (nc <= nn->
nc) ||
591 (0 != strcmp (nn->
nonce,
595 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 601 "Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n"));
606 if (64 >
nc - nn->
nc)
611 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 642 if (0 != strncmp (header,
652 return strdup (user);
678 struct DigestAlgorithm *da,
687 timestamp[0] = (
unsigned char) ((nonce_time & 0xff000000) >> 0x18);
688 timestamp[1] = (
unsigned char) ((nonce_time & 0x00ff0000) >> 0x10);
689 timestamp[2] = (
unsigned char) ((nonce_time & 0x0000ff00) >> 0x08);
690 timestamp[3] = (
unsigned char) ((nonce_time & 0x000000ff));
695 (
const unsigned char *)
":",
698 (
const unsigned char *) method,
701 (
const unsigned char *)
":",
705 (
const unsigned char *) rnd,
708 (
const unsigned char *)
":",
711 (
const unsigned char *) uri,
714 (
const unsigned char *)
":",
717 (
const unsigned char *) realm,
764 if (0 != memcmp (key,
799 unsigned int num_headers;
802 argb = strdup (args);
806 MHD_DLOG (connection->
daemon,
807 _ (
"Failed to allocate memory for copy of URI arguments.\n"));
828 if (0 != num_headers)
858 struct DigestAlgorithm *da,
860 const char *username,
861 const char *password,
862 const uint8_t *digest,
863 unsigned int nonce_timeout)
874 const char *hentity =
NULL;
891 if (0 != strncmp (header,
896 left = strlen (header);
906 (0 != strcmp (username,
909 left -= strlen (
"username") + len;
923 left -= strlen (
"realm") + len;
931 left -= strlen (
"nonce") + len;
932 if (left > 32 * 1024)
949 _ (
"Authentication failed, invalid timestamp format.\n"));
958 if ( (t > nonce_time + nonce_timeout) ||
959 (nonce_time + nonce_timeout < nonce_time) )
967 daemon->digest_auth_random,
968 daemon->digest_auth_rand_size,
981 if (0 != strcmp (nonce,
1007 #ifdef HAVE_MESSAGES 1009 _ (
"Authentication failed, invalid format.\n"));
1017 #ifdef HAVE_MESSAGES 1019 _ (
"Authentication failed, invalid nc format.\n"));
1039 uri = malloc (left + 1);
1042 #ifdef HAVE_MESSAGES 1044 _ (
"Failed to allocate memory for auth header processing.\n"));
1090 qmark = strchr (uri,
1099 if (0 != strcmp (uri,
1102 #ifdef HAVE_MESSAGES 1104 _ (
"Authentication failed, URI does not match.\n"));
1111 const char *args = qmark;
1121 #ifdef HAVE_MESSAGES 1123 _ (
"Authentication failed, arguments do not match.\n"));
1130 return (0 == strcmp (response,
1158 const char *username,
1159 const char *password,
1160 unsigned int nonce_timeout)
1179 #define SETUP_DA(algo,da) \ 1181 struct MD5Context md5; \ 1182 struct sha256_ctx sha256; \ 1185 char md5[MD5_DIGEST_SIZE * 2 + 1]; \ 1186 char sha256[SHA256_DIGEST_SIZE * 2 + 1]; \ 1188 struct DigestAlgorithm da; \ 1192 case MHD_DIGEST_ALG_MD5: \ 1193 da.digest_size = MD5_DIGEST_SIZE; \ 1194 da.ctx = &ctx.md5; \ 1196 da.sessionkey = skey.md5; \ 1197 da.init = &MHD_MD5Init; \ 1198 da.update = &MHD_MD5Update; \ 1199 da.digest = &MHD_MD5Final; \ 1201 case MHD_DIGEST_ALG_AUTO: \ 1203 case MHD_DIGEST_ALG_SHA256: \ 1204 da.digest_size = SHA256_DIGEST_SIZE; \ 1205 da.ctx = &ctx.sha256; \ 1206 da.alg = "sha-256"; \ 1207 da.sessionkey = skey.sha256; \ 1208 da.init = &MHD_SHA256_init; \ 1209 da.update = &MHD_SHA256_update; \ 1210 da.digest = &sha256_finish; \ 1233 const char *username,
1234 const char *password,
1235 unsigned int nonce_timeout,
1271 const char *username,
1272 const uint8_t *digest,
1274 unsigned int nonce_timeout,
1280 if (da.digest_size != digest_size)
1312 const char *username,
1314 unsigned int nonce_timeout)
1360 connection->
daemon->digest_auth_random,
1361 connection->
daemon->digest_auth_rand_size,
1371 #ifdef HAVE_MESSAGES 1372 MHD_DLOG (connection->
daemon,
1374 "Could not register nonce (is the nonce array size zero?).\n"));
1379 hlen = MHD_snprintf_ (
NULL,
1381 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
1397 #ifdef HAVE_MESSAGES 1398 MHD_DLOG (connection->
daemon,
1399 _ (
"Failed to allocate memory for auth response header.\n"));
1404 if (MHD_snprintf_ (header,
1406 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
1420 if ( (
MHD_YES == ret) && (AND in state : 100
continue aborting ...))
1439 #ifdef HAVE_MESSAGES 1440 MHD_DLOG (connection->
daemon,
1441 _ (
"Failed to add Digest auth header.\n"));
void * unescape_callback_cls
static int digest_auth_check_all(struct MHD_Connection *connection, struct DigestAlgorithm *da, const char *realm, const char *username, const char *password, const uint8_t *digest, unsigned int nonce_timeout)
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Header for platform missing functions.
#define MAX_AUTH_RESPONSE_LENGTH
static void cvthex(const unsigned char *bin, size_t len, char *hex)
static void calculate_nonce(uint32_t nonce_time, const char *method, const char *rnd, size_t rnd_size, const char *uri, const char *realm, struct DigestAlgorithm *da, char *nonce)
#define MHD_mutex_unlock_chk_(pmutex)
static size_t lookup_sub_value(char *dest, size_t size, const char *data, const char *key)
_MHD_EXTERN enum MHD_Result MHD_lookup_connection_value_n(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, size_t key_size, const char **value_ptr, size_t *value_size_ptr)
internal monotonic clock functions implementations
#define TIMESTAMP_BIN_SIZE
void * MHD_calloc_(size_t nelem, size_t elsize)
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
int MHD_str_equal_caseless_(const char *str1, const char *str2)
time_t MHD_monotonic_sec_counter(void)
#define MHD_INVALID_NONCE
_MHD_EXTERN int MHD_digest_auth_check(struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout)
struct MHD_Daemon * daemon
static void digest_calc_ha1_from_digest(const char *alg, struct DigestAlgorithm *da, const uint8_t *digest, const char *nonce, const char *cnonce)
#define MHD_MD5_DIGEST_SIZE
_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)
static void digest_calc_ha1_from_user(const char *alg, const char *username, const char *realm, const char *password, const char *nonce, const char *cnonce, struct DigestAlgorithm *da)
#define VLA_CHECK_LEN_DIGEST(n)
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
_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)
internal shared structures
_MHD_EXTERN enum MHD_Result MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
char nonce[MAX_NONCE_LENGTH]
static enum MHD_Result check_argument_match(struct MHD_Connection *connection, const char *args)
_MHD_EXTERN char * MHD_digest_auth_get_username(struct MHD_Connection *connection)
_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)
Header for string manipulating helpers.
_MHD_EXTERN enum MHD_Result MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
static enum MHD_Result check_nonce_nc(struct MHD_Connection *connection, const char *nonce, uint64_t nc)
#define MHD_STATICSTR_LEN_(macro)
UnescapeCallback unescape_callback
#define MHD_HTTP_UNAUTHORIZED
#define SETUP_DA(algo, da)
#define VLA_ARRAY_LEN_DIGEST(n)
#define MHD_mutex_lock_chk_(pmutex)
static void digest_calc_response(const char *ha1, const char *nonce, const char *noncecount, const char *cnonce, const char *qop, const char *method, const char *uri, const char *hentity, struct DigestAlgorithm *da)
_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)
#define NONCE_STD_LEN(digest_size)
#define MAX_USERNAME_LENGTH
_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)
static enum MHD_Result test_header(struct MHD_Connection *connection, const char *key, size_t key_size, const char *value, size_t value_size, enum MHD_ValueKind kind)
Calculation of SHA-256 digest.
struct MHD_HTTP_Header * headers_received
limits values definitions
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)