View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0007755||libmicrohttpd||digest authentication (HTTP)||public||2023-03-08 10:13||2023-03-08 10:13|
|Summary||0007755: Digest authentication nonce uniqueness|
|Description||Digest authentication is working for simple requests bu fails for requests sent concurrently (almost all of if requests are send within a second).|
The issue appears to be “nonce” value of the authentication header being not unqiue for each (independent) request. This behavior seems to be not compliant with RFC2617 https://datatracker.ietf.org/doc/html/rfc2617#section-3.2.1 and RFC7616 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).
Digest authentication implementation for popular frameworks (for Flask from https://flask-httpauth.readthedocs.io/en/latest, for Node.js from https://www.npmjs.com/package/http-auth, for httbin from https://hub.docker.com/r/kennethreitz/httpbin) they all seem to produce unique “nonce” values and handle concurrent requests without any issue.
This issue report is follow up from the mailing list thread "https://lists.gnu.org/archive/html/libmicrohttpd/2022-01/msg00000.html".
|Steps To Reproduce||Follow the steps at the "https://github.com/akermen/digest-nonce-test" repository that was specifically created for reproducing this issue.|
|Additional Information||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 */
make_digest_unique = make_digest_unique + 1;
calculate_nonce ((uint32_t) MHD_monotonic_sec_counter() + make_digest_unique,
|Tags||No tags attached.|