Details
-
Bug
-
Resolution: Done
-
P2: Important
-
4.8.5, 5.13.2
-
None
-
-
bbb3619a13526da5ec39fbfd62ab2e8150ed4fc3 (qt/qtbase/dev) 52ef2b60051ff57d497b29dedaca21423dc7566b (qt/qtbase/5.15)
Description
Hello,
when i use QTNetwork to cyclically request text data from a digest-protected URL on a nginx web server, i get 401-rejected by the server at the 20th request. This is no coincidence and due to the maximum number of nonce replays accepted by the nginx (default max. replays is 20).
See https://www.nginx.com/resources/wiki/modules/auth_digest/ for the digest security default values. These default values are important for this bug.
According to https://tools.ietf.org/html/rfc2617 the nginx behaves correctly:
nonce-count This MUST be specified if a qop directive is sent (see above), and MUST NOT be specified if the server did not send a qop directive in the WWW-Authenticate header field. The nc-value is the hexadecimal count of the number of requests (including the current request) that the client has sent with the nonce value in this request. For example, in the first request sent in response to a given nonce value, the client sends "nc=00000001". The purpose of this directive is to allow the server to detect request replays by maintaining its own copy of this count - if the same nc-value is seen twice, then the request is a replay. See the description below of the construction of the request-digest value.
However, the QTNetwork HTTP client doesn't reset the nonce-count value to 1 after a successful auth challenge. The nonce-count should reset with every nonce. QT keeps incrementing the nonce-count even when the nonce has changed. I attached a Wireshark dump of the bug: nginx_digest_QTNetwork_client.pcapng
The initial challenge occurs in frame 3 with nonce="29dc21f25f1ae07d" and nc=00000001
Client and server keep using the same nonce until frame 14 where the nginx requests the first reauth challenge because the inital nonce has been used for 10s and thus, expired. The client accepts the new nonce="50fa477c5f1ae087" from the server and continues. However, the client did NOT reset his nonce-count (nc) and continues to increment the one used for the initial nonce. Another nonce "refreshment" occurs in frame 26 after another 10s and finally, in frame 41 the nonce-count has reached 0x14 (decimal 20) and the server keeps rejecting all auth challenges because the nonce-count has exceeded the maximum of 20 challenge replays.
I also attached some stuff that should help you reproduce the bug:
- A Wireshark dump using a libsoup-based client where everything works
- The QTNetwork client i've hammered together
- A simple nginx.conf and a digest authentication file matching the following credentials: ExampleUser:ExamplePasswd
You may have to install the nginx auth_digest module. It didn't came with the nginx package on Fedora 32 at least.
Greetings and have a nice weekend!