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 |
Reporter | akermen | Assigned To | |||
Priority | normal | Severity | major | Reproducibility | always |
Status | new | Resolution | open | ||
Product Version | 0.9.75 | ||||
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 */ /*…*/ 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); /*…*/ | ||||
Tags | No tags attached. | ||||
Date Modified | Username | Field | Change |
---|---|---|---|
2023-03-08 10:13 | akermen | New Issue |