Bug 1263338

Summary: squid with digest auth on big endian systems start looping
Product: Red Hat Enterprise Linux 7 Reporter: Ondřej Pták <optak>
Component: squidAssignee: Luboš Uhliarik <luhliari>
Status: CLOSED ERRATA QA Contact: Ondřej Pták <optak>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.2CC: lmiksik, luhliari, psimerda, thozza
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: 3.3.8-21 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 1315662 (view as bug list) Environment:
Last Closed: 2015-11-19 12:20:42 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1315662    
Attachments:
Description Flags
squid.conf none

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

Version-Release number of selected component (if applicable):
squid-3.3.8-20.el7.ppc64
squid-3.3.8-20.el7.s390x

How reproducible:
always

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 15:09:24 UTC
Created attachment 1073712 [details]
squid.conf

Comment 3 Ondřej Pták 2015-09-16 12:22:09 UTC
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 09:44:09 UTC
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 11:36:38 UTC
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!

    base64.c:149

    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 13:04:25 UTC
Let's see what upstream thinks about the patch.

Comment 13 errata-xmlrpc 2015-11-19 12:20:42 UTC
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.

https://rhn.redhat.com/errata/RHSA-2015-2378.html