Add tls_peer_cert_chain_pem - To retreive the peer certificate and chain
authorbeck <beck@openbsd.org>
Wed, 5 Apr 2017 03:19:22 +0000 (03:19 +0000)
committerbeck <beck@openbsd.org>
Wed, 5 Apr 2017 03:19:22 +0000 (03:19 +0000)
as PEM format. This allows for it to be used or examined with tools
external to libtls
bump minor
ok jsing@

lib/libtls/Symbols.list
lib/libtls/shlib_version
lib/libtls/tls.c
lib/libtls/tls.h
lib/libtls/tls_conninfo.c
lib/libtls/tls_internal.h
lib/libtls/tls_peer.c

index 98465dd..248784a 100644 (file)
@@ -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
index 4c073ef..f0f244c 100644 (file)
@@ -1,2 +1,2 @@
 major=15
-minor=4
+minor=5
index 4195548..446f934 100644 (file)
@@ -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 <jsing@openbsd.org>
  *
@@ -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)
index d9b2972..c9da8aa 100644 (file)
@@ -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 <jsing@openbsd.org>
  *
@@ -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);
index c4d23c3..87660fa 100644 (file)
@@ -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 <jsing@openbsd.org>
  * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
@@ -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);
 }
 
index b1d53c8..5bbcadf 100644 (file)
@@ -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 <jca@openbsd.org>
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -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
 
index 802a9c2..1a9065d 100644 (file)
@@ -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 <jsing@openbsd.org>
  * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
@@ -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);
+}
+