libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 7e5206cc032c965f228d77696392d430ef4b5aa9
parent c024f7c8adeb98604c64a23cc30bf36e2df1f934
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Thu, 21 Jul 2022 18:49:15 +0300

digest_auth_check(): added support for userhash

Diffstat:
Msrc/microhttpd/digestauth.c | 72+++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 47 insertions(+), 25 deletions(-)

diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c @@ -1963,7 +1963,13 @@ digest_auth_check_all_inner (struct MHD_Connection *connection, return MHD_DAUTH_WRONG_HEADER; /* Parameters cannot be used together */ else if ((NULL != params->username_ext.value.str) && (MHD_DAUTH_EXT_PARAM_MIN_LEN > params->username_ext.value.len)) - return MHD_DAUTH_WRONG_HEADER; /* Broken extended notation */ + return MHD_DAUTH_WRONG_HEADER; /* Broken extended notation */ + else if (params->userhash && (NULL == params->username.value.str)) + return MHD_DAUTH_WRONG_HEADER; /* Userhash cannot be used with extended notation */ + else if (params->userhash && (digest_size * 2 > params->username.value.len)) + return MHD_DAUTH_WRONG_HEADER; /* Too few chars for correct userhash */ + else if (params->userhash && (digest_size * 4 < params->username.value.len)) + return MHD_DAUTH_WRONG_HEADER; /* Too many chars for correct userhash */ if (NULL == params->realm.value.str) return MHD_DAUTH_WRONG_HEADER; @@ -2039,32 +2045,48 @@ digest_auth_check_all_inner (struct MHD_Connection *connection, /* Check 'username' */ username_len = strlen (username); - if (NULL != params->username.value.str) - { /* Username in standard notation */ - if (! is_param_equal (&params->username, username, username_len)) - return MHD_DAUTH_WRONG_USERNAME; + if (! params->userhash) + { + if (NULL != params->username.value.str) + { /* Username in standard notation */ + if (! is_param_equal (&params->username, username, username_len)) + return MHD_DAUTH_WRONG_USERNAME; + } + else + { /* Username in extended notation */ + char *r_uname; + size_t buf_size = params->username_ext.value.len; + ssize_t res; + + mhd_assert (NULL != params->username_ext.value.str); + mhd_assert (MHD_DAUTH_EXT_PARAM_MIN_LEN <= buf_size); /* It was checked already */ + buf_size += 1; /* For zero-termination */ + buf_size -= MHD_DAUTH_EXT_PARAM_MIN_LEN; + r_uname = get_buffer_for_size (tmp1, ptmp2, &tmp2_size, buf_size); + if (NULL == r_uname) + return (_MHD_AUTH_DIGEST_MAX_PARAM_SIZE < buf_size) ? + MHD_DAUTH_TOO_LARGE : MHD_DAUTH_ERROR; + res = get_rq_extended_uname_copy_z (params->username_ext.value.str, + params->username_ext.value.len, + r_uname, buf_size); + if (0 > res) + return MHD_DAUTH_WRONG_HEADER; /* Broken extended notation */ + if ((username_len != (size_t) res) || + (0 != memcmp (username, r_uname, username_len))) + return MHD_DAUTH_WRONG_USERNAME; + } } else - { /* Username in extended notation */ - char *r_uname; - size_t buf_size = params->username_ext.value.len; - ssize_t res; - - mhd_assert (NULL != params->username_ext.value.str); - mhd_assert (MHD_DAUTH_EXT_PARAM_MIN_LEN <= buf_size); /* It was checked already */ - buf_size += 1; /* For zero-termination */ - buf_size -= MHD_DAUTH_EXT_PARAM_MIN_LEN; - r_uname = get_buffer_for_size (tmp1, ptmp2, &tmp2_size, buf_size); - if (NULL == r_uname) - return (_MHD_AUTH_DIGEST_MAX_PARAM_SIZE < buf_size) ? - MHD_DAUTH_TOO_LARGE : MHD_DAUTH_ERROR; - res = get_rq_extended_uname_copy_z (params->username_ext.value.str, - params->username_ext.value.len, - r_uname, buf_size); - if (0 > res) - return MHD_DAUTH_WRONG_HEADER; /* Broken extended notation */ - if ((username_len != (size_t) res) || - (0 != memcmp (username, r_uname, username_len))) + { /* Userhash */ + mhd_assert (NULL != params->username.value.str); + digest_init (da); + digest_update (da, username, username_len); + digest_update_with_colon (da); + digest_update (da, realm, realm_len); + digest_calc_hash (da, hash1_bin); + mhd_assert (sizeof (tmp1) >= (2 * digest_size + 1)); + MHD_bin_to_hex (hash1_bin, digest_size, tmp1); + if (! is_param_equal_caseless (&params->username, tmp1, 2 * digest_size)) return MHD_DAUTH_WRONG_USERNAME; } /* 'username' valid */