Author: des
Date: Mon Nov  5 10:54:14 2012
New Revision: 242608
URL: http://svnweb.freebsd.org/changeset/base/242608

Log:
  MFH r221820, r221821, r221822: increase WARNS
  MFH r221830: mark all descriptors close-on-exec
  MFH r225813: man page fixes
  MFH r225814: adjust copyright statement
  MFH r226537: latin1 -> utf8
  MFH r230307, r230478: fix SIGINFO infinite loop and data loss
  MFH r233648: man page fixes
  MFH r234138: support percent-encoded user and password
  MFH r234837: avoid busy-loop on slow connections
  MFH r234838: don't reuse credentials when redirected to another host
  MFH r236193: avoid SIGPIPE on network connections
  MFH r240496: use libmd if and only if OpenSSL is not available

Modified:
  stable/7/lib/libfetch/Makefile
  stable/7/lib/libfetch/common.c
  stable/7/lib/libfetch/common.h
  stable/7/lib/libfetch/fetch.3
  stable/7/lib/libfetch/fetch.c
  stable/7/lib/libfetch/fetch.h
  stable/7/lib/libfetch/file.c
  stable/7/lib/libfetch/ftp.c
  stable/7/lib/libfetch/http.c
Directory Properties:
  stable/7/lib/libfetch/   (props changed)

Modified: stable/7/lib/libfetch/Makefile
==============================================================================
--- stable/7/lib/libfetch/Makefile      Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/Makefile      Mon Nov  5 10:54:14 2012        
(r242608)
@@ -16,8 +16,8 @@ CFLAGS+=      -DINET6
 
 .if ${MK_OPENSSL} != "no"
 CFLAGS+=       -DWITH_SSL
-DPADD=         ${LIBSSL} ${LIBCRYPTO} ${LIBMD}
-LDADD=         -lssl -lcrypto -lmd
+DPADD=         ${LIBSSL} ${LIBCRYPTO}
+LDADD=         -lssl -lcrypto
 .else
 DPADD=         ${LIBMD}
 LDADD=         -lmd
@@ -26,7 +26,7 @@ LDADD=                -lmd
 CFLAGS+=       -DFTP_COMBINE_CWDS
 
 CSTD?=         c99
-WARNS?=                2
+WARNS?=                4
 
 SHLIB_MAJOR=    5
 

Modified: stable/7/lib/libfetch/common.c
==============================================================================
--- stable/7/lib/libfetch/common.c      Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/common.c      Mon Nov  5 10:54:14 2012        
(r242608)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -209,10 +209,13 @@ conn_t *
 fetch_reopen(int sd)
 {
        conn_t *conn;
+       int opt = 1;
 
        /* allocate and fill connection structure */
        if ((conn = calloc(1, sizeof(*conn))) == NULL)
                return (NULL);
+       fcntl(sd, F_SETFD, FD_CLOEXEC);
+       setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof opt);
        conn->sd = sd;
        ++conn->ref;
        return (conn);
@@ -403,6 +406,33 @@ fetch_ssl_read(SSL *ssl, char *buf, size
 }
 #endif
 
+/*
+ * Cache some data that was read from a socket but cannot be immediately
+ * returned because of an interrupted system call.
+ */
+static int
+fetch_cache_data(conn_t *conn, char *src, size_t nbytes)
+{
+       char *tmp;
+
+       if (conn->cache.size < nbytes) {
+               tmp = realloc(conn->cache.buf, nbytes);
+               if (tmp == NULL) {
+                       fetch_syserr();
+                       return (-1);
+               }
+               conn->cache.buf = tmp;
+               conn->cache.size = nbytes;
+       }
+
+       memcpy(conn->cache.buf, src, nbytes);
+       conn->cache.len = nbytes;
+       conn->cache.pos = 0;
+
+       return (0);
+}
+
+
 static ssize_t
 fetch_socket_read(int sd, char *buf, size_t len)
 {
@@ -427,15 +457,32 @@ fetch_read(conn_t *conn, char *buf, size
        struct timeval now, timeout, delta;
        fd_set readfds;
        ssize_t rlen, total;
-       int r;
+       char *start;
 
-       if (fetchTimeout) {
-               FD_ZERO(&readfds);
+       if (fetchTimeout > 0) {
                gettimeofday(&timeout, NULL);
                timeout.tv_sec += fetchTimeout;
        }
 
        total = 0;
+       start = buf;
+
+       if (conn->cache.len > 0) {
+               /*
+                * The last invocation of fetch_read was interrupted by a
+                * signal after some data had been read from the socket. Copy
+                * the cached data into the supplied buffer before trying to
+                * read from the socket again.
+                */
+               total = (conn->cache.len < len) ? conn->cache.len : len;
+               memcpy(buf, conn->cache.buf, total);
+
+               conn->cache.len -= total;
+               conn->cache.pos += total;
+               len -= total;
+               buf += total;
+       }
+
        while (len > 0) {
                /*
                 * The socket is non-blocking.  Instead of the canonical
@@ -471,28 +518,32 @@ fetch_read(conn_t *conn, char *buf, size
                        total += rlen;
                        continue;
                } else if (rlen == FETCH_READ_ERROR) {
+                       if (errno == EINTR)
+                               fetch_cache_data(conn, start, total);
                        return (-1);
                }
                // assert(rlen == FETCH_READ_WAIT);
-               while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) {
+               FD_ZERO(&readfds);
+               while (!FD_ISSET(conn->sd, &readfds)) {
                        FD_SET(conn->sd, &readfds);
-                       gettimeofday(&now, NULL);
-                       delta.tv_sec = timeout.tv_sec - now.tv_sec;
-                       delta.tv_usec = timeout.tv_usec - now.tv_usec;
-                       if (delta.tv_usec < 0) {
-                               delta.tv_usec += 1000000;
-                               delta.tv_sec--;
-                       }
-                       if (delta.tv_sec < 0) {
-                               errno = ETIMEDOUT;
-                               fetch_syserr();
-                               return (-1);
+                       if (fetchTimeout > 0) {
+                               gettimeofday(&now, NULL);
+                               if (!timercmp(&timeout, &now, >)) {
+                                       errno = ETIMEDOUT;
+                                       fetch_syserr();
+                                       return (-1);
+                               }
+                               timersub(&timeout, &now, &delta);
                        }
                        errno = 0;
-                       r = select(conn->sd + 1, &readfds, NULL, NULL, &delta);
-                       if (r == -1) {
-                               if (errno == EINTR && fetchRestartCalls)
-                                       continue;
+                       if (select(conn->sd + 1, &readfds, NULL, NULL,
+                               fetchTimeout > 0 ? &delta : NULL) < 0) {
+                               if (errno == EINTR) {
+                                       if (fetchRestartCalls)
+                                               continue;
+                                       /* Save anything that was read. */
+                                       fetch_cache_data(conn, start, total);
+                               }
                                fetch_syserr();
                                return (-1);
                        }
@@ -676,6 +727,7 @@ fetch_close(conn_t *conn)
        if (--conn->ref > 0)
                return (0);
        ret = close(conn->sd);
+       free(conn->cache.buf);
        free(conn->buf);
        free(conn);
        return (ret);

Modified: stable/7/lib/libfetch/common.h
==============================================================================
--- stable/7/lib/libfetch/common.h      Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/common.h      Mon Nov  5 10:54:14 2012        
(r242608)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,13 @@ struct fetchconn {
        size_t           bufsize;       /* buffer size */
        size_t           buflen;        /* length of buffer contents */
        int              err;           /* last protocol reply code */
+       struct {                        /* data cached after an interrupted
+                                          read */
+               char    *buf;
+               size_t   size;
+               size_t   pos;
+               size_t   len;
+       } cache;
 #ifdef WITH_SSL
        SSL             *ssl;           /* SSL handle */
        SSL_CTX         *ssl_ctx;       /* SSL context */

Modified: stable/7/lib/libfetch/fetch.3
==============================================================================
--- stable/7/lib/libfetch/fetch.3       Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/fetch.3       Mon Nov  5 10:54:14 2012        
(r242608)
@@ -1,5 +1,5 @@
 .\"-
-.\" Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
+.\" Copyright (c) 1998-2011 Dag-Erling Smørgrav
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 26, 2010
+.Dd September 27, 2011
 .Dt FETCH 3
 .Os
 .Sh NAME
@@ -365,7 +365,7 @@ If the
 (if-modified-since) flag is specified, and
 the
 .Va ims_time
-field is set in 
+field is set in
 .Vt "struct url" ,
 then
 .Fn fetchXGetHTTP

Modified: stable/7/lib/libfetch/fetch.c
==============================================================================
--- stable/7/lib/libfetch/fetch.c       Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/fetch.c       Mon Nov  5 10:54:14 2012        
(r242608)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
+ * Copyright (c) 1998-2004 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -289,6 +289,49 @@ fetchMakeURL(const char *scheme, const c
 }
 
 /*
+ * Return value of the given hex digit.
+ */
+static int
+fetch_hexval(char ch)
+{
+
+       if (ch >= '0' && ch <= '9')
+               return (ch - '0');
+       else if (ch >= 'a' && ch <= 'f')
+               return (ch - 'a' + 10);
+       else if (ch >= 'A' && ch <= 'F')
+               return (ch - 'A' + 10);
+       return (-1);
+}
+
+/*
+ * Decode percent-encoded URL component from src into dst, stopping at end
+ * of string, or at @ or : separators.  Returns a pointer to the unhandled
+ * part of the input string (null terminator, @, or :).  No terminator is
+ * written to dst (it is the caller's responsibility).
+ */
+static const char *
+fetch_pctdecode(char *dst, const char *src, size_t dlen)
+{
+       int d1, d2;
+       char c;
+       const char *s;
+
+       for (s = src; *s != '\0' && *s != '@' && *s != ':'; s++) {
+               if (s[0] == '%' && (d1 = fetch_hexval(s[1])) >= 0 &&
+                   (d2 = fetch_hexval(s[2])) >= 0 && (d1 > 0 || d2 > 0)) {
+                       c = d1 << 4 | d2;
+                       s += 2;
+               } else {
+                       c = *s;
+               }
+               if (dlen-- > 0)
+                       *dst++ = c;
+       }
+       return (s);
+}
+
+/*
  * Split an URL into components. URL syntax is:
  * [method:/][/[user[:pwd]@]host[:port]/][document]
  * This almost, but not quite, RFC1738 URL syntax.
@@ -329,15 +372,11 @@ fetchParseURL(const char *URL)
        p = strpbrk(URL, "/@");
        if (p && *p == '@') {
                /* username */
-               for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++)
-                       if (i < URL_USERLEN)
-                               u->user[i++] = *q;
+               q = fetch_pctdecode(u->user, URL, URL_USERLEN);
 
                /* password */
                if (*q == ':')
-                       for (q++, i = 0; (*q != ':') && (*q != '@'); q++)
-                               if (i < URL_PWDLEN)
-                                       u->pwd[i++] = *q;
+                       q = fetch_pctdecode(u->pwd, ++q, URL_PWDLEN);
 
                p++;
        } else {

Modified: stable/7/lib/libfetch/fetch.h
==============================================================================
--- stable/7/lib/libfetch/fetch.h       Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/fetch.h       Mon Nov  5 10:54:14 2012        
(r242608)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
+ * Copyright (c) 1998-2004 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without

Modified: stable/7/lib/libfetch/file.c
==============================================================================
--- stable/7/lib/libfetch/file.c        Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/file.c        Mon Nov  5 10:54:14 2012        
(r242608)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/stat.h>
 
 #include <dirent.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -60,6 +61,7 @@ fetchXGetFile(struct url *u, struct url_
                return (NULL);
        }
 
+       fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
        return (f);
 }
 
@@ -90,6 +92,7 @@ fetchPutFile(struct url *u, const char *
                return (NULL);
        }
 
+       fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
        return (f);
 }
 

Modified: stable/7/lib/libfetch/ftp.c
==============================================================================
--- stable/7/lib/libfetch/ftp.c Mon Nov  5 10:45:37 2012        (r242607)
+++ stable/7/lib/libfetch/ftp.c Mon Nov  5 10:54:14 2012        (r242608)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
  *
  * Major Changelog:
  *
- * Dag-Erling Co�dan Sm�rgrav
+ * Dag-Erling Smørgrav
  * 9 Jun 1998
  *
  * Incorporated into libfetch
@@ -127,7 +127,7 @@ unmappedaddr(struct sockaddr_in6 *sin6)
            !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
                return;
        sin4 = (struct sockaddr_in *)sin6;
-       addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
+       addr = *(u_int32_t *)(uintptr_t)&sin6->sin6_addr.s6_addr[12];
        port = sin6->sin6_port;
        memset(sin4, 0, sizeof(struct sockaddr_in));
        sin4->sin_addr.s_addr = addr;

Modified: stable/7/lib/libfetch/http.c
==============================================================================
--- stable/7/lib/libfetch/http.c        Mon Nov  5 10:45:37 2012        
(r242607)
+++ stable/7/lib/libfetch/http.c        Mon Nov  5 10:54:14 2012        
(r242608)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2000-2004 Dag-Erling Co�dan Sm�rgrav
+ * Copyright (c) 2000-2011 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -76,7 +76,15 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+
+#ifdef WITH_SSL
+#include <openssl/md5.h>
+#define MD5Init(c) MD5_Init(c)
+#define MD5Update(c, data, len) MD5_Update(c, data, len)
+#define MD5Final(md, c) MD5_Final(md, c)
+#else
 #include <md5.h>
+#endif
 
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -199,6 +207,8 @@ http_growbuf(struct httpio *io, size_t l
 static int
 http_fillbuf(struct httpio *io, size_t len)
 {
+       ssize_t nbytes;
+
        if (io->error)
                return (-1);
        if (io->eof)
@@ -207,10 +217,11 @@ http_fillbuf(struct httpio *io, size_t l
        if (io->chunked == 0) {
                if (http_growbuf(io, len) == -1)
                        return (-1);
-               if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) {
-                       io->error = 1;
+               if ((nbytes = fetch_read(io->conn, io->buf, len)) == -1) {
+                       io->error = errno;
                        return (-1);
                }
+               io->buflen = nbytes;
                io->bufpos = 0;
                return (io->buflen);
        }
@@ -230,10 +241,11 @@ http_fillbuf(struct httpio *io, size_t l
                len = io->chunksize;
        if (http_growbuf(io, len) == -1)
                return (-1);
-       if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) {
-               io->error = 1;
+       if ((nbytes = fetch_read(io->conn, io->buf, len)) == -1) {
+               io->error = errno;
                return (-1);
        }
+       io->buflen = nbytes;
        io->chunksize -= io->buflen;
 
        if (io->chunksize == 0) {
@@ -275,8 +287,11 @@ http_readfn(void *v, char *buf, int len)
                io->bufpos += l;
        }
 
-       if (!pos && io->error)
+       if (!pos && io->error) {
+               if (io->error == EINTR)
+                       io->error = 0;
                return (-1);
+       }
        return (pos);
 }
 
@@ -457,7 +472,7 @@ http_match(const char *str, const char *
  * Get the next header and return the appropriate symbolic code.  We
  * need to read one line ahead for checking for a continuation line
  * belonging to the current header (continuation lines start with
- * white space). 
+ * white space).
  *
  * We get called with a fresh line already in the conn buffer, either
  * from the previous http_next_header() invocation, or, the first
@@ -465,7 +480,7 @@ http_match(const char *str, const char *
  *
  * This stops when we encounter an empty line (we dont read beyond the header
  * area).
- * 
+ *
  * Note that the "headerbuf" is just a place to return the result. Its
  * contents are not used for the next call. This means that no cleanup
  * is needed when ie doing another connection, just call the cleanup when
@@ -490,7 +505,7 @@ init_http_headerbuf(http_headerbuf_t *bu
        buf->buflen = 0;
 }
 
-static void 
+static void
 clean_http_headerbuf(http_headerbuf_t *buf)
 {
        if (buf->buf)
@@ -499,10 +514,10 @@ clean_http_headerbuf(http_headerbuf_t *b
 }
 
 /* Remove whitespace at the end of the buffer */
-static void 
+static void
 http_conn_trimright(conn_t *conn)
 {
-       while (conn->buflen && 
+       while (conn->buflen &&
               isspace((unsigned char)conn->buf[conn->buflen - 1]))
                conn->buflen--;
        conn->buf[conn->buflen] = '\0';
@@ -511,11 +526,11 @@ http_conn_trimright(conn_t *conn)
 static hdr_t
 http_next_header(conn_t *conn, http_headerbuf_t *hbuf, const char **p)
 {
-       int i, len;
+       unsigned int i, len;
 
-       /* 
+       /*
         * Have to do the stripping here because of the first line. So
-        * it's done twice for the subsequent lines. No big deal 
+        * it's done twice for the subsequent lines. No big deal
         */
        http_conn_trimright(conn);
        if (conn->buflen == 0)
@@ -530,19 +545,19 @@ http_next_header(conn_t *conn, http_head
        strcpy(hbuf->buf, conn->buf);
        hbuf->buflen = conn->buflen;
 
-       /* 
+       /*
         * Fetch possible continuation lines. Stop at 1st non-continuation
-        * and leave it in the conn buffer 
-         */
+        * and leave it in the conn buffer
+        */
        for (i = 0; i < HTTP_MAX_CONT_LINES; i++) {
                if (fetch_getln(conn) == -1)
                        return (hdr_syserror);
 
-               /* 
+               /*
                 * Note: we carry on the idea from the previous version
                 * that a pure whitespace line is equivalent to an empty
                 * one (so it's not continuation and will be handled when
-                * we are called next) 
+                * we are called next)
                 */
                http_conn_trimright(conn);
                if (conn->buf[0] != ' ' && conn->buf[0] != "\t"[0])
@@ -558,7 +573,7 @@ http_next_header(conn_t *conn, http_head
                }
                strcpy(hbuf->buf + hbuf->buflen, conn->buf);
                hbuf->buflen += conn->buflen;
-       } 
+       }
 
        /*
         * We could check for malformed headers but we don't really care.
@@ -577,12 +592,12 @@ http_next_header(conn_t *conn, http_head
  * [Proxy-]Authenticate header parsing
  */
 
-/* 
- * Read doublequote-delimited string into output buffer obuf (allocated 
+/*
+ * Read doublequote-delimited string into output buffer obuf (allocated
  * by caller, whose responsibility it is to ensure that it's big enough)
  * cp points to the first char after the initial '"'
- * Handles \ quoting 
- * Returns pointer to the first char after the terminating double quote, or 
+ * Handles \ quoting
+ * Returns pointer to the first char after the terminating double quote, or
  * NULL for error.
  */
 static const char *
@@ -623,7 +638,7 @@ typedef struct {
        int      nc; /* Nonce count */
 } http_auth_challenge_t;
 
-static void 
+static void
 init_http_auth_challenge(http_auth_challenge_t *b)
 {
        b->scheme = HTTPAS_UNKNOWN;
@@ -631,18 +646,18 @@ init_http_auth_challenge(http_auth_chall
        b->stale = b->nc = 0;
 }
 
-static void 
+static void
 clean_http_auth_challenge(http_auth_challenge_t *b)
 {
-       if (b->realm) 
+       if (b->realm)
                free(b->realm);
-       if (b->qop) 
+       if (b->qop)
                free(b->qop);
-       if (b->nonce) 
+       if (b->nonce)
                free(b->nonce);
-       if (b->opaque) 
+       if (b->opaque)
                free(b->opaque);
-       if (b->algo) 
+       if (b->algo)
                free(b->algo);
        init_http_auth_challenge(b);
 }
@@ -655,7 +670,7 @@ typedef struct {
        int     valid; /* We did parse an authenticate header */
 } http_auth_challenges_t;
 
-static void 
+static void
 init_http_auth_challenges(http_auth_challenges_t *cs)
 {
        int i;
@@ -664,7 +679,7 @@ init_http_auth_challenges(http_auth_chal
        cs->count = cs->valid = 0;
 }
 
-static void 
+static void
 clean_http_auth_challenges(http_auth_challenges_t *cs)
 {
        int i;
@@ -678,19 +693,19 @@ clean_http_auth_challenges(http_auth_cha
        init_http_auth_challenges(cs);
 }
 
-/* 
+/*
  * Enumeration for lexical elements. Separators will be returned as their own
  * ascii value
  */
 typedef enum {HTTPHL_WORD=256, HTTPHL_STRING=257, HTTPHL_END=258,
              HTTPHL_ERROR = 259} http_header_lex_t;
 
-/* 
+/*
  * Determine what kind of token comes next and return possible value
  * in buf, which is supposed to have been allocated big enough by
- * caller. Advance input pointer and return element type. 
+ * caller. Advance input pointer and return element type.
  */
-static int 
+static int
 http_header_lex(const char **cpp, char *buf)
 {
        size_t l;
@@ -719,7 +734,7 @@ http_header_lex(const char **cpp, char *
        return (HTTPHL_WORD);
 }
 
-/* 
+/*
  * Read challenges from http xxx-authenticate header and accumulate them
  * in the challenges list structure.
  *
@@ -731,7 +746,7 @@ http_header_lex(const char **cpp, char *
  *
  * We support both approaches anyway
  */
-static int 
+static int
 http_parse_authenticate(const char *cp, http_auth_challenges_t *cs)
 {
        int ret = -1;
@@ -755,7 +770,7 @@ http_parse_authenticate(const char *cp, 
 
        /* Loop on challenges */
        for (; cs->count < MAX_CHALLENGES; cs->count++) {
-               cs->challenges[cs->count] = 
+               cs->challenges[cs->count] =
                        malloc(sizeof(http_auth_challenge_t));
                if (cs->challenges[cs->count] == NULL) {
                        fetch_syserr();
@@ -768,14 +783,14 @@ http_parse_authenticate(const char *cp, 
                        cs->challenges[cs->count]->scheme = HTTPAS_DIGEST;
                } else {
                        cs->challenges[cs->count]->scheme = HTTPAS_UNKNOWN;
-                       /* 
-                         * Continue parsing as basic or digest may
+                       /*
+                        * Continue parsing as basic or digest may
                         * follow, and the syntax is the same for
                         * all. We'll just ignore this one when
                         * looking at the list
                         */
                }
-       
+
                /* Loop on attributes */
                for (;;) {
                        /* Key */
@@ -794,31 +809,31 @@ http_parse_authenticate(const char *cp, 
                                goto out;
 
                        if (!strcasecmp(key, "realm"))
-                               cs->challenges[cs->count]->realm = 
+                               cs->challenges[cs->count]->realm =
                                        strdup(value);
                        else if (!strcasecmp(key, "qop"))
-                               cs->challenges[cs->count]->qop = 
+                               cs->challenges[cs->count]->qop =
                                        strdup(value);
                        else if (!strcasecmp(key, "nonce"))
-                               cs->challenges[cs->count]->nonce = 
+                               cs->challenges[cs->count]->nonce =
                                        strdup(value);
                        else if (!strcasecmp(key, "opaque"))
-                               cs->challenges[cs->count]->opaque = 
+                               cs->challenges[cs->count]->opaque =
                                        strdup(value);
                        else if (!strcasecmp(key, "algorithm"))
-                               cs->challenges[cs->count]->algo = 
+                               cs->challenges[cs->count]->algo =
                                        strdup(value);
                        else if (!strcasecmp(key, "stale"))
-                               cs->challenges[cs->count]->stale = 
+                               cs->challenges[cs->count]->stale =
                                        strcasecmp(value, "no");
                        /* Else ignore unknown attributes */
 
                        /* Comma or Next challenge or End */
                        lex = http_header_lex(&cp, key);
-                       /* 
-                         * If we get a word here, this is the beginning of the
-                        * next challenge. Break the attributes loop 
-                         */
+                       /*
+                        * If we get a word here, this is the beginning of the
+                        * next challenge. Break the attributes loop
+                        */
                        if (lex == HTTPHL_WORD)
                                break;
 
@@ -835,10 +850,10 @@ http_parse_authenticate(const char *cp, 
                } /* End attributes loop */
        } /* End challenge loop */
 
-       /* 
-         * Challenges max count exceeded. This really can't happen
-        * with normal data, something's fishy -> error 
-        */ 
+       /*
+        * Challenges max count exceeded. This really can't happen
+        * with normal data, something's fishy -> error
+        */
 
 out:
        if (key)
@@ -1014,16 +1029,16 @@ init_http_auth_params(http_auth_params_t
        s->scheme = s->realm = s->user = s->password = 0;
 }
 
-static void 
+static void
 clean_http_auth_params(http_auth_params_t *s)
 {
-       if (s->scheme) 
+       if (s->scheme)
                free(s->scheme);
-       if (s->realm) 
+       if (s->realm)
                free(s->realm);
-       if (s->user) 
+       if (s->user)
                free(s->user);
-       if (s->password) 
+       if (s->password)
                free(s->password);
        init_http_auth_params(s);
 }
@@ -1078,7 +1093,7 @@ http_authfromenv(const char *p, http_aut
        }
        ret = 0;
 out:
-       if (ret == -1) 
+       if (ret == -1)
                clean_http_auth_params(parms);
        if (str)
                free(str);
@@ -1086,11 +1101,11 @@ out:
 }
 
 
-/* 
+/*
  * Digest response: the code to compute the digest is taken from the
- * sample implementation in RFC2616 
+ * sample implementation in RFC2616
  */
-#define IN
+#define IN const
 #define OUT
 
 #define HASHLEN 16
@@ -1099,7 +1114,7 @@ typedef char HASH[HASHLEN];
 typedef char HASHHEX[HASHHEXLEN+1];
 
 static const char *hexchars = "0123456789abcdef";
-static void 
+static void
 CvtHex(IN HASH Bin, OUT HASHHEX Hex)
 {
        unsigned short i;
@@ -1115,7 +1130,7 @@ CvtHex(IN HASH Bin, OUT HASHHEX Hex)
 };
 
 /* calculate H(A1) as per spec */
-static void 
+static void
 DigestCalcHA1(
        IN char * pszAlg,
        IN char * pszUserName,
@@ -1150,7 +1165,7 @@ DigestCalcHA1(
 }
 
 /* calculate request-digest/response-digest as per HTTP Digest spec */
-static void 
+static void
 DigestCalcResponse(
        IN HASHHEX HA1,           /* H(A1) */
        IN char * pszNonce,       /* nonce from server */
@@ -1163,7 +1178,7 @@ DigestCalcResponse(
        OUT HASHHEX Response      /* request-digest or response-digest */
        )
 {
-/*     DEBUG(fprintf(stderr, 
+/*     DEBUG(fprintf(stderr,
                      "Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n",
                      HA1, pszNonce, pszQop, pszMethod, pszDigestUri));*/
        MD5_CTX Md5Ctx;
@@ -1202,8 +1217,8 @@ DigestCalcResponse(
        CvtHex(RespHash, Response);
 }
 
-/* 
- * Generate/Send a Digest authorization header 
+/*
+ * Generate/Send a Digest authorization header
  * This looks like: [Proxy-]Authorization: credentials
  *
  *  credentials      = "Digest" digest-response
@@ -1236,10 +1251,10 @@ http_digest_auth(conn_t *conn, const cha
                DEBUG(fprintf(stderr, "realm/nonce not set in challenge\n"));
                return(-1);
        }
-       if (!c->algo) 
+       if (!c->algo)
                c->algo = strdup("");
 
-       if (asprintf(&options, "%s%s%s%s", 
+       if (asprintf(&options, "%s%s%s%s",
                     *c->algo? ",algorithm=" : "", c->algo,
                     c->opaque? ",opaque=" : "", c->opaque?c->opaque:"")== -1)
                return (-1);
@@ -1267,13 +1282,13 @@ http_digest_auth(conn_t *conn, const cha
                r = http_cmd(conn, "%s: Digest username=\"%s\",realm=\"%s\","
                             "nonce=\"%s\",uri=\"%s\",response=\"%s\","
                             "qop=\"auth\", cnonce=\"%s\", nc=%s%s",
-                            hdr, parms->user, c->realm, 
+                            hdr, parms->user, c->realm,
                             c->nonce, url->doc, digest,
                             cnonce, noncecount, options);
        } else {
                r = http_cmd(conn, "%s: Digest username=\"%s\",realm=\"%s\","
                             "nonce=\"%s\",uri=\"%s\",response=\"%s\"%s",
-                            hdr, parms->user, c->realm, 
+                            hdr, parms->user, c->realm,
                             c->nonce, url->doc, digest, options);
        }
        if (options)
@@ -1304,7 +1319,7 @@ http_basic_auth(conn_t *conn, const char
 }
 
 /*
- * Chose the challenge to answer and call the appropriate routine to 
+ * Chose the challenge to answer and call the appropriate routine to
  * produce the header.
  */
 static int
@@ -1330,16 +1345,16 @@ http_authorize(conn_t *conn, const char 
        }
 
        /* Error if "Digest" was specified and there is no Digest challenge */
-       if (!digest && (parms->scheme && 
+       if (!digest && (parms->scheme &&
                        !strcasecmp(parms->scheme, "digest"))) {
-               DEBUG(fprintf(stderr, 
+               DEBUG(fprintf(stderr,
                              "Digest auth in env, not supported by peer\n"));
                return (-1);
        }
-       /* 
-         * If "basic" was specified in the environment, or there is no Digest
+       /*
+        * If "basic" was specified in the environment, or there is no Digest
         * challenge, do the basic thing. Don't need a challenge for this,
-        * so no need to check basic!=NULL 
+        * so no need to check basic!=NULL
         */
        if (!digest || (parms->scheme && !strcasecmp(parms->scheme,"basic")))
                return (http_basic_auth(conn,hdr,parms->user,parms->password));
@@ -1495,7 +1510,7 @@ http_request(struct url *URL, const char
        http_auth_challenges_t proxy_challenges;
 
        /* The following calls don't allocate anything */
-       init_http_headerbuf(&headerbuf); 
+       init_http_headerbuf(&headerbuf);
        init_http_auth_challenges(&server_challenges);
        init_http_auth_challenges(&proxy_challenges);
 
@@ -1580,65 +1595,65 @@ http_request(struct url *URL, const char
                /* virtual host */
                http_cmd(conn, "Host: %s", host);
 
-               /* 
-                 * Proxy authorization: we only send auth after we received
-                * a 407 error. We do not first try basic anyway (changed 
-                 * when support was added for digest-auth)
-                 */
+               /*
+                * Proxy authorization: we only send auth after we received
+                * a 407 error. We do not first try basic anyway (changed
+                * when support was added for digest-auth)
+                */
                if (purl && proxy_challenges.valid) {
                        http_auth_params_t aparams;
                        init_http_auth_params(&aparams);
                        if (*purl->user || *purl->pwd) {
-                               aparams.user = purl->user ? 
+                               aparams.user = purl->user ?
                                        strdup(purl->user) : strdup("");
                                aparams.password = purl->pwd?
                                        strdup(purl->pwd) : strdup("");
-                       } else if ((p = getenv("HTTP_PROXY_AUTH")) != NULL && 
+                       } else if ((p = getenv("HTTP_PROXY_AUTH")) != NULL &&
                                   *p != '\0') {
                                if (http_authfromenv(p, &aparams) < 0) {
                                        http_seterr(HTTP_NEED_PROXY_AUTH);
                                        goto ouch;
                                }
                        }
-                       http_authorize(conn, "Proxy-Authorization", 
+                       http_authorize(conn, "Proxy-Authorization",
                                       &proxy_challenges, &aparams, url);
                        clean_http_auth_params(&aparams);
                }
 
-               /* 
-                 * Server authorization: we never send "a priori"
+               /*
+                * Server authorization: we never send "a priori"
                 * Basic auth, which used to be done if user/pass were
                 * set in the url. This would be weird because we'd send the
-                * password in the clear even if Digest is finally to be 
+                * password in the clear even if Digest is finally to be
                 * used (it would have made more sense for the
-                * pre-digest version to do this when Basic was specified 
-                 * in the environment) 
-                 */
+                * pre-digest version to do this when Basic was specified
+                * in the environment)
+                */
                if (server_challenges.valid) {
                        http_auth_params_t aparams;
                        init_http_auth_params(&aparams);
                        if (*url->user || *url->pwd) {
-                               aparams.user = url->user ? 
+                               aparams.user = url->user ?
                                        strdup(url->user) : strdup("");
-                               aparams.password = url->pwd ? 
+                               aparams.password = url->pwd ?
                                        strdup(url->pwd) : strdup("");
-                       } else if ((p = getenv("HTTP_AUTH")) != NULL && 
+                       } else if ((p = getenv("HTTP_AUTH")) != NULL &&
                                   *p != '\0') {
                                if (http_authfromenv(p, &aparams) < 0) {
                                        http_seterr(HTTP_NEED_AUTH);
                                        goto ouch;
                                }
-                       } else if (fetchAuthMethod && 
+                       } else if (fetchAuthMethod &&
                                   fetchAuthMethod(url) == 0) {
-                               aparams.user = url->user ? 
+                               aparams.user = url->user ?
                                        strdup(url->user) : strdup("");
-                               aparams.password = url->pwd ? 
+                               aparams.password = url->pwd ?
                                        strdup(url->pwd) : strdup("");
                        } else {
                                http_seterr(HTTP_NEED_AUTH);
                                goto ouch;
                        }
-                       http_authorize(conn, "Authorization", 
+                       http_authorize(conn, "Authorization",
                                       &server_challenges, &aparams, url);
                        clean_http_auth_params(&aparams);
                }
@@ -1786,7 +1801,9 @@ http_request(struct url *URL, const char
                                        DEBUG(fprintf(stderr, "failed to parse 
new URL\n"));
                                        goto ouch;
                                }
-                               if (!*new->user && !*new->pwd) {
+
+                               /* Only copy credentials if the host matches */
+                               if (!strcmp(new->host, url->host) && 
!*new->user && !*new->pwd) {
                                        strcpy(new->user, url->user);
                                        strcpy(new->pwd, url->pwd);
                                }
@@ -1818,12 +1835,12 @@ http_request(struct url *URL, const char
                } while (h > hdr_end);
 
                /* we need to provide authentication */
-               if (conn->err == HTTP_NEED_AUTH || 
+               if (conn->err == HTTP_NEED_AUTH ||
                    conn->err == HTTP_NEED_PROXY_AUTH) {
                        e = conn->err;
-                       if ((conn->err == HTTP_NEED_AUTH && 
-                            !server_challenges.valid) || 
-                           (conn->err == HTTP_NEED_PROXY_AUTH && 
+                       if ((conn->err == HTTP_NEED_AUTH &&
+                            !server_challenges.valid) ||

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to