summaryrefslogtreecommitdiff
path: root/usr.bin/ftp
diff options
context:
space:
mode:
authorJeremie Courreges-Anglas <jca@cvs.openbsd.org>2019-11-03 19:26:16 +0000
committerJeremie Courreges-Anglas <jca@cvs.openbsd.org>2019-11-03 19:26:16 +0000
commitbf155297cd5af54c7a340ae69f93e06ddfdc195e (patch)
treec888f352167c37941c78a03fdfad805e888bf97a /usr.bin/ftp
parentf3eca2d3e373f96430f4d5ed1195d7ad92f317d1 (diff)
Also use stdio for TLS connections
Set up two wrappers around tls_read/write to be used along with the not-very-portable funopen(). This kills a bunch of local code, always a nice thing for an utility which ends up in bsd.rd. "seems legit" deraadt@, ok kn@
Diffstat (limited to 'usr.bin/ftp')
-rw-r--r--usr.bin/ftp/fetch.c216
1 files changed, 73 insertions, 143 deletions
diff --git a/usr.bin/ftp/fetch.c b/usr.bin/ftp/fetch.c
index 79105d3d6b2..68321a0efb9 100644
--- a/usr.bin/ftp/fetch.c
+++ b/usr.bin/ftp/fetch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fetch.c,v 1.175 2019/10/23 16:47:53 deraadt Exp $ */
+/* $OpenBSD: fetch.c,v 1.176 2019/11/03 19:26:15 jca Exp $ */
/* $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */
/*-
@@ -74,14 +74,13 @@ void abortfile(int);
char hextochar(const char *);
char *urldecode(const char *);
char *recode_credentials(const char *_userinfo);
-int ftp_printf(FILE *, struct tls *, const char *, ...) __attribute__((format(printf, 3, 4)));
-char *ftp_readline(FILE *, struct tls *, size_t *);
-size_t ftp_read(FILE *, struct tls *, char *, size_t);
+char *ftp_readline(FILE *, size_t *);
void ftp_close(FILE **fin, struct tls **tls, volatile int *fd);
+const char *sockerror(struct tls *);
#ifndef NOSSL
int proxy_connect(int, char *, char *);
-int SSL_vprintf(struct tls *, const char *, va_list);
-char *SSL_readline(struct tls *, size_t *);
+int stdio_tls_write_wrapper(void *, const char *, int);
+int stdio_tls_read_wrapper(void *, char *, int);
#endif /* !NOSSL */
#define FTP_URL "ftp://" /* ftp URL prefix */
@@ -638,6 +637,12 @@ noslash:
fprintf(ttyout, "SSL failure: %s\n", tls_error(tls));
goto cleanup_url_get;
}
+ if (tls_handshake(tls) != 0) {
+ fprintf(ttyout, "SSL failure: %s\n", tls_error(tls));
+ goto cleanup_url_get;
+ }
+ fin = funopen(tls, stdio_tls_read_wrapper,
+ stdio_tls_write_wrapper, NULL, NULL);
} else {
fin = fdopen(fd, "r+");
fd = -1;
@@ -682,13 +687,13 @@ noslash:
* the original URI (path).
*/
if (credentials)
- ftp_printf(fin, tls, "GET %s HTTP/1.0\r\n"
+ fprintf(fin, "GET %s HTTP/1.0\r\n"
"Proxy-Authorization: Basic %s\r\n"
"Host: %s\r\n%s%s\r\n\r\n",
epath, credentials,
proxyhost, buf ? buf : "", httpuseragent);
else
- ftp_printf(fin, tls, "GET %s HTTP/1.0\r\n"
+ fprintf(fin, "GET %s HTTP/1.0\r\n"
"Host: %s\r\n%s%s\r\n\r\n",
epath, proxyhost, buf ? buf : "", httpuseragent);
} else {
@@ -706,7 +711,7 @@ noslash:
#endif /* SMALL */
#ifndef NOSSL
if (credentials) {
- ftp_printf(fin, tls,
+ fprintf(fin,
"GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ",
epath, restart_point ?
"HTTP/1.1\r\nConnection: close" : "HTTP/1.0",
@@ -715,13 +720,13 @@ noslash:
credentials = NULL;
} else
#endif /* NOSSL */
- ftp_printf(fin, tls, "GET /%s %s\r\nHost: ", epath,
+ fprintf(fin, "GET /%s %s\r\nHost: ", epath,
#ifndef SMALL
restart_point ? "HTTP/1.1\r\nConnection: close" :
#endif /* !SMALL */
"HTTP/1.0");
if (proxyhost) {
- ftp_printf(fin, tls, "%s", proxyhost);
+ fprintf(fin, "%s", proxyhost);
port = NULL;
} else if (strchr(host, ':')) {
/*
@@ -733,10 +738,10 @@ noslash:
errx(1, "Can't allocate memory.");
if ((p = strchr(h, '%')) != NULL)
*p = '\0';
- ftp_printf(fin, tls, "[%s]", h);
+ fprintf(fin, "[%s]", h);
free(h);
} else
- ftp_printf(fin, tls, "%s", host);
+ fprintf(fin, "%s", host);
/*
* Send port number only if it's specified and does not equal
@@ -745,15 +750,15 @@ noslash:
*/
#ifndef NOSSL
if (port && strcmp(port, (ishttpsurl ? "443" : "80")) != 0)
- ftp_printf(fin, tls, ":%s", port);
+ fprintf(fin, ":%s", port);
if (restart_point)
- ftp_printf(fin, tls, "\r\nRange: bytes=%lld-",
+ fprintf(fin, "\r\nRange: bytes=%lld-",
(long long)restart_point);
#else /* !NOSSL */
if (port && strcmp(port, "80") != 0)
- ftp_printf(fin, tls, ":%s", port);
+ fprintf(fin, ":%s", port);
#endif /* !NOSSL */
- ftp_printf(fin, tls, "\r\n%s%s\r\n\r\n",
+ fprintf(fin, "\r\n%s%s\r\n\r\n",
buf ? buf : "", httpuseragent);
}
free(epath);
@@ -763,12 +768,12 @@ noslash:
#endif /* !NOSSL */
buf = NULL;
- if (fin != NULL && fflush(fin) == EOF) {
- warn("Writing HTTP request");
+ if (fflush(fin) == EOF) {
+ warnx("Writing HTTP request: %s", sockerror(tls));
goto cleanup_url_get;
}
- if ((buf = ftp_readline(fin, tls, &len)) == NULL) {
- warn("Receiving HTTP reply");
+ if ((buf = ftp_readline(fin, &len)) == NULL) {
+ warnx("Receiving HTTP reply: %s", sockerror(tls));
goto cleanup_url_get;
}
@@ -842,8 +847,8 @@ noslash:
filesize = -1;
for (;;) {
- if ((buf = ftp_readline(fin, tls, &len)) == NULL) {
- warn("Receiving HTTP reply");
+ if ((buf = ftp_readline(fin, &len)) == NULL) {
+ warnx("Receiving HTTP reply: %s", sockerror(tls));
goto cleanup_url_get;
}
@@ -1004,7 +1009,7 @@ noslash:
len = 1;
oldinti = signal(SIGINFO, psummary);
while (len > 0) {
- len = ftp_read(fin, tls, buf, buflen);
+ len = fread(buf, 1, buflen, fin);
bytes += len;
for (cp = buf, wlen = len; wlen > 0; wlen -= i, cp += i) {
if ((i = write(out, cp, wlen)) == -1) {
@@ -1031,7 +1036,7 @@ noslash:
(void)fflush(ttyout);
}
if (len != 0) {
- warn("Reading from socket");
+ warnx("Reading from socket: %s", sockerror(tls));
goto cleanup_url_get;
}
progressmeter(1, NULL);
@@ -1514,67 +1519,9 @@ isurl(const char *p)
}
char *
-ftp_readline(FILE *fp, struct tls *tls, size_t *lenp)
-{
- if (fp != NULL)
- return fparseln(fp, lenp, NULL, "\0\0\0", 0);
-#ifndef NOSSL
- else if (tls != NULL)
- return SSL_readline(tls, lenp);
-#endif /* !NOSSL */
- else
- return NULL;
-}
-
-size_t
-ftp_read(FILE *fp, struct tls *tls, char *buf, size_t len)
-{
-#ifndef NOSSL
- ssize_t tret;
-#endif
- size_t ret = 0;
-
- if (fp != NULL)
- ret = fread(buf, sizeof(char), len, fp);
-#ifndef NOSSL
- else if (tls != NULL) {
- do {
- tret = tls_read(tls, buf, len);
- } while (tret == TLS_WANT_POLLIN || tret == TLS_WANT_POLLOUT);
- if (tret == -1)
- errx(1, "SSL read error: %s", tls_error(tls));
- ret = (size_t)tret;
- }
-#endif /* !NOSSL */
- return (ret);
-}
-
-int
-ftp_printf(FILE *fp, struct tls *tls, const char *fmt, ...)
+ftp_readline(FILE *fp, size_t *lenp)
{
- int ret;
- va_list ap;
-
- va_start(ap, fmt);
-
- if (fp != NULL)
- ret = vfprintf(fp, fmt, ap);
-#ifndef NOSSL
- else if (tls != NULL)
- ret = SSL_vprintf(tls, fmt, ap);
-#endif /* !NOSSL */
- else
- ret = 0;
-
- va_end(ap);
-#ifndef SMALL
- if (debug) {
- va_start(ap, fmt);
- ret = vfprintf(ttyout, fmt, ap);
- va_end(ap);
- }
-#endif /* !SMALL */
- return (ret);
+ return fparseln(fp, lenp, NULL, "\0\0\0", 0);
}
void
@@ -1593,75 +1540,32 @@ ftp_close(FILE **fin, struct tls **tls, volatile int *fd)
tls_free(*tls);
*tls = NULL;
}
-#endif
- if (*fin != NULL) {
- fclose(*fin);
- *fin = NULL;
- }
if (*fd != -1) {
close(*fd);
*fd = -1;
}
-}
-
-#ifndef NOSSL
-int
-SSL_vprintf(struct tls *tls, const char *fmt, va_list ap)
-{
- char *string, *buf;
- size_t len;
- int ret;
-
- if ((ret = vasprintf(&string, fmt, ap)) == -1)
- return ret;
- buf = string;
- len = ret;
- while (len > 0) {
- ret = tls_write(tls, buf, len);
- if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT)
- continue;
- if (ret == -1)
- errx(1, "SSL write error: %s", tls_error(tls));
- buf += ret;
- len -= ret;
+#endif
+ if (*fin != NULL) {
+ fclose(*fin);
+ *fin = NULL;
}
- free(string);
- return ret;
}
-char *
-SSL_readline(struct tls *tls, size_t *lenp)
+const char *
+sockerror(struct tls *tls)
{
- size_t i, len;
- char *buf, *q, c;
- int ret;
-
- len = 128;
- if ((buf = malloc(len)) == NULL)
- errx(1, "Can't allocate memory for transfer buffer");
- for (i = 0; ; i++) {
- if (i >= len - 1) {
- if ((q = reallocarray(buf, len, 2)) == NULL)
- errx(1, "Can't expand transfer buffer");
- buf = q;
- len *= 2;
- }
- do {
- ret = tls_read(tls, &c, 1);
- } while (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT);
- if (ret == -1)
- errx(1, "SSL read error: %s", tls_error(tls));
-
- buf[i] = c;
- if (c == '\n') {
- buf[i] = '\0';
- break;
- }
+ int save_errno = errno;
+#ifndef NOSSL
+ if (tls != NULL) {
+ const char *tlserr = tls_error(tls);
+ if (tlserr != NULL)
+ return tlserr;
}
- *lenp = i;
- return (buf);
+#endif
+ return strerror(save_errno);
}
+#ifndef NOSSL
int
proxy_connect(int socket, char *host, char *cookie)
{
@@ -1703,4 +1607,30 @@ proxy_connect(int socket, char *host, char *cookie)
free(connstr);
return(200);
}
+
+int
+stdio_tls_write_wrapper(void *arg, const char *buf, int len)
+{
+ struct tls *tls = arg;
+ ssize_t ret;
+
+ do {
+ ret = tls_write(tls, buf, len);
+ } while (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT);
+
+ return ret;
+}
+
+int
+stdio_tls_read_wrapper(void *arg, char *buf, int len)
+{
+ struct tls *tls = arg;
+ ssize_t ret;
+
+ do {
+ ret = tls_read(tls, buf, len);
+ } while (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT);
+
+ return ret;
+}
#endif /* !NOSSL */