Hi Evgeny,
Simple setup to reproduce the nonce generation issue is available at
https://github.com/akermen/digest-nonce-test
<https://github.com/akermen/digest-nonce-test>. Hoping this helps to
easily identify the issue and can be used for testing.
To make values unique, I experimented with basic "mutex wrapped counter
mechanism" which appears to working for very limited test scope, but not
sure about performance and effect on other parts of the library:
/* global scope */
static int make_digest_unique = 1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/* at "MHD_queue_auth_fail_response" function */
/*…*/
pthread_mutex_lock(&mutex);
make_digest_unique = make_digest_unique + 1;
pthread_mutex_unlock(&mutex);
/*…*/
calculate_nonce ((uint32_t) MHD_monotonic_sec_counter() + make_digest_unique,
connection->method,
connection->daemon->digest_auth_random,
connection->daemon->digest_auth_rand_size,
connection->url,
realm,
nonce);
/*…*/
Best regards,
Ahmet Kermen
On 13 Jan 2022, at 20:43, Evgeny Grin <k2k@yandex.ru
<mailto:k2k@yandex.ru>> wrote:
Hi Ahmet,
Thank for the report.
I see some mistakes in our example (related to API complexity that
should be improved soon), but these mistakes shouldn't break the example.
nonce should be unique and it will be fixed.
I'll check it deeper.
In the meantime, any additional information and patches are welcome. :)
--
Evgeny
On 10.01.2022 18:56, Ahmet Kermen wrote:
Hi all,
Trying to implement digest authentication by following the sample
code “digest_auth_example.c” from
"https://git.gnunet.org/libmicrohttpd.git/tree/src/examples/digest_auth_example.c
<https://git.gnunet.org/libmicrohttpd.git/tree/src/examples/digest_auth_example.c>
<https://git.gnunet.org/libmicrohttpd.git/tree/src/examples/digest_auth_example.c
<https://git.gnunet.org/libmicrohttpd.git/tree/src/examples/digest_auth_example.c>>”.
For simple requests everything works fine without any issue.
When I try to send requests concurrently, some of them always fail,
even two concurrent requests.
Still not sure exact reason why concurrent handling is not working,
but at this point only clue I have for the issue appears to be
“nonce” value of the authentication header being not unqiue for each
(independent) request. This behaviour seems to be not compliant with
RFC2617 https://datatracker.ietf.org/doc/html/rfc2617#section-3.2.1
<https://datatracker.ietf.org/doc/html/rfc2617#section-3.2.1>
<https://datatracker.ietf.org/doc/html/rfc2617#section-3.2.1
<https://datatracker.ietf.org/doc/html/rfc2617#section-3.2.1>> and
RFC7616 https://datatracker.ietf.org/doc/html/rfc7616#section-3.2
<https://datatracker.ietf.org/doc/html/rfc7616#section-3.2>
<https://datatracker.ietf.org/doc/html/rfc7616#section-3.2
<https://datatracker.ietf.org/doc/html/rfc7616#section-3.2>> both
state “nonce" values should be uniquely generated each time a 401
response is made while the values generated by libmicrohttpd are only
unique for each second (by the “MHD_monotonic_sec_counter" function).
By the way the NONCE_NC_SIZE value is set to very large value to
eliminate hash collisions.
When same concurrent test run with digest authentication
implementation for popular frameworks (for Flask from
https://flask-httpauth.readthedocs.io/en/latest
<https://flask-httpauth.readthedocs.io/en/latest>
<https://flask-httpauth.readthedocs.io/en/latest
<https://flask-httpauth.readthedocs.io/en/latest>>, for Node.js from
https://www.npmjs.com/package/http-auth
<https://www.npmjs.com/package/http-auth>
<https://www.npmjs.com/package/http-auth
<https://www.npmjs.com/package/http-auth>>, for httbin from
https://hub.docker.com/r/kennethreitz/httpbin
<https://hub.docker.com/r/kennethreitz/httpbin>
<https://hub.docker.com/r/kennethreitz/httpbin
<https://hub.docker.com/r/kennethreitz/httpbin>>) they all seem to
produce unique “nonce” values and handle concurrent requests wihtout
any issue.
Please correct me If I’m wrong and missing something about the
"nonce” value handling or it being source of the isssue.
Best regards,
Ahmet Kermen