Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Update libfetch with latest version from FreeBSD head
Baptiste Daroussin committed 6 years ago
commit de9a03056e0973b9ea1f98159ffae15fc36b34c3
parent 2dc4a37
7 files changed +382 -255
modified external/libfetch/common.c
@@ -1,5 +1,7 @@
/*-
-
 * Copyright (c) 1998-2014 Dag-Erling Smørgrav
+
 * SPDX-License-Identifier: BSD-3-Clause
+
 *
+
 * Copyright (c) 1998-2016 Dag-Erling Smørgrav
 * Copyright (c) 2013 Michael Gmelin <freebsd@grem.de>
 * All rights reserved.
 *
@@ -28,6 +30,7 @@
 */

#include <sys/cdefs.h>
+
__FBSDID("$FreeBSD: head/lib/libfetch/common.c 347050 2019-05-03 06:06:39Z adrian $");

#include <sys/param.h>
#include <sys/socket.h>
@@ -156,7 +159,7 @@ fetch_syserr(void)
	case EHOSTDOWN:
		fetchLastErrCode = FETCH_DOWN;
		break;
-
default:
+
	default:
		fetchLastErrCode = FETCH_UNKNOWN;
	}
	snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno));
@@ -190,9 +193,9 @@ fetch_default_port(const char *scheme)

	if ((se = getservbyname(scheme, "tcp")) != NULL)
		return (ntohs(se->s_port));
-
	if (strcasecmp(scheme, SCHEME_FTP) == 0)
+
	if (strcmp(scheme, SCHEME_FTP) == 0)
		return (FTP_DEFAULT_PORT);
-
	if (strcasecmp(scheme, SCHEME_HTTP) == 0)
+
	if (strcmp(scheme, SCHEME_HTTP) == 0)
		return (HTTP_DEFAULT_PORT);
	return (0);
}
@@ -203,9 +206,9 @@ fetch_default_port(const char *scheme)
int
fetch_default_proxy_port(const char *scheme)
{
-
	if (strcasecmp(scheme, SCHEME_FTP) == 0)
+
	if (strcmp(scheme, SCHEME_FTP) == 0)
		return (FTP_DEFAULT_PROXY_PORT);
-
	if (strcasecmp(scheme, SCHEME_HTTP) == 0)
+
	if (strcmp(scheme, SCHEME_HTTP) == 0)
		return (HTTP_DEFAULT_PROXY_PORT);
	return (0);
}
@@ -218,17 +221,13 @@ conn_t *
fetch_reopen(int sd)
{
	conn_t *conn;
-
#ifdef SO_NOSIGPIPE
	int opt = 1;
-
#endif

	/* allocate and fill connection structure */
	if ((conn = calloc(1, sizeof(*conn))) == NULL)
		return (NULL);
	fcntl(sd, F_SETFD, FD_CLOEXEC);
-
#ifdef SO_NOSIGPIPE
	setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof opt);
-
#endif
	conn->sd = sd;
	++conn->ref;
	return (conn);
@@ -248,27 +247,96 @@ fetch_ref(conn_t *conn)


/*
+
 * Resolve an address
+
 */
+
struct addrinfo *
+
fetch_resolve(const char *addr, int port, int af)
+
{
+
	char hbuf[256], sbuf[8];
+
	struct addrinfo hints, *res;
+
	const char *hb, *he, *sep;
+
	const char *host, *service;
+
	int err, len;
+

+
	/* first, check for a bracketed IPv6 address */
+
	if (*addr == '[') {
+
		hb = addr + 1;
+
		if ((sep = strchr(hb, ']')) == NULL) {
+
			errno = EINVAL;
+
			goto syserr;
+
		}
+
		he = sep++;
+
	} else {
+
		hb = addr;
+
		sep = strchrnul(hb, ':');
+
		he = sep;
+
	}
+

+
	/* see if we need to copy the host name */
+
	if (*he != '\0') {
+
		len = snprintf(hbuf, sizeof(hbuf),
+
		    "%.*s", (int)(he - hb), hb);
+
		if (len < 0)
+
			goto syserr;
+
		if (len >= (int)sizeof(hbuf)) {
+
			errno = ENAMETOOLONG;
+
			goto syserr;
+
		}
+
		host = hbuf;
+
	} else {
+
		host = hb;
+
	}
+

+
	/* was it followed by a service name? */
+
	if (*sep == '\0' && port != 0) {
+
		if (port < 1 || port > 65535) {
+
			errno = EINVAL;
+
			goto syserr;
+
		}
+
		if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0)
+
			goto syserr;
+
		service = sbuf;
+
	} else if (*sep != '\0') {
+
		service = sep + 1;
+
	} else {
+
		service = NULL;
+
	}
+

+
	/* resolve */
+
	memset(&hints, 0, sizeof(hints));
+
	hints.ai_family = af;
+
	hints.ai_socktype = SOCK_STREAM;
+
	hints.ai_flags = AI_ADDRCONFIG;
+
	if ((err = getaddrinfo(host, service, &hints, &res)) != 0) {
+
		netdb_seterr(err);
+
		return (NULL);
+
	}
+
	return (res);
+
syserr:
+
	fetch_syserr();
+
	return (NULL);
+
}
+

+

+

+
/*
 * Bind a socket to a specific local address
 */
int
fetch_bind(int sd, int af, const char *addr)
{
-
	struct addrinfo hints, *res, *res0;
+
	struct addrinfo *cliai, *ai;
	int err;

-
	memset(&hints, 0, sizeof(hints));
-
	hints.ai_family = af;
-
	hints.ai_socktype = SOCK_STREAM;
-
	hints.ai_protocol = 0;
-
	if ((err = getaddrinfo(addr, NULL, &hints, &res0)) != 0)
+
	if ((cliai = fetch_resolve(addr, 0, af)) == NULL)
		return (-1);
-
	for (res = res0; res; res = res->ai_next)
-
		if (bind(sd, res->ai_addr, res->ai_addrlen) == 0) {
-
			freeaddrinfo(res0);
-
			return (0);
-
		}
-
	freeaddrinfo(res0);
-
	return (-1);
+
	for (ai = cliai; ai != NULL; ai = ai->ai_next)
+
		if ((err = bind(sd, ai->ai_addr, ai->ai_addrlen)) == 0)
+
			break;
+
	if (err != 0)
+
		fetch_syserr();
+
	freeaddrinfo(cliai);
+
	return (err == 0 ? 0 : -1);
}


@@ -278,59 +346,76 @@ fetch_bind(int sd, int af, const char *addr)
conn_t *
fetch_connect(const char *host, int port, int af, int verbose)
{
-
	conn_t *conn;
-
	char pbuf[10];
+
	struct addrinfo *cais = NULL, *sais = NULL, *cai, *sai;
	const char *bindaddr;
-
	struct addrinfo hints, *res, *res0;
-
	int sd, err;
+
	conn_t *conn = NULL;
+
	int err = 0, sd = -1;

-
	DEBUG(fprintf(stderr, "---> %s:%d\n", host, port));
+
	DEBUGF("---> %s:%d\n", host, port);

+
	/* resolve server address */
	if (verbose)
-
		fetch_info("looking up %s", host);
+
		fetch_info("resolving server address: %s:%d", host, port);
+
	if ((sais = fetch_resolve(host, port, af)) == NULL)
+
		goto fail;

-
	/* look up host name and set up socket address structure */
-
	snprintf(pbuf, sizeof(pbuf), "%d", port);
-
	memset(&hints, 0, sizeof(hints));
-
	hints.ai_family = af;
-
	hints.ai_socktype = SOCK_STREAM;
-
	hints.ai_protocol = 0;
-
	if ((err = getaddrinfo(host, pbuf, &hints, &res0)) != 0) {
-
		netdb_seterr(err);
-
		return (NULL);
-
	}
+
	/* resolve client address */
	bindaddr = getenv("FETCH_BIND_ADDRESS");
+
	if (bindaddr != NULL && *bindaddr != '\0') {
+
		if (verbose)
+
			fetch_info("resolving client address: %s", bindaddr);
+
		if ((cais = fetch_resolve(bindaddr, 0, af)) == NULL)
+
			goto fail;
+
	}

-
	if (verbose)
-
		fetch_info("connecting to %s:%d", host, port);
-

-
	/* try to connect */
-
	for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) {
-
		if ((sd = socket(res->ai_family, res->ai_socktype,
-
			 res->ai_protocol)) == -1)
-
			continue;
-
		if (bindaddr != NULL && *bindaddr != '\0' &&
-
		    fetch_bind(sd, res->ai_family, bindaddr) != 0) {
-
			fetch_info("failed to bind to '%s'", bindaddr);
-
			close(sd);
-
			continue;
+
	/* try each server address in turn */
+
	for (err = 0, sai = sais; sai != NULL; sai = sai->ai_next) {
+
		/* open socket */
+
		if ((sd = socket(sai->ai_family, SOCK_STREAM, 0)) < 0)
+
			goto syserr;
+
		/* attempt to bind to client address */
+
		for (err = 0, cai = cais; cai != NULL; cai = cai->ai_next) {
+
			if (cai->ai_family != sai->ai_family)
+
				continue;
+
			if ((err = bind(sd, cai->ai_addr, cai->ai_addrlen)) == 0)
+
				break;
+
		}
+
		if (err != 0) {
+
			if (verbose)
+
				fetch_info("failed to bind to %s", bindaddr);
+
			goto syserr;
		}
-
		if (connect(sd, res->ai_addr, res->ai_addrlen) == 0 &&
-
		    fcntl(sd, F_SETFL, O_NONBLOCK) == 0)
+
		/* attempt to connect to server address */
+
		if ((err = connect(sd, sai->ai_addr, sai->ai_addrlen)) == 0)
			break;
+
		/* clean up before next attempt */
		close(sd);
+
		sd = -1;
	}
-
	freeaddrinfo(res0);
-
	if (sd == -1) {
-
		fetch_syserr();
-
		return (NULL);
+
	if (err != 0) {
+
		if (verbose)
+
			fetch_info("failed to connect to %s:%d", host, port);
+
		goto syserr;
	}

-
	if ((conn = fetch_reopen(sd)) == NULL) {
-
		fetch_syserr();
-
		close(sd);
-
	}
+
	if ((conn = fetch_reopen(sd)) == NULL)
+
		goto syserr;
+
	if (cais != NULL)
+
		freeaddrinfo(cais);
+
	if (sais != NULL)
+
		freeaddrinfo(sais);
	return (conn);
+
syserr:
+
	fetch_syserr();
+
	goto fail;
+
fail:
+
	if (sd >= 0)
+
		close(sd);
+
	if (cais != NULL)
+
		freeaddrinfo(cais);
+
	if (sais != NULL)
+
		freeaddrinfo(sais);
+
	return (NULL);
}

#ifdef WITH_SSL
@@ -593,7 +678,11 @@ fetch_ssl_verify_altname(STACK_OF(GENERAL_NAME) *altnames,
#else
		name = sk_GENERAL_NAME_value(altnames, i);
#endif
+
#if OPENSSL_VERSION_NUMBER < 0x10100000L
		ns = (const char *)ASN1_STRING_data(name->d.ia5);
+
#else
+
		ns = (const char *)ASN1_STRING_get0_data(name->d.ia5);
+
#endif
		nslen = (size_t)ASN1_STRING_length(name->d.ia5);

		if (name->type == GEN_DNS && ip == NULL &&
@@ -688,14 +777,10 @@ fetch_ssl_setup_transport_layer(SSL_CTX *ctx, int verbose)
		ssl_ctx_options |= SSL_OP_NO_SSLv3;
	if (getenv("SSL_NO_TLS1") != NULL)
		ssl_ctx_options |= SSL_OP_NO_TLSv1;
-
#ifdef SSL_OP_NO_TLSv1_1
	if (getenv("SSL_NO_TLS1_1") != NULL)
		ssl_ctx_options |= SSL_OP_NO_TLSv1_1;
-
#endif
-
#ifdef SSL_OP_NO_TLSv1_2
	if (getenv("SSL_NO_TLS1_2") != NULL)
		ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
-
#endif
	if (verbose)
		fetch_info("SSL options: %lx", ssl_ctx_options);
	SSL_CTX_set_options(ctx, ssl_ctx_options);
@@ -913,6 +998,7 @@ fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
#else
	(void)conn;
	(void)verbose;
+
	(void)URL;
	fprintf(stderr, "SSL support disabled\n");
	return (-1);
#endif
@@ -1081,7 +1167,7 @@ fetch_getln(conn_t *conn)
	} while (c != '\n');

	conn->buf[conn->buflen] = '\0';
-
	DEBUG(fprintf(stderr, "<<< %s", conn->buf));
+
	DEBUGF("<<< %s", conn->buf);
	return (0);
}

@@ -1186,7 +1272,7 @@ fetch_putln(conn_t *conn, const char *str, size_t len)
	struct iovec iov[2];
	int ret;

-
	DEBUG(fprintf(stderr, ">>> %s\n", str));
+
	DEBUGF(">>> %s\n", str);
	iov[0].iov_base = __DECONST(char *, str);
	iov[0].iov_len = len;
	iov[1].iov_base = __DECONST(char *, ENDL);
@@ -1248,7 +1334,7 @@ fetch_add_entry(struct url_ent **p, int *size, int *len,
	}

	if (*len >= *size - 1) {
-
		tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p));
+
		tmp = reallocarray(*p, *size * 2 + 1, sizeof(**p));
		if (tmp == NULL) {
			errno = ENOMEM;
			fetch_syserr();
@@ -1281,27 +1367,23 @@ fetch_read_word(FILE *f)
	return (word);
}

-
/*
-
 * Get authentication data for a URL from .netrc
-
 */
-
int
-
fetch_netrc_auth(struct url *url)
+
static int
+
fetch_netrc_open(void)
{
+
	struct passwd *pwd;
	char fn[PATH_MAX];
-
	const char *word;
-
	char *p;
-
	FILE *f;
+
	const char *p;
+
	int fd, serrno;

	if ((p = getenv("NETRC")) != NULL) {
+
		DEBUGF("NETRC=%s\n", p);
		if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
			fetch_info("$NETRC specifies a file name "
			    "longer than PATH_MAX");
			return (-1);
		}
	} else {
-
		if ((p = getenv("HOME")) != NULL) {
-
			struct passwd *pwd;
-

+
		if ((p = getenv("HOME")) == NULL) {
			if ((pwd = getpwuid(getuid())) == NULL ||
			    (p = pwd->pw_dir) == NULL)
				return (-1);
@@ -1310,17 +1392,47 @@ fetch_netrc_auth(struct url *url)
			return (-1);
	}

-
	if ((f = fopen(fn, "r")) == NULL)
+
	if ((fd = open(fn, O_RDONLY)) < 0) {
+
		serrno = errno;
+
		DEBUGF("%s: %s\n", fn, strerror(serrno));
+
		errno = serrno;
+
	}
+
	return (fd);
+
}
+

+
/*
+
 * Get authentication data for a URL from .netrc
+
 */
+
int
+
fetch_netrc_auth(struct url *url)
+
{
+
	const char *word;
+
	int serrno;
+
	FILE *f;
+

+
	if (url->netrcfd < 0)
+
		url->netrcfd = fetch_netrc_open();
+
	if (url->netrcfd < 0)
		return (-1);
+
	if ((f = fdopen(url->netrcfd, "r")) == NULL) {
+
		serrno = errno;
+
		DEBUGF("fdopen(netrcfd): %s", strerror(errno));
+
		close(url->netrcfd);
+
		url->netrcfd = -1;
+
		errno = serrno;
+
		return (-1);
+
	}
+
	rewind(f);
+
	DEBUGF("searching netrc for %s\n", url->host);
	while ((word = fetch_read_word(f)) != NULL) {
		if (strcmp(word, "default") == 0) {
-
			DEBUG(fetch_info("Using default .netrc settings"));
+
			DEBUGF("using default netrc settings\n");
			break;
		}
		if (strcmp(word, "machine") == 0 &&
		    (word = fetch_read_word(f)) != NULL &&
		    strcasecmp(word, url->host) == 0) {
-
			DEBUG(fetch_info("Using .netrc settings for %s", word));
+
			DEBUGF("using netrc settings for %s\n", word);
			break;
		}
	}
@@ -1352,9 +1464,13 @@ fetch_netrc_auth(struct url *url)
		}
	}
	fclose(f);
+
	url->netrcfd = -1;
	return (0);
-
 ferr:
+
ferr:
+
	serrno = errno;
	fclose(f);
+
	url->netrcfd = -1;
+
	errno = serrno;
	return (-1);
}

@@ -1363,7 +1479,7 @@ fetch_netrc_auth(struct url *url)
 * which the proxy should not be consulted; the contents is a comma-,
 * or space-separated list of domain names.  A single asterisk will
 * override all proxy variables and no transactions will be proxied
-
 * (for compatability with lynx and curl, see the discussion at
+
 * (for compatibility with lynx and curl, see the discussion at
 * <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>).
 */
int
modified external/libfetch/common.h
@@ -1,4 +1,6 @@
/*-
+
 * SPDX-License-Identifier: BSD-3-Clause
+
 *
 * Copyright (c) 1998-2014 Dag-Erling Smørgrav
 * All rights reserved.
 *
@@ -25,7 +27,7 @@
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
-
 * $FreeBSD: head/lib/libfetch/common.h 267133 2014-06-05 22:16:26Z bapt $
+
 * $FreeBSD: head/lib/libfetch/common.h 334317 2018-05-29 10:28:20Z des $
 */

#ifndef _COMMON_H_INCLUDED
@@ -73,9 +75,10 @@ struct iovec;

void		 fetch_seterr(struct fetcherr *, int);
void		 fetch_syserr(void);
-
void		 fetch_info(const char *, ...);
+
void		 fetch_info(const char *, ...) __printflike(1, 2);
int		 fetch_default_port(const char *);
int		 fetch_default_proxy_port(const char *);
+
struct addrinfo *fetch_resolve(const char *, int, int);
int		 fetch_bind(int, int, const char *);
conn_t		*fetch_connect(const char *, int, int, int);
conn_t		*fetch_reopen(int);
@@ -101,9 +104,16 @@ int fetch_no_proxy_match(const char *);
#define url_seterr(n)	 fetch_seterr(url_errlist, n)

#ifndef NDEBUG
-
#define DEBUG(x) do { if (fetchDebug) { x; } } while (0)
+
#define DEBUGF(...)							\
+
	do {								\
+
		if (fetchDebug)						\
+
			fprintf(stderr, __VA_ARGS__);			\
+
	} while (0)
#else
-
#define DEBUG(x) do { } while (0)
+
#define DEBUGF(...)							\
+
	do {								\
+
		/* nothing */						\
+
	} while (0)
#endif

/*
modified external/libfetch/fetch.c
@@ -1,4 +1,6 @@
/*-
+
 * SPDX-License-Identifier: BSD-3-Clause
+
 *
 * Copyright (c) 1998-2004 Dag-Erling Smørgrav
 * All rights reserved.
 *
@@ -27,12 +29,13 @@
 */

#include <sys/cdefs.h>
-
#include "bsd_compat.h"
-
__FBSDID("$FreeBSD: head/lib/libfetch/fetch.c 252375 2013-06-29 15:51:27Z kientzle $");
+
__FBSDID("$FreeBSD: head/lib/libfetch/fetch.c 341013 2018-11-27 10:45:14Z des $");

#include <sys/param.h>
-
#include <sys/errno.h>

+
#include <netinet/in.h>
+

+
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@@ -80,13 +83,13 @@ fetchXGet(struct url *URL, struct url_stat *us, const char *flags)
		us->size = -1;
		us->atime = us->mtime = 0;
	}
-
	if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
+
	if (strcmp(URL->scheme, SCHEME_FILE) == 0)
		return (fetchXGetFile(URL, us, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_FTP) == 0)
		return (fetchXGetFTP(URL, us, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTP) == 0)
		return (fetchXGetHTTP(URL, us, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTPS) == 0)
		return (fetchXGetHTTP(URL, us, flags));
	url_seterr(URL_BAD_SCHEME);
	return (NULL);
@@ -110,13 +113,13 @@ FILE *
fetchPut(struct url *URL, const char *flags)
{

-
	if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
+
	if (strcmp(URL->scheme, SCHEME_FILE) == 0)
		return (fetchPutFile(URL, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_FTP) == 0)
		return (fetchPutFTP(URL, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTP) == 0)
		return (fetchPutHTTP(URL, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTPS) == 0)
		return (fetchPutHTTP(URL, flags));
	url_seterr(URL_BAD_SCHEME);
	return (NULL);
@@ -134,13 +137,13 @@ fetchStat(struct url *URL, struct url_stat *us, const char *flags)
		us->size = -1;
		us->atime = us->mtime = 0;
	}
-
	if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
+
	if (strcmp(URL->scheme, SCHEME_FILE) == 0)
		return (fetchStatFile(URL, us, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_FTP) == 0)
		return (fetchStatFTP(URL, us, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTP) == 0)
		return (fetchStatHTTP(URL, us, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTPS) == 0)
		return (fetchStatHTTP(URL, us, flags));
	url_seterr(URL_BAD_SCHEME);
	return (-1);
@@ -154,13 +157,13 @@ struct url_ent *
fetchList(struct url *URL, const char *flags)
{

-
	if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
+
	if (strcmp(URL->scheme, SCHEME_FILE) == 0)
		return (fetchListFile(URL, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_FTP) == 0)
		return (fetchListFTP(URL, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTP) == 0)
		return (fetchListHTTP(URL, flags));
-
	else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
+
	else if (strcmp(URL->scheme, SCHEME_HTTPS) == 0)
		return (fetchListHTTP(URL, flags));
	url_seterr(URL_BAD_SCHEME);
	return (NULL);
@@ -271,6 +274,7 @@ fetchMakeURL(const char *scheme, const char *host, int port, const char *doc,
		fetch_syserr();
		return (NULL);
	}
+
	u->netrcfd = -1;

	if ((u->doc = strdup(doc ? doc : "/")) == NULL) {
		fetch_syserr();
@@ -343,18 +347,21 @@ fetchParseURL(const char *URL)
	char *doc;
	const char *p, *q;
	struct url *u;
-
	int i;
+
	int i, n;

	/* allocate struct url */
	if ((u = calloc(1, sizeof(*u))) == NULL) {
		fetch_syserr();
		return (NULL);
	}
+
	u->netrcfd = -1;

	/* scheme name */
	if ((p = strstr(URL, ":/"))) {
-
		snprintf(u->scheme, URL_SCHEMELEN+1,
-
		    "%.*s", (int)(p - URL), URL);
+
                if (p - URL > URL_SCHEMELEN)
+
                        goto ouch;
+
                for (i = 0; URL + i < p; i++)
+
                        u->scheme[i] = tolower((unsigned char)URL[i]);
		URL = ++p;
		/*
		 * Only one slash: no host, leave slash as part of document
@@ -385,29 +392,37 @@ fetchParseURL(const char *URL)
	}

	/* hostname */
-
#ifdef INET6
-
	if (*p == '[' && (q = strchr(p + 1, ']')) != NULL &&
-
	    (*++q == '\0' || *q == '/' || *q == ':')) {
-
		if ((i = q - p - 2) > MAXHOSTNAMELEN)
-
			i = MAXHOSTNAMELEN;
-
		strncpy(u->host, ++p, i);
-
		p = q;
-
	} else
-
#endif
-
		for (i = 0; *p && (*p != '/') && (*p != ':'); p++)
-
			if (i < MAXHOSTNAMELEN)
-
				u->host[i++] = *p;
+
	if (*p == '[') {
+
		q = p + 1 + strspn(p + 1, ":0123456789ABCDEFabcdef");
+
		if (*q++ != ']')
+
			goto ouch;
+
	} else {
+
		/* valid characters in a DNS name */
+
		q = p + strspn(p, "-." "0123456789"
+
		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "_"
+
		    "abcdefghijklmnopqrstuvwxyz");
+
	}
+
	if ((*q != '\0' && *q != '/' && *q != ':') || q - p > MAXHOSTNAMELEN)
+
		goto ouch;
+
	for (i = 0; p + i < q; i++)
+
		u->host[i] = tolower((unsigned char)p[i]);
+
	u->host[i] = '\0';
+
	p = q;

	/* port */
	if (*p == ':') {
-
		for (q = ++p; *q && (*q != '/'); q++)
-
			if (isdigit((unsigned char)*q))
-
				u->port = u->port * 10 + (*q - '0');
-
			else {
+
		for (n = 0, q = ++p; *q && (*q != '/'); q++) {
+
			if (*q >= '0' && *q <= '9' && n < INT_MAX / 10) {
+
				n = n * 10 + (*q - '0');
+
			} else {
				/* invalid port */
				url_seterr(URL_BAD_PORT);
				goto ouch;
			}
+
		}
+
		if (n < 1 || n > IPPORT_MAX)
+
			goto ouch;
+
		u->port = n;
		p = q;
	}

@@ -416,8 +431,8 @@ nohost:
	if (!*p)
		p = "/";

-
	if (strcasecmp(u->scheme, SCHEME_HTTP) == 0 ||
-
	    strcasecmp(u->scheme, SCHEME_HTTPS) == 0) {
+
	if (strcmp(u->scheme, SCHEME_HTTP) == 0 ||
+
	    strcmp(u->scheme, SCHEME_HTTPS) == 0) {
		const char hexnums[] = "0123456789abcdef";

		/* percent-escape whitespace. */
@@ -442,15 +457,14 @@ nohost:
		goto ouch;
	}

-
	DEBUG(fprintf(stderr,
-
		  "scheme:   [%s]\n"
-
		  "user:     [%s]\n"
-
		  "password: [%s]\n"
-
		  "host:     [%s]\n"
-
		  "port:     [%d]\n"
-
		  "document: [%s]\n",
-
		  u->scheme, u->user, u->pwd,
-
		  u->host, u->port, u->doc));
+
	DEBUGF("scheme:   \"%s\"\n"
+
	    "user:     \"%s\"\n"
+
	    "password: \"%s\"\n"
+
	    "host:     \"%s\"\n"
+
	    "port:     \"%d\"\n"
+
	    "document: \"%s\"\n",
+
	    u->scheme, u->user, u->pwd,
+
	    u->host, u->port, u->doc);

	return (u);

modified external/libfetch/fetch.h
@@ -1,4 +1,6 @@
/*-
+
 * SPDX-License-Identifier: BSD-3-Clause
+
 *
 * Copyright (c) 1998-2004 Dag-Erling Smørgrav
 * All rights reserved.
 *
@@ -25,7 +27,7 @@
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
-
 * $FreeBSD: head/lib/libfetch/fetch.h 267133 2014-06-05 22:16:26Z bapt $
+
 * $FreeBSD: head/lib/libfetch/fetch.h 326219 2017-11-26 02:00:33Z pfg $
 */

#ifndef _FETCH_H_INCLUDED
@@ -47,6 +49,7 @@ struct url {
	off_t		 offset;
	size_t		 length;
	time_t		 ims_time;
+
	int		 netrcfd;
};

struct url_stat {
@@ -87,8 +90,6 @@ struct url_ent {
#define	FETCH_URL	18
#define	FETCH_VERBOSE	19

-
#include <sys/cdefs.h>
-

__BEGIN_DECLS

/* FILE-specific functions */
modified external/libfetch/file.c
@@ -1,4 +1,6 @@
/*-
+
 * SPDX-License-Identifier: BSD-3-Clause
+
 *
 * Copyright (c) 1998-2011 Dag-Erling Smørgrav
 * All rights reserved.
 *
@@ -27,8 +29,7 @@
 */

#include <sys/cdefs.h>
-
#include "bsd_compat.h"
-
__FBSDID("$FreeBSD: head/lib/libfetch/file.c 240495 2012-09-14 12:15:13Z eadler $");
+
__FBSDID("$FreeBSD: head/lib/libfetch/file.c 326219 2017-11-26 02:00:33Z pfg $");

#include <sys/param.h>
#include <sys/stat.h>
modified external/libfetch/ftp.c
@@ -1,4 +1,6 @@
/*-
+
 * SPDX-License-Identifier: (BSD-3-Clause AND Beerware)
+
 *
 * Copyright (c) 1998-2011 Dag-Erling Smørgrav
 * All rights reserved.
 *
@@ -27,6 +29,7 @@
 */

#include <sys/cdefs.h>
+
__FBSDID("$FreeBSD: head/lib/libfetch/ftp.c 341013 2018-11-27 10:45:14Z des $");

/*
 * Portions of this code were taken from or based on ftpio.c:
@@ -55,10 +58,6 @@
 *
 */

-
#ifdef __NetBSD__
-
#define _NETBSD_SOURCE
-
#endif
-

#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -76,7 +75,6 @@
#include <time.h>
#include <unistd.h>

-
#include "bsd_compat.h"
#include "fetch.h"
#include "common.h"
#include "ftperr.h"
@@ -137,9 +135,7 @@ unmappedaddr(struct sockaddr_in6 *sin6)
	sin4->sin_addr.s_addr = addr;
	sin4->sin_port = port;
	sin4->sin_family = AF_INET;
-
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
	sin4->sin_len = sizeof(struct sockaddr_in);
-
#endif
}

/*
@@ -263,7 +259,7 @@ ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen)
		return (FTP_PROTOCOL_ERROR);
	*dst = '\0';
#if 0
-
	DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd));
+
	DEBUGF("pwd: [%s]\n", pwd);
#endif
	return (FTP_OK);
}
@@ -295,8 +291,8 @@ ftp_cwd(conn_t *conn, const char *file)
			if (pwd[i] != file[i])
				break;
#if 0
-
		DEBUG(fprintf(stderr, "have: [%.*s|%s]\n", i, pwd, pwd + i));
-
		DEBUG(fprintf(stderr, "want: [%.*s|%s]\n", i, file, file + i));
+
		DEBUGF("have: [%.*s|%s]\n", i, pwd, pwd + i);
+
		DEBUGF("want: [%.*s|%s]\n", i, file, file + i);
#endif
		/* Keep going up a dir until we have a matching prefix. */
		if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/'))
@@ -437,7 +433,7 @@ ftp_stat(conn_t *conn, const char *file, struct url_stat *us)
	}
	if (us->size == 0)
		us->size = -1;
-
	DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size));
+
	DEBUGF("size: [%lld]\n", (long long)us->size);

	e = ftp_cmd(conn, "MDTM %.*s", filenamelen, filename);
	if (e != FTP_FILE_STATUS) {
@@ -472,10 +468,9 @@ ftp_stat(conn_t *conn, const char *file, struct url_stat *us)
		t = time(NULL);
	us->mtime = t;
	us->atime = t;
-
	DEBUG(fprintf(stderr,
-
	    "last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n",
+
	DEBUGF("last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n",
	    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-
	    tm.tm_hour, tm.tm_min, tm.tm_sec));
+
	    tm.tm_hour, tm.tm_min, tm.tm_sec);
	return (0);
}

@@ -492,7 +487,7 @@ struct ftpio {

static int	 ftp_readfn(void *, char *, int);
static int	 ftp_writefn(void *, const char *, int);
-
static off_t	 ftp_seekfn(void *, off_t, int);
+
static fpos_t	 ftp_seekfn(void *, fpos_t, int);
static int	 ftp_closefn(void *);

static int
@@ -555,8 +550,8 @@ ftp_writefn(void *v, const char *buf, int len)
	return (-1);
}

-
static off_t
-
ftp_seekfn(void *v, off_t pos __unused, int whence __unused)
+
static fpos_t
+
ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused)
{
	struct ftpio *io;

@@ -589,7 +584,7 @@ ftp_closefn(void *v)
	fetch_close(io->dconn);
	io->dir = -1;
	io->dconn = NULL;
-
	DEBUG(fprintf(stderr, "Waiting for final status\n"));
+
	DEBUGF("Waiting for final status\n");
	r = ftp_chkerr(io->cconn);
	if (io->cconn == cached_connection && io->cconn->ref == 1)
		cached_connection = NULL;
@@ -774,9 +769,9 @@ ftp_transfer(conn_t *conn, const char *oper, const char *file,
			fetch_info("opening data connection");
		bindaddr = getenv("FETCH_BIND_ADDRESS");
		if (bindaddr != NULL && *bindaddr != '\0' &&
-
		    fetch_bind(sd, sa.ss_family, bindaddr) != 0)
-
			goto sysouch;
-
		if (connect(sd, (struct sockaddr *)&sa, l) == -1)
+
		    (e = fetch_bind(sd, sa.ss_family, bindaddr)) != 0)
+
			goto ouch;
+
		if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
			goto sysouch;

		/* make the server initiate the transfer */
@@ -790,14 +785,12 @@ ftp_transfer(conn_t *conn, const char *oper, const char *file,
		u_int32_t a;
		u_short p;
		int arg, d;
-
		socklen_t sslen;
		char *ap;
		char hname[INET6_ADDRSTRLEN];

		switch (sa.ss_family) {
		case AF_INET6:
			((struct sockaddr_in6 *)&sa)->sin6_port = 0;
-
			sslen = sizeof(struct sockaddr_in6);
#ifdef IPV6_PORTRANGE
			arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH;
			if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE,
@@ -807,18 +800,15 @@ ftp_transfer(conn_t *conn, const char *oper, const char *file,
			break;
		case AF_INET:
			((struct sockaddr_in *)&sa)->sin_port = 0;
-
			sslen = sizeof(struct sockaddr_in);
-
#ifdef IP_PORTRANGE
			arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH;
			if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
				(char *)&arg, sizeof(arg)) == -1)
				goto sysouch;
-
#endif
			break;
		}
		if (verbose)
			fetch_info("binding data socket");
-
		if (bind(sd, (struct sockaddr *)&sa, sslen) == -1)
+
		if (bind(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
			goto sysouch;
		if (listen(sd, 1) == -1)
			goto sysouch;
@@ -841,7 +831,7 @@ ftp_transfer(conn_t *conn, const char *oper, const char *file,
			e = -1;
			sin6 = (struct sockaddr_in6 *)&sa;
			sin6->sin6_scope_id = 0;
-
			if (getnameinfo((struct sockaddr *)&sa, sslen,
+
			if (getnameinfo((struct sockaddr *)&sa, sa.ss_len,
				hname, sizeof(hname),
				NULL, 0, NI_NUMERICHOST) == 0) {
				e = ftp_cmd(conn, "EPRT |%d|%s|%d|", 2, hname,
@@ -924,7 +914,8 @@ ftp_authenticate(conn_t *conn, struct url *url, struct url *purl)
		fetch_netrc_auth(url);
	user = url->user;
	if (*user == '\0')
-
		user = getenv("FTP_LOGIN");
+
		if ((user = getenv("FTP_LOGIN")) != NULL)
+
			DEBUGF("FTP_LOGIN=%s\n", user);
	if (user == NULL || *user == '\0')
		user = FTP_ANONYMOUS_USER;
	if (purl && url->port == fetch_default_port(url->scheme))
@@ -938,7 +929,8 @@ ftp_authenticate(conn_t *conn, struct url *url, struct url *purl)
	if (e == FTP_NEED_PASSWORD) {
		pwd = url->pwd;
		if (*pwd == '\0')
-
			pwd = getenv("FTP_PASSWORD");
+
			if ((pwd = getenv("FTP_PASSWORD")) != NULL)
+
				DEBUGF("FTP_PASSWORD=%s\n", pwd);
		if (pwd == NULL || *pwd == '\0') {
			if ((logname = getlogin()) == NULL)
				logname = FTP_ANONYMOUS_USER;
@@ -1093,8 +1085,8 @@ ftp_get_proxy(struct url * url, const char *flags)
		}
		if (!purl->port)
			purl->port = fetch_default_proxy_port(purl->scheme);
-
		if (strcasecmp(purl->scheme, SCHEME_FTP) == 0 ||
-
		    strcasecmp(purl->scheme, SCHEME_HTTP) == 0)
+
		if (strcmp(purl->scheme, SCHEME_FTP) == 0 ||
+
		    strcmp(purl->scheme, SCHEME_HTTP) == 0)
			return (purl);
		fetchFreeURL(purl);
	}
@@ -1112,7 +1104,8 @@ ftp_request(struct url *url, const char *op, struct url_stat *us,
	int oflag;

	/* check if we should use HTTP instead */
-
	if (purl && strcasecmp(purl->scheme, SCHEME_HTTP) == 0) {
+
	if (purl && (strcmp(purl->scheme, SCHEME_HTTP) == 0 ||
+
	    strcmp(purl->scheme, SCHEME_HTTPS) == 0)) {
		if (strcmp(op, "STAT") == 0)
			return (http_request(url, "HEAD", us, purl, flags));
		else if (strcmp(op, "RETR") == 0)
modified external/libfetch/http.c
@@ -1,4 +1,6 @@
/*-
+
 * SPDX-License-Identifier: BSD-3-Clause
+
 *
 * Copyright (c) 2000-2014 Dag-Erling Smørgrav
 * All rights reserved.
 *
@@ -27,6 +29,7 @@
 */

#include <sys/cdefs.h>
+
__FBSDID("$FreeBSD: head/lib/libfetch/http.c 351573 2019-08-28 17:01:28Z markj $");

/*
 * The following copyright applies to the base64 code:
@@ -59,10 +62,7 @@
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
-
#define _XOPEN_SOURCE
-
#ifdef __NetBSD__
-
#define _NETBSD_SOURCE
-
#endif
+

#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
@@ -91,7 +91,6 @@
#include <netinet/in.h>
#include <netinet/tcp.h>

-
#include "bsd_compat.h"
#include "fetch.h"
#include "common.h"
#include "httperr.h"
@@ -121,7 +120,7 @@
			    || (xyz) == HTTP_USE_PROXY \
			    || (xyz) == HTTP_SEE_OTHER)

-
#define HTTP_ERROR(xyz) ((xyz) > 400 && (xyz) < 599)
+
#define HTTP_ERROR(xyz) ((xyz) >= 400 && (xyz) <= 599)


/*****************************************************************************
@@ -781,9 +780,9 @@ http_parse_authenticate(const char *cp, http_auth_challenges_t *cs)
			goto out;
		}
		init_http_auth_challenge(cs->challenges[cs->count]);
-
		if (!strcasecmp(key, "basic")) {
+
		if (strcasecmp(key, "basic") == 0) {
			cs->challenges[cs->count]->scheme = HTTPAS_BASIC;
-
		} else if (!strcasecmp(key, "digest")) {
+
		} else if (strcasecmp(key, "digest") == 0) {
			cs->challenges[cs->count]->scheme = HTTPAS_DIGEST;
		} else {
			cs->challenges[cs->count]->scheme = HTTPAS_UNKNOWN;
@@ -812,25 +811,27 @@ http_parse_authenticate(const char *cp, http_auth_challenges_t *cs)
			if (lex != HTTPHL_WORD && lex != HTTPHL_STRING)
				goto out;

-
			if (!strcasecmp(key, "realm"))
+
			if (strcasecmp(key, "realm") == 0) {
				cs->challenges[cs->count]->realm =
-
					strdup(value);
-
			else if (!strcasecmp(key, "qop"))
+
				    strdup(value);
+
			} else if (strcasecmp(key, "qop") == 0) {
				cs->challenges[cs->count]->qop =
-
					strdup(value);
-
			else if (!strcasecmp(key, "nonce"))
+
				    strdup(value);
+
			} else if (strcasecmp(key, "nonce") == 0) {
				cs->challenges[cs->count]->nonce =
-
					strdup(value);
-
			else if (!strcasecmp(key, "opaque"))
+
				    strdup(value);
+
			} else if (strcasecmp(key, "opaque") == 0) {
				cs->challenges[cs->count]->opaque =
-
					strdup(value);
-
			else if (!strcasecmp(key, "algorithm"))
+
				    strdup(value);
+
			} else if (strcasecmp(key, "algorithm") == 0) {
				cs->challenges[cs->count]->algo =
-
					strdup(value);
-
			else if (!strcasecmp(key, "stale"))
+
				    strdup(value);
+
			} else if (strcasecmp(key, "stale") == 0) {
				cs->challenges[cs->count]->stale =
-
					strcasecmp(value, "no");
-
			/* Else ignore unknown attributes */
+
				    strcasecmp(value, "no");
+
			} else {
+
				/* ignore unknown attributes */
+
			}

			/* Comma or Next challenge or End */
			lex = http_header_lex(&cp, key);
@@ -892,10 +893,9 @@ http_parse_mtime(const char *p, time_t *mtime)
	setlocale(LC_TIME, locale);
	if (r == NULL)
		return (-1);
-
	DEBUG(fprintf(stderr, "last modified: [%04d-%02d-%02d "
-
		  "%02d:%02d:%02d]\n",
-
		  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-
		  tm.tm_hour, tm.tm_min, tm.tm_sec));
+
	DEBUGF("last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n",
+
	    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+
	    tm.tm_hour, tm.tm_min, tm.tm_sec);
	*mtime = timegm(&tm);
	return (0);
}
@@ -912,8 +912,7 @@ http_parse_length(const char *p, off_t *length)
		len = len * 10 + (*p - '0');
	if (*p)
		return (-1);
-
	DEBUG(fprintf(stderr, "content length: [%lld]\n",
-
	    (long long)len));
+
	DEBUGF("content length: [%lld]\n", (long long)len);
	*length = len;
	return (0);
}
@@ -947,12 +946,11 @@ http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size)
	if (*p || len < last - first + 1)
		return (-1);
	if (first == -1) {
-
		DEBUG(fprintf(stderr, "content range: [*/%lld]\n",
-
		    (long long)len));
+
		DEBUGF("content range: [*/%lld]\n", (long long)len);
		*length = 0;
	} else {
-
		DEBUG(fprintf(stderr, "content range: [%lld-%lld/%lld]\n",
-
		    (long long)first, (long long)last, (long long)len));
+
		DEBUGF("content range: [%lld-%lld/%lld]\n",
+
		    (long long)first, (long long)last, (long long)len);
		*length = last - first + 1;
	}
	*offset = first;
@@ -1188,9 +1186,10 @@ DigestCalcResponse(
	OUT HASHHEX Response      /* request-digest or response-digest */
	)
{
-
/*	DEBUG(fprintf(stderr,
-
		      "Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n",
-
		      HA1, pszNonce, pszQop, pszMethod, pszDigestUri));*/
+
#if 0
+
	DEBUGF("Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n",
+
	    HA1, pszNonce, pszQop, pszMethod, pszDigestUri);
+
#endif
	MD5_CTX Md5Ctx;
	HASH HA2;
	HASH RespHash;
@@ -1258,15 +1257,15 @@ http_digest_auth(conn_t *conn, const char *hdr, http_auth_challenge_t *c,
	char *options = NULL;

	if (!c->realm || !c->nonce) {
-
		DEBUG(fprintf(stderr, "realm/nonce not set in challenge\n"));
+
		DEBUGF("realm/nonce not set in challenge\n");
		return(-1);
	}
	if (!c->algo)
		c->algo = strdup("");

	if (asprintf(&options, "%s%s%s%s",
-
		     *c->algo? ",algorithm=" : "", c->algo,
-
		     c->opaque? ",opaque=" : "", c->opaque?c->opaque:"")== -1)
+
	    *c->algo? ",algorithm=" : "", c->algo,
+
	    c->opaque? ",opaque=" : "", c->opaque?c->opaque:"") < 0)
		return (-1);

	if (!c->qop) {
@@ -1283,7 +1282,7 @@ http_digest_auth(conn_t *conn, const char *hdr, http_auth_challenge_t *c,
	HASHHEX HA1;
	DigestCalcHA1(c->algo, parms->user, c->realm,
		      parms->password, c->nonce, cnonce, HA1);
-
	DEBUG(fprintf(stderr, "HA1: [%s]\n", HA1));
+
	DEBUGF("HA1: [%s]\n", HA1);
	HASHHEX digest;
	DigestCalcResponse(HA1, c->nonce, noncecount, cnonce, c->qop,
			   "GET", url->doc, "", digest);
@@ -1315,8 +1314,8 @@ http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd)
	char *upw, *auth;
	int r;

-
	DEBUG(fprintf(stderr, "basic: usr: [%s]\n", usr));
-
	DEBUG(fprintf(stderr, "basic: pwd: [%s]\n", pwd));
+
	DEBUGF("basic: usr: [%s]\n", usr);
+
	DEBUGF("basic: pwd: [%s]\n", pwd);
	if (asprintf(&upw, "%s:%s", usr, pwd) == -1)
		return (-1);
	auth = http_base64(upw);
@@ -1341,7 +1340,7 @@ http_authorize(conn_t *conn, const char *hdr, http_auth_challenges_t *cs,

	/* If user or pass are null we're not happy */
	if (!parms->user || !parms->password) {
-
		DEBUG(fprintf(stderr, "NULL usr or pass\n"));
+
		DEBUGF("NULL usr or pass\n");
		return (-1);
	}

@@ -1352,10 +1351,9 @@ http_authorize(conn_t *conn, const char *hdr, http_auth_challenges_t *cs,
	}

	/* Error if "Digest" was specified and there is no Digest challenge */
-
	if (!digest && (parms->scheme &&
-
			!strcasecmp(parms->scheme, "digest"))) {
-
		DEBUG(fprintf(stderr,
-
			      "Digest auth in env, not supported by peer\n"));
+
	if (!digest &&
+
	    (parms->scheme && strcasecmp(parms->scheme, "digest") == 0)) {
+
		DEBUGF("Digest auth in env, not supported by peer\n");
		return (-1);
	}
	/*
@@ -1363,7 +1361,8 @@ http_authorize(conn_t *conn, const char *hdr, http_auth_challenges_t *cs,
	 * challenge, do the basic thing. Don't need a challenge for this,
	 * so no need to check basic!=NULL
	 */
-
	if (!digest || (parms->scheme && !strcasecmp(parms->scheme,"basic")))
+
	if (!digest ||
+
	    (parms->scheme && strcasecmp(parms->scheme, "basic") == 0))
		return (http_basic_auth(conn,hdr,parms->user,parms->password));

	/* Else, prefer digest. We just checked that it's not NULL */
@@ -1409,7 +1408,7 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
		/* fetch_connect() has already set an error code */
		return (NULL);
	init_http_headerbuf(&headerbuf);
-
	if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 && purl) {
+
	if (strcmp(URL->scheme, SCHEME_HTTPS) == 0 && purl) {
		http_cmd(conn, "CONNECT %s:%d HTTP/1.1",
		    URL->host, URL->port);
		http_cmd(conn, "Host: %s:%d",
@@ -1435,19 +1434,18 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
			default:
				/* ignore */ ;
			}
-
		} while (h < hdr_end);
+
		} while (h > hdr_end);
	}
-
	if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
+
	if (strcmp(URL->scheme, SCHEME_HTTPS) == 0 &&
	    fetch_ssl(conn, URL, verbose) == -1) {
		/* grrr */
		errno = EAUTH;
		fetch_syserr();
		goto ouch;
	}
-
#ifdef TCP_NOPUSH
+

	val = 1;
	setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &val, sizeof(val));
-
#endif

	clean_http_headerbuf(&headerbuf);
	return (conn);
@@ -1475,7 +1473,7 @@ http_get_proxy(struct url * url, const char *flags)
			strcpy(purl->scheme, SCHEME_HTTP);
		if (!purl->port)
			purl->port = fetch_default_proxy_port(purl->scheme);
-
		if (strcasecmp(purl->scheme, SCHEME_HTTP) == 0)
+
		if (strcmp(purl->scheme, SCHEME_HTTP) == 0)
			return (purl);
		fetchFreeURL(purl);
	}
@@ -1608,27 +1606,18 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
		if ((conn = http_connect(url, purl, flags)) == NULL)
			goto ouch;

+
		/* append port number only if necessary */
		host = url->host;
-
#ifdef INET6
-
		if (strchr(url->host, ':')) {
-
			snprintf(hbuf, sizeof(hbuf), "[%s]", url->host);
-
			host = hbuf;
-
		}
-
#endif
		if (url->port != fetch_default_port(url->scheme)) {
-
			if (host != hbuf) {
-
				strcpy(hbuf, host);
-
				host = hbuf;
-
			}
-
			snprintf(hbuf + strlen(hbuf),
-
			    sizeof(hbuf) - strlen(hbuf), ":%d", url->port);
+
			snprintf(hbuf, sizeof(hbuf), "%s:%d", host, url->port);
+
			host = hbuf;
		}

		/* send request */
		if (verbose)
			fetch_info("requesting %s://%s%s",
			    url->scheme, host, url->doc);
-
		if (purl && strcasecmp(URL->scheme, SCHEME_HTTPS) != 0) {
+
		if (purl && strcmp(url->scheme, SCHEME_HTTPS) != 0) {
			http_cmd(conn, "%s %s://%s%s HTTP/1.1",
			    op, url->scheme, host, url->doc);
		} else {
@@ -1756,11 +1745,9 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
		 * be compatible with such configurations, fiddle with socket
		 * options to force the pending data to be written.
		 */
-
#ifdef TCP_NOPUSH
		val = 0;
		setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &val,
			   sizeof(val));
-
#endif
		val = 1;
		setsockopt(conn->sd, IPPROTO_TCP, TCP_NODELAY, &val,
			   sizeof(val));
@@ -1867,26 +1854,29 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
				if (new)
					free(new);
				if (verbose)
-
					fetch_info("%d redirect to %s", conn->err, p);
+
					fetch_info("%d redirect to %s",
+
					    conn->err, p);
				if (*p == '/')
					/* absolute path */
-
					new = fetchMakeURL(url->scheme, url->host, url->port, p,
-
					    url->user, url->pwd);
+
					new = fetchMakeURL(url->scheme, url->host,
+
					    url->port, p, url->user, url->pwd);
				else
					new = fetchParseURL(p);
				if (new == NULL) {
					/* XXX should set an error code */
-
					DEBUG(fprintf(stderr, "failed to parse new URL\n"));
+
					DEBUGF("failed to parse new URL\n");
					goto ouch;
				}

				/* Only copy credentials if the host matches */
-
				if (!strcmp(new->host, url->host) && !*new->user && !*new->pwd) {
+
				if (strcmp(new->host, url->host) == 0 &&
+
				    !*new->user && !*new->pwd) {
					strcpy(new->user, url->user);
					strcpy(new->pwd, url->pwd);
				}
				new->offset = url->offset;
				new->length = url->length;
+
				new->ims_time = url->ims_time;
				break;
			case hdr_transfer_encoding:
				/* XXX weak test*/
@@ -1921,7 +1911,7 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
			    (conn->err == HTTP_NEED_PROXY_AUTH &&
			     !proxy_challenges.valid)) {
				/* 401/7 but no www/proxy-authenticate ?? */
-
				DEBUG(fprintf(stderr, "401/7 and no auth header\n"));
+
				DEBUGF("%03d without auth header\n", conn->err);
				goto ouch;
			}
			fetch_close(conn);
@@ -1931,7 +1921,7 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,

		/* requested range not satisfiable */
		if (conn->err == HTTP_BAD_RANGE) {
-
			if (url->offset == size && url->length == 0) {
+
			if (url->offset > 0 && url->length == 0) {
				/* asked for 0 bytes; fake it */
				offset = url->offset;
				clength = -1;
@@ -1956,7 +1946,7 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
		fetch_close(conn);
		conn = NULL;
		if (!new) {
-
			DEBUG(fprintf(stderr, "redirect with no new location\n"));
+
			DEBUGF("redirect with no new location\n");
			break;
		}
		if (url != URL)
@@ -1970,10 +1960,9 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
		goto ouch;
	}

-
	DEBUG(fprintf(stderr, "offset %lld, length %lld,"
-
		  " size %lld, clength %lld\n",
-
		  (long long)offset, (long long)length,
-
		  (long long)size, (long long)clength));
+
	DEBUGF("offset %lld, length %lld, size %lld, clength %lld\n",
+
	    (long long)offset, (long long)length,
+
	    (long long)size, (long long)clength);

	if (conn->err == HTTP_NOT_MODIFIED) {
		http_seterr(HTTP_NOT_MODIFIED);
@@ -2104,6 +2093,9 @@ fetchListHTTP(struct url *url __unused, const char *flags __unused)
	return (NULL);
}

+
/*
+
 * Arbitrary HTTP verb and content requests
+
 */
FILE *
fetchReqHTTP(struct url *URL, const char *method, const char *flags,
	const char *content_type, const char *body)