From: beck Date: Wed, 5 Apr 2017 03:19:22 +0000 (+0000) Subject: Add tls_peer_cert_chain_pem - To retreive the peer certificate and chain X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c67861f722ec9aaffcb1fbbacbe7d9d49ada2c73;p=openbsd Add tls_peer_cert_chain_pem - To retreive the peer certificate and chain as PEM format. This allows for it to be used or examined with tools external to libtls bump minor ok jsing@ --- diff --git a/lib/libtls/Symbols.list b/lib/libtls/Symbols.list index 98465dde273..248784a4887 100644 --- a/lib/libtls/Symbols.list +++ b/lib/libtls/Symbols.list @@ -60,6 +60,7 @@ tls_handshake tls_init tls_load_file tls_ocsp_process_response +tls_peer_cert_chain_pem tls_peer_cert_contains_name tls_peer_cert_hash tls_peer_cert_issuer diff --git a/lib/libtls/shlib_version b/lib/libtls/shlib_version index 4c073ef03c9..f0f244c56ae 100644 --- a/lib/libtls/shlib_version +++ b/lib/libtls/shlib_version @@ -1,2 +1,2 @@ major=15 -minor=4 +minor=5 diff --git a/lib/libtls/tls.c b/lib/libtls/tls.c index 419554818c3..446f93430d7 100644 --- a/lib/libtls/tls.c +++ b/lib/libtls/tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.c,v 1.60 2017/04/05 03:13:53 beck Exp $ */ +/* $OpenBSD: tls.c,v 1.61 2017/04/05 03:19:22 beck Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -528,6 +528,8 @@ tls_reset(struct tls *ctx) ctx->ssl_conn = NULL; ctx->ssl_ctx = NULL; ctx->ssl_peer_cert = NULL; + /* X509 objects in chain are freed with the SSL */ + ctx->ssl_peer_chain = NULL; ctx->socket = -1; ctx->state = 0; @@ -625,6 +627,7 @@ tls_handshake(struct tls *ctx) if (rv == 0) { ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn); + ctx->ssl_peer_chain = SSL_get_peer_cert_chain(ctx->ssl_conn); if (tls_conninfo_populate(ctx) == -1) rv = -1; if (ctx->ocsp == NULL) diff --git a/lib/libtls/tls.h b/lib/libtls/tls.h index d9b2972e92a..c9da8aa06e6 100644 --- a/lib/libtls/tls.h +++ b/lib/libtls/tls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.h,v 1.47 2017/01/31 16:18:57 beck Exp $ */ +/* $OpenBSD: tls.h,v 1.48 2017/04/05 03:19:22 beck Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -179,6 +179,7 @@ const char *tls_peer_cert_issuer(struct tls *_ctx); const char *tls_peer_cert_subject(struct tls *_ctx); time_t tls_peer_cert_notbefore(struct tls *_ctx); time_t tls_peer_cert_notafter(struct tls *_ctx); +const uint8_t *tls_peer_cert_chain_pem(struct tls *_ctx, size_t *_len); const char *tls_conn_alpn_selected(struct tls *_ctx); const char *tls_conn_cipher(struct tls *_ctx); diff --git a/lib/libtls/tls_conninfo.c b/lib/libtls/tls_conninfo.c index c4d23c308b5..87660fa9899 100644 --- a/lib/libtls/tls_conninfo.c +++ b/lib/libtls/tls_conninfo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_conninfo.c,v 1.14 2017/04/05 03:13:53 beck Exp $ */ +/* $OpenBSD: tls_conninfo.c,v 1.15 2017/04/05 03:19:22 beck Exp $ */ /* * Copyright (c) 2015 Joel Sing * Copyright (c) 2015 Bob Beck @@ -174,6 +174,49 @@ tls_conninfo_alpn_proto(struct tls *ctx) return (0); } +static int +tls_conninfo_cert_pem(struct tls *ctx) +{ + int i, rv = -1; + BIO *membio = NULL; + BUF_MEM *bptr = NULL; + + if (ctx->conninfo == NULL) + goto err; + if (ctx->ssl_peer_cert == NULL) + return 0; + if ((membio = BIO_new(BIO_s_mem()))== NULL) + goto err; + + /* + * We have to write the peer cert out separately, because + * the certificate chain may or may not contain it. + */ + if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert)) + goto err; + for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) { + X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i); + if (chaincert != ctx->ssl_peer_cert && + !PEM_write_bio_X509(membio, chaincert)) + goto err; + } + + BIO_get_mem_ptr(membio, &bptr); + free(ctx->conninfo->peer_cert); + ctx->conninfo->peer_cert_len = 0; + if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL) + goto err; + ctx->conninfo->peer_cert_len = bptr->length; + memcpy(ctx->conninfo->peer_cert, bptr->data, + ctx->conninfo->peer_cert_len); + + /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */ + rv = 0; + err: + BIO_free(membio); + return rv; +} + int tls_conninfo_populate(struct tls *ctx) { @@ -210,6 +253,9 @@ tls_conninfo_populate(struct tls *ctx) if (tls_get_peer_cert_info(ctx) == -1) goto err; + if (tls_conninfo_cert_pem(ctx) == -1) + goto err; + return (0); err: @@ -241,6 +287,10 @@ tls_conninfo_free(struct tls_conninfo *conninfo) free(conninfo->subject); conninfo->subject = NULL; + free(conninfo->peer_cert); + conninfo->peer_cert = NULL; + conninfo->peer_cert_len = 0; + free(conninfo); } diff --git a/lib/libtls/tls_internal.h b/lib/libtls/tls_internal.h index b1d53c8fa30..5bbcadf8043 100644 --- a/lib/libtls/tls_internal.h +++ b/lib/libtls/tls_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_internal.h,v 1.54 2017/04/05 03:13:53 beck Exp $ */ +/* $OpenBSD: tls_internal.h,v 1.55 2017/04/05 03:19:22 beck Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas * Copyright (c) 2014 Joel Sing @@ -110,6 +110,9 @@ struct tls_conninfo { char *issuer; char *subject; + u_int8_t *peer_cert; + size_t peer_cert_len; + time_t notbefore; time_t notafter; }; @@ -166,6 +169,7 @@ struct tls { struct tls_sni_ctx *sni_ctx; X509 *ssl_peer_cert; + STACK_OF(X509) *ssl_peer_chain; struct tls_conninfo *conninfo; @@ -237,6 +241,7 @@ struct tls_ocsp *tls_ocsp_setup_from_peer(struct tls *ctx); int tls_hex_string(const unsigned char *_in, size_t _inlen, char **_out, size_t *_outlen); int tls_cert_hash(X509 *_cert, char **_hash); +void tls_config_skip_private_key_check(struct tls_config *config); __END_HIDDEN_DECLS diff --git a/lib/libtls/tls_peer.c b/lib/libtls/tls_peer.c index 802a9c2780d..1a9065dfb1a 100644 --- a/lib/libtls/tls_peer.c +++ b/lib/libtls/tls_peer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_peer.c,v 1.6 2016/08/22 17:08:10 jsing Exp $ */ +/* $OpenBSD: tls_peer.c,v 1.7 2017/04/05 03:19:22 beck Exp $ */ /* * Copyright (c) 2015 Joel Sing * Copyright (c) 2015 Bob Beck @@ -81,3 +81,14 @@ tls_peer_cert_notafter(struct tls *ctx) return (ctx->conninfo->notafter); } +const uint8_t * +tls_peer_cert_chain_pem(struct tls *ctx, size_t *size) +{ + if (ctx->ssl_peer_cert == NULL) + return (NULL); + if (ctx->conninfo == NULL) + return (NULL); + *size = ctx->conninfo->peer_cert_len; + return (ctx->conninfo->peer_cert); +} +