summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2017-03-24 14:26:01 +0000
committerdes <des@FreeBSD.org>2017-03-24 14:26:01 +0000
commitbb1be6c053d51686918f67daf4818da800b24687 (patch)
tree1e503dd3feaf102dfb289d919f0ec472b21b5a91
parentee4124b33f70470844978d1c8e4cd6ae062ebb0a (diff)
downloadFreeBSD-src-bb1be6c053d51686918f67daf4818da800b24687.zip
FreeBSD-src-bb1be6c053d51686918f67daf4818da800b24687.tar.gz
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
-rw-r--r--lib/libfetch/common.c87
-rw-r--r--lib/libfetch/common.h2
-rw-r--r--lib/libfetch/fetch.c23
-rw-r--r--lib/libfetch/fetch.h1
-rw-r--r--lib/libfetch/http.c19
5 files changed, 77 insertions, 55 deletions
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
index 304c289..0981a44 100644
--- a/lib/libfetch/common.c
+++ b/lib/libfetch/common.c
@@ -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, int af)
{
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, int af)
return (NULL);
}
return (res);
+syserr:
+ fetch_syserr();
+ return (NULL);
}
@@ -371,7 +388,7 @@ fetch_connect(const char *host, int port, int af, int verbose)
}
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"));
diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h
index e881c88..aaa22ed 100644
--- a/lib/libfetch/common.h
+++ b/lib/libfetch/common.h
@@ -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);
diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c
index 8d92bbc..f251083 100644
--- a/lib/libfetch/fetch.c
+++ b/lib/libfetch/fetch.c
@@ -284,6 +284,7 @@ fetchMakeURL(const char *scheme, const char *host, int port, const char *doc,
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));
diff --git a/lib/libfetch/fetch.h b/lib/libfetch/fetch.h
index d56a103..319fca9 100644
--- a/lib/libfetch/fetch.h
+++ b/lib/libfetch/fetch.h
@@ -47,6 +47,7 @@ struct url {
off_t offset;
size_t length;
time_t ims_time;
+ int netrcfd;
};
struct url_stat {
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index bb509c1..fe4e9de 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -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 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 */
@@ -1925,7 +1916,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;
OpenPOWER on IntegriCloud