summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2016-08-22 14:51:37 +0000
committerjsing <>2016-08-22 14:51:37 +0000
commit74ebdd842595c2d6c66a0aa102dc5c4b98412c8d (patch)
treee04823f4dbd54041cadc277b3cfa2714bd318c36 /src/lib
parent60132b75420595a9684003b199d3299fe13ec457 (diff)
downloadopenbsd-74ebdd842595c2d6c66a0aa102dc5c4b98412c8d.tar.gz
openbsd-74ebdd842595c2d6c66a0aa102dc5c4b98412c8d.tar.bz2
openbsd-74ebdd842595c2d6c66a0aa102dc5c4b98412c8d.zip
Create contexts for server side SNI - these include the additional SSL_CTX
that is required for certificate switching with libssl and the certificate itself so that we can match against the subject and SANs. Hook up the servername callback and switch to the appropriate SSL_CTX if we find a matching certificate. ok beck@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libtls/tls.c28
-rw-r--r--src/lib/libtls/tls_internal.h15
-rw-r--r--src/lib/libtls/tls_server.c134
3 files changed, 174 insertions, 3 deletions
diff --git a/src/lib/libtls/tls.c b/src/lib/libtls/tls.c
index bf0e1f769f..df610fe238 100644
--- a/src/lib/libtls/tls.c
+++ b/src/lib/libtls/tls.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls.c,v 1.46 2016/08/15 14:04:23 jsing Exp $ */ 1/* $OpenBSD: tls.c,v 1.47 2016/08/22 14:51:37 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -177,6 +177,24 @@ tls_set_errorx(struct tls *ctx, const char *fmt, ...)
177 return (rv); 177 return (rv);
178} 178}
179 179
180struct tls_sni_ctx *
181tls_sni_ctx_new(void)
182{
183 return (calloc(1, sizeof(struct tls_sni_ctx)));
184}
185
186void
187tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx)
188{
189 if (sni_ctx == NULL)
190 return;
191
192 SSL_CTX_free(sni_ctx->ssl_ctx);
193 X509_free(sni_ctx->ssl_cert);
194
195 free(sni_ctx);
196}
197
180struct tls * 198struct tls *
181tls_new(void) 199tls_new(void)
182{ 200{
@@ -376,6 +394,8 @@ tls_free(struct tls *ctx)
376void 394void
377tls_reset(struct tls *ctx) 395tls_reset(struct tls *ctx)
378{ 396{
397 struct tls_sni_ctx *sni, *nsni;
398
379 SSL_CTX_free(ctx->ssl_ctx); 399 SSL_CTX_free(ctx->ssl_ctx);
380 SSL_free(ctx->ssl_conn); 400 SSL_free(ctx->ssl_conn);
381 X509_free(ctx->ssl_peer_cert); 401 X509_free(ctx->ssl_peer_cert);
@@ -397,6 +417,12 @@ tls_reset(struct tls *ctx)
397 tls_free_conninfo(ctx->conninfo); 417 tls_free_conninfo(ctx->conninfo);
398 free(ctx->conninfo); 418 free(ctx->conninfo);
399 ctx->conninfo = NULL; 419 ctx->conninfo = NULL;
420
421 for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) {
422 nsni = sni->next;
423 tls_sni_ctx_free(sni);
424 }
425 ctx->sni_ctx = NULL;
400} 426}
401 427
402int 428int
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h
index bbd231e00e..428e29c857 100644
--- a/src/lib/libtls/tls_internal.h
+++ b/src/lib/libtls/tls_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_internal.h,v 1.39 2016/08/15 15:44:58 jsing Exp $ */ 1/* $OpenBSD: tls_internal.h,v 1.40 2016/08/22 14:51:37 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> 3 * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
4 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 4 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -91,6 +91,13 @@ struct tls_conninfo {
91#define TLS_EOF_NO_CLOSE_NOTIFY (1 << 0) 91#define TLS_EOF_NO_CLOSE_NOTIFY (1 << 0)
92#define TLS_HANDSHAKE_COMPLETE (1 << 1) 92#define TLS_HANDSHAKE_COMPLETE (1 << 1)
93 93
94struct tls_sni_ctx {
95 struct tls_sni_ctx *next;
96
97 SSL_CTX *ssl_ctx;
98 X509 *ssl_cert;
99};
100
94struct tls { 101struct tls {
95 struct tls_config *config; 102 struct tls_config *config;
96 struct tls_error error; 103 struct tls_error error;
@@ -103,11 +110,17 @@ struct tls {
103 110
104 SSL *ssl_conn; 111 SSL *ssl_conn;
105 SSL_CTX *ssl_ctx; 112 SSL_CTX *ssl_ctx;
113
114 struct tls_sni_ctx *sni_ctx;
115
106 X509 *ssl_peer_cert; 116 X509 *ssl_peer_cert;
107 117
108 struct tls_conninfo *conninfo; 118 struct tls_conninfo *conninfo;
109}; 119};
110 120
121struct tls_sni_ctx *tls_sni_ctx_new(void);
122void tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx);
123
111struct tls *tls_new(void); 124struct tls *tls_new(void);
112struct tls *tls_server_conn(struct tls *ctx); 125struct tls *tls_server_conn(struct tls *ctx);
113 126
diff --git a/src/lib/libtls/tls_server.c b/src/lib/libtls/tls_server.c
index 40096ae99f..044678c705 100644
--- a/src/lib/libtls/tls_server.c
+++ b/src/lib/libtls/tls_server.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_server.c,v 1.24 2016/08/18 15:52:03 jsing Exp $ */ 1/* $OpenBSD: tls_server.c,v 1.25 2016/08/22 14:51:37 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -15,6 +15,10 @@
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */ 16 */
17 17
18#include <sys/socket.h>
19
20#include <arpa/inet.h>
21
18#include <openssl/ec.h> 22#include <openssl/ec.h>
19#include <openssl/err.h> 23#include <openssl/err.h>
20#include <openssl/ssl.h> 24#include <openssl/ssl.h>
@@ -63,6 +67,92 @@ tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
63} 67}
64 68
65static int 69static int
70tls_servername_cb(SSL *ssl, int *al, void *arg)
71{
72 struct tls *ctx = (struct tls *)arg;
73 struct tls_sni_ctx *sni_ctx;
74 union tls_addr addrbuf;
75 struct tls *conn_ctx;
76 const char *name;
77
78 if ((conn_ctx = SSL_get_app_data(ssl)) == NULL)
79 goto err;
80
81 if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) == NULL) {
82 /*
83 * The servername callback gets called even when there is no
84 * TLS servername extension provided by the client. Sigh!
85 */
86 return (SSL_TLSEXT_ERR_NOACK);
87 }
88
89 /* Per RFC 6066 section 3: ensure that name is not an IP literal. */
90 if (inet_pton(AF_INET, name, &addrbuf) == 1 ||
91 inet_pton(AF_INET6, name, &addrbuf) == 1)
92 goto err;
93
94 free((char *)conn_ctx->servername);
95 if ((conn_ctx->servername = strdup(name)) == NULL)
96 goto err;
97
98 /* Find appropriate SSL context for requested servername. */
99 for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) {
100 if (tls_check_name(ctx, sni_ctx->ssl_cert, name) == 0) {
101 SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx);
102 return (SSL_TLSEXT_ERR_OK);
103 }
104 }
105
106 /* No match, use the existing context/certificate. */
107 return (SSL_TLSEXT_ERR_OK);
108
109 err:
110 /*
111 * There is no way to tell libssl that an internal failure occurred.
112 * The only option we have is to return a fatal alert.
113 */
114 *al = TLS1_AD_INTERNAL_ERROR;
115 return (SSL_TLSEXT_ERR_ALERT_FATAL);
116}
117
118static int
119tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error,
120 X509 **cert)
121{
122 char *errstr = "unknown";
123 BIO *cert_bio = NULL;
124 int ssl_err;
125
126 X509_free(*cert);
127 *cert = NULL;
128
129 if (keypair->cert_mem == NULL) {
130 tls_error_set(error, "keypair has no certificate");
131 goto err;
132 }
133 if ((cert_bio = BIO_new_mem_buf(keypair->cert_mem,
134 keypair->cert_len)) == NULL) {
135 tls_error_set(error, "failed to create certificate bio");
136 goto err;
137 }
138 if ((*cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL)) == NULL) {
139 if ((ssl_err = ERR_peek_error()) != 0)
140 errstr = ERR_error_string(ssl_err, NULL);
141 tls_error_set(error, "failed to load certificate: %s", errstr);
142 goto err;
143 }
144
145 BIO_free(cert_bio);
146
147 return (0);
148
149 err:
150 BIO_free(cert_bio);
151
152 return (-1);
153}
154
155static int
66tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, 156tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx,
67 struct tls_keypair *keypair) 157 struct tls_keypair *keypair)
68{ 158{
@@ -76,6 +166,16 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx,
76 goto err; 166 goto err;
77 } 167 }
78 168
169 if (SSL_CTX_set_tlsext_servername_callback(*ssl_ctx,
170 tls_servername_cb) != 1) {
171 tls_set_error(ctx, "failed to set servername callback");
172 goto err;
173 }
174 if (SSL_CTX_set_tlsext_servername_arg(*ssl_ctx, ctx) != 1) {
175 tls_set_error(ctx, "failed to set servername callback arg");
176 goto err;
177 }
178
79 if (tls_configure_ssl(ctx, *ssl_ctx) != 0) 179 if (tls_configure_ssl(ctx, *ssl_ctx) != 0)
80 goto err; 180 goto err;
81 if (tls_configure_ssl_keypair(ctx, *ssl_ctx, keypair, 1) != 0) 181 if (tls_configure_ssl_keypair(ctx, *ssl_ctx, keypair, 1) != 0)
@@ -134,12 +234,44 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx,
134 return (-1); 234 return (-1);
135} 235}
136 236
237static int
238tls_configure_server_sni(struct tls *ctx)
239{
240 struct tls_sni_ctx **sni_ctx;
241 struct tls_keypair *kp;
242
243 if (ctx->config->keypair->next == NULL)
244 return (0);
245
246 /* Set up additional SSL contexts for SNI. */
247 sni_ctx = &ctx->sni_ctx;
248 for (kp = ctx->config->keypair->next; kp != NULL; kp = kp->next) {
249 if ((*sni_ctx = tls_sni_ctx_new()) == NULL) {
250 tls_set_errorx(ctx, "out of memory");
251 goto err;
252 }
253 if (tls_configure_server_ssl(ctx, &(*sni_ctx)->ssl_ctx, kp) == -1)
254 goto err;
255 if (tls_keypair_load_cert(kp, &ctx->error,
256 &(*sni_ctx)->ssl_cert) == -1)
257 goto err;
258 sni_ctx = &(*sni_ctx)->next;
259 }
260
261 return (0);
262
263 err:
264 return (-1);
265}
266
137int 267int
138tls_configure_server(struct tls *ctx) 268tls_configure_server(struct tls *ctx)
139{ 269{
140 if (tls_configure_server_ssl(ctx, &ctx->ssl_ctx, 270 if (tls_configure_server_ssl(ctx, &ctx->ssl_ctx,
141 ctx->config->keypair) == -1) 271 ctx->config->keypair) == -1)
142 goto err; 272 goto err;
273 if (tls_configure_server_sni(ctx) == -1)
274 goto err;
143 275
144 return (0); 276 return (0);
145 277