Re: [squid-dev] [PATCH] snprintf result used without validating its range

2016-02-10 Thread Amos Jeffries
On 10/02/2016 6:25 a.m., Yuriy M. Kaminskiy wrote:
> In several cases, snprintf result was used without validating its range.
> 
> When formatted string would overflow buffer or error happens, snprintf
> will return either value larger than buffer size, or -1. In both cases,
> if you add this value to pointer (or similar), bad things will happen.
> 
> Pattern to watch for: =.*snprintf
> 
> I have not verified if any of this is exploitable. In some cases, I was
> not sure about proper error handling (watch for XXX comments).
> 
> While fixing this error, I noticed typo in Ip::Qos::Config::dumpConfigLine:
> markMissMask was used instead of tosMissMask.
> 
> Patches compile-tested (however, only on linux/x86/gcc49 and in default
> configuration).
> 
> 

I've merge this one immediately:

> squid-3.5.13-fix-typo.patch
> Index: squid-3.5.13/src/ip/QosConfig.cc


The rest are going to take a bit of reviw for portability and other
compilers. I have vague recollections of something about that -1 and
portability when I looked into it years ago.

Amos

___
squid-dev mailing list
squid-dev@lists.squid-cache.org
http://lists.squid-cache.org/listinfo/squid-dev


Re: [squid-dev] [PATCH] snprintf result used without validating its range

2016-02-09 Thread Alex Rousskov
On 02/09/2016 10:25 AM, Yuriy M. Kaminskiy wrote:
> Index: squid-3.5.13/src/log/File.cc
> ===
> --- squid-3.5.13.orig/src/log/File.cc
> +++ squid-3.5.13/src/log/File.cc
> @@ -104,13 +104,16 @@ logfilePrintf(Logfile * lf, const char *
...
> +if (s < 0) {
> +xstrncpy(buf, "snprintf error in logfilePrintf\n", sizeof(buf));
...


We should not write error messages to access.log. When an overflow
happens: If all logfilePrintf() callers cannot meaningfully handle the
error anyway, then we should just log the error message to cache.log and
return from logfilePrintf(). Otherwise, a more complex solution is needed.


N.B. IMHO, logging truncated lines is a bad idea but that wrong decision
was probably made long time ago, and changing it is both difficult and
probably outside your patch scope.


Thank you,

Alex.

___
squid-dev mailing list
squid-dev@lists.squid-cache.org
http://lists.squid-cache.org/listinfo/squid-dev


[squid-dev] [PATCH] snprintf result used without validating its range

2016-02-09 Thread Yuriy M. Kaminskiy
In several cases, snprintf result was used without validating its range.

When formatted string would overflow buffer or error happens, snprintf
will return either value larger than buffer size, or -1. In both cases,
if you add this value to pointer (or similar), bad things will happen.

Pattern to watch for: =.*snprintf

I have not verified if any of this is exploitable. In some cases, I was
not sure about proper error handling (watch for XXX comments).

While fixing this error, I noticed typo in Ip::Qos::Config::dumpConfigLine:
markMissMask was used instead of tosMissMask.

Patches compile-tested (however, only on linux/x86/gcc49 and in default
configuration).

Index: squid-3.5.13/src/ip/QosConfig.cc
===
--- squid-3.5.13.orig/src/ip/QosConfig.cc
+++ squid-3.5.13/src/ip/QosConfig.cc
@@ -392,7 +392,7 @@ Ip::Qos::Config::dumpConfigLine(char *en
 if (tosMiss > 0) {
 p += snprintf(p, 11, " miss=0x%02X", tosMiss);
 if (tosMissMask!=0xFFU) {
-p += snprintf(p, 6, "/0x%02X", markMissMask);
+p += snprintf(p, 6, "/0x%02X", tosMissMask);
 }
 }
 if (preserveMissTos == 0) {
Index: squid-3.5.13/helpers/digest_auth/file/text_backend.cc
===
--- squid-3.5.13.orig/helpers/digest_auth/file/text_backend.cc
+++ squid-3.5.13/helpers/digest_auth/file/text_backend.cc
@@ -171,7 +171,7 @@ GetPassword(RequestData * requestData)
 if (!hash)
 return NULL;
 len = snprintf(buf, sizeof(buf), "%s:%s", requestData->user, requestData->realm);
-if (len >= static_cast(sizeof(buf)))
+if (len < 0 || len >= static_cast(sizeof(buf)))
 return NULL;
 u = (user_data*)hash_lookup(hash, buf);
 if (u)
Index: squid-3.5.13/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc
===
--- squid-3.5.13.orig/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc
+++ squid-3.5.13/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc
@@ -227,7 +227,7 @@ local_printfx(const char *msg,...)
 va_start(ap, msg);
 x = vsnprintf(dbuf, sz, msg, ap);
 va_end(ap);
-if (x > 0) {
+if (x > 0 || x >= sz) {
 dbuf[x] = '\0';
 ++x;
 fputs(dbuf, stdout);
@@ -879,6 +879,7 @@ ConvertIP(edui_ldap_t *l, char *ip)
 return LDAP_ERR_OOB;/* Out of bounds -- Invalid address */
 memset(hexc, '\0', sizeof(hexc));
 int hlen = snprintf(hexc, sizeof(hexc), "%02X", (int)x);
+if (hlen < 0 || hlen >= static_cast(sizeof(hexc))) hlen = 0; /* impossible */
 strncat(l->search_ip, hexc, hlen);
 } else
 break;  /* reached end of octet */
@@ -1106,10 +1107,12 @@ SearchFilterLDAP(edui_ldap_t *l, char *g
 if (l->status & LDAP_IPV4_S) {
 int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \
   bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
 strncat(bufb, bufd, ln);
 } else if (l->status & LDAP_IPV6_S) {
 int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \
   bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
 strncat(bufb, bufd, ln);
 } else
 strncat(bufb, ")", 1);
@@ -1132,10 +1135,12 @@ SearchFilterLDAP(edui_ldap_t *l, char *g
 if (l->status & LDAP_IPV4_S) {
 int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \
   bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
 strncat(bufb, bufd, ln);
 } else if (l->status & LDAP_IPV6_S) {
 int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \
   bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
 strncat(bufb, bufd, ln);
 } else
 strncat(bufb, ")", 1);
@@ -1278,6 +1283,7 @@ SearchIPLDAP(edui_ldap_t *l)
 if (c < 0)
 c = c + 256;
 int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
+if (hlen < 0 || hlen >= static_cast(sizeof(hexc))) return LDAP_ERR_FAILED;
 if (k == 0)
 xstrncpy(bufb, hexc, sizeof(bufb));
 else
@@ -1313,6 +