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)
58 #define _BASE "Digest "
63 #define MAX_USERNAME_LENGTH 128
68 #define MAX_REALM_LENGTH 256
73 #define MAX_AUTH_RESPONSE_LENGTH 256
81 struct DigestAlgorithm
86 unsigned int digest_size;
150 for (i = 0; i < len; ++i)
152 j = (bin[i] >> 4) & 0x0f;
153 hex[i * 2] = (char)((j <= 9) ? (j +
'0') : (j - 10 +
'a'));
155 hex[i * 2 + 1] = (char)((j <= 9) ? (j +
'0') : (j - 10 +
'a'));
178 struct DigestAlgorithm *da,
179 const uint8_t *digest,
188 uint8_t dig[da->digest_size];
195 (
const unsigned char *)
":",
198 (
const unsigned char *) nonce,
201 (
const unsigned char *)
":",
204 (
const unsigned char *) cnonce,
237 const char *username,
239 const char *password,
242 struct DigestAlgorithm *da)
244 unsigned char ha1[da->digest_size];
248 (
const unsigned char *) username,
251 (
const unsigned char *)
":",
254 (
const unsigned char *) realm,
257 (
const unsigned char *)
":",
260 (
const unsigned char *) password,
291 const char *noncecount,
297 struct DigestAlgorithm *da)
299 unsigned char ha2[da->digest_size];
300 unsigned char resphash[da->digest_size];
305 (
const unsigned char *) method,
308 (
const unsigned char *)
":",
311 (
const unsigned char *) uri,
314 if (0 == strcasecmp (qop,
336 (
const unsigned char *) ha1,
337 da->digest_size * 2);
339 (
const unsigned char *)
":",
342 (
const unsigned char *) nonce,
345 (
const unsigned char*)
":",
350 (
const unsigned char *) noncecount,
351 strlen (noncecount));
353 (
const unsigned char *)
":",
356 (
const unsigned char *) cnonce,
359 (
const unsigned char *)
":",
362 (
const unsigned char *) qop,
365 (
const unsigned char *)
":",
369 (
const unsigned char *) da->sessionkey,
370 da->digest_size * 2);
409 keylen = strlen (key);
413 if (
NULL == (eq = strchr (ptr,
437 (eq == &ptr[keylen]) )
441 len = strlen (q1) + 1;
453 if (size > (
size_t) ((q2 - q1) + 1))
454 size = (q2 - q1) + 1;
498 noncelen = strlen (nonce) + 1;
504 mod = daemon->nonce_nc_size;
512 off = (off << 8) | (*np ^ (off >> 24));
521 nn = &daemon->nnc[off];
522 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
533 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
540 if ( (nc < nn->nc) &&
542 (nc + 64 >= nn->
nc) &&
543 (0 == ((1LLU << (nn->
nc - nc - 1)) & nn->
nmask)) )
546 nn->
nmask |= (1LLU << (nn->
nc - nc - 1));
547 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
553 if ( (nc <= nn->nc) ||
554 (0 != strcmp (nn->
nonce,
558 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
563 _(
"Stale nonce received. If this happens a lot, you should probably increase the size of the nonce array.\n"));
568 if (64 > nc - nn->
nc)
573 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
596 if (
NULL == (header =
601 if (0 != strncmp (header,
611 return strdup (user);
637 struct DigestAlgorithm *da,
641 unsigned char tmpnonce[da->digest_size];
645 timestamp[0] = (
unsigned char)((nonce_time & 0xff000000) >> 0x18);
646 timestamp[1] = (
unsigned char)((nonce_time & 0x00ff0000) >> 0x10);
647 timestamp[2] = (
unsigned char)((nonce_time & 0x0000ff00) >> 0x08);
648 timestamp[3] = (
unsigned char)((nonce_time & 0x000000ff));
653 (
const unsigned char *)
":",
656 (
const unsigned char *) method,
659 (
const unsigned char *)
":",
663 (
const unsigned char *) rnd,
666 (
const unsigned char *)
":",
669 (
const unsigned char *) uri,
672 (
const unsigned char *)
":",
675 (
const unsigned char *) realm,
712 if (kind != pos->
kind)
714 if (0 != strcmp (key,
717 if ( (
NULL == value) &&
720 if ( (
NULL == value) ||
747 unsigned int num_headers;
750 argb = strdup (args);
754 MHD_DLOG (connection->
daemon,
755 _(
"Failed to allocate memory for copy of URI arguments\n"));
776 if (0 != num_headers)
806 struct DigestAlgorithm *da,
808 const char *username,
809 const char *password,
810 const uint8_t *digest,
811 unsigned int nonce_timeout)
818 char ha1[da->digest_size * 2 + 1];
822 const char *hentity =
NULL;
834 if (0 != strncmp (header,
839 left = strlen (header);
849 (0 != strcmp (username,
852 left -= strlen (
"username") + len;
866 left -= strlen (
"realm") + len;
874 left -= strlen (
"nonce") + len;
875 if (left > 32 * 1024)
893 _(
"Authentication failed, invalid timestamp format.\n"));
903 if ( (t > nonce_time + nonce_timeout) ||
904 (nonce_time + nonce_timeout < nonce_time) )
912 daemon->digest_auth_random,
913 daemon->digest_auth_rand_size,
928 if (0 != strcmp (nonce,
956 _(
"Authentication failed, invalid format.\n"));
966 _(
"Authentication failed, invalid nc format.\n"));
987 uri = malloc (left + 1);
992 _(
"Failed to allocate memory for auth header processing\n"));
1043 if (0 != strncmp (uri,
1045 strlen (connection->
url)))
1047 #ifdef HAVE_MESSAGES
1049 _(
"Authentication failed, URI does not match.\n"));
1056 const char *args = strchr (uri,
1067 #ifdef HAVE_MESSAGES
1069 _(
"Authentication failed, arguments do not match.\n"));
1076 return (0 == strcmp (response,
1104 const char *username,
1105 const char *password,
1106 unsigned int nonce_timeout)
1125 #define SETUP_DA(algo,da) \
1127 struct MD5Context md5; \
1128 struct sha256_ctx sha256; \
1131 char md5[MD5_DIGEST_SIZE * 2 + 1]; \
1132 char sha256[SHA256_DIGEST_SIZE * 2 + 1]; \
1134 struct DigestAlgorithm da; \
1137 case MHD_DIGEST_ALG_MD5: \
1138 da.digest_size = MD5_DIGEST_SIZE; \
1139 da.ctx = &ctx.md5; \
1141 da.sessionkey = skey.md5; \
1142 da.init = &MD5Init; \
1143 da.update = &MD5Update; \
1144 da.digest = &MD5Final; \
1146 case MHD_DIGEST_ALG_AUTO: \
1148 case MHD_DIGEST_ALG_SHA256: \
1149 da.digest_size = SHA256_DIGEST_SIZE; \
1150 da.ctx = &ctx.sha256; \
1151 da.alg = "sha-256"; \
1152 da.sessionkey = skey.sha256; \
1153 da.init = &sha256_init; \
1154 da.update = &sha256_update; \
1155 da.digest = &sha256_digest; \
1178 const char *username,
1179 const char *password,
1180 unsigned int nonce_timeout,
1215 const char *username,
1216 const uint8_t *digest,
1218 unsigned int nonce_timeout,
1223 if (da.digest_size != digest_size)
1255 const char *username,
1257 unsigned int nonce_timeout)
1263 MHD_MD5_DIGEST_SIZE,
1301 connection->
daemon->digest_auth_random,
1302 connection->
daemon->digest_auth_rand_size,
1312 #ifdef HAVE_MESSAGES
1313 MHD_DLOG (connection->
daemon,
1314 _(
"Could not register nonce (is the nonce array size zero?).\n"));
1319 hlen = MHD_snprintf_ (
NULL,
1321 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
1337 #ifdef HAVE_MESSAGES
1338 MHD_DLOG(connection->
daemon,
1339 _(
"Failed to allocate memory for auth response header\n"));
1344 if (MHD_snprintf_ (header,
1346 "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
1373 #ifdef HAVE_MESSAGES
1374 MHD_DLOG (connection->
daemon,
1375 _(
"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
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
static void cvthex(const unsigned char *bin, size_t len, char *hex)
MHD_mutex_lock_chk_ & daemon
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)
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)
_MHD_EXTERN int 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)
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)
_MHD_EXTERN int MHD_queue_auth_fail_response(struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale)
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
static int test_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
char nonce[MAX_NONCE_LENGTH]
_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)
static int check_argument_match(struct MHD_Connection *connection, const char *args)
Header for string manipulating helpers.
#define MHD_STATICSTR_LEN_(macro)
UnescapeCallback unescape_callback
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
#define MHD_HTTP_UNAUTHORIZED
#define SETUP_DA(algo, da)
#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)
static int check_nonce_nc(struct MHD_Connection *connection, const char *nonce, uint64_t nc)
#define NONCE_STD_LEN(digest_size)
#define MAX_USERNAME_LENGTH
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)