aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/digestauth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/digestauth.c')
-rw-r--r--src/microhttpd/digestauth.c932
1 files changed, 572 insertions, 360 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index 7ac5ad8b..23b41193 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -26,6 +26,7 @@
26 * @author Karlson2k (Evgeny Grin) 26 * @author Karlson2k (Evgeny Grin)
27 */ 27 */
28#include "digestauth.h" 28#include "digestauth.h"
29#include "gen_auth.h"
29#include "platform.h" 30#include "platform.h"
30#include "mhd_limits.h" 31#include "mhd_limits.h"
31#include "internal.h" 32#include "internal.h"
@@ -158,19 +159,19 @@ enum MHD_CheckNonceNC_
158 /** 159 /**
159 * The nonce and NC are OK (valid and NC was not used before). 160 * The nonce and NC are OK (valid and NC was not used before).
160 */ 161 */
161 MHD_DAUTH_NONCENC_OK = MHD_DAUTH_OK, 162 MHD_CHECK_NONCENC_OK = MHD_DAUTH_OK,
162 163
163 /** 164 /**
164 * The 'nonce' was overwritten with newer 'nonce' in the same slot or 165 * The 'nonce' was overwritten with newer 'nonce' in the same slot or
165 * NC was already used. 166 * NC was already used.
166 * The validity of the 'nonce' was not be checked. 167 * The validity of the 'nonce' was not be checked.
167 */ 168 */
168 MHD_DAUTH_NONCENC_STALE = MHD_DAUTH_NONCE_STALE, 169 MHD_CHECK_NONCENC_STALE = MHD_DAUTH_NONCE_STALE,
169 170
170 /** 171 /**
171 * The 'nonce' is wrong, it was not generated before. 172 * The 'nonce' is wrong, it was not generated before.
172 */ 173 */
173 MHD_DAUTH_NONCENC_WRONG = MHD_DAUTH_NONCE_WRONG, 174 MHD_CHECK_NONCENC_WRONG = MHD_DAUTH_NONCE_WRONG,
174}; 175};
175 176
176 177
@@ -536,7 +537,8 @@ digest_calc_ha1_from_user (const char *alg,
536 * @param cnonce client nonce 537 * @param cnonce client nonce
537 * @param qop qop-value: "", "auth" or "auth-int" (NOTE: only 'auth' is supported today.) 538 * @param qop qop-value: "", "auth" or "auth-int" (NOTE: only 'auth' is supported today.)
538 * @param method method from request 539 * @param method method from request
539 * @param uri requested URL 540 * @param uri requested URL, could be not zero-terminated
541 * @param uri_len the length of @a uri, in characters
540 * @param hentity H(entity body) if qop="auth-int" 542 * @param hentity H(entity body) if qop="auth-int"
541 * @param[in,out] da digest algorithm to use, also 543 * @param[in,out] da digest algorithm to use, also
542 * we write da->sessionkey (set to response request-digest or response-digest) 544 * we write da->sessionkey (set to response request-digest or response-digest)
@@ -549,6 +551,7 @@ digest_calc_response (const char *ha1,
549 const char *qop, 551 const char *qop,
550 const char *method, 552 const char *method,
551 const char *uri, 553 const char *uri,
554 size_t uri_len,
552 const char *hentity, 555 const char *hentity,
553 struct DigestAlgorithm *da) 556 struct DigestAlgorithm *da)
554{ 557{
@@ -564,7 +567,7 @@ digest_calc_response (const char *ha1,
564 1); 567 1);
565 digest_update (da, 568 digest_update (da,
566 (const unsigned char *) uri, 569 (const unsigned char *) uri,
567 strlen (uri)); 570 uri_len);
568#if 0 571#if 0
569 if (0 == strcasecmp (qop, 572 if (0 == strcasecmp (qop,
570 "auth-int")) 573 "auth-int"))
@@ -627,101 +630,17 @@ digest_calc_response (const char *ha1,
627} 630}
628 631
629 632
630/** 633static const struct MHD_RqDAuth *
631 * Lookup subvalue off of the HTTP Authorization header. 634get_rq_dauth_params (struct MHD_Connection *connection)
632 *
633 * A description of the input format for 'data' is at
634 * http://en.wikipedia.org/wiki/Digest_access_authentication
635 *
636 *
637 * @param dest where to store the result (possibly truncated if
638 * the buffer is not big enough).
639 * @param size size of dest
640 * @param data pointer to the Authorization header
641 * @param key key to look up in data
642 * @return size of the located value, 0 if otherwise
643 */
644static size_t
645lookup_sub_value (char *dest,
646 size_t size,
647 const char *data,
648 const char *key)
649{ 635{
650 size_t keylen; 636 const struct MHD_AuthRqHeader *rq_params;
651 size_t len; 637
652 const char *ptr; 638 rq_params = MHD_get_auth_rq_params_ (connection);
653 const char *eq; 639 if ( (NULL == rq_params) ||
654 const char *q1; 640 (MHD_AUTHTYPE_DIGEST != rq_params->auth_type) )
655 const char *q2; 641 return NULL;
656 const char *qn; 642
657 643 return rq_params->params.dauth;
658 if (0 == size)
659 return 0;
660 keylen = strlen (key);
661 ptr = data;
662 while ('\0' != *ptr)
663 {
664 if (NULL == (eq = strchr (ptr,
665 '=')))
666 return 0;
667 q1 = eq + 1;
668 while (' ' == *q1)
669 q1++;
670 if ('\"' != *q1)
671 {
672 q2 = strchr (q1,
673 ',');
674 qn = q2;
675 }
676 else
677 {
678 q1++;
679 q2 = strchr (q1,
680 '\"');
681 if (NULL == q2)
682 return 0; /* end quote not found */
683 qn = q2 + 1;
684 }
685 if ( (MHD_str_equal_caseless_n_ (ptr,
686 key,
687 keylen)) &&
688 (eq == &ptr[keylen]) )
689 {
690 if (NULL == q2)
691 {
692 len = strlen (q1) + 1;
693 if (size > len)
694 size = len;
695 size--;
696 memcpy (dest,
697 q1,
698 size);
699 dest[size] = '\0';
700 return size;
701 }
702 else
703 {
704 if (size > (size_t) ((q2 - q1) + 1))
705 size = (size_t) (q2 - q1) + 1;
706 size--;
707 memcpy (dest,
708 q1,
709 size);
710 dest[size] = '\0';
711 return size;
712 }
713 }
714 if (NULL == qn)
715 return 0;
716 ptr = strchr (qn,
717 ',');
718 if (NULL == ptr)
719 return 0;
720 ptr++;
721 while (' ' == *ptr)
722 ptr++;
723 }
724 return 0;
725} 644}
726 645
727 646
@@ -738,7 +657,6 @@ get_nonce_timestamp (const char *const nonce,
738 size_t noncelen, 657 size_t noncelen,
739 uint64_t *const ptimestamp) 658 uint64_t *const ptimestamp)
740{ 659{
741 mhd_assert ((0 == noncelen) || (strlen (nonce) == noncelen));
742 if (0 == noncelen) 660 if (0 == noncelen)
743 noncelen = strlen (nonce); 661 noncelen = strlen (nonce);
744 662
@@ -826,18 +744,19 @@ check_nonce_nc (struct MHD_Connection *connection,
826 uint32_t mod; 744 uint32_t mod;
827 enum MHD_CheckNonceNC_ ret; 745 enum MHD_CheckNonceNC_ ret;
828 746
747 mhd_assert (0 != noncelen);
829 mhd_assert (strlen (nonce) == noncelen); 748 mhd_assert (strlen (nonce) == noncelen);
830 mhd_assert (0 != nc); 749 mhd_assert (0 != nc);
831 if (MAX_NONCE_LENGTH < noncelen) 750 if (MAX_NONCE_LENGTH < noncelen)
832 return MHD_DAUTH_NONCENC_WRONG; /* This should be impossible, but static analysis 751 return MHD_CHECK_NONCENC_WRONG; /* This should be impossible, but static analysis
833 tools have a hard time with it *and* this also 752 tools have a hard time with it *and* this also
834 protects against unsafe modifications that may 753 protects against unsafe modifications that may
835 happen in the future... */ 754 happen in the future... */
836 mod = daemon->nonce_nc_size; 755 mod = daemon->nonce_nc_size;
837 if (0 == mod) 756 if (0 == mod)
838 return MHD_DAUTH_NONCENC_STALE; /* no array! */ 757 return MHD_CHECK_NONCENC_STALE; /* no array! */
839 if (nc >= UINT64_MAX - 64) 758 if (nc >= UINT64_MAX - 64)
840 return MHD_DAUTH_NONCENC_STALE; /* Overflow, unrealistically high value */ 759 return MHD_CHECK_NONCENC_STALE; /* Overflow, unrealistically high value */
841 760
842 nn = &daemon->nnc[get_nonce_nc_idx (mod, nonce, noncelen)]; 761 nn = &daemon->nnc[get_nonce_nc_idx (mod, nonce, noncelen)];
843 762
@@ -851,11 +770,11 @@ check_nonce_nc (struct MHD_Connection *connection,
851 if (0 == nn->nonce[0]) 770 if (0 == nn->nonce[0])
852 { /* The slot was never used, while the client's nonce value should be 771 { /* The slot was never used, while the client's nonce value should be
853 * recorded when it was generated by MHD */ 772 * recorded when it was generated by MHD */
854 ret = MHD_DAUTH_NONCENC_WRONG; 773 ret = MHD_CHECK_NONCENC_WRONG;
855 } 774 }
856 else if (0 != nn->nonce[noncelen]) 775 else if (0 != nn->nonce[noncelen])
857 { /* The value is the slot is wrong */ 776 { /* The value is the slot is wrong */
858 ret = MHD_DAUTH_NONCENC_STALE; 777 ret = MHD_CHECK_NONCENC_STALE;
859 } 778 }
860 else 779 else
861 { 780 {
@@ -863,7 +782,7 @@ check_nonce_nc (struct MHD_Connection *connection,
863 if (! get_nonce_timestamp (nn->nonce, 0, &slot_ts)) 782 if (! get_nonce_timestamp (nn->nonce, 0, &slot_ts))
864 { 783 {
865 mhd_assert (0); /* The value is the slot is wrong */ 784 mhd_assert (0); /* The value is the slot is wrong */
866 ret = MHD_DAUTH_NONCENC_STALE; 785 ret = MHD_CHECK_NONCENC_STALE;
867 } 786 }
868 else 787 else
869 { 788 {
@@ -873,21 +792,21 @@ check_nonce_nc (struct MHD_Connection *connection,
873 { 792 {
874 /* The nonce from the client may not have been placed in the slot 793 /* The nonce from the client may not have been placed in the slot
875 * because another nonce in that slot has not yet expired. */ 794 * because another nonce in that slot has not yet expired. */
876 ret = MHD_DAUTH_NONCENC_STALE; 795 ret = MHD_CHECK_NONCENC_STALE;
877 } 796 }
878 else if (TRIM_TO_TIMESTAMP (UINT64_MAX) / 2 >= ts_diff) 797 else if (TRIM_TO_TIMESTAMP (UINT64_MAX) / 2 >= ts_diff)
879 { 798 {
880 /* Too large value means that nonce_time is less than slot_ts. 799 /* Too large value means that nonce_time is less than slot_ts.
881 * The nonce from the client may have been overwritten by the newer 800 * The nonce from the client may have been overwritten by the newer
882 * nonce. */ 801 * nonce. */
883 ret = MHD_DAUTH_NONCENC_STALE; 802 ret = MHD_CHECK_NONCENC_STALE;
884 } 803 }
885 else 804 else
886 { 805 {
887 /* The nonce from the client should be generated after the nonce 806 /* The nonce from the client should be generated after the nonce
888 * in the slot has been expired, the nonce must be recorded, but 807 * in the slot has been expired, the nonce must be recorded, but
889 * it's not. */ 808 * it's not. */
890 ret = MHD_DAUTH_NONCENC_WRONG; 809 ret = MHD_CHECK_NONCENC_WRONG;
891 } 810 }
892 } 811 }
893 } 812 }
@@ -908,7 +827,7 @@ check_nonce_nc (struct MHD_Connection *connection,
908 else 827 else
909 nn->nmask = 0; /* big jump, unset all bits in the mask */ 828 nn->nmask = 0; /* big jump, unset all bits in the mask */
910 nn->nc = nc; 829 nn->nc = nc;
911 ret = MHD_DAUTH_NONCENC_OK; 830 ret = MHD_CHECK_NONCENC_OK;
912 } 831 }
913 else if (nc < nn->nc) 832 else if (nc < nn->nc)
914 { 833 {
@@ -919,15 +838,15 @@ check_nonce_nc (struct MHD_Connection *connection,
919 { 838 {
920 /* Out-of-order nonce, but within 64-bit bitmask, set bit */ 839 /* Out-of-order nonce, but within 64-bit bitmask, set bit */
921 nn->nmask |= (UINT64_C (1) << (nn->nc - nc - 1)); 840 nn->nmask |= (UINT64_C (1) << (nn->nc - nc - 1));
922 ret = MHD_DAUTH_NONCENC_OK; 841 ret = MHD_CHECK_NONCENC_OK;
923 } 842 }
924 else 843 else
925 /* 'nc' was already used or too old (more then 64 values ago) */ 844 /* 'nc' was already used or too old (more then 64 values ago) */
926 ret = MHD_DAUTH_NONCENC_STALE; 845 ret = MHD_CHECK_NONCENC_STALE;
927 } 846 }
928 else /* if (nc == nn->nc) */ 847 else /* if (nc == nn->nc) */
929 /* 'nc' was already used */ 848 /* 'nc' was already used */
930 ret = MHD_DAUTH_NONCENC_STALE; 849 ret = MHD_CHECK_NONCENC_STALE;
931 850
932 MHD_mutex_unlock_chk_ (&daemon->nnc_lock); 851 MHD_mutex_unlock_chk_ (&daemon->nnc_lock);
933 852
@@ -947,28 +866,40 @@ check_nonce_nc (struct MHD_Connection *connection,
947_MHD_EXTERN char * 866_MHD_EXTERN char *
948MHD_digest_auth_get_username (struct MHD_Connection *connection) 867MHD_digest_auth_get_username (struct MHD_Connection *connection)
949{ 868{
950 char user[MAX_USERNAME_LENGTH]; 869 const struct MHD_RqDAuth *params;
951 const char *header; 870 char *username;
952 871 size_t username_len;
953 if (MHD_NO == MHD_lookup_connection_value_n (connection, 872
954 MHD_HEADER_KIND, 873 params = get_rq_dauth_params (connection);
955 MHD_HTTP_HEADER_AUTHORIZATION, 874 if (NULL == params)
956 MHD_STATICSTR_LEN_ (
957 MHD_HTTP_HEADER_AUTHORIZATION),
958 &header,
959 NULL))
960 return NULL; 875 return NULL;
961 if (0 != strncmp (header, 876
962 _MHD_AUTH_DIGEST_BASE, 877 if (NULL == params->username.value.str)
963 MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE)))
964 return NULL; 878 return NULL;
965 header += MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE); 879
966 if (0 == lookup_sub_value (user, 880 username_len = params->username.value.len;
967 sizeof (user), 881 username = malloc (username_len + 1);
968 header, 882 if (NULL == username)
969 "username"))
970 return NULL; 883 return NULL;
971 return strdup (user); 884
885 if (! params->username.quoted)
886 {
887 /* The username is not quoted, no need to unquote */
888 if (0 != username_len)
889 memcpy (username, params->username.value.str, username_len);
890 username[username_len] = 0; /* Zero-terminate */
891 }
892 else
893 {
894 /* Need to properly unquote the username */
895 mhd_assert (0 != username_len); /* Quoted string may not be zero-legth */
896 username_len = MHD_str_unquote (params->username.value.str, username_len,
897 username);
898 mhd_assert (0 != username_len); /* The unquoted string cannot be empty */
899 username[username_len] = 0; /* Zero-terminate */
900 }
901
902 return username;
972} 903}
973 904
974 905
@@ -1347,6 +1278,91 @@ check_argument_match (struct MHD_Connection *connection,
1347 1278
1348 1279
1349/** 1280/**
1281 * The size of the unquoting buffer in stack
1282 */
1283#define _MHD_STATIC_UNQ_BUFFER_SIZE 128
1284
1285/**
1286 * The result of parameter unquoting
1287 */
1288enum _MHD_GetUnqResult
1289{
1290 _MHD_UNQ_NON_EMPTY = 0, /**< The sting is not empty */
1291 _MHD_UNQ_NO_STRING = MHD_DAUTH_WRONG_HEADER, /**< No string (no such parameter) */
1292 _MHD_UNQ_EMPTY = 1, /**< The string is empty */
1293 _MHD_UNQ_TOO_LARGE = 2, /**< The string is too large to unqoute */
1294 _MHD_UNQ_OUT_OF_MEM = 3 /**< Out of memory error */
1295};
1296
1297
1298/**
1299 * Get Digest authorisation parameter as unquoted string.
1300 * @param param the parameter to process
1301 * @param tmp1 the small buffer in stack
1302 * @param ptmp2 the pointer to pointer to malloc'ed buffer
1303 * @param ptmp2_size the pointer to the size of the buffer pointed by @a ptmp2
1304 * @param[out] unquoted the pointer to store the result, NOT zero terminated
1305 * @return enum code indicating result of the process
1306 */
1307static enum _MHD_GetUnqResult
1308get_unqouted_param (const struct MHD_RqDAuthParam *param,
1309 char tmp1[_MHD_STATIC_UNQ_BUFFER_SIZE],
1310 char **ptmp2,
1311 size_t *ptmp2_size,
1312 struct _MHD_cstr_w_len *unquoted)
1313{
1314 char *str;
1315 size_t len;
1316 mhd_assert ((0 == *ptmp2_size) || (NULL != *ptmp2));
1317 mhd_assert ((NULL != *ptmp2) || (0 == *ptmp2_size));
1318 mhd_assert ((0 == *ptmp2_size) || \
1319 (_MHD_STATIC_UNQ_BUFFER_SIZE < *ptmp2_size));
1320
1321 if (NULL == param->value.str)
1322 {
1323 const struct _MHD_cstr_w_len res = {NULL, 0};
1324 mhd_assert (! param->quoted);
1325 mhd_assert (0 == param->value.len);
1326 memcpy (unquoted, &res, sizeof(res));
1327 return _MHD_UNQ_NO_STRING;
1328 }
1329 if (! param->quoted)
1330 {
1331 memcpy (unquoted, &param->value, sizeof(param->value));
1332 return (0 == param->value.len) ? _MHD_UNQ_EMPTY : _MHD_UNQ_NON_EMPTY;
1333 }
1334 /* The value is present and is quoted, needs to be copied and unquoted */
1335 mhd_assert (0 != param->value.len);
1336 if (param->value.len <= _MHD_STATIC_UNQ_BUFFER_SIZE)
1337 str = tmp1;
1338 else if (param->value.len <= *ptmp2_size)
1339 str = *ptmp2;
1340 else
1341 {
1342 if (param->value.len > _MHD_AUTH_DIGEST_MAX_PARAM_SIZE)
1343 return _MHD_UNQ_TOO_LARGE;
1344 if (NULL != *ptmp2)
1345 free (*ptmp2);
1346 *ptmp2 = (char *) malloc (param->value.len);
1347 if (NULL == *ptmp2)
1348 return _MHD_UNQ_OUT_OF_MEM;
1349 *ptmp2_size = param->value.len;
1350 str = *ptmp2;
1351 }
1352
1353 len = MHD_str_unquote (param->value.str, param->value.len, str);
1354 if (1)
1355 {
1356 const struct _MHD_cstr_w_len res = {str, len};
1357 memcpy (unquoted, &res, sizeof(res));
1358 }
1359 mhd_assert (0 != unquoted->len);
1360 mhd_assert (unquoted->len < param->value.len);
1361 return _MHD_UNQ_NON_EMPTY;
1362}
1363
1364
1365/**
1350 * Authenticates the authorization header sent by the client 1366 * Authenticates the authorization header sent by the client
1351 * 1367 *
1352 * @param connection The MHD connection structure 1368 * @param connection The MHD connection structure
@@ -1375,10 +1391,6 @@ digest_auth_check_all (struct MHD_Connection *connection,
1375 unsigned int nonce_timeout) 1391 unsigned int nonce_timeout)
1376{ 1392{
1377 struct MHD_Daemon *daemon = MHD_get_master (connection->daemon); 1393 struct MHD_Daemon *daemon = MHD_get_master (connection->daemon);
1378 size_t len;
1379 const char *header;
1380 char nonce[MAX_NONCE_LENGTH];
1381 size_t nonce_len;
1382 char cnonce[MAX_NONCE_LENGTH]; 1394 char cnonce[MAX_NONCE_LENGTH];
1383 const unsigned int digest_size = digest_get_size (da); 1395 const unsigned int digest_size = digest_get_size (da);
1384 char ha1[VLA_ARRAY_LEN_DIGEST (digest_size) * 2 + 1]; 1396 char ha1[VLA_ARRAY_LEN_DIGEST (digest_size) * 2 + 1];
@@ -1389,219 +1401,368 @@ digest_auth_check_all (struct MHD_Connection *connection,
1389 char noncehashexp[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (digest_size)) + 1]; 1401 char noncehashexp[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (digest_size)) + 1];
1390 uint64_t nonce_time; 1402 uint64_t nonce_time;
1391 uint64_t t; 1403 uint64_t t;
1392 size_t left; /* number of characters left in 'header' for 'uri' */
1393 uint64_t nci; 1404 uint64_t nci;
1394 char *qmark; 1405 char *qmark;
1406 const struct MHD_RqDAuth *params;
1407 char tmp1[_MHD_STATIC_UNQ_BUFFER_SIZE]; /**< Temporal buffer in stack for unqouting */
1408 char *tmp2; /**< Temporal malloc'ed buffer for unqouting */
1409 size_t tmp2_size; /**< The size of @a tmp2 buffer */
1410 struct _MHD_cstr_w_len unquoted;
1411 enum _MHD_GetUnqResult unq_res;
1412 enum MHD_DigestAuthResult ret;
1413#ifdef HAVE_MESSAGES
1414 bool err_logged;
1415#endif /* HAVE_MESSAGES */
1395 1416
1396 VLA_CHECK_LEN_DIGEST (digest_size); 1417 tmp2 = NULL;
1397 if (MHD_NO == MHD_lookup_connection_value_n (connection, 1418 tmp2_size = 0;
1398 MHD_HEADER_KIND,
1399 MHD_HTTP_HEADER_AUTHORIZATION,
1400 MHD_STATICSTR_LEN_ (
1401 MHD_HTTP_HEADER_AUTHORIZATION),
1402 &header,
1403 NULL))
1404 return MHD_DAUTH_WRONG_HEADER;
1405 if (0 != strncmp (header,
1406 _MHD_AUTH_DIGEST_BASE,
1407 MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE)))
1408 return MHD_DAUTH_WRONG_HEADER;
1409 header += MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE);
1410 left = strlen (header);
1411
1412 if (1)
1413 {
1414 char un[MAX_USERNAME_LENGTH];
1415
1416 len = lookup_sub_value (un,
1417 sizeof (un),
1418 header,
1419 "username");
1420 if (0 == len)
1421 return MHD_DAUTH_WRONG_HEADER;
1422 if (0 != strcmp (username,
1423 un))
1424 return MHD_DAUTH_WRONG_USERNAME;
1425 left -= strlen ("username") + len;
1426 }
1427
1428 if (1)
1429 {
1430 char r[MAX_REALM_LENGTH];
1431
1432 len = lookup_sub_value (r,
1433 sizeof (r),
1434 header,
1435 "realm");
1436 if (0 == len)
1437 return MHD_DAUTH_WRONG_HEADER;
1438 if (0 != strcmp (realm,
1439 r))
1440 return MHD_DAUTH_WRONG_REALM;
1441 left -= strlen ("realm") + len;
1442 }
1443
1444 if (0 == (len = lookup_sub_value (nonce,
1445 sizeof (nonce),
1446 header,
1447 "nonce")))
1448 return MHD_DAUTH_WRONG_HEADER;
1449 nonce_len = len;
1450 left -= strlen ("nonce") + len;
1451 if (left > 32 * 1024)
1452 {
1453 /* we do not permit URIs longer than 32k, as we want to
1454 make sure to not blow our stack (or per-connection
1455 heap memory limit). Besides, 32k is already insanely
1456 large, but of course in theory the
1457 #MHD_OPTION_CONNECTION_MEMORY_LIMIT might be very large
1458 and would thus permit sending a >32k authorization
1459 header value. */
1460 return MHD_DAUTH_WRONG_HEADER;
1461 }
1462 if (! get_nonce_timestamp (nonce, nonce_len, &nonce_time))
1463 {
1464#ifdef HAVE_MESSAGES 1419#ifdef HAVE_MESSAGES
1465 MHD_DLOG (daemon, 1420 err_logged = false;
1466 _ ("Authentication failed, invalid timestamp format.\n")); 1421#endif /* HAVE_MESSAGES */
1467#endif 1422
1423 params = get_rq_dauth_params (connection);
1424 if (NULL == params)
1468 return MHD_DAUTH_WRONG_HEADER; 1425 return MHD_DAUTH_WRONG_HEADER;
1469 }
1470 1426
1471 t = MHD_monotonic_msec_counter (); 1427 do /* Only to avoid "goto" */
1472 /*
1473 * First level vetting for the nonce validity: if the timestamp
1474 * attached to the nonce exceeds `nonce_timeout', then the nonce is
1475 * invalid.
1476 */
1477 if (TRIM_TO_TIMESTAMP (t - nonce_time) > (nonce_timeout * 1000))
1478 { 1428 {
1479 /* too old */ 1429 /* Check 'username' */
1480 return MHD_DAUTH_NONCE_STALE; 1430 unq_res = get_unqouted_param (&params->username, tmp1, &tmp2, &tmp2_size,
1481 } 1431 &unquoted);
1432 if (_MHD_UNQ_NON_EMPTY != unq_res)
1433 {
1434 if (_MHD_UNQ_NO_STRING == unq_res)
1435 ret = MHD_DAUTH_WRONG_HEADER;
1436 else if (_MHD_UNQ_EMPTY == unq_res)
1437 ret = MHD_DAUTH_WRONG_USERNAME;
1438 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1439 ret = MHD_DAUTH_WRONG_HEADER;
1440 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1441 ret = MHD_DAUTH_ERROR;
1442 else
1443 {
1444 mhd_assert (0); /* Must not happen */
1445 ret = MHD_DAUTH_ERROR;
1446 }
1447 break;
1448 }
1449 /* 'unquoted" may not contain binary zero */
1450 if ( (0 != strncmp (username, unquoted.str, unquoted.len)) ||
1451 (0 != username[unquoted.len]) )
1452 {
1453 ret = MHD_DAUTH_WRONG_USERNAME;
1454 break;
1455 }
1456 /* 'username' valid */
1482 1457
1483 calculate_nonce (nonce_time, 1458 /* Check 'realm' */
1484 connection->method, 1459 unq_res = get_unqouted_param (&params->realm, tmp1, &tmp2, &tmp2_size,
1485 daemon->digest_auth_random, 1460 &unquoted);
1486 daemon->digest_auth_rand_size, 1461 if (_MHD_UNQ_NON_EMPTY != unq_res)
1487 connection->url, 1462 {
1488 realm, 1463 if (_MHD_UNQ_NO_STRING == unq_res)
1489 da, 1464 ret = MHD_DAUTH_WRONG_HEADER;
1490 noncehashexp); 1465 else if (_MHD_UNQ_EMPTY == unq_res)
1491 /* 1466 ret = MHD_DAUTH_WRONG_REALM;
1492 * Second level vetting for the nonce validity 1467 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1493 * if the timestamp attached to the nonce is valid 1468 ret = MHD_DAUTH_WRONG_HEADER;
1494 * and possibly fabricated (in case of an attack) 1469 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1495 * the attacker must also know the random seed to be 1470 ret = MHD_DAUTH_ERROR;
1496 * able to generate a "sane" nonce, which if he does 1471 else
1497 * not, the nonce fabrication process going to be 1472 {
1498 * very hard to achieve. 1473 mhd_assert (0); /* Must not happen */
1499 */ 1474 ret = MHD_DAUTH_ERROR;
1500 if (0 != strcmp (nonce, 1475 }
1501 noncehashexp)) 1476 break;
1502 { 1477 }
1503 return MHD_DAUTH_NONCE_WRONG; 1478 /* 'unquoted" may not contain binary zero */
1504 } 1479 if ( (0 != strncmp (realm, unquoted.str, unquoted.len)) ||
1505 if ( (0 == lookup_sub_value (cnonce, 1480 (0 != realm[unquoted.len]) )
1506 sizeof (cnonce), 1481 {
1507 header, 1482 ret = MHD_DAUTH_WRONG_REALM;
1508 "cnonce")) || 1483 break;
1509 (0 == lookup_sub_value (qop, 1484 }
1510 sizeof (qop), 1485 /* 'realm' valid */
1511 header, 1486
1512 "qop")) || 1487 /* Check 'nonce' */
1513 ( (0 != strcmp (qop, 1488 unq_res = get_unqouted_param (&params->nonce, tmp1, &tmp2, &tmp2_size,
1514 "auth")) && 1489 &unquoted);
1515 (0 != strcmp (qop, 1490 if (_MHD_UNQ_NON_EMPTY != unq_res)
1516 "")) ) || 1491 {
1517 (0 == (len = lookup_sub_value (nc, 1492 if (_MHD_UNQ_NO_STRING == unq_res)
1518 sizeof (nc), 1493 ret = MHD_DAUTH_WRONG_HEADER;
1519 header, 1494 else if (_MHD_UNQ_EMPTY == unq_res)
1520 "nc")) ) || 1495 ret = MHD_DAUTH_NONCE_WRONG;
1521 (0 == lookup_sub_value (response, 1496 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1522 sizeof (response), 1497 ret = MHD_DAUTH_WRONG_HEADER;
1523 header, 1498 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1524 "response")) ) 1499 ret = MHD_DAUTH_ERROR;
1525 { 1500 else
1526#ifdef HAVE_MESSAGES 1501 {
1527 MHD_DLOG (daemon, 1502 mhd_assert (0); /* Must not happen */
1528 _ ("Authentication failed, invalid format.\n")); 1503 ret = MHD_DAUTH_ERROR;
1529#endif 1504 }
1530 return MHD_DAUTH_WRONG_HEADER; 1505 break;
1531 } 1506 }
1532 if (len != MHD_strx_to_uint64_n_ (nc, 1507 /* TODO: check correct 'nonce' length */
1533 len, 1508 if (! get_nonce_timestamp (unquoted.str, unquoted.len, &nonce_time))
1534 &nci)) 1509 {
1535 {
1536#ifdef HAVE_MESSAGES
1537 MHD_DLOG (daemon,
1538 _ ("Authentication failed, invalid nc format.\n"));
1539#endif
1540 return MHD_DAUTH_WRONG_HEADER; /* invalid nonce format */
1541 }
1542 if (0 == nci)
1543 {
1544#ifdef HAVE_MESSAGES 1510#ifdef HAVE_MESSAGES
1545 MHD_DLOG (daemon, 1511 MHD_DLOG (daemon,
1546 _ ("Authentication failed, invalid 'nc' value.\n")); 1512 _ ("Authentication failed, invalid timestamp format.\n"));
1513 err_logged = true;
1547#endif 1514#endif
1548 return MHD_DAUTH_WRONG_HEADER; /* invalid nc value */ 1515 ret = MHD_DAUTH_NONCE_WRONG;
1549 } 1516 break;
1517 }
1518 t = MHD_monotonic_msec_counter ();
1519 /*
1520 * First level vetting for the nonce validity: if the timestamp
1521 * attached to the nonce exceeds `nonce_timeout', then the nonce is
1522 * invalid.
1523 */
1524 if (TRIM_TO_TIMESTAMP (t - nonce_time) > (nonce_timeout * 1000))
1525 {
1526 /* too old */
1527 ret = MHD_DAUTH_NONCE_STALE;
1528 break;
1529 }
1550 1530
1551 if (1) 1531 calculate_nonce (nonce_time,
1552 { 1532 connection->method,
1553 enum MHD_CheckNonceNC_ nonce_nc_check; 1533 daemon->digest_auth_random,
1534 daemon->digest_auth_rand_size,
1535 connection->url,
1536 realm,
1537 da,
1538 noncehashexp);
1554 /* 1539 /*
1555 * Checking if that combination of nonce and nc is sound 1540 * Second level vetting for the nonce validity
1556 * and not a replay attack attempt. Refuse if nonce was not 1541 * if the timestamp attached to the nonce is valid
1557 * generated previously. 1542 * and possibly fabricated (in case of an attack)
1543 * the attacker must also know the random seed to be
1544 * able to generate a "sane" nonce, which if he does
1545 * not, the nonce fabrication process going to be
1546 * very hard to achieve.
1558 */ 1547 */
1559 nonce_nc_check = check_nonce_nc (connection, 1548 if ((0 != strncmp (noncehashexp, unquoted.str, unquoted.len)) ||
1560 nonce, 1549 (0 != noncehashexp[unquoted.len]))
1561 nonce_len, 1550 {
1562 nonce_time, 1551 ret = MHD_DAUTH_NONCE_WRONG;
1563 nci); 1552 break;
1564 if (MHD_DAUTH_NONCENC_STALE == nonce_nc_check) 1553 }
1554 /* 'nonce' valid */
1555
1556 /* Get 'cnonce' */
1557 unq_res = get_unqouted_param (&params->cnonce, tmp1, &tmp2, &tmp2_size,
1558 &unquoted);
1559 if (_MHD_UNQ_NON_EMPTY != unq_res)
1560 {
1561 if (_MHD_UNQ_NO_STRING == unq_res)
1562 ret = MHD_DAUTH_WRONG_HEADER;
1563 else if (_MHD_UNQ_EMPTY == unq_res)
1564 ret = MHD_DAUTH_WRONG_HEADER;
1565 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1566 ret = MHD_DAUTH_WRONG_HEADER;
1567 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1568 ret = MHD_DAUTH_ERROR;
1569 else
1570 {
1571 mhd_assert (0); /* Must not happen */
1572 ret = MHD_DAUTH_ERROR;
1573 }
1574 break;
1575 }
1576 if (sizeof(cnonce) <= unquoted.len)
1577 {
1578 /* TODO: handle large client nonces */
1579 ret = MHD_DAUTH_ERROR;
1580 break;
1581 }
1582 /* TODO: avoid memcpy() */
1583 memcpy (cnonce, unquoted.str, unquoted.len);
1584 cnonce[unquoted.len] = 0;
1585 /* Got 'cnonce' */
1586
1587 /* Get 'qop' */
1588 unq_res = get_unqouted_param (&params->qop, tmp1, &tmp2, &tmp2_size,
1589 &unquoted);
1590 if (_MHD_UNQ_NON_EMPTY != unq_res)
1591 {
1592 if (_MHD_UNQ_NO_STRING == unq_res)
1593 ret = MHD_DAUTH_WRONG_HEADER;
1594 else if (_MHD_UNQ_EMPTY == unq_res)
1595 ret = MHD_DAUTH_WRONG_HEADER;
1596 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1597 ret = MHD_DAUTH_WRONG_HEADER;
1598 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1599 ret = MHD_DAUTH_ERROR;
1600 else
1601 {
1602 mhd_assert (0); /* Must not happen */
1603 ret = MHD_DAUTH_ERROR;
1604 }
1605 break;
1606 }
1607 if (sizeof(qop) <= unquoted.len)
1608 {
1609 /* TODO: handle large client qop */
1610 ret = MHD_DAUTH_ERROR;
1611 break;
1612 }
1613 /* TODO: avoid memcpy() */
1614 memcpy (qop, unquoted.str, unquoted.len);
1615 qop[unquoted.len] = 0;
1616 /* TODO: use caseless match, use dedicated return code */
1617 if ( (0 != strcmp (qop, "auth")) &&
1618 (0 != strcmp (qop,"")) )
1619 {
1620 ret = MHD_DAUTH_WRONG_HEADER;
1621 break;
1622 }
1623 /* Got 'qop' */
1624
1625 /* Get 'nc' */
1626 unq_res = get_unqouted_param (&params->nc, tmp1, &tmp2, &tmp2_size,
1627 &unquoted);
1628 if (_MHD_UNQ_NON_EMPTY != unq_res)
1629 {
1630 if (_MHD_UNQ_NO_STRING == unq_res)
1631 ret = MHD_DAUTH_WRONG_HEADER;
1632 else if (_MHD_UNQ_EMPTY == unq_res)
1633 ret = MHD_DAUTH_WRONG_HEADER;
1634 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1635 ret = MHD_DAUTH_WRONG_HEADER;
1636 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1637 ret = MHD_DAUTH_ERROR;
1638 else
1639 {
1640 mhd_assert (0); /* Must not happen */
1641 ret = MHD_DAUTH_ERROR;
1642 }
1643 break;
1644 }
1645 if (sizeof(nc) <= unquoted.len)
1646 {
1647 /* TODO: handle large client nc */
1648 ret = MHD_DAUTH_ERROR;
1649 break;
1650 }
1651 /* TODO: avoid memcpy() */
1652 memcpy (nc, unquoted.str, unquoted.len);
1653 nc[unquoted.len] = 0;
1654 if (unquoted.len != MHD_strx_to_uint64_n_ (nc,
1655 unquoted.len,
1656 &nci))
1565 { 1657 {
1566#ifdef HAVE_MESSAGES 1658#ifdef HAVE_MESSAGES
1567 MHD_DLOG (daemon, 1659 MHD_DLOG (daemon,
1568 _ ("Stale nonce received. If this happens a lot, you should " 1660 _ ("Authentication failed, invalid nc format.\n"));
1569 "probably increase the size of the nonce array.\n")); 1661 err_logged = true;
1570#endif 1662#endif
1571 return MHD_DAUTH_NONCE_STALE; 1663 ret = MHD_DAUTH_WRONG_HEADER; /* invalid nonce format */
1664 break;
1572 } 1665 }
1573 else if (MHD_DAUTH_NONCENC_WRONG == nonce_nc_check) 1666 if (0 == nci)
1574 { 1667 {
1575#ifdef HAVE_MESSAGES 1668#ifdef HAVE_MESSAGES
1576 MHD_DLOG (daemon, 1669 MHD_DLOG (daemon,
1577 _ ("Received nonce that technically valid, but was not " 1670 _ ("Authentication failed, invalid 'nc' value.\n"));
1578 "generated by MHD. This may indicate an attack attempt.\n")); 1671 err_logged = true;
1579#endif 1672#endif
1580 return MHD_DAUTH_NONCE_WRONG; 1673 ret = MHD_DAUTH_WRONG_HEADER; /* invalid nc value */
1674 break;
1581 } 1675 }
1582 mhd_assert (MHD_DAUTH_NONCENC_OK == nonce_nc_check); 1676 /* Got 'nc' */
1583 }
1584 1677
1585 if (1) 1678 /* Get 'response' */
1586 { 1679 unq_res = get_unqouted_param (&params->response, tmp1, &tmp2, &tmp2_size,
1587 char *uri; 1680 &unquoted);
1681 if (_MHD_UNQ_NON_EMPTY != unq_res)
1682 {
1683 if (_MHD_UNQ_NO_STRING == unq_res)
1684 ret = MHD_DAUTH_WRONG_HEADER;
1685 else if (_MHD_UNQ_EMPTY == unq_res)
1686 ret = MHD_DAUTH_WRONG_HEADER;
1687 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1688 ret = MHD_DAUTH_WRONG_HEADER;
1689 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1690 ret = MHD_DAUTH_ERROR;
1691 else
1692 {
1693 mhd_assert (0); /* Must not happen */
1694 ret = MHD_DAUTH_ERROR;
1695 }
1696 break;
1697 }
1698 if (sizeof(response) <= unquoted.len)
1699 {
1700 /* TODO: handle large client response */
1701 ret = MHD_DAUTH_ERROR;
1702 break;
1703 }
1704 /* TODO: avoid memcpy() */
1705 memcpy (response, unquoted.str, unquoted.len);
1706 response[unquoted.len] = 0;
1707 /* Got 'response' */
1588 1708
1589 uri = malloc (left + 1); 1709 if (1)
1590 if (NULL == uri)
1591 { 1710 {
1711 enum MHD_CheckNonceNC_ nonce_nc_check;
1712 /*
1713 * Checking if that combination of nonce and nc is sound
1714 * and not a replay attack attempt. Refuse if nonce was not
1715 * generated previously.
1716 */
1717 nonce_nc_check = check_nonce_nc (connection,
1718 noncehashexp,
1719 NONCE_STD_LEN (digest_size),
1720 nonce_time,
1721 nci);
1722 if (MHD_CHECK_NONCENC_STALE == nonce_nc_check)
1723 {
1592#ifdef HAVE_MESSAGES 1724#ifdef HAVE_MESSAGES
1593 MHD_DLOG (daemon, 1725 MHD_DLOG (daemon,
1594 _ ("Failed to allocate memory for auth header processing.\n")); 1726 _ ("Stale nonce received. If this happens a lot, you should "
1595#endif /* HAVE_MESSAGES */ 1727 "probably increase the size of the nonce array.\n"));
1596 return MHD_DAUTH_ERROR; 1728 err_logged = true;
1729#endif
1730 ret = MHD_DAUTH_NONCE_STALE;
1731 break;
1732 }
1733 else if (MHD_CHECK_NONCENC_WRONG == nonce_nc_check)
1734 {
1735#ifdef HAVE_MESSAGES
1736 MHD_DLOG (daemon,
1737 _ ("Received nonce that technically valid, but was not "
1738 "generated by MHD. This may indicate an attack attempt.\n"));
1739 err_logged = true;
1740#endif
1741 ret = MHD_DAUTH_NONCE_WRONG;
1742 break;
1743 }
1744 mhd_assert (MHD_CHECK_NONCENC_OK == nonce_nc_check);
1597 } 1745 }
1598 if (0 == lookup_sub_value (uri, 1746
1599 left + 1, 1747 /* Get 'uri' */
1600 header, 1748 unq_res = get_unqouted_param (&params->uri, tmp1, &tmp2, &tmp2_size,
1601 "uri")) 1749 &unquoted);
1750 if (_MHD_UNQ_NON_EMPTY != unq_res)
1602 { 1751 {
1603 free (uri); 1752 if (_MHD_UNQ_NO_STRING == unq_res)
1604 return MHD_DAUTH_WRONG_HEADER; 1753 ret = MHD_DAUTH_WRONG_HEADER;
1754 else if (_MHD_UNQ_EMPTY == unq_res)
1755 ret = MHD_DAUTH_WRONG_HEADER;
1756 else if (_MHD_UNQ_TOO_LARGE == unq_res)
1757 ret = MHD_DAUTH_WRONG_HEADER;
1758 else if (_MHD_UNQ_OUT_OF_MEM == unq_res)
1759 ret = MHD_DAUTH_ERROR;
1760 else
1761 {
1762 mhd_assert (0); /* Must not happen */
1763 ret = MHD_DAUTH_ERROR;
1764 }
1765 break;
1605 } 1766 }
1606 if (NULL != digest) 1767 if (NULL != digest)
1607 { 1768 {
@@ -1609,7 +1770,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1609 digest_calc_ha1_from_digest (digest_get_algo_name (da), 1770 digest_calc_ha1_from_digest (digest_get_algo_name (da),
1610 da, 1771 da,
1611 digest, 1772 digest,
1612 nonce, 1773 noncehashexp,
1613 cnonce); 1774 cnonce);
1614 } 1775 }
1615 else 1776 else
@@ -1620,7 +1781,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1620 username, 1781 username,
1621 realm, 1782 realm,
1622 password, 1783 password,
1623 nonce, 1784 noncehashexp,
1624 cnonce, 1785 cnonce,
1625 da); 1786 da);
1626 } 1787 }
@@ -1629,60 +1790,111 @@ digest_auth_check_all (struct MHD_Connection *connection,
1629 digest_size * 2 + 1); 1790 digest_size * 2 + 1);
1630 /* This will initialize da->sessionkey (respexp) */ 1791 /* This will initialize da->sessionkey (respexp) */
1631 digest_calc_response (ha1, 1792 digest_calc_response (ha1,
1632 nonce, 1793 noncehashexp,
1633 nc, 1794 nc,
1634 cnonce, 1795 cnonce,
1635 qop, 1796 qop,
1636 connection->method, 1797 connection->method,
1637 uri, 1798 unquoted.str,
1799 unquoted.len,
1638 hentity, 1800 hentity,
1639 da); 1801 da);
1640 qmark = strchr (uri,
1641 '?');
1642 if (NULL != qmark)
1643 *qmark = '\0';
1644
1645 /* Need to unescape URI before comparing with connection->url */
1646 daemon->unescape_callback (daemon->unescape_callback_cls,
1647 connection,
1648 uri);
1649 if (0 != strcmp (uri,
1650 connection->url))
1651 {
1652#ifdef HAVE_MESSAGES
1653 MHD_DLOG (daemon,
1654 _ ("Authentication failed, URI does not match.\n"));
1655#endif
1656 free (uri);
1657 return MHD_DAUTH_WRONG_URI;
1658 }
1659
1660 if (1) 1802 if (1)
1661 { 1803 {
1662 const char *args = qmark; 1804 char *uri;
1663 1805 size_t uri_len;
1664 if (NULL == args) 1806 uri_len = unquoted.len;
1665 args = ""; 1807 /* TODO: simplify string copy, avoid potential double copy */
1808 if ( ((tmp1 != unquoted.str) && (tmp2 != unquoted.str)) ||
1809 ((tmp1 == unquoted.str) && (sizeof(tmp1) >= unquoted.len)) ||
1810 ((tmp2 == unquoted.str) && (tmp2_size >= unquoted.len)))
1811 {
1812 char *buf;
1813 mhd_assert ((tmp1 != unquoted.str) || \
1814 (sizeof(tmp1) == unquoted.len));
1815 mhd_assert ((tmp2 != unquoted.str) || \
1816 (tmp2_size == unquoted.len));
1817 buf = malloc (unquoted.len + 1);
1818 if (NULL == buf)
1819 {
1820 ret = MHD_DAUTH_ERROR;
1821 break;
1822 }
1823 memcpy (buf, unquoted.str, unquoted.len);
1824 if (NULL != tmp2)
1825 free (tmp2);
1826 tmp2 = buf;
1827 tmp2_size = unquoted.len + 1;
1828 uri = tmp2;
1829 }
1830 else if (tmp1 == unquoted.str)
1831 uri = tmp1;
1666 else 1832 else
1667 args++; 1833 {
1668 if (MHD_NO == 1834 mhd_assert (tmp2 == unquoted.str);
1669 check_argument_match (connection, 1835 uri = tmp2;
1670 args) ) 1836 }
1837
1838 uri[uri_len] = 0;
1839 qmark = memchr (uri,
1840 '?',
1841 uri_len);
1842 if (NULL != qmark)
1843 *qmark = '\0';
1844
1845 /* Need to unescape URI before comparing with connection->url */
1846 daemon->unescape_callback (daemon->unescape_callback_cls,
1847 connection,
1848 uri);
1849 if (0 != strcmp (uri,
1850 connection->url))
1671 { 1851 {
1672#ifdef HAVE_MESSAGES 1852#ifdef HAVE_MESSAGES
1673 MHD_DLOG (daemon, 1853 MHD_DLOG (daemon,
1674 _ ("Authentication failed, arguments do not match.\n")); 1854 _ ("Authentication failed, URI does not match.\n"));
1855 err_logged = true;
1675#endif 1856#endif
1676 free (uri); 1857 ret = MHD_DAUTH_WRONG_URI;
1677 return MHD_DAUTH_WRONG_URI; 1858 break;
1678 } 1859 }
1860
1861 if (1)
1862 {
1863 const char *args = qmark;
1864
1865 if (NULL == args)
1866 args = "";
1867 else
1868 args++;
1869 if (MHD_NO ==
1870 check_argument_match (connection,
1871 args) )
1872 {
1873#ifdef HAVE_MESSAGES
1874 MHD_DLOG (daemon,
1875 _ ("Authentication failed, arguments do not match.\n"));
1876 err_logged = true;
1877#endif
1878 ret = MHD_DAUTH_WRONG_URI;
1879 break;
1880 }
1881 }
1882
1883 ret = (0 == strcmp (response,
1884 digest_get_hex_buffer (da)))
1885 ? MHD_DAUTH_OK
1886 : MHD_DAUTH_RESPONSE_WRONG;
1679 } 1887 }
1680 free (uri); 1888 } while (0);
1889 if (NULL != tmp2)
1890 free (tmp2);
1891
1892 if ((MHD_DAUTH_OK != ret) && ! err_logged)
1893 {
1894 (void) 0; /* TODO: add logging */
1681 } 1895 }
1682 return (0 == strcmp (response, 1896
1683 digest_get_hex_buffer (da))) 1897 return ret;
1684 ? MHD_DAUTH_OK
1685 : MHD_DAUTH_RESPONSE_WRONG;
1686} 1898}
1687 1899
1688 1900