On Sat, Sep 05, 2015 at 01:00:54PM -0600, Bob Beck wrote:
> OK to put it in and have others turdshine along?
I think some things should be fixed before.
$ mandoc -Tlint nc.1
mandoc: nc.1:105:64: WARNING: whitespace at end of input line
mandoc: nc.1:188:69: WARNING: whitespace at end of input line
mandoc: nc.1:190:17: WARNING: whitespace at end of input line
mandoc: nc.1:210:16: WARNING: whitespace at end of input line
mandoc: nc.1:212:14: WARNING: whitespace at end of input line
$ WARNINGS=yes make
cc -O2 -pipe -Wall -Wpointer-arith -Wuninitialized -Wstrict-prototypes
-Wmissing-prototypes -Wunused -Wsign-compare -Wshadow
-Wdeclaration-after-statement -c netcat.c
netcat.c: In function 'main':
netcat.c:593: warning: declaration of 'i' shadows a previous local
netcat.c:534: warning: shadowed declaration is here
re-wrap the long lines
> @@ -98,6 +98,11 @@ to use IPv4 addresses only.
> Forces
> .Nm
> to use IPv6 addresses only.
> +.It Fl c
> +If using a tcp socket to connect or listen, use TLS. Illegal if not using
> TCP sockets.
> +.It Fl C Ar certificate_filename
> +Specifies the filename from which the public part of the TLS
> +certificate is loaded, in pem format. Illegal if not using TLS.
> .It Fl D
> Enable debugging on the socket.
> .It Fl d
C should be before c
> @@ -132,6 +137,9 @@ Forces
> to stay listening for another connection after its current connection
> is completed.
> It is an error to use this option without the
> +.It Fl K Ar key_filename
> +Specifies the filename from which the private key for the TLS certificate
> +is loaded in pem format. Illegal if not using TLS.
> .Fl l
> option.
> When used together with the
This flag is in the middle of another.
> @@ -176,6 +184,11 @@ option.
> Specifies that source and/or destination ports should be chosen randomly
> instead of sequentially within a range or in the order that the system
> assigns them.
> +.It Fl R Ar CA_filename
> +Specifies the filename from which the root CA bundle for Certificate
> +verification is loaded in pem format. Illegal if not using TLS.
> +Default value is
> +.Pa /etc/ssl/cert.pem .
> .It Fl S
> Enables the RFC 2385 TCP MD5 signature option.
> .It Fl s Ar source
R should be before r
> @@ -95,6 +102,13 @@ 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 cachanged; /* Using non-default CA file */
> +int TLSopt; /* TLS options */
Don't mix tab and spaces after the type.
> @@ -145,7 +162,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) {
> + "46DcC:dFhI:i:kK:lNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
Upper case before lower case.
The R is missing.
> @@ -183,6 +203,9 @@ main(int argc, char *argv[])
> case 'k':
> kflag = 1;
> break;
> + case 'K':
> + Kflag = optarg;
> + break;
Upper case before lower case.
> @@ -195,12 +218,19 @@ main(int argc, char *argv[])
> case 'P':
> Pflag = optarg;
> break;
> + case 'C':
> + Cflag = optarg;
> + break;
Move the C up.
> case 'p':
> pflag = optarg;
> break;
> case 'r':
> rflag = 1;
> break;
> + case 'R':
> + cachanged = 1;
> + Rflag = optarg;
> + break;
Upper case before lower case.
Keeping the same order everywhere is important to check that all
list are equal.
> @@ -347,6 +391,25 @@ main(int argc, char *argv[])
> proxyhints.ai_flags |= AI_NUMERICHOST;
> }
>
> + if (usetls) {
> + if (tls_init() == -1)
> + errx(1, "unable to initialize tls");
> + if ((tlsc = tls_config_new()) == NULL)
> + errx(1, "unable allocate tls config");
> + if (Cflag && (tls_config_set_cert_file(tlsc, Cflag) == -1))
> + errx(1, "unable to set TLS certificate file %s", Cflag);
> + if (Kflag && (tls_config_set_key_file(tlsc, Kflag) == -1))
> + errx(1, "unable to set TLS key file %s", Kflag);
When you set Rflag here to DEFAULT_CA_FILE if it is NULL, you can
get rid of the additional variable cachanged.
> + if (Rflag && (tls_config_set_ca_file(tlsc, Rflag) == -1))
> + errx(1, "unable to set Root CA file %s", Rflag);
> @@ -405,11 +469,44 @@ main(int argc, char *argv[])
> }
> if (vflag)
> report_connect((struct sockaddr
> *)&cliaddr, len);
> -
> - readwrite(connfd);
> + if (usetls) {
> + int i;
> + if ((ctx = tls_server()) == NULL)
> + errx(1, "tls client creation
> failed");
> + if (tls_configure(ctx, tlsc) == -1)
> + errx(1, "tls configuration
> failed (%s)",
> + tls_error(ctx));
> + do {
> + i = tls_accept_socket(ctx,
> &cctx, connfd);
> + if (i == -1) {
> + warn ("tls connection
> failed (%s)",
> + tls_error(ctx));
> + cctx = NULL;
You may leak an allocated cctx here. I think you have to free it.
I don't like this part of tls_accept_socket(), it should be changed
there. tls_accept_socket() should take a context created before.
> + }
> + } while (i == TLS_READ_AGAIN || i ==
> TLS_WRITE_AGAIN);
> + }
> + if (usetls && cctx)
> + readwrite(connfd, cctx);
> + if (!usetls)
> + readwrite(connfd, NULL);
> + if (ctx) {
> + int i;
> + do {
> + i = tls_close(ctx);
> + } while (i == TLS_READ_AGAIN || i ==
> TLS_WRITE_AGAIN);
> + tls_free(ctx);
> + ctx = NULL;
> + }
> + if (cctx) {
> + int i;
> + do {
> + i = tls_close(cctx);
> + } while (i == TLS_READ_AGAIN || i ==
> TLS_WRITE_AGAIN);
> + tls_free(cctx);
> + cctx = NULL;
> + }
> close(connfd);
This is a double close, tls_close() should not close(2) the fd.
> @@ -772,6 +889,7 @@ readwrite(int net_fd)
> pfd[POLL_STDOUT].fd = stdout_fd;
> pfd[POLL_STDOUT].events = 0;
>
> +
> while (1) {
> /* both inputs are gone, buffers are empty, we are done */
> if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
Useless chunk.
> @@ -922,17 +1040,27 @@ 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)
Call all struct tls pointer ctx for consistency.
> {
> ssize_t n;
> ssize_t adjust;
> + size_t t;
>
> - n = write(fd, buf, *bufpos);
> - /* don't treat EAGAIN, EINTR as error */
> - if (n == -1 && (errno == EAGAIN || errno == EINTR))
> - n = -2;
> - if (n <= 0)
> - return n;
> + if (tls) {
> + n = tls_write(tls, buf, *bufpos, &t);
> + if (n == TLS_READ_AGAIN || n == TLS_WRITE_AGAIN)
> + n = -2;
This does not set the poll(2) read/write flags correctly.
> + if (n < 0)
> + return n;
> + n = t;
Return 0 if t is 0 to avoid the adjust buffer code below. I would
recommend that the n returned by tls_write() works like the n from
write(2) to make this consistent. It should be ssize_t and contain
the length.
> + } else {
> + n = write(fd, buf, *bufpos);
> + /* don't treat EAGAIN, EINTR as error */
> + if (n == -1 && (errno == EAGAIN || errno == EINTR))
> + n = -2;
> + if (n <= 0)
> + return n;
> + }
> /* adjust buffer */
> adjust = *bufpos - n;
> if (adjust > 0)