Author: delphij
Date: Sun Apr 24 22:12:47 2016
New Revision: 298554
URL: https://svnweb.freebsd.org/changeset/base/298554

Log:
  Vendor import nc(1) from OPENBSD_5_9.

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

Modified: vendor/netcat/dist/Makefile
==============================================================================
--- vendor/netcat/dist/Makefile Sun Apr 24 21:35:01 2016        (r298553)
+++ vendor/netcat/dist/Makefile Sun Apr 24 22:12:47 2016        (r298554)
@@ -1,6 +1,8 @@
-#      $OpenBSD: Makefile,v 1.6 2001/09/02 18:45:41 jakob Exp $
+#      $OpenBSD: Makefile,v 1.7 2015/09/11 21:07:01 beck Exp $
 
 PROG=  nc
 SRCS=  netcat.c atomicio.c socks.c
+LDADD+= -ltls -lssl -lcrypto
+DPADD+=  ${LIBTLS} ${LIBSSL} ${LIBCRYPTO}
 
 .include <bsd.prog.mk>

Modified: vendor/netcat/dist/nc.1
==============================================================================
--- vendor/netcat/dist/nc.1     Sun Apr 24 21:35:01 2016        (r298553)
+++ vendor/netcat/dist/nc.1     Sun Apr 24 22:12:47 2016        (r298554)
@@ -1,4 +1,4 @@
-.\"     $OpenBSD: nc.1,v 1.68 2015/03/26 10:35:04 tobias Exp $
+.\"     $OpenBSD: nc.1,v 1.71 2015/09/25 14:56:33 schwarze 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 26 2014 $
+.Dd $Mdocdate: September 12 2015 $
 .Dt NC 1
 .Os
 .Sh NAME
@@ -33,25 +33,25 @@
 .Nd arbitrary TCP and UDP connections and listens
 .Sh SYNOPSIS
 .Nm nc
-.Bk -words
-.Op Fl 46DdFhklNnrStUuvz
+.Op Fl 46cDdFhklNnrStUuvz
+.Op Fl C Ar certfile
+.Op Fl e Ar name
+.Op Fl H Ar hash
 .Op Fl I Ar length
 .Op Fl i Ar interval
+.Op Fl K Ar keyfile
 .Op Fl O Ar length
 .Op Fl P Ar proxy_username
 .Op Fl p Ar source_port
+.Op Fl R Ar CAfile
 .Op Fl s Ar source
-.Op Fl T Ar toskeyword
+.Op Fl T Ar keyword
 .Op Fl V Ar rtable
 .Op Fl w Ar timeout
 .Op Fl X Ar proxy_protocol
-.Oo Xo
-.Fl x Ar proxy_address Ns Oo : Ns
-.Ar port Oc
-.Xc Oc
+.Op Fl x Ar proxy_address Ns Op : Ns Ar port
 .Op Ar destination
 .Op Ar port
-.Ek
 .Sh DESCRIPTION
 The
 .Nm
@@ -98,10 +98,20 @@ to use IPv4 addresses only.
 Forces
 .Nm
 to use IPv6 addresses only.
+.It Fl C Ar certfile
+Specifies the filename from which the public key part of the TLS
+certificate is loaded, in PEM format.
+May only be used with TLS.
+.It Fl c
+If using a TCP socket to connect or listen, use TLS.
+Illegal if not using TCP sockets.
 .It Fl D
 Enable debugging on the socket.
 .It Fl d
 Do not attempt to read from stdin.
+.It Fl e Ar name
+Specify the name that must be present in the peer certificate when using TLS.
+Illegal if not using TLS.
 .It Fl F
 Pass the first connected socket using
 .Xr sendmsg 2
@@ -117,6 +127,11 @@ using the
 .Xr ssh_config 5
 .Cm ProxyUseFdpass
 option).
+.It Fl H Ar hash
+Specifies the required hash string of the peer certificate when using TLS.
+The string format required is that used by
+.Xr tls_peer_cert_hash 3 .
+Illegal if not using TLS, and may not be used with -T noverify.
 .It Fl h
 Prints out
 .Nm
@@ -126,6 +141,10 @@ Specifies the size of the TCP receive bu
 .It Fl i Ar interval
 Specifies a delay time interval between lines of text sent and received.
 Also causes a delay time between connections to multiple ports.
+.It Fl K Ar keyfile
+Specifies the filename from which the private key
+is loaded in PEM format.
+May only be used with TLS.
 .It Fl k
 Forces
 .Nm
@@ -172,6 +191,12 @@ should use, subject to privilege restric
 It is an error to use this option in conjunction with the
 .Fl l
 option.
+.It Fl R Ar CAfile
+Specifies the filename from which the root CA bundle for certificate
+verification is loaded, in PEM format.
+Illegal if not using TLS.
+The default is
+.Pa /etc/ssl/cert.pem .
 .It Fl r
 Specifies that source and/or destination ports should be chosen randomly
 instead of sequentially within a range or in the order that the system
@@ -187,9 +212,23 @@ to create and use so that datagrams can 
 It is an error to use this option in conjunction with the
 .Fl l
 option.
-.It Fl T Ar toskeyword
-Change IPv4 TOS value.
-.Ar toskeyword
+.It Fl T Ar keyword
+Change IPv4 TOS value or TLS options.
+For TLS options
+.Ar keyword
+may be one of
+.Ar tlslegacy ,
+which allows legacy TLS protocols;
+.Ar noverify ,
+which disables certificate verification;
+.Ar noname ,
+which disables certificate name checking; or
+.Ar clientcert ,
+which requires a client certificate on incoming connections.
+It is illegal to specify TLS options if not using TLS.
+.Pp
+For IPv4 TOS value
+.Ar keyword
 may be one of
 .Ar critical ,
 .Ar inetcontrol ,
@@ -258,10 +297,7 @@ and
 .Dq connect
 (HTTPS proxy).
 If the protocol is not specified, SOCKS version 5 is used.
-.It Xo
-.Fl x Ar proxy_address Ns Oo : Ns
-.Ar port Oc
-.Xc
+.It Fl x Ar proxy_address Ns Op : Ns Ar port
 Requests that
 .Nm
 should connect to
@@ -429,6 +465,11 @@ the source port, with a timeout of 5 sec
 .Pp
 .Dl $ nc -p 31337 -w 5 host.example.com 42
 .Pp
+Open a TCP connection to port 443 of www.google.ca, and negotiate TLS.
+Check for a different name in the certificate for validation.
+.Pp
+.Dl $  nc -v -c -e adsf.au.doubleclick.net www.google.ca 443
+.Pp
 Open a UDP connection to port 53 of host.example.com:
 .Pp
 .Dl $ nc -u host.example.com 53

Modified: vendor/netcat/dist/netcat.c
==============================================================================
--- vendor/netcat/dist/netcat.c Sun Apr 24 21:35:01 2016        (r298553)
+++ vendor/netcat/dist/netcat.c Sun Apr 24 22:12:47 2016        (r298554)
@@ -1,6 +1,7 @@
-/* $OpenBSD: netcat.c,v 1.130 2015/07/26 19:12:28 chl Exp $ */
+/* $OpenBSD: netcat.c,v 1.150 2016/01/04 02:18:31 bcook Exp $ */
 /*
  * Copyright (c) 2001 Eric Jackson <er...@monkey.org>
+ * Copyright (c) 2015 Bob Beck.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +34,6 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <sys/time.h>
 #include <sys/uio.h>
 #include <sys/un.h>
 
@@ -44,7 +44,6 @@
 
 #include <err.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <limits.h>
 #include <netdb.h>
 #include <poll.h>
@@ -53,16 +52,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
+#include <tls.h>
 #include "atomicio.h"
 
-#ifndef SUN_LEN
-#define SUN_LEN(su) \
-       (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
-#endif
-
 #define PORT_MAX       65535
-#define PORT_MAX_LEN   6
 #define UNIX_DG_TMP_SOCKET_SIZE        19
 
 #define POLL_STDIN 0
@@ -70,6 +65,12 @@
 #define POLL_NETIN 2
 #define POLL_STDOUT 3
 #define BUFSIZE 16384
+#define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
+
+#define TLS_LEGACY     (1 << 1)
+#define TLS_NOVERIFY   (1 << 2)
+#define TLS_NONAME     (1 << 3)
+#define TLS_CCERT      (1 << 4)
 
 /* Command Line Options */
 int    dflag;                                  /* detached, no stdin */
@@ -95,6 +96,21 @@ int  Sflag;                                  /* TCP MD5 
signature opti
 int    Tflag = -1;                             /* IP Type of Service */
 int    rtableid = -1;
 
+int    usetls;                                 /* use TLS */
+char    *Cflag;                                        /* Public cert file */
+char    *Kflag;                                        /* Private key file */
+char    *Rflag = DEFAULT_CA_FILE;              /* Root CA file */
+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 */
+uint8_t *cacert;
+size_t  cacertlen;
+uint8_t *privkey;
+size_t  privkeylen;
+uint8_t *pubcert;
+size_t  pubcertlen;
+
 int timeout = -1;
 int family = AF_UNSPEC;
 char *portlist[PORT_MAX+1];
@@ -104,22 +120,26 @@ void      atelnet(int, unsigned char *, unsig
 void   build_ports(char *);
 void   help(void);
 int    local_listen(char *, char *, struct addrinfo);
-void   readwrite(int);
+void   readwrite(int, struct tls *);
 void   fdpass(int nfd) __attribute__((noreturn));
 int    remote_connect(const char *, const char *, struct addrinfo);
 int    timeout_connect(int, const struct sockaddr *, socklen_t);
 int    socks_connect(const char *, const char *, struct addrinfo,
            const char *, const char *, struct addrinfo, int, const char *);
 int    udptest(int);
-int    unix_bind(char *);
+int    unix_bind(char *, int);
 int    unix_connect(char *);
 int    unix_listen(char *);
 void   set_common_sockopts(int, int);
 int    map_tos(char *, int *);
+int    map_tls(char *, int *);
 void   report_connect(const struct sockaddr *, socklen_t);
+void   report_tls(struct tls *tls_ctx, char * host, char *tls_expectname);
 void   usage(int);
-ssize_t drainbuf(int, unsigned char *, size_t *);
-ssize_t fillbuf(int, unsigned char *, size_t *);
+ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *);
+ssize_t fillbuf(int, unsigned char *, size_t *, struct tls *);
+void   tls_setup_client(struct tls *, int, char *);
+struct tls *tls_setup_server(struct tls *, int, char *);
 
 int
 main(int argc, char *argv[])
@@ -134,6 +154,8 @@ main(int argc, char *argv[])
        const char *errstr, *proxyhost = "", *proxyport = NULL;
        struct addrinfo proxyhints;
        char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
+       struct tls_config *tls_cfg = NULL;
+       struct tls *tls_ctx = NULL;
 
        ret = 1;
        s = 0;
@@ -145,7 +167,7 @@ main(int argc, char *argv[])
        signal(SIGPIPE, SIG_IGN);
 
        while ((ch = getopt(argc, argv,
-           "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
+           "46C:cDde:FH:hI:i:K:klNnO:P:p:R:rSs:T:tUuV:vw:X:x:z")) != -1) {
                switch (ch) {
                case '4':
                        family = AF_INET;
@@ -166,12 +188,24 @@ main(int argc, char *argv[])
                        else
                                errx(1, "unsupported proxy protocol");
                        break;
+               case 'C':
+                       Cflag = optarg;
+                       break;
+               case 'c':
+                       usetls = 1;
+                       break;
                case 'd':
                        dflag = 1;
                        break;
+               case 'e':
+                       tls_expectname = optarg;
+                       break;
                case 'F':
                        Fflag = 1;
                        break;
+               case 'H':
+                       tls_expecthash = optarg;
+                       break;
                case 'h':
                        help();
                        break;
@@ -180,6 +214,9 @@ main(int argc, char *argv[])
                        if (errstr)
                                errx(1, "interval %s: %s", errstr, optarg);
                        break;
+               case 'K':
+                       Kflag = optarg;
+                       break;
                case 'k':
                        kflag = 1;
                        break;
@@ -198,6 +235,10 @@ main(int argc, char *argv[])
                case 'p':
                        pflag = optarg;
                        break;
+               case 'R':
+                       tls_cachanged = 1;
+                       Rflag = optarg;
+                       break;
                case 'r':
                        rflag = 1;
                        break;
@@ -256,6 +297,8 @@ main(int argc, char *argv[])
                        errno = 0;
                        if (map_tos(optarg, &Tflag))
                                break;
+                       if (map_tls(optarg, &TLSopt))
+                               break;
                        if (strlen(optarg) > 1 && optarg[0] == '0' &&
                            optarg[1] == 'x')
                                Tflag = (int)strtol(optarg, NULL, 16);
@@ -263,7 +306,7 @@ main(int argc, char *argv[])
                                Tflag = (int)strtonum(optarg, 0, 255,
                                    &errstr);
                        if (Tflag < 0 || Tflag > 255 || errstr || errno)
-                               errx(1, "illegal tos value %s", optarg);
+                               errx(1, "illegal tos/tls value %s", optarg);
                        break;
                default:
                        usage(1);
@@ -272,6 +315,22 @@ main(int argc, char *argv[])
        argc -= optind;
        argv += optind;
 
+       if (rtableid >= 0)
+               if (setrtable(rtableid) == -1)
+                       err(1, "setrtable");
+
+       if (family == AF_UNIX) {
+               if (pledge("stdio rpath wpath cpath tmppath unix", NULL) == -1)
+                       err(1, "pledge");
+       } else if (Fflag) {
+               if (pledge("stdio inet dns sendfd", NULL) == -1)
+                       err(1, "pledge");
+       } else if (usetls) {
+               if (pledge("stdio rpath inet dns", NULL) == -1)
+                       err(1, "pledge");
+       } else if (pledge("stdio inet dns", NULL) == -1)
+               err(1, "pledge");
+
        /* Cruft to make sure options are clean, and used properly. */
        if (argv[0] && !argv[1] && family == AF_UNIX) {
                host = argv[0];
@@ -295,6 +354,26 @@ main(int argc, char *argv[])
                errx(1, "cannot use -z and -l");
        if (!lflag && kflag)
                errx(1, "must use -l with -k");
+       if (uflag && usetls)
+               errx(1, "cannot use -c and -u");
+       if ((family == AF_UNIX) && usetls)
+               errx(1, "cannot use -c and -U");
+       if ((family == AF_UNIX) && Fflag)
+               errx(1, "cannot use -F and -U");
+       if (Fflag && usetls)
+               errx(1, "cannot use -c and -F");
+       if (TLSopt && !usetls)
+               errx(1, "you must specify -c to use TLS options");
+       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 (tls_cachanged && !usetls)
+               errx(1, "you must specify -c to use -R");
+       if (tls_expecthash && !usetls)
+               errx(1, "you must specify -c to use -H");
+       if (tls_expectname && !usetls)
+               errx(1, "you must specify -c to use -e");
 
        /* Get name of temporary socket for unix datagram client */
        if ((family == AF_UNIX) && uflag && !lflag) {
@@ -302,7 +381,7 @@ main(int argc, char *argv[])
                        unix_dg_tmp_socket = sflag;
                } else {
                        strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
-                               UNIX_DG_TMP_SOCKET_SIZE);
+                           UNIX_DG_TMP_SOCKET_SIZE);
                        if (mktemp(unix_dg_tmp_socket_buf) == NULL)
                                err(1, "mktemp");
                        unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
@@ -347,17 +426,62 @@ main(int argc, char *argv[])
                        proxyhints.ai_flags |= AI_NUMERICHOST;
        }
 
+       if (usetls) {
+               if (Rflag && (cacert = tls_load_file(Rflag, &cacertlen, NULL)) 
== NULL)
+                       errx(1, "unable to load root CA file %s", Rflag);
+               if (Cflag && (pubcert = tls_load_file(Cflag, &pubcertlen, 
NULL)) == NULL)
+                       errx(1, "unable to load TLS certificate file %s", 
Cflag);
+               if (Kflag && (privkey = tls_load_file(Kflag, &privkeylen, 
NULL)) == NULL)
+                       errx(1, "unable to load TLS key file %s", Kflag);
+
+               if (pledge("stdio inet dns", NULL) == -1)
+                       err(1, "pledge");
+
+               if (tls_init() == -1)
+                       errx(1, "unable to initialize TLS");
+               if ((tls_cfg = tls_config_new()) == NULL)
+                       errx(1, "unable to allocate TLS config");
+               if (Rflag && tls_config_set_ca_mem(tls_cfg, cacert, cacertlen) 
== -1)
+                       errx(1, "unable to set root CA file %s", Rflag);
+               if (Cflag && tls_config_set_cert_mem(tls_cfg, pubcert, 
pubcertlen) == -1)
+                       errx(1, "unable to set TLS certificate file %s", Cflag);
+               if (Kflag && tls_config_set_key_mem(tls_cfg, privkey, 
privkeylen) == -1)
+                       errx(1, "unable to set TLS key file %s", Kflag);
+               if (TLSopt & TLS_LEGACY) {
+                       tls_config_set_protocols(tls_cfg, TLS_PROTOCOLS_ALL);
+                       tls_config_set_ciphers(tls_cfg, "legacy");
+               }
+               if (!lflag && (TLSopt & TLS_CCERT))
+                       errx(1, "clientcert is only valid with -l");
+               if (TLSopt & TLS_NONAME)
+                       tls_config_insecure_noverifyname(tls_cfg);
+               if (TLSopt & TLS_NOVERIFY) {
+                       if (tls_expecthash != NULL)
+                               errx(1, "-H and -T noverify may not be used"
+                                   "together");
+                       tls_config_insecure_noverifycert(tls_cfg);
+               }
+       }
        if (lflag) {
+               struct tls *tls_cctx = NULL;
                int connfd;
                ret = 0;
 
                if (family == AF_UNIX) {
                        if (uflag)
-                               s = unix_bind(host);
+                               s = unix_bind(host, 0);
                        else
                                s = unix_listen(host);
                }
 
+               if (usetls) {
+                       tls_config_verify_client_optional(tls_cfg);
+                       if ((tls_ctx = tls_server()) == NULL)
+                               errx(1, "tls server creation failed");
+                       if (tls_configure(tls_ctx, tls_cfg) == -1)
+                               errx(1, "tls configuration failed (%s)",
+                                   tls_error(tls_ctx));
+               }
                /* Allow only one connection at a time, but stay alive. */
                for (;;) {
                        if (family != AF_UNIX)
@@ -369,7 +493,7 @@ main(int argc, char *argv[])
                         * receive datagrams from multiple socket pairs.
                         */
                        if (uflag && kflag)
-                               readwrite(s);
+                               readwrite(s, NULL);
                        /*
                         * For UDP and not -k, we will use recvfrom() initially
                         * to wait for a caller, then use the regular functions
@@ -394,22 +518,34 @@ main(int argc, char *argv[])
                                if (vflag)
                                        report_connect((struct sockaddr *)&z, 
len);
 
-                               readwrite(s);
+                               readwrite(s, NULL);
                        } else {
                                len = sizeof(cliaddr);
-                               connfd = accept(s, (struct sockaddr *)&cliaddr,
-                                   &len);
+                               connfd = accept4(s, (struct sockaddr *)&cliaddr,
+                                   &len, SOCK_NONBLOCK);
                                if (connfd == -1) {
                                        /* For now, all errnos are fatal */
                                        err(1, "accept");
                                }
                                if (vflag)
                                        report_connect((struct sockaddr 
*)&cliaddr, len);
-
-                               readwrite(connfd);
+                               if ((usetls) &&
+                                   (tls_cctx = tls_setup_server(tls_ctx, 
connfd, host)))
+                                       readwrite(connfd, tls_cctx);
+                               if (!usetls)
+                                       readwrite(connfd, NULL);
+                               if (tls_cctx) {
+                                       int i;
+
+                                       do {
+                                               i = tls_close(tls_cctx);
+                                       } while (i == TLS_WANT_POLLIN ||
+                                           i == TLS_WANT_POLLOUT);
+                                       tls_free(tls_cctx);
+                                       tls_cctx = NULL;
+                               }
                                close(connfd);
                        }
-
                        if (family != AF_UNIX)
                                close(s);
                        else if (uflag) {
@@ -424,7 +560,7 @@ main(int argc, char *argv[])
                ret = 0;
 
                if ((s = unix_connect(host)) > 0 && !zflag) {
-                       readwrite(s);
+                       readwrite(s, NULL);
                        close(s);
                } else
                        ret = 1;
@@ -444,6 +580,13 @@ main(int argc, char *argv[])
                        if (s)
                                close(s);
 
+                       if (usetls) {
+                               if ((tls_ctx = tls_client()) == NULL)
+                                       errx(1, "tls client creation failed");
+                               if (tls_configure(tls_ctx, tls_cfg) == -1)
+                                       errx(1, "tls configuration failed (%s)",
+                                           tls_error(tls_ctx));
+                       }
                        if (xflag)
                                s = socks_connect(host, portlist[i], hints,
                                    proxyhost, proxyport, proxyhints, socksv,
@@ -481,14 +624,30 @@ main(int argc, char *argv[])
                        }
                        if (Fflag)
                                fdpass(s);
-                       else if (!zflag)
-                               readwrite(s);
+                       else {
+                               if (usetls)
+                                       tls_setup_client(tls_ctx, s, host);
+                               if (!zflag)
+                                       readwrite(s, tls_ctx);
+                               if (tls_ctx) {
+                                       int j;
+
+                                       do {
+                                               j = tls_close(tls_ctx);
+                                       } while (j == TLS_WANT_POLLIN ||
+                                           j == TLS_WANT_POLLOUT);
+                                       tls_free(tls_ctx);
+                                       tls_ctx = NULL;
+                               }
+                       }
                }
        }
 
        if (s)
                close(s);
 
+       tls_config_free(tls_cfg);
+
        exit(ret);
 }
 
@@ -497,33 +656,95 @@ main(int argc, char *argv[])
  * Returns a unix socket bound to the given path
  */
 int
-unix_bind(char *path)
+unix_bind(char *path, int flags)
 {
-       struct sockaddr_un sun;
+       struct sockaddr_un s_un;
        int s;
 
        /* Create unix domain socket. */
-       if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
-            0)) < 0)
+       if ((s = socket(AF_UNIX, flags | (uflag ? SOCK_DGRAM : SOCK_STREAM),
+           0)) < 0)
                return (-1);
 
-       memset(&sun, 0, sizeof(struct sockaddr_un));
-       sun.sun_family = AF_UNIX;
+       memset(&s_un, 0, sizeof(struct sockaddr_un));
+       s_un.sun_family = AF_UNIX;
 
-       if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
-           sizeof(sun.sun_path)) {
+       if (strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)) >=
+           sizeof(s_un.sun_path)) {
                close(s);
                errno = ENAMETOOLONG;
                return (-1);
        }
 
-       if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
+       if (bind(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
                close(s);
                return (-1);
        }
        return (s);
 }
 
+void
+tls_setup_client(struct tls *tls_ctx, int s, char *host)
+{
+       int i;
+
+       if (tls_connect_socket(tls_ctx, s,
+               tls_expectname ? tls_expectname : host) == -1) {
+               errx(1, "tls connection failed (%s)",
+                   tls_error(tls_ctx));
+       }
+       do {
+               if ((i = tls_handshake(tls_ctx)) == -1)
+                       errx(1, "tls handshake failed (%s)",
+                           tls_error(tls_ctx));
+       } while (i == TLS_WANT_POLLIN || i == TLS_WANT_POLLOUT);
+       if (vflag)
+               report_tls(tls_ctx, host, tls_expectname);
+       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);
+}
+
+struct tls *
+tls_setup_server(struct tls *tls_ctx, int connfd, char *host)
+{
+       struct tls *tls_cctx;
+
+       if (tls_accept_socket(tls_ctx, &tls_cctx,
+               connfd) == -1) {
+               warnx("tls accept failed (%s)",
+                   tls_error(tls_ctx));
+               tls_cctx = NULL;
+       } else {
+               int i;
+
+               do {
+                       if ((i = tls_handshake(tls_cctx)) == -1)
+                               warnx("tls handshake failed (%s)",
+                                   tls_error(tls_cctx));
+               } while(i == TLS_WANT_POLLIN || i == TLS_WANT_POLLOUT);
+       }
+       if (tls_cctx) {
+               int gotcert = tls_peer_cert_provided(tls_cctx);
+
+               if (vflag && gotcert)
+                       report_tls(tls_cctx, host, tls_expectname);
+               if ((TLSopt & TLS_CCERT) && !gotcert)
+                       warnx("No client certificate provided");
+               else if (gotcert && tls_peer_cert_hash(tls_ctx) && 
tls_expecthash &&
+                   strcmp(tls_expecthash, tls_peer_cert_hash(tls_ctx)) != 0)
+                       warnx("peer certificate is not %s", tls_expecthash);
+               else if (gotcert && tls_expectname &&
+                   (!tls_peer_cert_contains_name(tls_cctx, tls_expectname)))
+                       warnx("name (%s) not found in client cert",
+                           tls_expectname);
+               else {
+                       return tls_cctx;
+               }
+       }
+       return NULL;
+}
+
 /*
  * unix_connect()
  * Returns a socket connected to a local unix socket. Returns -1 on failure.
@@ -531,28 +752,27 @@ unix_bind(char *path)
 int
 unix_connect(char *path)
 {
-       struct sockaddr_un sun;
+       struct sockaddr_un s_un;
        int s;
 
        if (uflag) {
-               if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
+               if ((s = unix_bind(unix_dg_tmp_socket, SOCK_CLOEXEC)) < 0)
                        return (-1);
        } else {
-               if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+               if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0)
                        return (-1);
        }
-       (void)fcntl(s, F_SETFD, FD_CLOEXEC);
 
-       memset(&sun, 0, sizeof(struct sockaddr_un));
-       sun.sun_family = AF_UNIX;
+       memset(&s_un, 0, sizeof(struct sockaddr_un));
+       s_un.sun_family = AF_UNIX;
 
-       if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
-           sizeof(sun.sun_path)) {
+       if (strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)) >=
+           sizeof(s_un.sun_path)) {
                close(s);
                errno = ENAMETOOLONG;
                return (-1);
        }
-       if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
+       if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
                close(s);
                return (-1);
        }
@@ -568,7 +788,7 @@ int
 unix_listen(char *path)
 {
        int s;
-       if ((s = unix_bind(path)) < 0)
+       if ((s = unix_bind(path, 0)) < 0)
                return (-1);
 
        if (listen(s, 5) < 0) {
@@ -594,14 +814,10 @@ remote_connect(const char *host, const c
 
        res0 = res;
        do {
-               if ((s = socket(res0->ai_family, res0->ai_socktype,
-                   res0->ai_protocol)) < 0)
+               if ((s = socket(res0->ai_family, res0->ai_socktype |
+                   SOCK_NONBLOCK, res0->ai_protocol)) < 0)
                        continue;
 
-               if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
-                   &rtableid, sizeof(rtableid)) == -1))
-                       err(1, "setsockopt SO_RTABLE");
-
                /* Bind to a local port or source address if specified. */
                if (sflag || pflag) {
                        struct addrinfo ahints, *ares;
@@ -626,7 +842,7 @@ remote_connect(const char *host, const c
 
                if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
                        break;
-               else if (vflag)
+               if (vflag)
                        warn("connect to %s port %s (%s) failed", host, port,
                            uflag ? "udp" : "tcp");
 
@@ -644,15 +860,9 @@ timeout_connect(int s, const struct sock
 {
        struct pollfd pfd;
        socklen_t optlen;
-       int flags, optval;
+       int optval;
        int ret;
 
-       if (timeout != -1) {
-               flags = fcntl(s, F_GETFL, 0);
-               if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
-                       err(1, "set non-blocking mode");
-       }
-
        if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
                pfd.fd = s;
                pfd.events = POLLOUT;
@@ -670,9 +880,6 @@ timeout_connect(int s, const struct sock
                        err(1, "poll failed");
        }
 
-       if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
-               err(1, "restoring flags");
-
        return (ret);
 }
 
@@ -707,10 +914,6 @@ local_listen(char *host, char *port, str
                    res0->ai_protocol)) < 0)
                        continue;
 
-               if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
-                   &rtableid, sizeof(rtableid)) == -1))
-                       err(1, "setsockopt SO_RTABLE");
-
                ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
                if (ret == -1)
                        err(1, NULL);
@@ -740,7 +943,7 @@ local_listen(char *host, char *port, str
  * Loop that polls on the network file descriptor and stdin.
  */
 void
-readwrite(int net_fd)
+readwrite(int net_fd, struct tls *tls_ctx)
 {
        struct pollfd pfd[4];
        int stdin_fd = STDIN_FILENO;
@@ -774,8 +977,8 @@ readwrite(int net_fd)
 
        while (1) {
                /* both inputs are gone, buffers are empty, we are done */
-               if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
-                   && stdinbufpos == 0 && netinbufpos == 0) {
+               if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 &&
+                   stdinbufpos == 0 && netinbufpos == 0) {
                        close(net_fd);
                        return;
                }
@@ -785,8 +988,8 @@ readwrite(int net_fd)
                        return;
                }
                /* listen and net in gone, queues empty, done */
-               if (lflag && pfd[POLL_NETIN].fd == -1
-                   && stdinbufpos == 0 && netinbufpos == 0) {
+               if (lflag && pfd[POLL_NETIN].fd == -1 &&
+                   stdinbufpos == 0 && netinbufpos == 0) {
                        close(net_fd);
                        return;
                }
@@ -819,13 +1022,13 @@ readwrite(int net_fd)
                /* reading is possible after HUP */
                if (pfd[POLL_STDIN].events & POLLIN &&
                    pfd[POLL_STDIN].revents & POLLHUP &&
-                   ! (pfd[POLL_STDIN].revents & POLLIN))
-                               pfd[POLL_STDIN].fd = -1;
+                   !(pfd[POLL_STDIN].revents & POLLIN))
+                       pfd[POLL_STDIN].fd = -1;
 
                if (pfd[POLL_NETIN].events & POLLIN &&
                    pfd[POLL_NETIN].revents & POLLHUP &&
-                   ! (pfd[POLL_NETIN].revents & POLLIN))
-                               pfd[POLL_NETIN].fd = -1;
+                   !(pfd[POLL_NETIN].revents & POLLIN))
+                       pfd[POLL_NETIN].fd = -1;
 
                if (pfd[POLL_NETOUT].revents & POLLHUP) {
                        if (Nflag)
@@ -848,9 +1051,12 @@ readwrite(int net_fd)
                /* try to read from stdin */
                if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
                        ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
-                           &stdinbufpos);
-                       /* error or eof on stdin - remove from pfd */
-                       if (ret == 0 || ret == -1)
+                           &stdinbufpos, NULL);
+                       if (ret == TLS_WANT_POLLIN)
+                               pfd[POLL_STDIN].events = POLLIN;
+                       else if (ret == TLS_WANT_POLLOUT)
+                               pfd[POLL_STDIN].events = POLLOUT;
+                       else if (ret == 0 || ret == -1)
                                pfd[POLL_STDIN].fd = -1;
                        /* read something - poll net out */
                        if (stdinbufpos > 0)
@@ -862,8 +1068,12 @@ readwrite(int net_fd)
                /* try to write to network */
                if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
                        ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
-                           &stdinbufpos);
-                       if (ret == -1)
+                           &stdinbufpos, tls_ctx);
+                       if (ret == TLS_WANT_POLLIN)
+                               pfd[POLL_NETOUT].events = POLLIN;
+                       else if (ret == TLS_WANT_POLLOUT)
+                               pfd[POLL_NETOUT].events = POLLOUT;
+                       else if (ret == -1)
                                pfd[POLL_NETOUT].fd = -1;
                        /* buffer empty - remove self from polling */
                        if (stdinbufpos == 0)
@@ -875,8 +1085,12 @@ readwrite(int net_fd)
                /* try to read from network */
                if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
                        ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
-                           &netinbufpos);
-                       if (ret == -1)
+                           &netinbufpos, tls_ctx);
+                       if (ret == TLS_WANT_POLLIN)
+                               pfd[POLL_NETIN].events = POLLIN;
+                       else if (ret == TLS_WANT_POLLOUT)
+                               pfd[POLL_NETIN].events = POLLOUT;
+                       else if (ret == -1)
                                pfd[POLL_NETIN].fd = -1;
                        /* eof on net in - remove from pfd */
                        if (ret == 0) {
@@ -897,8 +1111,12 @@ readwrite(int net_fd)
                /* try to write to stdout */
                if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
                        ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
-                           &netinbufpos);
-                       if (ret == -1)
+                           &netinbufpos, NULL);
+                       if (ret == TLS_WANT_POLLIN)
+                               pfd[POLL_STDOUT].events = POLLIN;
+                       else if (ret == TLS_WANT_POLLOUT)
+                               pfd[POLL_STDOUT].events = POLLOUT;
+                       else if (ret == -1)
                                pfd[POLL_STDOUT].fd = -1;
                        /* buffer empty - remove self from polling */
                        if (netinbufpos == 0)
@@ -922,15 +1140,19 @@ readwrite(int net_fd)
 }
 
 ssize_t
-drainbuf(int fd, unsigned char *buf, size_t *bufpos)
+drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls)
 {
        ssize_t n;
        ssize_t adjust;
 
-       n = write(fd, buf, *bufpos);
-       /* don't treat EAGAIN, EINTR as error */
-       if (n == -1 && (errno == EAGAIN || errno == EINTR))
-               n = -2;
+       if (tls)
+               n = tls_write(tls, buf, *bufpos);
+       else {
+               n = write(fd, buf, *bufpos);
+               /* don't treat EAGAIN, EINTR as error */
+               if (n == -1 && (errno == EAGAIN || errno == EINTR))
+                       n = TLS_WANT_POLLOUT;
+       }
        if (n <= 0)
                return n;
        /* adjust buffer */
@@ -941,17 +1163,20 @@ drainbuf(int fd, unsigned char *buf, siz
        return n;
 }
 
-
 ssize_t
-fillbuf(int fd, unsigned char *buf, size_t *bufpos)
+fillbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls)
 {
        size_t num = BUFSIZE - *bufpos;
        ssize_t n;
 
-       n = read(fd, buf + *bufpos, num);
-       /* don't treat EAGAIN, EINTR as error */
-       if (n == -1 && (errno == EAGAIN || errno == EINTR))
-               n = -2;
+       if (tls)
+               n = tls_read(tls, buf + *bufpos, num);
+       else {
+               n = read(fd, buf + *bufpos, num);
+               /* don't treat EAGAIN, EINTR as error */
+               if (n == -1 && (errno == EAGAIN || errno == EINTR))
+                       n = TLS_WANT_POLLIN;
+       }
        if (n <= 0)
                return n;
        *bufpos += n;
@@ -1079,25 +1304,22 @@ build_ports(char *p)
                        lo = cp;
                }
 
-               /* Load ports sequentially. */
-               for (cp = lo; cp <= hi; cp++) {
-                       portlist[x] = calloc(1, PORT_MAX_LEN);
-                       if (portlist[x] == NULL)
-                               err(1, NULL);
-                       snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
-                       x++;
-               }
-
-               /* Randomly swap ports. */
+               /*
+                * Initialize portlist with a random permutation.  Based on
+                * Knuth, as in ip_randomid() in sys/netinet/ip_id.c.
+                */
                if (rflag) {
-                       int y;
-                       char *c;
-
-                       for (x = 0; x <= (hi - lo); x++) {
-                               y = (arc4random() & 0xFFFF) % (hi - lo);
-                               c = portlist[x];
-                               portlist[x] = portlist[y];
-                               portlist[y] = c;
+                       for (x = 0; x <= hi - lo; x++) {
+                               cp = arc4random_uniform(x + 1);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to