Sync with pkgsrc and try to fix more memory corruption from PR/57179.

This commit is contained in:
christos 2024-02-02 22:19:05 +00:00
parent c865d5f423
commit 914f0ba5d8
5 changed files with 195 additions and 50 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: common.c,v 1.6 2024/01/03 11:40:38 riastradh Exp $ */
/* $NetBSD: common.c,v 1.7 2024/02/02 22:19:05 christos Exp $ */
/*-
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
* Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org>
@ -41,6 +41,13 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#if defined(HAVE_POLL_H) || defined(NETBSD)
#include <poll.h>
#define HAVE_POLL
#elif HAVE_SYS_POLL_H
#define HAVE_POLL
#include <sys/poll.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
@ -236,6 +243,9 @@ fetch_reopen(int sd)
conn->next_buf = NULL;
conn->next_len = 0;
conn->sd = sd;
#ifdef HAVE_POLL
conn->buf_events = POLLIN;
#endif
return (conn);
}
@ -316,6 +326,7 @@ fetch_connect(struct url *url, int af, int verbose)
if ((conn = fetch_reopen(sd)) == NULL) {
fetch_syserr();
close(sd);
return (NULL);
}
conn->cache_url = fetchCopyURL(url);
conn->cache_af = af;
@ -398,7 +409,7 @@ void
fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *))
{
conn_t *iter, *last, *oiter;
int global_count, host_count;
int global_count, host_count, added;
if (conn->cache_url == NULL || cache_global_limit == 0) {
(*closecb)(conn);
@ -409,20 +420,23 @@ fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *))
last = NULL;
for (iter = connection_cache; iter; ) {
++global_count;
if (strcmp(conn->cache_url->host, iter->cache_url->host) == 0)
added = !strcmp(conn->cache_url->host, iter->cache_url->host);
if (added)
++host_count;
if (global_count < cache_global_limit &&
host_count < cache_per_host_limit)
host_count < cache_per_host_limit) {
oiter = NULL;
else {
last = iter;
} else {
--global_count;
if (added)
--host_count;
if (last != NULL)
last->next_cached = iter->next_cached;
else
connection_cache = iter->next_cached;
oiter = iter;
}
last = iter;
iter = iter->next_cached;
if (oiter)
(*oiter->cache_close)(oiter);
@ -437,7 +451,7 @@ fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *))
* Enable SSL on a connection.
*/
int
fetch_ssl(conn_t *conn, int verbose)
fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
{
#ifdef WITH_SSL
@ -462,11 +476,17 @@ fetch_ssl(conn_t *conn, int verbose)
fprintf(stderr, "SSL context creation failed\n");
return (-1);
}
conn->buf_events = 0;
SSL_set_fd(conn->ssl, conn->sd);
if (!SSL_set_tlsext_host_name(conn->ssl, conn->cache_url->host)) {
fprintf(stderr, "SSL hostname setting failed\n");
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
if (!SSL_set_tlsext_host_name(conn->ssl, (char *)(uintptr_t)URL->host))
{
fprintf(stderr,
"TLS server name indication extension failed for host %s\n",
URL->host);
return (-1);
}
#endif
if (SSL_connect(conn->ssl) == -1){
ERR_print_errors_fp(stderr);
return (-1);
@ -498,6 +518,17 @@ fetch_ssl(conn_t *conn, int verbose)
#endif
}
#ifdef HAVE_POLL
static int
compute_timeout(const struct timeval *tv)
{
struct timeval cur;
gettimeofday(&cur, NULL);
return (tv->tv_sec - cur.tv_sec) * 1000
+ (tv->tv_usec - cur.tv_usec) / 1000;
}
#endif
/*
* Read a character from a connection w/ timeout
@ -505,8 +536,13 @@ fetch_ssl(conn_t *conn, int verbose)
ssize_t
fetch_read(conn_t *conn, char *buf, size_t len)
{
struct timeval now, timeout, waittv;
struct timeval timeout_end;
#ifdef HAVE_POLL
struct pollfd pfd;
#else
fd_set readfds;
#endif
int timeout_cur;
ssize_t rlen;
int r;
@ -523,17 +559,41 @@ fetch_read(conn_t *conn, char *buf, size_t len)
}
if (fetchTimeout) {
#ifndef HAVE_POLL
FD_ZERO(&readfds);
gettimeofday(&timeout, NULL);
timeout.tv_sec += fetchTimeout;
#endif
gettimeofday(&timeout_end, NULL);
timeout_end.tv_sec += fetchTimeout;
}
for (;;) {
#ifdef HAVE_POLL
pfd.fd = conn->sd;
pfd.events = conn->buf_events;
if (fetchTimeout && pfd.events) {
do {
timeout_cur = compute_timeout(&timeout_end);
if (timeout_cur < 0) {
errno = ETIMEDOUT;
fetch_syserr();
return (-1);
}
errno = 0;
r = poll(&pfd, 1, timeout_cur);
if (r == -1) {
if (errno == EINTR && fetchRestartCalls)
continue;
fetch_syserr();
return (-1);
}
} while (pfd.revents == 0);
#else
while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) {
struct timeval waittv, now;
FD_SET(conn->sd, &readfds);
gettimeofday(&now, NULL);
waittv.tv_sec = timeout.tv_sec - now.tv_sec;
waittv.tv_usec = timeout.tv_usec - now.tv_usec;
waittv.tv_sec = timeout_end.tv_sec - now.tv_sec;
waittv.tv_usec = timeout_end.tv_usec - now.tv_usec;
if (waittv.tv_usec < 0) {
waittv.tv_usec += 1000000;
waittv.tv_sec--;
@ -551,11 +611,29 @@ fetch_read(conn_t *conn, char *buf, size_t len)
fetch_syserr();
return (-1);
}
#endif
}
#ifdef WITH_SSL
if (conn->ssl != NULL)
rlen = SSL_read(conn->ssl, buf, (int)len);
else
if (conn->ssl != NULL) {
rlen = SSL_read(conn->ssl, buf, len);
if (rlen == -1) {
switch (SSL_get_error(conn->ssl, rlen)) {
case SSL_ERROR_WANT_READ:
conn->buf_events = POLLIN;
break;
case SSL_ERROR_WANT_WRITE:
conn->buf_events = POLLOUT;
break;
default:
errno = EIO;
fetch_syserr();
return -1;
}
} else {
/* Assume buffering on the SSL layer. */
conn->buf_events = 0;
}
} else
#endif
rlen = read(conn->sd, buf, len);
if (rlen >= 0)

View File

@ -1,4 +1,4 @@
/* $NetBSD: common.h,v 1.2 2014/01/07 02:13:00 joerg Exp $ */
/* $NetBSD: common.h,v 1.3 2024/02/02 22:19:05 christos Exp $ */
/*-
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
* All rights reserved.
@ -45,9 +45,16 @@
#include <openssl/err.h>
#endif
#if defined(__GNUC__) && __GNUC__ >= 3
#define LIBFETCH_PRINTFLIKE(fmtarg, firstvararg) \
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
#else
#define LIBFETCH_PRINTFLIKE(fmtarg, firstvararg)
#endif
#if !defined(__sun) && !defined(__hpux) && !defined(__INTERIX) && \
!defined(__digital__) && !defined(__linux) && !defined(__MINT__) && \
!defined(__sgi)
!defined(__sgi) && !defined(__minix) && !defined(__CYGWIN__)
#define HAVE_SA_LEN
#endif
@ -59,6 +66,7 @@ struct fetchconn {
char *buf; /* buffer */
size_t bufsize; /* buffer size */
size_t buflen; /* length of buffer contents */
int buf_events; /* poll flags for the next cycle */
char *next_buf; /* pending buffer, e.g. after getln */
size_t next_len; /* size of pending buffer */
int err; /* last protocol reply code */
@ -90,7 +98,7 @@ struct fetcherr {
void fetch_seterr(struct fetcherr *, int);
void fetch_syserr(void);
void fetch_info(const char *, ...) __printflike(1, 2);
void fetch_info(const char *, ...) LIBFETCH_PRINTFLIKE(1, 2);
int fetch_default_port(const char *);
int fetch_default_proxy_port(const char *);
int fetch_bind(int, int, const char *);
@ -98,7 +106,7 @@ conn_t *fetch_cache_get(const struct url *, int);
void fetch_cache_put(conn_t *, int (*)(conn_t *));
conn_t *fetch_connect(struct url *, int, int);
conn_t *fetch_reopen(int);
int fetch_ssl(conn_t *, int);
int fetch_ssl(conn_t *, const struct url *, int);
ssize_t fetch_read(conn_t *, char *, size_t);
int fetch_getln(conn_t *);
ssize_t fetch_write(conn_t *, const void *, size_t);

View File

@ -25,9 +25,9 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: fetch.3,v 1.64 2007/12/18 11:03:26 des Exp $
.\" $NetBSD: fetch.3,v 1.4 2016/05/31 16:26:47 abhinav Exp $
.\" $NetBSD: fetch.3,v 1.5 2024/02/02 22:19:05 christos Exp $
.\"
.Dd January 22, 2010
.Dd December 22, 2023
.Dt FETCH 3
.Os
.Sh NAME
@ -638,6 +638,10 @@ which proxies should not be used.
Same as
.Ev NO_PROXY ,
for compatibility.
.It Ev SSL_NO_VERIFY_PEER
If defined,
.Nm
will skip validating certificates when fetching HTTPS URLs.
.El
.Sh EXAMPLES
To access a proxy server on

View File

@ -1,4 +1,4 @@
/* $NetBSD: ftp.c,v 1.7 2014/01/07 02:13:00 joerg Exp $ */
/* $NetBSD: ftp.c,v 1.8 2024/02/02 22:19:05 christos Exp $ */
/*-
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
* Copyright (c) 2008, 2009, 2010 Joerg Sonnenberger <joerg@NetBSD.org>
@ -138,7 +138,6 @@ static void
unmappedaddr(struct sockaddr_in6 *sin6, socklen_t *len)
{
struct sockaddr_in *sin4;
void *addrp;
uint32_t addr;
int port;
@ -146,8 +145,11 @@ unmappedaddr(struct sockaddr_in6 *sin6, socklen_t *len)
!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
return;
sin4 = (struct sockaddr_in *)(void *)sin6;
addrp = &sin6->sin6_addr.s6_addr[12];
addr = *(uint32_t *)addrp;
#ifdef s6_addr32
addr = sin6->sin6_addr.s6_addr32[3];
#else
memcpy(&addr, &sin6->sin6_addr.s6_addr[12], sizeof(addr));
#endif
port = sin6->sin6_port;
memset(sin4, 0, sizeof(struct sockaddr_in));
sin4->sin_addr.s_addr = addr;
@ -198,7 +200,7 @@ ftp_chkerr(conn_t *conn)
/*
* Send a command and check reply
*/
__printflike(2, 3)
LIBFETCH_PRINTFLIKE(2, 3)
static int
ftp_cmd(conn_t *conn, const char *fmt, ...)
{
@ -331,7 +333,8 @@ ftp_cwd(conn_t *conn, const char *path, int subdir)
} else if (strcmp(conn->ftp_home, "/") == 0) {
dst = strdup(path - 1);
} else {
asprintf(&dst, "%s/%s", conn->ftp_home, path);
if (asprintf(&dst, "%s/%s", conn->ftp_home, path) == -1)
dst = NULL;
}
if (dst == NULL) {
fetch_syserr();
@ -1170,12 +1173,14 @@ ftp_request(struct url *url, const char *op, const char *op_arg,
return (NULL);
if ((path = fetchUnquotePath(url)) == NULL) {
fetch_close(conn);
fetch_syserr();
return NULL;
}
/* change directory */
if (ftp_cwd(conn, path, op_arg != NULL) == -1) {
fetch_close(conn);
free(path);
return (NULL);
}
@ -1188,12 +1193,14 @@ ftp_request(struct url *url, const char *op, const char *op_arg,
if (us && ftp_stat(conn, path, us) == -1
&& fetchLastErrCode != FETCH_PROTO
&& fetchLastErrCode != FETCH_UNAVAIL) {
fetch_close(conn);
free(path);
return (NULL);
}
if (if_modified_since && url->last_modified > 0 &&
url->last_modified >= us->mtime) {
fetch_cache_put(conn, ftp_disconnect);
free(path);
fetchLastErrCode = FETCH_UNCHANGED;
snprintf(fetchLastErrString, MAXERRSTRING, "Unchanged");
@ -1202,6 +1209,7 @@ ftp_request(struct url *url, const char *op, const char *op_arg,
/* just a stat */
if (strcmp(op, "STAT") == 0) {
fetch_cache_put(conn, ftp_disconnect);
free(path);
return fetchIO_unopen(NULL, NULL, NULL, NULL);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: http.c,v 1.4 2020/06/01 00:55:24 kamil Exp $ */
/* $NetBSD: http.c,v 1.5 2024/02/02 22:19:05 christos Exp $ */
/*-
* Copyright (c) 2000-2004 Dag-Erling Coïdan Smørgrav
* Copyright (c) 2003 Thomas Klausner <wiz@NetBSD.org>
@ -63,8 +63,12 @@
* SUCH DAMAGE.
*/
#if defined(__linux__) || defined(__MINT__)
#if defined(__linux__) || defined(__MINT__) || defined(__FreeBSD_kernel__)
/* Keep this down to Linux or MiNT, it can create surprises elsewhere. */
/*
__FreeBSD_kernel__ is defined for GNU/kFreeBSD.
See http://glibc-bsd.alioth.debian.org/porting/PORTING .
*/
#define _GNU_SOURCE
#endif
@ -329,7 +333,7 @@ http_closefn(void *v)
setsockopt(io->conn->sd, IPPROTO_TCP, TCP_NODELAY, &val,
(socklen_t)sizeof(val));
fetch_cache_put(io->conn, fetch_close);
#ifdef TCP_NOPUSH
#if defined(TCP_NOPUSH) && !defined(__APPLE__)
val = 1;
setsockopt(io->conn->sd, IPPROTO_TCP, TCP_NOPUSH, &val,
sizeof(val));
@ -406,7 +410,7 @@ static struct {
/*
* Send a formatted line; optionally echo to terminal
*/
__printflike(2, 3)
LIBFETCH_PRINTFLIKE(2, 3)
static int
http_cmd(conn_t *conn, const char *fmt, ...)
{
@ -523,16 +527,26 @@ http_next_header(conn_t *conn, const char **p)
static int
http_parse_mtime(const char *p, time_t *mtime)
{
char locale[64], *r;
struct tm tm;
char *r;
#ifdef LC_C_LOCALE
r = strptime_l(p, "%a, %d %b %Y %H:%M:%S GMT", &tm, LC_C_LOCALE);
#else
char *locale;
locale = strdup(setlocale(LC_TIME, NULL));
if (locale == NULL)
return (-1);
strncpy(locale, setlocale(LC_TIME, NULL), sizeof(locale));
setlocale(LC_TIME, "C");
r = strptime(p, "%a, %d %b %Y %H:%M:%S GMT", &tm);
/* XXX should add support for date-2 and date-3 */
setlocale(LC_TIME, locale);
if (r == NULL)
return (-1);
free(locale);
#endif
if (r == NULL)
return (-1);
*mtime = timegm(&tm);
return (0);
}
@ -710,13 +724,16 @@ http_authorize(conn_t *conn, const char *hdr, const char *p)
static conn_t *
http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
{
struct url *curl;
conn_t *conn;
hdr_t h;
const char *p;
int af, verbose;
#ifdef TCP_NOPUSH
#if defined(TCP_NOPUSH) && !defined(__APPLE__)
int val;
#endif
*cached = 1;
*cached = 0;
#ifdef INET6
af = AF_UNSPEC;
@ -732,6 +749,7 @@ http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
af = AF_INET6;
#endif
curl = (purl != NULL) ? purl : URL;
if (purl && strcasecmp(URL->scheme, SCHEME_HTTPS) != 0) {
URL = purl;
} else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) {
@ -740,33 +758,62 @@ http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
return (NULL);
}
if ((conn = fetch_cache_get(URL, af)) != NULL) {
if ((conn = fetch_cache_get(curl, af)) != NULL) {
*cached = 1;
return (conn);
}
if ((conn = fetch_connect(URL, af, verbose)) == NULL)
if ((conn = fetch_connect(curl, af, verbose)) == NULL)
/* fetch_connect() has already set an error code */
return (NULL);
if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 && purl) {
http_cmd(conn, "CONNECT %s:%d HTTP/1.1\r\n",
URL->host, URL->port);
http_cmd(conn, "Host: %s:%d\r\n",
URL->host, URL->port);
http_cmd(conn, "\r\n");
if (http_get_reply(conn) != HTTP_OK) {
http_seterr(conn->err);
goto ouch;
}
/* Read and discard the rest of the proxy response */
if (fetch_getln(conn) < 0) {
fetch_syserr();
goto ouch;
}
do {
switch ((h = http_next_header(conn, &p))) {
case hdr_syserror:
fetch_syserr();
goto ouch;
case hdr_error:
http_seterr(HTTP_PROTOCOL_ERROR);
goto ouch;
default:
/* ignore */ ;
}
} while (h < hdr_end);
}
if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
fetch_ssl(conn, verbose) == -1) {
fetch_close(conn);
fetch_ssl(conn, URL, verbose) == -1) {
/* grrr */
#ifdef EAUTH
errno = EAUTH;
#else
errno = EPERM;
#endif
fetch_syserr();
return (NULL);
goto ouch;
}
#ifdef TCP_NOPUSH
#if defined(TCP_NOPUSH) && !defined(__APPLE__)
val = 1;
setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &val, sizeof(val));
#endif
return (conn);
ouch:
fetch_close(conn);
return (NULL);
}
static struct url *
@ -800,9 +847,9 @@ set_if_modified_since(conn_t *conn, time_t last_modified)
struct tm tm;
char buf[80];
gmtime_r(&last_modified, &tm);
snprintf(buf, sizeof(buf), "%.3s, %02d %.3s %4d %02d:%02d:%02d GMT",
snprintf(buf, sizeof(buf), "%.3s, %02d %.3s %4ld %02d:%02d:%02d GMT",
weekdays + tm.tm_wday * 3, tm.tm_mday, months + tm.tm_mon * 3,
tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
(long)tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
http_cmd(conn, "If-Modified-Since: %s\r\n", buf);
}
@ -898,7 +945,7 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
if (verbose)
fetch_info("requesting %s://%s%s",
url->scheme, host, url->doc);
if (purl) {
if (purl && strcasecmp(URL->scheme, SCHEME_HTTPS) != 0) {
http_cmd(conn, "%s %s://%s%s HTTP/1.1\r\n",
op, url->scheme, host, url->doc);
} else {
@ -958,7 +1005,7 @@ http_request(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
#if defined(TCP_NOPUSH) && !defined(__APPLE__)
val = 0;
setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &val,
sizeof(val));