From 3c5d789ee4348b60fae93ed13e9ec107943b2926 Mon Sep 17 00:00:00 2001 From: beck Date: Wed, 5 Apr 2017 03:20:19 +0000 Subject: [PATCH] Allow nc to save the peer certificate and chain in a pem file specified with -Z ok jsing@ --- usr.bin/nc/nc.1 | 9 +++++++-- usr.bin/nc/netcat.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/usr.bin/nc/nc.1 b/usr.bin/nc/nc.1 index b1f96488ab0..0f1263da7ce 100644 --- a/usr.bin/nc/nc.1 +++ b/usr.bin/nc/nc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nc.1,v 1.82 2017/02/09 20:15:59 jca Exp $ +.\" $OpenBSD: nc.1,v 1.83 2017/04/05 03:20:19 beck 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: April 5 2017 $ .Dt NC 1 .Os .Sh NAME @@ -53,6 +53,7 @@ .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 @@ -337,6 +338,10 @@ should just scan for listening daemons, without sending any data to them. It is an error to use this option in conjunction with the .Fl l option. +.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. .El .Pp .Ar destination diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c index e222e1e7311..74074aa9387 100644 --- a/usr.bin/nc/netcat.c +++ b/usr.bin/nc/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.178 2017/03/09 13:58:00 bluhm Exp $ */ +/* $OpenBSD: netcat.c,v 1.179 2017/04/05 03:20:19 beck Exp $ */ /* * Copyright (c) 2001 Eric Jackson * Copyright (c) 2015 Bob Beck. All rights reserved. @@ -106,6 +106,7 @@ 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 timeout = -1; int family = AF_UNSPEC; @@ -132,6 +133,7 @@ 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 usage(int); @@ -165,7 +167,7 @@ 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:X:x:Z:z")) != -1) { switch (ch) { case '4': family = AF_INET; @@ -279,6 +281,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; @@ -385,6 +393,8 @@ main(int argc, char *argv[]) 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) @@ -766,6 +776,11 @@ tls_setup_client(struct tls *tls_ctx, int s, char *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 * @@ -1548,6 +1563,21 @@ map_tls(char *s, int *val) return (0); } +void +save_peer_cert(struct tls *tls_ctx, FILE *fp) +{ + const char *pem; + size_t plen; + FILE *out; + + if ((pem = tls_peer_cert_chain_pem(tls_ctx, &plen)) == NULL) + errx(1, "Can't get peer certificate"); + if (fprintf(fp, "%.*s", 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, char *tls_expectname) { -- 2.20.1