Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 May 2019 17:29:30 +0000 (UTC)
From:      =?UTF-8?Q?Dag-Erling_Sm=c3=b8rgrav?= <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r347450 - vendor/netcat/dist
Message-ID:  <201905101729.x4AHTUKC009469@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: des
Date: Fri May 10 17:29:30 2019
New Revision: 347450
URL: https://svnweb.freebsd.org/changeset/base/347450

Log:
  Import netcat from OpenBSD 6.2.

Modified:
  vendor/netcat/dist/nc.1
  vendor/netcat/dist/netcat.c

Modified: vendor/netcat/dist/nc.1
==============================================================================
--- vendor/netcat/dist/nc.1	Fri May 10 17:29:22 2019	(r347449)
+++ vendor/netcat/dist/nc.1	Fri May 10 17:29:30 2019	(r347450)
@@ -1,4 +1,4 @@
-.\"     $OpenBSD: nc.1,v 1.82 2017/02/09 20:15:59 jca Exp $
+.\"     $OpenBSD: nc.1,v 1.87 2017/07/15 18:11:47 jmc Exp $
 .\"
 .\" Copyright (c) 1996 David Sacerdote
 .\" All rights reserved.
@@ -25,7 +25,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: February 9 2017 $
+.Dd $Mdocdate: July 15 2017 $
 .Dt NC 1
 .Os
 .Sh NAME
@@ -50,9 +50,11 @@
 .Op Fl s Ar source
 .Op Fl T Ar keyword
 .Op Fl V Ar rtable
+.Op Fl W Ar recvlimit
 .Op Fl w Ar timeout
 .Op Fl X Ar proxy_protocol
 .Op Fl x Ar proxy_address Ns Op : Ns Ar port
+.Op Fl Z Ar peercertfile
 .Op Ar destination
 .Op Ar port
 .Sh DESCRIPTION
@@ -230,10 +232,12 @@ option.
 Change IPv4 TOS value or TLS options.
 For TLS options
 .Ar keyword
-may be one of
-.Ar tlsall ;
-which allows the use of all supported TLS protocols and ciphers,
-.Ar noverify ;
+may be one of:
+.Ar tlsall ,
+which allows the use of all supported TLS protocols and ciphers;
+.Ar tlscompat ,
+which allows the use of all supported TLS protocols and "compat" ciphers;
+.Ar noverify ,
 which disables certificate verification;
 .Ar noname ,
 which disables certificate name checking;
@@ -287,6 +291,10 @@ Set the routing table to be used.
 Have
 .Nm
 give more verbose output.
+.It Fl W Ar recvlimit
+Terminate after receiving
+.Ar recvlimit
+packets from the network.
 .It Fl w Ar timeout
 Connections which cannot be established or are idle timeout after
 .Ar timeout
@@ -330,6 +338,10 @@ for SOCKS, 3128 for HTTPS).
 An IPv6 address can be specified unambiguously by enclosing
 .Ar proxy_address
 in square brackets.
+.It Fl Z Ar peercertfile
+Specifies the filename in which the peer supplied certificates will be saved
+in PEM format.
+May only be used with TLS.
 .It Fl z
 Specifies that
 .Nm

Modified: vendor/netcat/dist/netcat.c
==============================================================================
--- vendor/netcat/dist/netcat.c	Fri May 10 17:29:22 2019	(r347449)
+++ vendor/netcat/dist/netcat.c	Fri May 10 17:29:30 2019	(r347450)
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.178 2017/03/09 13:58:00 bluhm Exp $ */
+/* $OpenBSD: netcat.c,v 1.187 2017/07/15 17:27:39 jsing Exp $ */
 /*
  * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
  * Copyright (c) 2015 Bob Beck.  All rights reserved.
@@ -53,25 +53,27 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <unistd.h>
 #include <tls.h>
+#include <unistd.h>
+
 #include "atomicio.h"
 
 #define PORT_MAX	65535
 #define UNIX_DG_TMP_SOCKET_SIZE	19
 
-#define POLL_STDIN 0
-#define POLL_NETOUT 1
-#define POLL_NETIN 2
-#define POLL_STDOUT 3
-#define BUFSIZE 16384
-#define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
+#define POLL_STDIN	0
+#define POLL_NETOUT	1
+#define POLL_NETIN	2
+#define POLL_STDOUT	3
+#define BUFSIZE		16384
+#define DEFAULT_CA_FILE	"/etc/ssl/cert.pem"
 
 #define TLS_ALL	(1 << 1)
 #define TLS_NOVERIFY	(1 << 2)
 #define TLS_NONAME	(1 << 3)
 #define TLS_CCERT	(1 << 4)
 #define TLS_MUSTSTAPLE	(1 << 5)
+#define TLS_COMPAT	(1 << 6)
 
 /* Command Line Options */
 int	dflag;					/* detached, no stdin */
@@ -106,7 +108,9 @@ int	tls_cachanged;				/* Using non-default CA file */
 int     TLSopt;					/* TLS options */
 char	*tls_expectname;			/* required name in peer cert */
 char	*tls_expecthash;			/* required hash of peer cert */
+FILE	*Zflag;					/* file to save peer cert */
 
+int recvcount, recvlimit;
 int timeout = -1;
 int family = AF_UNSPEC;
 char *portlist[PORT_MAX+1];
@@ -115,8 +119,9 @@ int ttl = -1;
 int minttl = -1;
 
 void	atelnet(int, unsigned char *, unsigned int);
+int	strtoport(char *portstr, int udp);
 void	build_ports(char *);
-void	help(void);
+void	help(void) __attribute__((noreturn));
 int	local_listen(char *, char *, struct addrinfo);
 void	readwrite(int, struct tls *);
 void	fdpass(int nfd) __attribute__((noreturn));
@@ -132,8 +137,9 @@ int	unix_listen(char *);
 void	set_common_sockopts(int, int);
 int	map_tos(char *, int *);
 int	map_tls(char *, int *);
+void	save_peer_cert(struct tls *_tls_ctx, FILE *_fp);
 void	report_connect(const struct sockaddr *, socklen_t, char *);
-void	report_tls(struct tls *tls_ctx, char * host, char *tls_expectname);
+void	report_tls(struct tls *tls_ctx, char * host);
 void	usage(int);
 ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *);
 ssize_t fillbuf(int, unsigned char *, size_t *, struct tls *);
@@ -149,7 +155,7 @@ main(int argc, char *argv[])
 	struct servent *sv;
 	socklen_t len;
 	struct sockaddr_storage cliaddr;
-	char *proxy, *proxyport = NULL;
+	char *proxy = NULL, *proxyport = NULL;
 	const char *errstr;
 	struct addrinfo proxyhints;
 	char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
@@ -165,7 +171,8 @@ main(int argc, char *argv[])
 	signal(SIGPIPE, SIG_IGN);
 
 	while ((ch = getopt(argc, argv,
-	    "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:R:rSs:T:tUuV:vw:X:x:z")) != -1) {
+	    "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:R:rSs:T:tUuV:vW:w:X:x:Z:z"))
+	    != -1) {
 		switch (ch) {
 		case '4':
 			family = AF_INET;
@@ -268,6 +275,11 @@ main(int argc, char *argv[])
 		case 'v':
 			vflag = 1;
 			break;
+		case 'W':
+			recvlimit = strtonum(optarg, 1, INT_MAX, &errstr);
+			if (errstr)
+				errx(1, "receive limit %s: %s", errstr, optarg);
+			break;
 		case 'w':
 			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
 			if (errstr)
@@ -279,6 +291,12 @@ main(int argc, char *argv[])
 			if ((proxy = strdup(optarg)) == NULL)
 				err(1, NULL);
 			break;
+		case 'Z':
+			if (strcmp(optarg, "-") == 0)
+				Zflag = stderr;
+			else if ((Zflag = fopen(optarg, "w")) == NULL)
+				err(1, "can't open %s", optarg);
+			break;
 		case 'z':
 			zflag = 1;
 			break;
@@ -333,12 +351,15 @@ main(int argc, char *argv[])
 	if (family == AF_UNIX) {
 		if (pledge("stdio rpath wpath cpath tmppath unix", NULL) == -1)
 			err(1, "pledge");
-	} else if (Fflag) {
-		if (Pflag) {
-			if (pledge("stdio inet dns sendfd tty", NULL) == -1)
-				err(1, "pledge");
-		} else if (pledge("stdio inet dns sendfd", NULL) == -1)
+	} else if (Fflag && Pflag) {
+		if (pledge("stdio inet dns sendfd tty", NULL) == -1)
 			err(1, "pledge");
+	} else if (Fflag) { 
+		if (pledge("stdio inet dns sendfd", NULL) == -1)
+			err(1, "pledge");
+	} else if (Pflag && usetls) {
+		if (pledge("stdio rpath inet dns tty", NULL) == -1)
+			err(1, "pledge");
 	} else if (Pflag) {
 		if (pledge("stdio inet dns tty", NULL) == -1)
 			err(1, "pledge");
@@ -353,7 +374,7 @@ main(int argc, char *argv[])
 		host = argv[0];
 		uport = NULL;
 	} else if (argv[0] && !argv[1]) {
-		if  (!lflag)
+		if (!lflag)
 			usage(1);
 		uport = argv[0];
 		host = NULL;
@@ -381,10 +402,14 @@ main(int argc, char *argv[])
 		errx(1, "cannot use -c and -F");
 	if (TLSopt && !usetls)
 		errx(1, "you must specify -c to use TLS options");
+	if ((TLSopt & (TLS_ALL|TLS_COMPAT)) == (TLS_ALL|TLS_COMPAT))
+		errx(1, "cannot use -T tlsall and -T tlscompat");
 	if (Cflag && !usetls)
 		errx(1, "you must specify -c to use -C");
 	if (Kflag && !usetls)
 		errx(1, "you must specify -c to use -K");
+	if (Zflag && !usetls)
+		errx(1, "you must specify -c to use -Z");
 	if (oflag && !Cflag)
 		errx(1, "you must specify -C to use -o");
 	if (tls_cachanged && !usetls)
@@ -460,12 +485,6 @@ main(int argc, char *argv[])
 	}
 
 	if (usetls) {
-		if (Pflag) {
-			if (pledge("stdio inet dns tty rpath", NULL) == -1)
-				err(1, "pledge");
-		} else if (pledge("stdio inet dns rpath", NULL) == -1)
-			err(1, "pledge");
-
 		if (tls_init() == -1)
 			errx(1, "unable to initialize TLS");
 		if ((tls_cfg = tls_config_new()) == NULL)
@@ -478,11 +497,12 @@ main(int argc, char *argv[])
 			errx(1, "%s", tls_config_error(tls_cfg));
 		if (oflag && tls_config_set_ocsp_staple_file(tls_cfg, oflag) == -1)
 			errx(1, "%s", tls_config_error(tls_cfg));
-		if (TLSopt & TLS_ALL) {
+		if (TLSopt & (TLS_ALL|TLS_COMPAT)) {
 			if (tls_config_set_protocols(tls_cfg,
 			    TLS_PROTOCOLS_ALL) != 0)
 				errx(1, "%s", tls_config_error(tls_cfg));
-			if (tls_config_set_ciphers(tls_cfg, "all") != 0)
+			if (tls_config_set_ciphers(tls_cfg,
+			    (TLSopt & TLS_ALL) ? "all" : "compat") != 0)
 				errx(1, "%s", tls_config_error(tls_cfg));
 		}
 		if (!lflag && (TLSopt & TLS_CCERT))
@@ -491,7 +511,7 @@ main(int argc, char *argv[])
 			tls_config_insecure_noverifyname(tls_cfg);
 		if (TLSopt & TLS_NOVERIFY) {
 			if (tls_expecthash != NULL)
-				errx(1, "-H and -T noverify may not be used"
+				errx(1, "-H and -T noverify may not be used "
 				    "together");
 			tls_config_insecure_noverifycert(tls_cfg);
 		}
@@ -530,18 +550,19 @@ main(int argc, char *argv[])
 				s = local_listen(host, uport, hints);
 			if (s < 0)
 				err(1, NULL);
-			/*
-			 * For UDP and -k, don't connect the socket, let it
-			 * receive datagrams from multiple socket pairs.
-			 */
-			if (uflag && kflag)
+			if (uflag && kflag) {
+				/*
+				 * For UDP and -k, don't connect the socket,
+				 * let it receive datagrams from multiple
+				 * socket pairs.
+				 */
 				readwrite(s, NULL);
-			/*
-			 * For UDP and not -k, we will use recvfrom() initially
-			 * to wait for a caller, then use the regular functions
-			 * to talk to the caller.
-			 */
-			else if (uflag && !kflag) {
+			} else if (uflag && !kflag) {
+				/*
+				 * For UDP and not -k, we will use recvfrom()
+				 * initially to wait for a caller, then use
+				 * the regular functions to talk to the caller.
+				 */
 				int rv, plen;
 				char buf[16384];
 				struct sockaddr_storage z;
@@ -606,7 +627,7 @@ main(int argc, char *argv[])
 
 		if (uflag)
 			unlink(unix_dg_tmp_socket);
-		exit(ret);
+		return ret;
 
 	} else {
 		int i = 0;
@@ -682,7 +703,7 @@ main(int argc, char *argv[])
 
 	tls_config_free(tls_cfg);
 
-	exit(ret);
+	return ret;
 }
 
 /*
@@ -698,7 +719,7 @@ unix_bind(char *path, int flags)
 	/* Create unix domain socket. */
 	if ((s = socket(AF_UNIX, flags | (uflag ? SOCK_DGRAM : SOCK_STREAM),
 	    0)) < 0)
-		return (-1);
+		return -1;
 
 	memset(&s_un, 0, sizeof(struct sockaddr_un));
 	s_un.sun_family = AF_UNIX;
@@ -707,16 +728,17 @@ unix_bind(char *path, int flags)
 	    sizeof(s_un.sun_path)) {
 		close(s);
 		errno = ENAMETOOLONG;
-		return (-1);
+		return -1;
 	}
 
 	if (bind(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
 		save_errno = errno;
 		close(s);
 		errno = save_errno;
-		return (-1);
+		return -1;
 	}
-	return (s);
+
+	return s;
 }
 
 int
@@ -743,7 +765,7 @@ timeout_tls(int s, struct tls *tls_ctx, int (*func)(st
 			err(1, "poll failed");
 	}
 
-	return (ret);
+	return ret;
 }
 
 void
@@ -762,10 +784,15 @@ tls_setup_client(struct tls *tls_ctx, int s, char *hos
 		errx(1, "tls handshake failed (%s)", errstr);
 	}
 	if (vflag)
-		report_tls(tls_ctx, host, tls_expectname);
+		report_tls(tls_ctx, host);
 	if (tls_expecthash && tls_peer_cert_hash(tls_ctx) &&
 	    strcmp(tls_expecthash, tls_peer_cert_hash(tls_ctx)) != 0)
 		errx(1, "peer certificate is not %s", tls_expecthash);
+	if (Zflag) {
+		save_peer_cert(tls_ctx, Zflag);
+		if (Zflag != stderr && (fclose(Zflag) != 0))
+			err(1, "fclose failed saving peer cert");
+	}
 }
 
 struct tls *
@@ -784,7 +811,7 @@ tls_setup_server(struct tls *tls_ctx, int connfd, char
 		int gotcert = tls_peer_cert_provided(tls_cctx);
 
 		if (vflag && gotcert)
-			report_tls(tls_cctx, host, tls_expectname);
+			report_tls(tls_cctx, host);
 		if ((TLSopt & TLS_CCERT) && !gotcert)
 			warnx("No client certificate provided");
 		else if (gotcert && tls_peer_cert_hash(tls_ctx) && tls_expecthash &&
@@ -813,10 +840,10 @@ unix_connect(char *path)
 
 	if (uflag) {
 		if ((s = unix_bind(unix_dg_tmp_socket, SOCK_CLOEXEC)) < 0)
-			return (-1);
+			return -1;
 	} else {
 		if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0)
-			return (-1);
+			return -1;
 	}
 
 	memset(&s_un, 0, sizeof(struct sockaddr_un));
@@ -826,15 +853,15 @@ unix_connect(char *path)
 	    sizeof(s_un.sun_path)) {
 		close(s);
 		errno = ENAMETOOLONG;
-		return (-1);
+		return -1;
 	}
 	if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
 		save_errno = errno;
 		close(s);
 		errno = save_errno;
-		return (-1);
+		return -1;
 	}
-	return (s);
+	return s;
 
 }
 
@@ -847,13 +874,13 @@ unix_listen(char *path)
 {
 	int s;
 	if ((s = unix_bind(path, 0)) < 0)
-		return (-1);
+		return -1;
 
 	if (listen(s, 5) < 0) {
 		close(s);
-		return (-1);
+		return -1;
 	}
-	return (s);
+	return s;
 }
 
 /*
@@ -912,7 +939,7 @@ remote_connect(const char *host, const char *port, str
 
 	freeaddrinfo(res0);
 
-	return (s);
+	return s;
 }
 
 int
@@ -940,7 +967,7 @@ timeout_connect(int s, const struct sockaddr *name, so
 			err(1, "poll failed");
 	}
 
-	return (ret);
+	return ret;
 }
 
 /*
@@ -996,7 +1023,7 @@ local_listen(char *host, char *port, struct addrinfo h
 
 	freeaddrinfo(res0);
 
-	return (s);
+	return s;
 }
 
 /*
@@ -1150,6 +1177,12 @@ readwrite(int net_fd, struct tls *tls_ctx)
 				shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
 				pfd[POLL_NETIN].fd = -1;
 			}
+			if (recvlimit > 0 && ++recvcount >= recvlimit) {
+				if (pfd[POLL_NETIN].fd != -1)
+					shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+				pfd[POLL_NETIN].fd = -1;
+				pfd[POLL_STDIN].fd = -1;
+			}
 			/* read something - poll stdout */
 			if (netinbufpos > 0)
 				pfd[POLL_STDOUT].events = POLLOUT;
@@ -1417,7 +1450,7 @@ udptest(int s)
 		else
 			ret = -1;
 	}
-	return (ret);
+	return ret;
 }
 
 void
@@ -1517,11 +1550,11 @@ map_tos(char *s, int *val)
 	for (t = toskeywords; t->keyword != NULL; t++) {
 		if (strcmp(s, t->keyword) == 0) {
 			*val = t->val;
-			return (1);
+			return 1;
 		}
 	}
 
-	return (0);
+	return 0;
 }
 
 int
@@ -1536,21 +1569,36 @@ map_tls(char *s, int *val)
 		{ "noname",		TLS_NONAME },
 		{ "clientcert",		TLS_CCERT},
 		{ "muststaple",		TLS_MUSTSTAPLE},
+		{ "tlscompat",		TLS_COMPAT },
 		{ NULL,			-1 },
 	};
 
 	for (t = tlskeywords; t->keyword != NULL; t++) {
 		if (strcmp(s, t->keyword) == 0) {
 			*val |= t->val;
-			return (1);
+			return 1;
 		}
 	}
-	return (0);
+	return 0;
 }
 
 void
-report_tls(struct tls * tls_ctx, char * host, char *tls_expectname)
+save_peer_cert(struct tls *tls_ctx, FILE *fp)
 {
+	const char *pem;
+	size_t plen;
+
+	if ((pem = tls_peer_cert_chain_pem(tls_ctx, &plen)) == NULL)
+		errx(1, "Can't get peer certificate");
+	if (fprintf(fp, "%.*s", (int)plen, pem) < 0)
+		err(1, "unable to save peer cert");
+	if (fflush(fp) != 0)
+		err(1, "unable to flush peer cert");
+}
+
+void
+report_tls(struct tls * tls_ctx, char * host)
+{
 	time_t t;
 	const char *ocsp_url;
 
@@ -1675,9 +1723,11 @@ help(void)
 	\t-u		UDP mode\n\
 	\t-V rtable	Specify alternate routing table\n\
 	\t-v		Verbose\n\
+	\t-W recvlimit	Terminate after receiving a number of packets\n\
 	\t-w timeout	Timeout for connects and final net reads\n\
 	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
 	\t-x addr[:port]\tSpecify proxy address and port\n\
+	\t-Z		Peer certificate file\n\
 	\t-z		Zero-I/O mode [used for scanning]\n\
 	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
 	exit(1);
@@ -1692,9 +1742,11 @@ usage(int ret)
 	    "\t  [-i interval] [-K keyfile] [-M ttl] [-m minttl] [-O length]\n"
 	    "\t  [-o staplefile] [-P proxy_username] [-p source_port] "
 	    "[-R CAfile]\n"
-	    "\t  [-s source] [-T keyword] [-V rtable] [-w timeout] "
-	    "[-X proxy_protocol]\n"
-	    "\t  [-x proxy_address[:port]] [destination] [port]\n");
+	    "\t  [-s source] [-T keyword] [-V rtable] [-W recvlimit] "
+	    "[-w timeout]\n"
+	    "\t  [-X proxy_protocol] [-x proxy_address[:port]] "
+	    "[-Z peercertfile]\n"
+	    "\t  [destination] [port]\n");
 	if (ret)
 		exit(1);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905101729.x4AHTUKC009469>