diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libtls/tls.c | 28 | ||||
-rw-r--r-- | src/lib/libtls/tls_internal.h | 15 | ||||
-rw-r--r-- | src/lib/libtls/tls_server.c | 134 |
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 | ||
180 | struct tls_sni_ctx * | ||
181 | tls_sni_ctx_new(void) | ||
182 | { | ||
183 | return (calloc(1, sizeof(struct tls_sni_ctx))); | ||
184 | } | ||
185 | |||
186 | void | ||
187 | tls_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 | |||
180 | struct tls * | 198 | struct tls * |
181 | tls_new(void) | 199 | tls_new(void) |
182 | { | 200 | { |
@@ -376,6 +394,8 @@ tls_free(struct tls *ctx) | |||
376 | void | 394 | void |
377 | tls_reset(struct tls *ctx) | 395 | tls_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 | ||
402 | int | 428 | int |
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 | ||
94 | struct tls_sni_ctx { | ||
95 | struct tls_sni_ctx *next; | ||
96 | |||
97 | SSL_CTX *ssl_ctx; | ||
98 | X509 *ssl_cert; | ||
99 | }; | ||
100 | |||
94 | struct tls { | 101 | struct 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 | ||
121 | struct tls_sni_ctx *tls_sni_ctx_new(void); | ||
122 | void tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx); | ||
123 | |||
111 | struct tls *tls_new(void); | 124 | struct tls *tls_new(void); |
112 | struct tls *tls_server_conn(struct tls *ctx); | 125 | struct 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 | ||
65 | static int | 69 | static int |
70 | tls_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 | |||
118 | static int | ||
119 | tls_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 | |||
155 | static int | ||
66 | tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, | 156 | tls_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 | ||
237 | static int | ||
238 | tls_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 | |||
137 | int | 267 | int |
138 | tls_configure_server(struct tls *ctx) | 268 | tls_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 | ||