Bug 1263338 - squid with digest auth on big endian systems start looping
squid with digest auth on big endian systems start looping
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: squid (Show other bugs)
Unspecified Unspecified
unspecified Severity unspecified
: rc
: ---
Assigned To: Luboš Uhliarik
Ondřej Pták
Depends On:
Blocks: 1315662
  Show dependency treegraph
Reported: 2015-09-15 11:03 EDT by Ondřej Pták
Modified: 2016-03-08 06:39 EST (History)
4 users (show)

See Also:
Fixed In Version: 3.3.8-21
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 1315662 (view as bug list)
Last Closed: 2015-11-19 07:20:42 EST
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)
squid.conf (415 bytes, text/plain)
2015-09-15 11:09 EDT, Ondřej Pták
no flags Details

  None (edit)
Description Ondřej Pták 2015-09-15 11:03:13 EDT
Description of problem:
Squid with digest auth loops on big endian systems (ppc64,s390x)

Version-Release number of selected component (if applicable):

How reproducible:

Steps to Reproduce:
1. copy squid.conf from this bugzilla to /etc/squid/squid.conf
2. echo 'user:Squid_realm:747821a76d9093aaba08e1f3c00f1d80' > /etc/squid/users
3. systemctl start squid
4. echo hello > /var/www/html/page.html
5. systemctl start httpd
6. curl -v --proxy-digest -H 'Proxy-Authorization: Digest username="user" realm="Squid_realm" nonce="sdlfkjalkdfja"' -x http://localhost:3128/ -D header_log -U user:password http://localhost/page.html

Actual results:
no response from server, squid process use 100% of CPU (for at least half an hour)

Expected results:
some response and working squid for other requests

Additional info:
no problem on little endian systems (x86_64, aarch64, ppc64_le)
Comment 1 Ondřej Pták 2015-09-15 11:09:24 EDT
Created attachment 1073712 [details]
Comment 3 Ondřej Pták 2015-09-16 08:22:09 EDT
Note: this is not a regression, it's just 1st time of running the test on rhel-7 at big endian systems. The same problem is in squid-3.3.8-12.el7_0.
On RHEL-6 (squid-3.1.23-9.el6) there is no such problem.
Comment 4 Pavel Šimerda (pavlix) 2015-09-17 05:44:09 EDT
Thanks Ondřej for helping with the debugging. The infinite loop is located in `auth_digest.cc` function `authenticateDigestNonceNew()`:

186         while ((temp = authenticateDigestNonceFindNonce((char const *) (newnonce->key)))) {
187             /* create a new nonce */
188             newnonce->noncedata.randomdata = squid_random();
189             /* Bug 3526 high performance fix: add 1 second to creationtime to avoid duplication */
190             ++newnonce->noncedata.creationtime;
191             authDigestNonceEncode(newnonce);
192         }

So far the most suspicious part is a typecast in `authenticateDigestNonceFindNonce()`:

354         nonce = static_cast < digest_nonce_h * >(hash_lookup(digest_nonce_cache, nonceb64));

As the problem depends on endianess, my first guess is endianess of `struct _digest_nonce_h` members.
Comment 5 Pavel Šimerda (pavlix) 2015-09-17 07:36:38 EDT
Got it. The problem is not in the typecasts but rather in the base64 code turning a binary string into a base64 encoded string. The code not only checks the data pointer for being non-NULL but also the first byte for being non-zero and returns an empty string otherwise!


    if (!data || !*data || !result || result_size < 1 || data_size < 1)

It's binary data. I don't see any reason not to encode binary data starting with a zero byte. The first struct member is a relatively small number and therefore is encoded as a sequence of non-zero and zero bytes in little endian byte order. In big endian it is the other way round, starting with a zero byte.

Unless there is another issue, the following patch should fix it.

--- ./lib/base64.c.orig 2015-09-17 13:35:07.654617797 +0200
+++ ./lib/base64.c      2015-09-17 13:35:35.734700154 +0200
@@ -146,7 +146,7 @@
     int char_count = 0;
     int out_cnt = 0;
-    if (!data || !*data || !result || result_size < 1 || data_size < 1)
+    if (!data || !result || result_size < 1 || data_size < 1)
         return 0;
     if (!base64_initialized)
Comment 6 Pavel Šimerda (pavlix) 2015-09-17 09:04:25 EDT
Let's see what upstream thinks about the patch.
Comment 13 errata-xmlrpc 2015-11-19 07:20:42 EST
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.


Note You need to log in before you can comment on or make changes to this bug.