Package: mpg123
Version: 0.59r-19
Severity: grave
Tags: security patch sarge pending
Justification: user security hole

[This problem is fixed already in 0.59r-20 (currently in unstable). I'm
filing this report so the issue can be tracked by the testing security team
more easily.]

The security patch to the http parser (httpget.c) applied in 0.59r-18
has introduced potential integer overflows in several places. They are
triggered when a playlist contains extremely long URL strings. As mpg123
allows to access playlists via http, this is a potential remote exploit.

I'm attaching the patch applied in 0.59r-20 to fix the integer overflow.
The only other change in 0.59r-20 with respect to the version in sarge
is a fix for a regression caused by the same security patch to 0.59r-18
(cf. #294801).

Daniel.

-- System Information:
Debian Release: 3.1
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)
Kernel: Linux 2.4.27
Locale: LANG=C, LC_CTYPE=de_DE (charmap=ISO-8859-1)

Versions of packages mpg123 depends on:
ii  libc6                       2.3.2.ds1-21 GNU C Library: Shared libraries an

-- no debconf information
---------------------
PatchSet 220 
Date: 2005/05/08 18:38:50
Author: kobras
Branch: HEAD
Tag: (none) 
Log:
Fix integer overflows in http parser. [dk]

Members: 
        httpget.c:1.14->1.15 
        debian/changelog:1.44->1.45 

Index: debian/mpg123/httpget.c
diff -u debian/mpg123/httpget.c:1.14 debian/mpg123/httpget.c:1.15
--- debian/mpg123/httpget.c:1.14        Sun May  8 18:46:14 2005
+++ debian/mpg123/httpget.c     Sun May  8 19:38:50 2005
@@ -13,6 +13,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <limits.h>
 #include <netdb.h>
 #include <sys/param.h>
 #include <sys/types.h>
@@ -197,7 +198,7 @@
 int http_open (char *url)
 {
        char *purl, *host, *request, *sptr;
-       size_t linelength, linelengthbase;
+       size_t linelength, linelengthbase, tmp;
        unsigned long myip;
        unsigned int myport;
        int sock;
@@ -227,6 +228,11 @@
        
        /* The length of purl is upper bound by 3*strlen(url) + 1 if
         * everything in it is a space */
+       if (strlen(url) >= ULONG_MAX/3) {
+               fprintf (stderr, "URL too long. Skipping...\n");
+               sock = -1;
+               goto exit;
+       }
        purl = (char *)malloc(strlen(url)*3 + 1);
        if (!purl) {
                fprintf (stderr, "malloc() failed, out of memory.\n");
@@ -272,11 +278,27 @@
        linelengthbase = 62 + strlen(prgName) + strlen(prgVersion)
                         + strlen(ACCEPT_HEAD);
 
-       if(httpauth)
-               linelengthbase += (strlen(httpauth) + 1) * 4;
+       if(httpauth) {
+               tmp = (strlen(httpauth) + 1) * 4;
+               if (strlen(httpauth) >= ULONG_MAX/4 - 1 ||
+                   linelengthbase + tmp < linelengthbase) {
+                       fprintf(stderr, "HTTP authentication too long. 
Skipping...\n");
+                       sock = -1;
+                       goto exit;
+               }
+               linelengthbase += tmp;
+       }
 
-       if(httpauth1)
-               linelengthbase += (strlen(httpauth1) + 1) * 4;
+       if(httpauth1) {
+               tmp = (strlen(httpauth1) + 1) * 4;
+               if (strlen(httpauth1) >= ULONG_MAX/4 - 1 ||
+                   linelengthbase + tmp < linelengthbase) {
+                       fprintf(stderr, "HTTP authentication too long. 
Skipping...\n");
+                       sock = -1;
+                       goto exit;
+               }
+               linelengthbase += tmp;
+       }
 
        do {
                if (proxyip != INADDR_NONE) {
@@ -284,9 +306,23 @@
                        myip = proxyip;
 
                        linelength = linelengthbase + strlen(purl);
-                       if(host)
+                       if (linelength < linelengthbase) {
+                               fprintf(stderr, "URL too long. Skipping...\n");
+                               sock = -1;
+                               goto exit;
+                       }
+
+                       if(host) {
+                               tmp = 9 + strlen(host) + 5;
+                               if (strlen(host) >= ULONG_MAX - 14 ||
+                                   linelength + tmp < linelength) {
+                                       fprintf(stderr, "Hostname info too 
long. Skipping...\n");
+                                       sock = -1;
+                                       goto exit;
+                               }
                                /* "Host: <host>:<port>\r\n" */
-                               linelength += 9 + strlen(host) + 5;
+                               linelength += tmp;
+                       }
 
                        /* Buffer is reused for receiving later on, so ensure
                         * minimum size. */
@@ -316,9 +352,23 @@
                        }
 
                        linelength = linelengthbase + strlen(sptr);
-                       if (host)
+                       if (linelength < linelengthbase) {
+                               fprintf(stderr, "URL too long. Skipping...\n");
+                               sock = -1;
+                               goto exit;
+                       }
+
+                       if(host) {
+                               tmp = 9 + strlen(host) + 5;
+                               if (strlen(host) >= ULONG_MAX - 14 ||
+                                   linelength + tmp < linelength) {
+                                       fprintf(stderr, "Hostname info too 
long. Skipping...\n");
+                                       sock = -1;
+                                       goto exit;
+                               }
                                /* "Host: <host>:<port>\r\n" */
-                               linelength += 9 + strlen(host) + 5;
+                               linelength += tmp;
+                       }
 
                        /* Buffer is reused for receiving later on, so ensure
                         * minimum size. */
Index: debian/mpg123/debian/changelog
diff -u debian/mpg123/debian/changelog:1.44 debian/mpg123/debian/changelog:1.45
--- debian/mpg123/debian/changelog:1.44 Sun May  8 18:46:14 2005
+++ debian/mpg123/debian/changelog      Sun May  8 19:38:50 2005
@@ -1,9 +1,11 @@
-mpg123 (0.59r-20) unstable; urgency=medium
+mpg123 (0.59r-20) unstable; urgency=high
 
+  * httpget.c: Fix integer overflows in http parser, introduced by
+    security patch for CAN-2004-0982.
   * httpget.c: Ensure minimum size of receive buffer to fix regression
     in 0.59r-18, caused by patch for CAN-2004-0982. Closes: #294801
 
- -- Daniel Kobras <[EMAIL PROTECTED]>  Sun,  8 May 2005 18:43:18 +0200
+ -- Daniel Kobras <[EMAIL PROTECTED]>  Sun,  8 May 2005 19:37:18 +0200
 
 mpg123 (0.59r-19) unstable; urgency=high
 

Reply via email to