summaryrefslogtreecommitdiffstats
path: root/lib/libfetch/common.c
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2017-03-24 14:19:52 +0000
committerdes <des@FreeBSD.org>2017-03-24 14:19:52 +0000
commit9cc8c478616cc8ad4c03db6529c1064888fc1acf (patch)
tree988e2bfb49ffca19739e87e0d00446a65d7e1b95 /lib/libfetch/common.c
parent4df1b0ecbe8b97b7b2a33fe8acc3e1936f273f92 (diff)
downloadFreeBSD-src-9cc8c478616cc8ad4c03db6529c1064888fc1acf.zip
FreeBSD-src-9cc8c478616cc8ad4c03db6529c1064888fc1acf.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
Diffstat (limited to 'lib/libfetch/common.c')
-rw-r--r--lib/libfetch/common.c87
1 files changed, 58 insertions, 29 deletions
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
index 4145314..40fc2a7 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"));
OpenPOWER on IntegriCloud