svn commit: r315904 - stable/10/lib/libfetch

Dag-Erling Smørgrav des at FreeBSD.org
Fri Mar 24 14:26:03 UTC 2017


Author: des
Date: Fri Mar 24 14:26:01 2017
New Revision: 315904
URL: https://svnweb.freebsd.org/changeset/base/315904

Log:
  MFH (r313974,r314596): open .netrc early in case we want to drop privs
  MFH (r314396,r315143): fix a crash caused by an incorrect format string
  MFH (r314701): fix handling of 416 errors when requesting a range
  MFH (r315455): fix parsing of IP literals (square brackets)
  
  PR:		212065, 217723

Modified:
  stable/10/lib/libfetch/common.c
  stable/10/lib/libfetch/common.h
  stable/10/lib/libfetch/fetch.c
  stable/10/lib/libfetch/fetch.h
  stable/10/lib/libfetch/http.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libfetch/common.c
==============================================================================
--- stable/10/lib/libfetch/common.c	Fri Mar 24 14:25:56 2017	(r315903)
+++ stable/10/lib/libfetch/common.c	Fri Mar 24 14:26:01 2017	(r315904)
@@ -153,7 +153,7 @@ fetch_syserr(void)
 	case EHOSTDOWN:
 		fetchLastErrCode = FETCH_DOWN;
 		break;
-default:
+	default:
 		fetchLastErrCode = FETCH_UNKNOWN;
 	}
 	snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno));
@@ -248,37 +248,51 @@ fetch_resolve(const char *addr, int port
 {
 	char hbuf[256], sbuf[8];
 	struct addrinfo hints, *res;
-	const char *sep, *host, *service;
+	const char *hb, *he, *sep;
+	const char *host, *service;
 	int err, len;
 
-	/* split address if necessary */
-	err = EAI_SYSTEM;
-	if ((sep = strchr(addr, ':')) != NULL) {
+	/* 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)(sep - addr), addr);
+		    "%.*s", (int)(he - hb), hb);
 		if (len < 0)
-			return (NULL);
+			goto syserr;
 		if (len >= (int)sizeof(hbuf)) {
 			errno = ENAMETOOLONG;
-			fetch_syserr();
-			return (NULL);
+			goto syserr;
 		}
 		host = hbuf;
-		service = sep + 1;
-	} else if (port != 0) {
+	} else {
+		host = hb;
+	}
+
+	/* was it followed by a service name? */
+	if (*sep == '\0' && port != 0) {
 		if (port < 1 || port > 65535) {
 			errno = EINVAL;
-			fetch_syserr();
-			return (NULL);
-		}
-		if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0) {
-			fetch_syserr();
-			return (NULL);
+			goto syserr;
 		}
-		host = addr;
+		if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0)
+			goto syserr;
 		service = sbuf;
+	} else if (*sep != '\0') {
+		service = sep;
 	} else {
-		host = addr;
 		service = NULL;
 	}
 
@@ -292,6 +306,9 @@ fetch_resolve(const char *addr, int port
 		return (NULL);
 	}
 	return (res);
+syserr:
+	fetch_syserr();
+	return (NULL);
 }
 
 
@@ -371,7 +388,7 @@ fetch_connect(const char *host, int port
 	}
 	if (err != 0) {
 		if (verbose)
-			fetch_info("failed to connect to %s:%s", host, port);
+			fetch_info("failed to connect to %s:%d", host, port);
 		goto syserr;
 	}
 
@@ -1339,16 +1356,11 @@ 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)
 {
+	const char *p;
 	char fn[PATH_MAX];
-	const char *word;
-	char *p;
-	FILE *f;
 
 	if ((p = getenv("NETRC")) != NULL) {
 		if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
@@ -1368,8 +1380,25 @@ fetch_netrc_auth(struct url *url)
 			return (-1);
 	}
 
-	if ((f = fopen(fn, "r")) == NULL)
+	return (open(fn, O_RDONLY));
+}
+
+/*
+ * Get authentication data for a URL from .netrc
+ */
+int
+fetch_netrc_auth(struct url *url)
+{
+	const char *word;
+	FILE *f;
+
+	if (url->netrcfd == -2)
+		url->netrcfd = fetch_netrc_open();
+	if (url->netrcfd < 0)
+		return (-1);
+	if ((f = fdopen(url->netrcfd, "r")) == NULL)
 		return (-1);
+	rewind(f);
 	while ((word = fetch_read_word(f)) != NULL) {
 		if (strcmp(word, "default") == 0) {
 			DEBUG(fetch_info("Using default .netrc settings"));

Modified: stable/10/lib/libfetch/common.h
==============================================================================
--- stable/10/lib/libfetch/common.h	Fri Mar 24 14:25:56 2017	(r315903)
+++ stable/10/lib/libfetch/common.h	Fri Mar 24 14:26:01 2017	(r315904)
@@ -73,7 +73,7 @@ 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);

Modified: stable/10/lib/libfetch/fetch.c
==============================================================================
--- stable/10/lib/libfetch/fetch.c	Fri Mar 24 14:25:56 2017	(r315903)
+++ stable/10/lib/libfetch/fetch.c	Fri Mar 24 14:26:01 2017	(r315904)
@@ -284,6 +284,7 @@ fetchMakeURL(const char *scheme, const c
 	seturl(pwd);
 #undef seturl
 	u->port = port;
+	u->netrcfd = -2;
 
 	return (u);
 }
@@ -349,6 +350,7 @@ fetchParseURL(const char *URL)
 		fetch_syserr();
 		return (NULL);
 	}
+	u->netrcfd = -2;
 
 	/* scheme name */
 	if ((p = strstr(URL, ":/"))) {
@@ -384,18 +386,17 @@ fetchParseURL(const char *URL)
 	}
 
 	/* hostname */
-#ifdef INET6
 	if (*p == '[' && (q = strchr(p + 1, ']')) != NULL &&
 	    (*++q == '\0' || *q == '/' || *q == ':')) {
-		if ((i = q - p - 2) > MAXHOSTNAMELEN)
+		if ((i = q - p) > MAXHOSTNAMELEN)
 			i = MAXHOSTNAMELEN;
-		strncpy(u->host, ++p, i);
+		strncpy(u->host, p, i);
 		p = q;
-	} else
-#endif
+	} else {
 		for (i = 0; *p && (*p != '/') && (*p != ':'); p++)
 			if (i < MAXHOSTNAMELEN)
 				u->host[i++] = *p;
+	}
 
 	/* port */
 	if (*p == ':') {
@@ -442,12 +443,12 @@ nohost:
 	}
 
 	DEBUG(fprintf(stderr,
-		  "scheme:   [%s]\n"
-		  "user:     [%s]\n"
-		  "password: [%s]\n"
-		  "host:     [%s]\n"
-		  "port:     [%d]\n"
-		  "document: [%s]\n",
+		  "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));
 

Modified: stable/10/lib/libfetch/fetch.h
==============================================================================
--- stable/10/lib/libfetch/fetch.h	Fri Mar 24 14:25:56 2017	(r315903)
+++ stable/10/lib/libfetch/fetch.h	Fri Mar 24 14:26:01 2017	(r315904)
@@ -47,6 +47,7 @@ struct url {
 	off_t		 offset;
 	size_t		 length;
 	time_t		 ims_time;
+	int		 netrcfd;
 };
 
 struct url_stat {

Modified: stable/10/lib/libfetch/http.c
==============================================================================
--- stable/10/lib/libfetch/http.c	Fri Mar 24 14:25:56 2017	(r315903)
+++ stable/10/lib/libfetch/http.c	Fri Mar 24 14:26:01 2017	(r315904)
@@ -118,7 +118,7 @@ __FBSDID("$FreeBSD$");
 			    || (xyz) == HTTP_USE_PROXY \
 			    || (xyz) == HTTP_SEE_OTHER)
 
-#define HTTP_ERROR(xyz) ((xyz) > 400 && (xyz) < 599)
+#define HTTP_ERROR(xyz) ((xyz) >= 400 && (xyz) <= 599)
 
 
 /*****************************************************************************
@@ -1604,20 +1604,11 @@ http_request_body(struct url *URL, const
 		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 */
@@ -1925,7 +1916,7 @@ http_request_body(struct url *URL, const
 
 		/* 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;


More information about the svn-src-all mailing list