[BACK]Return to netcat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / nc

Diff for /src/usr.bin/nc/netcat.c between version 1.132 and 1.133

version 1.132, 2015/09/08 17:28:47 version 1.133, 2015/09/11 21:07:01
Line 1 
Line 1 
 /* $OpenBSD$ */  /* $OpenBSD$ */
 /*  /*
  * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>   * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
    * Copyright (c) 2015 Bob Beck.  All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 54 
Line 55 
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   #include <tls.h>
 #include "atomicio.h"  #include "atomicio.h"
   
 #ifndef SUN_LEN  #ifndef SUN_LEN
Line 70 
Line 72 
 #define POLL_NETIN 2  #define POLL_NETIN 2
 #define POLL_STDOUT 3  #define POLL_STDOUT 3
 #define BUFSIZE 16384  #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 */  /* Command Line Options */
 int     dflag;                                  /* detached, no stdin */  int     dflag;                                  /* detached, no stdin */
 int     Fflag;                                  /* fdpass sock to stdout */  int     Fflag;                                  /* fdpass sock to stdout */
Line 95 
Line 103 
 int     Tflag = -1;                             /* IP Type of Service */  int     Tflag = -1;                             /* IP Type of Service */
 int     rtableid = -1;  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_peerhash;                          /* hash of peer cert */
   char    *tls_expecthash;                        /* required hash of peer cert */
   
 int timeout = -1;  int timeout = -1;
 int family = AF_UNSPEC;  int family = AF_UNSPEC;
 char *portlist[PORT_MAX+1];  char *portlist[PORT_MAX+1];
Line 104 
Line 122 
 void    build_ports(char *);  void    build_ports(char *);
 void    help(void);  void    help(void);
 int     local_listen(char *, char *, struct addrinfo);  int     local_listen(char *, char *, struct addrinfo);
 void    readwrite(int);  void    readwrite(int, struct tls *);
 void    fdpass(int nfd) __attribute__((noreturn));  void    fdpass(int nfd) __attribute__((noreturn));
 int     remote_connect(const char *, const char *, struct addrinfo);  int     remote_connect(const char *, const char *, struct addrinfo);
 int     timeout_connect(int, const struct sockaddr *, socklen_t);  int     timeout_connect(int, const struct sockaddr *, socklen_t);
Line 116 
Line 134 
 int     unix_listen(char *);  int     unix_listen(char *);
 void    set_common_sockopts(int, int);  void    set_common_sockopts(int, int);
 int     map_tos(char *, int *);  int     map_tos(char *, int *);
   int     map_tls(char *, int *);
 void    report_connect(const struct sockaddr *, socklen_t);  void    report_connect(const struct sockaddr *, socklen_t);
   void    report_tls(struct tls * tls_ctx, char * host, char *tls_expectname);
 void    usage(int);  void    usage(int);
 ssize_t drainbuf(int, unsigned char *, size_t *);  ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *);
 ssize_t fillbuf(int, unsigned char *, size_t *);  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  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
Line 134 
Line 156 
         const char *errstr, *proxyhost = "", *proxyport = NULL;          const char *errstr, *proxyhost = "", *proxyport = NULL;
         struct addrinfo proxyhints;          struct addrinfo proxyhints;
         char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];          char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
           struct tls_config *tls_cfg = NULL;
           struct tls *tls_ctx = NULL;
   
         ret = 1;          ret = 1;
         s = 0;          s = 0;
Line 145 
Line 169 
         signal(SIGPIPE, SIG_IGN);          signal(SIGPIPE, SIG_IGN);
   
         while ((ch = getopt(argc, argv,          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) {                  switch (ch) {
                 case '4':                  case '4':
                         family = AF_INET;                          family = AF_INET;
Line 166 
Line 190 
                         else                          else
                                 errx(1, "unsupported proxy protocol");                                  errx(1, "unsupported proxy protocol");
                         break;                          break;
                   case 'C':
                           Cflag = optarg;
                           break;
                   case 'c':
                           usetls = 1;
                           break;
                 case 'd':                  case 'd':
                         dflag = 1;                          dflag = 1;
                         break;                          break;
                   case 'e':
                           tls_expectname = optarg;
                           break;
                 case 'F':                  case 'F':
                         Fflag = 1;                          Fflag = 1;
                         break;                          break;
                   case 'H':
                           tls_expecthash = optarg;
                           break;
                 case 'h':                  case 'h':
                         help();                          help();
                         break;                          break;
Line 180 
Line 216 
                         if (errstr)                          if (errstr)
                                 errx(1, "interval %s: %s", errstr, optarg);                                  errx(1, "interval %s: %s", errstr, optarg);
                         break;                          break;
                   case 'K':
                           Kflag = optarg;
                           break;
                 case 'k':                  case 'k':
                         kflag = 1;                          kflag = 1;
                         break;                          break;
Line 198 
Line 237 
                 case 'p':                  case 'p':
                         pflag = optarg;                          pflag = optarg;
                         break;                          break;
                   case 'R':
                           tls_cachanged = 1;
                           Rflag = optarg;
                           break;
                 case 'r':                  case 'r':
                         rflag = 1;                          rflag = 1;
                         break;                          break;
Line 256 
Line 299 
                         errno = 0;                          errno = 0;
                         if (map_tos(optarg, &Tflag))                          if (map_tos(optarg, &Tflag))
                                 break;                                  break;
                           if (map_tls(optarg, &TLSopt))
                                   break;
                         if (strlen(optarg) > 1 && optarg[0] == '0' &&                          if (strlen(optarg) > 1 && optarg[0] == '0' &&
                             optarg[1] == 'x')                              optarg[1] == 'x')
                                 Tflag = (int)strtol(optarg, NULL, 16);                                  Tflag = (int)strtol(optarg, NULL, 16);
Line 263 
Line 308 
                                 Tflag = (int)strtonum(optarg, 0, 255,                                  Tflag = (int)strtonum(optarg, 0, 255,
                                     &errstr);                                      &errstr);
                         if (Tflag < 0 || Tflag > 255 || errstr || errno)                          if (Tflag < 0 || Tflag > 255 || errstr || errno)
                                 errx(1, "illegal tos value %s", optarg);                                  errx(1, "illegal tos/tls value %s", optarg);
                         break;                          break;
                 default:                  default:
                         usage(1);                          usage(1);
Line 295 
Line 340 
                 errx(1, "cannot use -z and -l");                  errx(1, "cannot use -z and -l");
         if (!lflag && kflag)          if (!lflag && kflag)
                 errx(1, "must use -l with -k");                  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 (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 */          /* Get name of temporary socket for unix datagram client */
         if ((family == AF_UNIX) && uflag && !lflag) {          if ((family == AF_UNIX) && uflag && !lflag) {
Line 347 
Line 408 
                         proxyhints.ai_flags |= AI_NUMERICHOST;                          proxyhints.ai_flags |= AI_NUMERICHOST;
         }          }
   
           if (usetls) {
                   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 (Cflag && (tls_config_set_cert_file(tls_cfg, Cflag) == -1))
                           errx(1, "unable to set TLS certificate file %s", Cflag);
                   if (Kflag && (tls_config_set_key_file(tls_cfg, Kflag) == -1))
                           errx(1, "unable to set TLS key file %s", Kflag);
                   if (Rflag && (tls_config_set_ca_file(tls_cfg, Rflag) == -1))
                           errx(1, "unable to set root CA file %s", Rflag);
                   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) {          if (lflag) {
                   struct tls *tls_cctx = NULL;
                 int connfd;                  int connfd;
                 ret = 0;                  ret = 0;
   
Line 358 
Line 446 
                                 s = unix_listen(host);                                  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. */                  /* Allow only one connection at a time, but stay alive. */
                 for (;;) {                  for (;;) {
                         if (family != AF_UNIX)                          if (family != AF_UNIX)
Line 369 
Line 465 
                          * receive datagrams from multiple socket pairs.                           * receive datagrams from multiple socket pairs.
                          */                           */
                         if (uflag && kflag)                          if (uflag && kflag)
                                 readwrite(s);                                  readwrite(s, NULL);
                         /*                          /*
                          * For UDP and not -k, we will use recvfrom() initially                           * For UDP and not -k, we will use recvfrom() initially
                          * to wait for a caller, then use the regular functions                           * to wait for a caller, then use the regular functions
Line 394 
Line 490 
                                 if (vflag)                                  if (vflag)
                                         report_connect((struct sockaddr *)&z, len);                                          report_connect((struct sockaddr *)&z, len);
   
                                 readwrite(s);                                  readwrite(s, NULL);
                         } else {                          } else {
                                 len = sizeof(cliaddr);                                  len = sizeof(cliaddr);
                                 connfd = accept4(s, (struct sockaddr *)&cliaddr,                                  connfd = accept4(s, (struct sockaddr *)&cliaddr,
Line 405 
Line 501 
                                 }                                  }
                                 if (vflag)                                  if (vflag)
                                         report_connect((struct sockaddr *)&cliaddr, len);                                          report_connect((struct sockaddr *)&cliaddr, len);
                                   if ((usetls) &&
                                 readwrite(connfd);                                      (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);                                  close(connfd);
                         }                          }
   
                         if (family != AF_UNIX)                          if (family != AF_UNIX)
                                 close(s);                                  close(s);
                         else if (uflag) {                          else if (uflag) {
Line 424 
Line 532 
                 ret = 0;                  ret = 0;
   
                 if ((s = unix_connect(host)) > 0 && !zflag) {                  if ((s = unix_connect(host)) > 0 && !zflag) {
                         readwrite(s);                          readwrite(s, NULL);
                         close(s);                          close(s);
                 } else                  } else
                         ret = 1;                          ret = 1;
Line 444 
Line 552 
                         if (s)                          if (s)
                                 close(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)                          if (xflag)
                                 s = socks_connect(host, portlist[i], hints,                                  s = socks_connect(host, portlist[i], hints,
                                     proxyhost, proxyport, proxyhints, socksv,                                      proxyhost, proxyport, proxyhints, socksv,
Line 481 
Line 596 
                         }                          }
                         if (Fflag)                          if (Fflag)
                                 fdpass(s);                                  fdpass(s);
                         else if (!zflag)                          else {
                                 readwrite(s);                                  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)          if (s)
                 close(s);                  close(s);
   
           free(tls_peerhash);
           tls_config_free(tls_cfg);
   
         exit(ret);          exit(ret);
 }  }
   
Line 524 
Line 655 
         return (s);          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 (tls_peer_cert_hash(tls_ctx, &tls_peerhash) == -1)
                   errx(1, "hash of peer certificate failed");
           if (vflag)
                   report_tls(tls_ctx, host, tls_expectname);
           if (tls_expecthash && tls_peerhash &&
               strcmp(tls_expecthash, tls_peerhash) != 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 (gotcert && tls_peer_cert_hash(tls_cctx, &tls_peerhash) == -1)
                           warn("hash of peer certificate failed");
                   if (vflag && gotcert)
                           report_tls(tls_cctx, host, tls_expectname);
                   if ((TLSopt & TLS_CCERT) && !gotcert)
                           warnx("No client certificate provided");
                   else if (gotcert && tls_peerhash && tls_expecthash &&
                       strcmp(tls_expecthash, tls_peerhash) != 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()   * unix_connect()
  * Returns a socket connected to a local unix socket. Returns -1 on failure.   * Returns a socket connected to a local unix socket. Returns -1 on failure.
Line 731 
Line 923 
  * Loop that polls on the network file descriptor and stdin.   * Loop that polls on the network file descriptor and stdin.
  */   */
 void  void
 readwrite(int net_fd)  readwrite(int net_fd, struct tls *tls_ctx)
 {  {
         struct pollfd pfd[4];          struct pollfd pfd[4];
         int stdin_fd = STDIN_FILENO;          int stdin_fd = STDIN_FILENO;
Line 839 
Line 1031 
                 /* try to read from stdin */                  /* try to read from stdin */
                 if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {                  if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
                         ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,                          ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
                             &stdinbufpos);                              &stdinbufpos, NULL);
                         /* error or eof on stdin - remove from pfd */                          if (ret == TLS_WANT_POLLIN)
                         if (ret == 0 || ret == -1)                                  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;                                  pfd[POLL_STDIN].fd = -1;
                         /* read something - poll net out */                          /* read something - poll net out */
                         if (stdinbufpos > 0)                          if (stdinbufpos > 0)
Line 853 
Line 1048 
                 /* try to write to network */                  /* try to write to network */
                 if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {                  if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
                         ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,                          ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
                             &stdinbufpos);                              &stdinbufpos, tls_ctx);
                         if (ret == -1)                          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;                                  pfd[POLL_NETOUT].fd = -1;
                         /* buffer empty - remove self from polling */                          /* buffer empty - remove self from polling */
                         if (stdinbufpos == 0)                          if (stdinbufpos == 0)
Line 866 
Line 1065 
                 /* try to read from network */                  /* try to read from network */
                 if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {                  if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
                         ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,                          ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
                             &netinbufpos);                              &netinbufpos, tls_ctx);
                         if (ret == -1)                          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;                                  pfd[POLL_NETIN].fd = -1;
                         /* eof on net in - remove from pfd */                          /* eof on net in - remove from pfd */
                         if (ret == 0) {                          if (ret == 0) {
Line 888 
Line 1091 
                 /* try to write to stdout */                  /* try to write to stdout */
                 if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {                  if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
                         ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,                          ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
                             &netinbufpos);                              &netinbufpos, NULL);
                         if (ret == -1)                          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;                                  pfd[POLL_STDOUT].fd = -1;
                         /* buffer empty - remove self from polling */                          /* buffer empty - remove self from polling */
                         if (netinbufpos == 0)                          if (netinbufpos == 0)
Line 913 
Line 1120 
 }  }
   
 ssize_t  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 n;
         ssize_t adjust;          ssize_t adjust;
   
         n = write(fd, buf, *bufpos);          if (tls)
         /* don't treat EAGAIN, EINTR as error */                  n = tls_write(tls, buf, *bufpos);
         if (n == -1 && (errno == EAGAIN || errno == EINTR))          else {
                 n = -2;                  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)          if (n <= 0)
                 return n;                  return n;
         /* adjust buffer */          /* adjust buffer */
Line 934 
Line 1145 
   
   
 ssize_t  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;          size_t num = BUFSIZE - *bufpos;
         ssize_t n;          ssize_t n;
   
         n = read(fd, buf + *bufpos, num);          if (tls)
         /* don't treat EAGAIN, EINTR as error */                  n = tls_read(tls, buf + *bufpos, num);
         if (n == -1 && (errno == EAGAIN || errno == EINTR))          else {
                 n = -2;                  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)          if (n <= 0)
                 return n;                  return n;
         *bufpos += n;          *bufpos += n;
Line 1209 
Line 1424 
         return (0);          return (0);
 }  }
   
   int
   map_tls(char *s, int *val)
   {
           const struct tlskeywords {
                   const char      *keyword;
                   int              val;
           } *t, tlskeywords[] = {
                   { "tlslegacy",          TLS_LEGACY },
                   { "noverify",           TLS_NOVERIFY },
                   { "noname",             TLS_NONAME },
                   { "clientcert",         TLS_CCERT},
                   { NULL,                 -1 },
           };
   
           for (t = tlskeywords; t->keyword != NULL; t++) {
                   if (strcmp(s, t->keyword) == 0) {
                           *val |= t->val;
                           return (1);
                   }
           }
           return (0);
   }
   
 void  void
   report_tls(struct tls * tls_ctx, char * host, char *tls_expectname)
   {
           char *subject = NULL, *issuer = NULL;
           if (tls_peer_cert_subject(tls_ctx, &subject) == -1)
                   errx(1, "unable to get certificate subject");
           if (tls_peer_cert_issuer(tls_ctx, &issuer) == -1)
                   errx(1, "unable to get certificate issuer");
           fprintf(stderr, "TLS handshake completed with %s\n", host);
           fprintf(stderr, "Peer name %s\n",
               tls_expectname ? tls_expectname : host);
           if (subject)
                   fprintf(stderr, "Subject: %s\n", subject);
           if (issuer)
                   fprintf(stderr, "Issuer: %s\n", issuer);
           if (tls_peerhash)
                   fprintf(stderr, "Cert Hash: %s\n", tls_peerhash);
           free(subject);
           free(issuer);
   }
   void
 report_connect(const struct sockaddr *sa, socklen_t salen)  report_connect(const struct sockaddr *sa, socklen_t salen)
 {  {
         char remote_host[NI_MAXHOST];          char remote_host[NI_MAXHOST];
Line 1276 
Line 1534 
 usage(int ret)  usage(int ret)
 {  {
         fprintf(stderr,          fprintf(stderr,
             "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"              "usage: nc [-46cDdFhklNnrStUuvz] [-C certfile] [-e name] \n"
             "\t  [-P proxy_username] [-p source_port] [-s source] [-T toskeyword]\n"              "\t  [-I length] [-i interval] [-H hash] [-K keyfile] [-O length]\n"
             "\t  [-V rtable] [-w timeout] [-X proxy_protocol]\n"              "\t  [-P proxy_username] [-p source_port] [-R cafile] [-s source]\n"
             "\t  [-x proxy_address[:port]] [destination] [port]\n");              "\t  [-T tls|toskeyword] [-V rtable] [-w timeout]\n"
               "\t  [-X proxy_protocol] [-x proxy_address[:port]]\n"
               "\t  [destination] [port]\n");
         if (ret)          if (ret)
                 exit(1);                  exit(1);
 }  }

Legend:
Removed from v.1.132  
changed lines
  Added in v.1.133