From 869b2e79c9ff30e6144dddc6562522a90c73bb14 Mon Sep 17 00:00:00 2001
From: beck <>
Date: Wed, 9 Sep 2015 19:23:04 +0000
Subject: Add client certificate support. Still needs a few tweaks but this
 will ride upcoming minor bump ok jsing@

---
 src/lib/libtls/tls.c          | 42 ++++++++++++++++++++++++++++++++++++++++--
 src/lib/libtls/tls.h          |  5 ++++-
 src/lib/libtls/tls_client.c   | 32 ++++++--------------------------
 src/lib/libtls/tls_config.c   | 14 +++++++++++++-
 src/lib/libtls/tls_internal.h |  6 ++++--
 src/lib/libtls/tls_server.c   | 11 +++++++++--
 6 files changed, 76 insertions(+), 34 deletions(-)

(limited to 'src')

diff --git a/src/lib/libtls/tls.c b/src/lib/libtls/tls.c
index db14d3fc7d..0c4793cc9a 100644
--- a/src/lib/libtls/tls.c
+++ b/src/lib/libtls/tls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls.c,v 1.17 2015/09/09 18:22:33 beck Exp $ */
+/* $OpenBSD: tls.c,v 1.18 2015/09/09 19:23:04 beck Exp $ */
 /*
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
  *
@@ -147,12 +147,19 @@ tls_configure(struct tls *ctx, struct tls_config *config)
 }
 
 int
-tls_configure_keypair(struct tls *ctx)
+tls_configure_keypair(struct tls *ctx, int required)
 {
 	EVP_PKEY *pkey = NULL;
 	X509 *cert = NULL;
 	BIO *bio = NULL;
 
+	if (!required &&
+	    ctx->config->cert_mem == NULL &&
+	    ctx->config->key_mem == NULL &&
+	    ctx->config->cert_file == NULL &&
+	    ctx->config->key_file == NULL)
+		return(0);
+
 	if (ctx->config->cert_mem != NULL) {
 		if (ctx->config->cert_len > INT_MAX) {
 			tls_set_errorx(ctx, "certificate too long");
@@ -256,6 +263,37 @@ err:
 	return (-1);
 }
 
+int
+tls_configure_ssl_verify(struct tls *ctx, int verify)
+{
+	SSL_CTX_set_verify(ctx->ssl_ctx, verify, NULL);
+
+	if (ctx->config->ca_mem != NULL) {
+		/* XXX do this in set. */
+		if (ctx->config->ca_len > INT_MAX) {
+			tls_set_error(ctx, "client ca too long");
+			goto err;
+		}
+		if (SSL_CTX_load_verify_mem(ctx->ssl_ctx,
+		    ctx->config->ca_mem, ctx->config->ca_len) != 1) {
+			tls_set_error(ctx,
+			    "ssl verify memory setup failure");
+			goto err;
+		}
+	} else if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
+            ctx->config->ca_file, ctx->config->ca_path) != 1) {
+		tls_set_error(ctx, "ssl verify setup failure");
+		goto err;
+	}
+	if (ctx->config->verify_depth >= 0)
+		SSL_CTX_set_verify_depth(ctx->ssl_ctx,
+		    ctx->config->verify_depth);
+	return (0);
+
+ err:
+	return (-1);
+}
+
 void
 tls_free(struct tls *ctx)
 {
diff --git a/src/lib/libtls/tls.h b/src/lib/libtls/tls.h
index cb02ee8824..1a6257232c 100644
--- a/src/lib/libtls/tls.h
+++ b/src/lib/libtls/tls.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls.h,v 1.13 2015/06/19 06:20:11 bcook Exp $ */
+/* $OpenBSD: tls.h,v 1.14 2015/09/09 19:23:04 beck Exp $ */
 /*
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
  *
@@ -73,6 +73,9 @@ void tls_config_insecure_noverifycert(struct tls_config *_config);
 void tls_config_insecure_noverifyname(struct tls_config *_config);
 void tls_config_verify(struct tls_config *_config);
 
+void tls_config_verify_client(struct tls_config *_config);
+void tls_config_verify_client_optional(struct tls_config *_config);
+
 struct tls *tls_client(void);
 struct tls *tls_server(void);
 int tls_configure(struct tls *_ctx, struct tls_config *_config);
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c
index 81b5510431..056526ddc3 100644
--- a/src/lib/libtls/tls_client.c
+++ b/src/lib/libtls/tls_client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_client.c,v 1.23 2015/09/09 14:32:06 jsing Exp $ */
+/* $OpenBSD: tls_client.c,v 1.24 2015/09/09 19:23:04 beck Exp $ */
 /*
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
  *
@@ -21,7 +21,6 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-#include <limits.h>
 #include <netdb.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -190,6 +189,8 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
 
 	if (tls_configure_ssl(ctx) != 0)
 		goto err;
+	if (tls_configure_keypair(ctx, 0) != 0)
+		goto err;
 
 	if (ctx->config->verify_name) {
 		if (servername == NULL) {
@@ -198,30 +199,9 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
 		}
 	}
 
-	if (ctx->config->verify_cert) {
-		SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
-
-		if (ctx->config->ca_mem != NULL) {
-			if (ctx->config->ca_len > INT_MAX) {
-				tls_set_errorx(ctx, "ca too long");
-				goto err;
-			}
-
-			if (SSL_CTX_load_verify_mem(ctx->ssl_ctx,
-			    ctx->config->ca_mem, ctx->config->ca_len) != 1) {
-				tls_set_errorx(ctx,
-				    "ssl verify memory setup failure");
-				goto err;
-			}
-		} else if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
-		    ctx->config->ca_file, ctx->config->ca_path) != 1) {
-			tls_set_errorx(ctx, "ssl verify setup failure");
-			goto err;
-		}
-		if (ctx->config->verify_depth >= 0)
-			SSL_CTX_set_verify_depth(ctx->ssl_ctx,
-			    ctx->config->verify_depth);
-	}
+	if (ctx->config->verify_cert &&
+	    (tls_configure_ssl_verify(ctx, SSL_VERIFY_PEER) == -1))
+		goto err;
 
 	if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
 		tls_set_errorx(ctx, "ssl connection failure");
diff --git a/src/lib/libtls/tls_config.c b/src/lib/libtls/tls_config.c
index 4c25a79303..73073d8ff7 100644
--- a/src/lib/libtls/tls_config.c
+++ b/src/lib/libtls/tls_config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_config.c,v 1.9 2015/02/22 15:09:54 jsing Exp $ */
+/* $OpenBSD: tls_config.c,v 1.10 2015/09/09 19:23:04 beck Exp $ */
 /*
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
  *
@@ -300,3 +300,15 @@ tls_config_verify(struct tls_config *config)
 	config->verify_cert = 1;
 	config->verify_name = 1;
 }
+
+void
+tls_config_verify_client(struct tls_config *config)
+{
+	config->verify_client = 1;
+}
+
+void
+tls_config_verify_client_optional(struct tls_config *config)
+{
+	config->verify_client = 2;
+}
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h
index d767c37494..58834c999f 100644
--- a/src/lib/libtls/tls_internal.h
+++ b/src/lib/libtls/tls_internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_internal.h,v 1.15 2015/09/08 15:29:34 jsing Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.16 2015/09/09 19:23:04 beck Exp $ */
 /*
  * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -42,6 +42,7 @@ struct tls_config {
 	size_t key_len;
 	uint32_t protocols;
 	int verify_cert;
+	int verify_client;
 	int verify_depth;
 	int verify_name;
 };
@@ -70,9 +71,10 @@ struct tls *tls_new(void);
 struct tls *tls_server_conn(struct tls *ctx);
 
 int tls_check_servername(struct tls *ctx, X509 *cert, const char *servername);
-int tls_configure_keypair(struct tls *ctx);
+int tls_configure_keypair(struct tls *ctx, int);
 int tls_configure_server(struct tls *ctx);
 int tls_configure_ssl(struct tls *ctx);
+int tls_configure_ssl_verify(struct tls *ctx, int verify);
 int tls_host_port(const char *hostport, char **host, char **port);
 int tls_set_error(struct tls *ctx, const char *fmt, ...)
     __attribute__((__format__ (printf, 2, 3)))
diff --git a/src/lib/libtls/tls_server.c b/src/lib/libtls/tls_server.c
index 190682e630..6f8daa0aca 100644
--- a/src/lib/libtls/tls_server.c
+++ b/src/lib/libtls/tls_server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_server.c,v 1.11 2015/09/09 14:32:06 jsing Exp $ */
+/* $OpenBSD: tls_server.c,v 1.12 2015/09/09 19:23:04 beck Exp $ */
 /*
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
  *
@@ -60,8 +60,15 @@ tls_configure_server(struct tls *ctx)
 
 	if (tls_configure_ssl(ctx) != 0)
 		goto err;
-	if (tls_configure_keypair(ctx) != 0)
+	if (tls_configure_keypair(ctx, 1) != 0)
 		goto err;
+	if (ctx->config->verify_client != 0) {
+		int verify = SSL_VERIFY_PEER;
+		if (ctx->config->verify_client == 1)
+			verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+		if (tls_configure_ssl_verify(ctx, verify) == -1)
+			goto err;
+	}
 
 	if (ctx->config->dheparams == -1)
 		SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1);
-- 
cgit v1.2.3-55-g6feb