libfetch: Fix PROXY_HOST bug, socket leak, cache-crash
authorJohn Marino <draco@marino.st>
Thu, 1 Nov 2012 19:02:52 +0000 (20:02 +0100)
committerJohn Marino <draco@marino.st>
Thu, 1 Nov 2012 21:56:18 +0000 (22:56 +0100)
As described in FreeBSD PR kern/139751, NO_PROXY=localhost doesn't work
due to bad for loop count.

As described in FreeBSD PR kern/153748, an ftp-cached connection will
close the connection too early when trying to send a request.

There is a socket leak in ftp_request that occurs after a connection is
established.  Make sure socket is disconnected before exiting.

Taken-From: FreeBSD SVN 198339 (21 OCT 2009)
Taken-From: FreeBSD SVN 199801 (25 NOV 2009)
Taken-From: FreeBSD SVN 217505 (17 JAN 2011)

lib/libfetch/common.c
lib/libfetch/ftp.c

index 9c8c990..d6fe226 100644 (file)
@@ -26,7 +26,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/lib/libfetch/common.c,v 1.56 2008/04/15 23:29:51 cperciva Exp $
- * $DragonFly: src/lib/libfetch/common.c,v 1.5 2008/04/02 14:46:37 joerg Exp $
  */
 
 #include <sys/param.h>
@@ -772,7 +771,7 @@ fetch_no_proxy_match(const char *host)
                                break;
 
                d_len = q - p;
-               if (d_len > 0 && h_len > d_len &&
+               if (d_len > 0 && h_len >= d_len &&
                    strncasecmp(host + h_len - d_len,
                        p, d_len) == 0) {
                        /* domain name matches */
index 063a7d9..be246ca 100644 (file)
@@ -1122,17 +1122,19 @@ ftp_request(struct url *url, const char *op, struct url_stat *us,
 
        /* change directory */
        if (ftp_cwd(conn, url->doc) == -1)
-               return (NULL);
+               goto errsock;
 
        /* stat file */
        if (us && ftp_stat(conn, url->doc, us) == -1
            && fetchLastErrCode != FETCH_PROTO
            && fetchLastErrCode != FETCH_UNAVAIL)
-               return (NULL);
+               goto errsock;
 
        /* just a stat */
-       if (strcmp(op, "STAT") == 0)
+       if (strcmp(op, "STAT") == 0) {
+               ftp_disconnect(conn);
                return (FILE *)1; /* bogus return value */
+       }
        if (strcmp(op, "STOR") == 0 || strcmp(op, "APPE") == 0)
                oflag = O_WRONLY;
        else
@@ -1140,6 +1142,10 @@ ftp_request(struct url *url, const char *op, struct url_stat *us,
 
        /* initiate the transfer */
        return (ftp_transfer(conn, op, url->doc, oflag, url->offset, flags));
+
+errsock:
+       ftp_disconnect(conn);
+       return (NULL);
 }
 
 /*