1 |
|
|
/* $OpenBSD: tls_server.c,v 1.42 2017/09/20 17:05:17 jsing Exp $ */ |
2 |
|
|
/* |
3 |
|
|
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 |
|
|
* |
5 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
6 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
7 |
|
|
* copyright notice and this permission notice appear in all copies. |
8 |
|
|
* |
9 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 |
|
|
*/ |
17 |
|
|
|
18 |
|
|
#include <sys/socket.h> |
19 |
|
|
|
20 |
|
|
#include <arpa/inet.h> |
21 |
|
|
|
22 |
|
|
#include <openssl/ec.h> |
23 |
|
|
#include <openssl/err.h> |
24 |
|
|
#include <openssl/ssl.h> |
25 |
|
|
|
26 |
|
|
#include <tls.h> |
27 |
|
|
#include "tls_internal.h" |
28 |
|
|
|
29 |
|
|
struct tls * |
30 |
|
|
tls_server(void) |
31 |
|
|
{ |
32 |
|
|
struct tls *ctx; |
33 |
|
|
|
34 |
✗✓ |
12 |
if ((ctx = tls_new()) == NULL) |
35 |
|
|
return (NULL); |
36 |
|
|
|
37 |
|
6 |
ctx->flags |= TLS_SERVER; |
38 |
|
|
|
39 |
|
6 |
return (ctx); |
40 |
|
6 |
} |
41 |
|
|
|
42 |
|
|
struct tls * |
43 |
|
|
tls_server_conn(struct tls *ctx) |
44 |
|
|
{ |
45 |
|
|
struct tls *conn_ctx; |
46 |
|
|
|
47 |
✗✓ |
24 |
if ((conn_ctx = tls_new()) == NULL) |
48 |
|
|
return (NULL); |
49 |
|
|
|
50 |
|
12 |
conn_ctx->flags |= TLS_SERVER_CONN; |
51 |
|
|
|
52 |
|
12 |
ctx->config->refcount++; |
53 |
|
|
|
54 |
|
12 |
conn_ctx->config = ctx->config; |
55 |
|
12 |
conn_ctx->keypair = ctx->config->keypair; |
56 |
|
|
|
57 |
|
12 |
return (conn_ctx); |
58 |
|
12 |
} |
59 |
|
|
|
60 |
|
|
static int |
61 |
|
|
tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, |
62 |
|
|
const unsigned char *in, unsigned int inlen, void *arg) |
63 |
|
|
{ |
64 |
|
|
struct tls *ctx = arg; |
65 |
|
|
|
66 |
|
|
if (SSL_select_next_proto((unsigned char**)out, outlen, |
67 |
|
|
ctx->config->alpn, ctx->config->alpn_len, in, inlen) == |
68 |
|
|
OPENSSL_NPN_NEGOTIATED) |
69 |
|
|
return (SSL_TLSEXT_ERR_OK); |
70 |
|
|
|
71 |
|
|
return (SSL_TLSEXT_ERR_NOACK); |
72 |
|
|
} |
73 |
|
|
|
74 |
|
|
static int |
75 |
|
|
tls_servername_cb(SSL *ssl, int *al, void *arg) |
76 |
|
|
{ |
77 |
|
24 |
struct tls *ctx = (struct tls *)arg; |
78 |
|
|
struct tls_sni_ctx *sni_ctx; |
79 |
|
12 |
union tls_addr addrbuf; |
80 |
|
|
struct tls *conn_ctx; |
81 |
|
|
const char *name; |
82 |
|
12 |
int match; |
83 |
|
|
|
84 |
✓✗ |
12 |
if ((conn_ctx = SSL_get_app_data(ssl)) == NULL) |
85 |
|
|
goto err; |
86 |
|
|
|
87 |
✗✓ |
12 |
if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) == |
88 |
|
|
NULL) { |
89 |
|
|
/* |
90 |
|
|
* The servername callback gets called even when there is no |
91 |
|
|
* TLS servername extension provided by the client. Sigh! |
92 |
|
|
*/ |
93 |
|
|
return (SSL_TLSEXT_ERR_NOACK); |
94 |
|
|
} |
95 |
|
|
|
96 |
|
|
/* |
97 |
|
|
* Per RFC 6066 section 3: ensure that name is not an IP literal. |
98 |
|
|
* |
99 |
|
|
* While we should treat this as an error, a number of clients |
100 |
|
|
* (Python, Ruby and Safari) are not RFC compliant. To avoid handshake |
101 |
|
|
* failures, pretend that we did not receive the extension. |
102 |
|
|
*/ |
103 |
✓✗✗✓
|
24 |
if (inet_pton(AF_INET, name, &addrbuf) == 1 || |
104 |
|
12 |
inet_pton(AF_INET6, name, &addrbuf) == 1) |
105 |
|
|
return (SSL_TLSEXT_ERR_NOACK); |
106 |
|
|
|
107 |
|
12 |
free((char *)conn_ctx->servername); |
108 |
✓✗ |
12 |
if ((conn_ctx->servername = strdup(name)) == NULL) |
109 |
|
|
goto err; |
110 |
|
|
|
111 |
|
|
/* Find appropriate SSL context for requested servername. */ |
112 |
✗✓ |
24 |
for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) { |
113 |
|
|
if (tls_check_name(ctx, sni_ctx->ssl_cert, name, |
114 |
|
|
&match) == -1) |
115 |
|
|
goto err; |
116 |
|
|
if (match) { |
117 |
|
|
conn_ctx->keypair = sni_ctx->keypair; |
118 |
|
|
SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx); |
119 |
|
|
return (SSL_TLSEXT_ERR_OK); |
120 |
|
|
} |
121 |
|
|
} |
122 |
|
|
|
123 |
|
|
/* No match, use the existing context/certificate. */ |
124 |
|
12 |
return (SSL_TLSEXT_ERR_OK); |
125 |
|
|
|
126 |
|
|
err: |
127 |
|
|
/* |
128 |
|
|
* There is no way to tell libssl that an internal failure occurred. |
129 |
|
|
* The only option we have is to return a fatal alert. |
130 |
|
|
*/ |
131 |
|
|
*al = TLS1_AD_INTERNAL_ERROR; |
132 |
|
|
return (SSL_TLSEXT_ERR_ALERT_FATAL); |
133 |
|
12 |
} |
134 |
|
|
|
135 |
|
|
static struct tls_ticket_key * |
136 |
|
|
tls_server_ticket_key(struct tls_config *config, unsigned char *keyname) |
137 |
|
|
{ |
138 |
|
|
struct tls_ticket_key *key = NULL; |
139 |
|
|
time_t now; |
140 |
|
|
int i; |
141 |
|
|
|
142 |
|
|
now = time(NULL); |
143 |
|
|
if (config->ticket_autorekey == 1) { |
144 |
|
|
if (now - 3 * (config->session_lifetime / 4) > |
145 |
|
|
config->ticket_keys[0].time) { |
146 |
|
|
if (tls_config_ticket_autorekey(config) == -1) |
147 |
|
|
return (NULL); |
148 |
|
|
} |
149 |
|
|
} |
150 |
|
|
for (i = 0; i < TLS_NUM_TICKETS; i++) { |
151 |
|
|
struct tls_ticket_key *tk = &config->ticket_keys[i]; |
152 |
|
|
if (now - config->session_lifetime > tk->time) |
153 |
|
|
continue; |
154 |
|
|
if (keyname == NULL || timingsafe_memcmp(keyname, |
155 |
|
|
tk->key_name, sizeof(tk->key_name)) == 0) { |
156 |
|
|
key = tk; |
157 |
|
|
break; |
158 |
|
|
} |
159 |
|
|
} |
160 |
|
|
return (key); |
161 |
|
|
} |
162 |
|
|
|
163 |
|
|
static int |
164 |
|
|
tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, |
165 |
|
|
EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode) |
166 |
|
|
{ |
167 |
|
|
struct tls_ticket_key *key; |
168 |
|
|
struct tls *tls_ctx; |
169 |
|
|
|
170 |
|
|
if ((tls_ctx = SSL_get_app_data(ssl)) == NULL) |
171 |
|
|
return (-1); |
172 |
|
|
|
173 |
|
|
if (mode == 1) { |
174 |
|
|
/* create new session */ |
175 |
|
|
key = tls_server_ticket_key(tls_ctx->config, NULL); |
176 |
|
|
if (key == NULL) { |
177 |
|
|
tls_set_errorx(tls_ctx, "no valid ticket key found"); |
178 |
|
|
return (-1); |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
memcpy(keyname, key->key_name, sizeof(key->key_name)); |
182 |
|
|
arc4random_buf(iv, EVP_MAX_IV_LENGTH); |
183 |
|
|
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, |
184 |
|
|
key->aes_key, iv); |
185 |
|
|
HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), |
186 |
|
|
EVP_sha256(), NULL); |
187 |
|
|
return (0); |
188 |
|
|
} else { |
189 |
|
|
/* get key by name */ |
190 |
|
|
key = tls_server_ticket_key(tls_ctx->config, keyname); |
191 |
|
|
if (key == NULL) |
192 |
|
|
return (0); |
193 |
|
|
|
194 |
|
|
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, |
195 |
|
|
key->aes_key, iv); |
196 |
|
|
HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), |
197 |
|
|
EVP_sha256(), NULL); |
198 |
|
|
|
199 |
|
|
/* time to renew the ticket? is it the primary key? */ |
200 |
|
|
if (key != &tls_ctx->config->ticket_keys[0]) |
201 |
|
|
return (2); |
202 |
|
|
return (1); |
203 |
|
|
} |
204 |
|
|
} |
205 |
|
|
|
206 |
|
|
static int |
207 |
|
|
tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error, |
208 |
|
|
X509 **cert) |
209 |
|
|
{ |
210 |
|
|
char *errstr = "unknown"; |
211 |
|
|
BIO *cert_bio = NULL; |
212 |
|
|
int ssl_err; |
213 |
|
|
int rv = -1; |
214 |
|
|
|
215 |
|
|
X509_free(*cert); |
216 |
|
|
*cert = NULL; |
217 |
|
|
|
218 |
|
|
if (keypair->cert_mem == NULL) { |
219 |
|
|
tls_error_set(error, "keypair has no certificate"); |
220 |
|
|
goto err; |
221 |
|
|
} |
222 |
|
|
if ((cert_bio = BIO_new_mem_buf(keypair->cert_mem, |
223 |
|
|
keypair->cert_len)) == NULL) { |
224 |
|
|
tls_error_set(error, "failed to create certificate bio"); |
225 |
|
|
goto err; |
226 |
|
|
} |
227 |
|
|
if ((*cert = PEM_read_bio_X509(cert_bio, NULL, tls_password_cb, |
228 |
|
|
NULL)) == NULL) { |
229 |
|
|
if ((ssl_err = ERR_peek_error()) != 0) |
230 |
|
|
errstr = ERR_error_string(ssl_err, NULL); |
231 |
|
|
tls_error_set(error, "failed to load certificate: %s", errstr); |
232 |
|
|
goto err; |
233 |
|
|
} |
234 |
|
|
|
235 |
|
|
rv = 0; |
236 |
|
|
|
237 |
|
|
err: |
238 |
|
|
BIO_free(cert_bio); |
239 |
|
|
|
240 |
|
|
return (rv); |
241 |
|
|
} |
242 |
|
|
|
243 |
|
|
static int |
244 |
|
|
tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, |
245 |
|
|
struct tls_keypair *keypair) |
246 |
|
|
{ |
247 |
|
24 |
SSL_CTX_free(*ssl_ctx); |
248 |
|
|
|
249 |
✗✓ |
12 |
if ((*ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { |
250 |
|
|
tls_set_errorx(ctx, "ssl context failure"); |
251 |
|
|
goto err; |
252 |
|
|
} |
253 |
|
|
|
254 |
|
12 |
SSL_CTX_set_options(*ssl_ctx, SSL_OP_NO_CLIENT_RENEGOTIATION); |
255 |
|
|
|
256 |
✗✓ |
24 |
if (SSL_CTX_set_tlsext_servername_callback(*ssl_ctx, |
257 |
|
12 |
tls_servername_cb) != 1) { |
258 |
|
|
tls_set_error(ctx, "failed to set servername callback"); |
259 |
|
|
goto err; |
260 |
|
|
} |
261 |
✗✓ |
12 |
if (SSL_CTX_set_tlsext_servername_arg(*ssl_ctx, ctx) != 1) { |
262 |
|
|
tls_set_error(ctx, "failed to set servername callback arg"); |
263 |
|
|
goto err; |
264 |
|
|
} |
265 |
|
|
|
266 |
✓✗ |
12 |
if (tls_configure_ssl(ctx, *ssl_ctx) != 0) |
267 |
|
|
goto err; |
268 |
✓✗ |
12 |
if (tls_configure_ssl_keypair(ctx, *ssl_ctx, keypair, 1) != 0) |
269 |
|
|
goto err; |
270 |
✗✓ |
12 |
if (ctx->config->verify_client != 0) { |
271 |
|
|
int verify = SSL_VERIFY_PEER; |
272 |
|
|
if (ctx->config->verify_client == 1) |
273 |
|
|
verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; |
274 |
|
|
if (tls_configure_ssl_verify(ctx, *ssl_ctx, verify) == -1) |
275 |
|
|
goto err; |
276 |
|
|
} |
277 |
|
|
|
278 |
✗✓ |
12 |
if (ctx->config->alpn != NULL) |
279 |
|
|
SSL_CTX_set_alpn_select_cb(*ssl_ctx, tls_server_alpn_cb, |
280 |
|
|
ctx); |
281 |
|
|
|
282 |
✗✓ |
12 |
if (ctx->config->dheparams == -1) |
283 |
|
|
SSL_CTX_set_dh_auto(*ssl_ctx, 1); |
284 |
✗✓ |
12 |
else if (ctx->config->dheparams == 1024) |
285 |
|
|
SSL_CTX_set_dh_auto(*ssl_ctx, 2); |
286 |
|
|
|
287 |
✓✗ |
12 |
if (ctx->config->ecdhecurves != NULL) { |
288 |
|
12 |
SSL_CTX_set_ecdh_auto(*ssl_ctx, 1); |
289 |
✗✓ |
36 |
if (SSL_CTX_set1_groups(*ssl_ctx, ctx->config->ecdhecurves, |
290 |
|
24 |
ctx->config->ecdhecurves_len) != 1) { |
291 |
|
|
tls_set_errorx(ctx, "failed to set ecdhe curves"); |
292 |
|
|
goto err; |
293 |
|
|
} |
294 |
|
|
} |
295 |
|
|
|
296 |
✓✗ |
12 |
if (ctx->config->ciphers_server == 1) |
297 |
|
12 |
SSL_CTX_set_options(*ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); |
298 |
|
|
|
299 |
✗✓ |
12 |
if (SSL_CTX_set_tlsext_status_cb(*ssl_ctx, tls_ocsp_stapling_cb) != 1) { |
300 |
|
|
tls_set_errorx(ctx, "failed to add OCSP stapling callback"); |
301 |
|
|
goto err; |
302 |
|
|
} |
303 |
|
|
|
304 |
✗✓ |
12 |
if (ctx->config->session_lifetime > 0) { |
305 |
|
|
/* set the session lifetime and enable tickets */ |
306 |
|
|
SSL_CTX_set_timeout(*ssl_ctx, ctx->config->session_lifetime); |
307 |
|
|
SSL_CTX_clear_options(*ssl_ctx, SSL_OP_NO_TICKET); |
308 |
|
|
if (!SSL_CTX_set_tlsext_ticket_key_cb(*ssl_ctx, |
309 |
|
|
tls_server_ticket_cb)) { |
310 |
|
|
tls_set_error(ctx, |
311 |
|
|
"failed to set the TLS ticket callback"); |
312 |
|
|
goto err; |
313 |
|
|
} |
314 |
|
|
} |
315 |
|
|
|
316 |
✗✓ |
24 |
if (SSL_CTX_set_session_id_context(*ssl_ctx, ctx->config->session_id, |
317 |
|
12 |
sizeof(ctx->config->session_id)) != 1) { |
318 |
|
|
tls_set_error(ctx, "failed to set session id context"); |
319 |
|
|
goto err; |
320 |
|
|
} |
321 |
|
|
|
322 |
|
12 |
return (0); |
323 |
|
|
|
324 |
|
|
err: |
325 |
|
|
SSL_CTX_free(*ssl_ctx); |
326 |
|
|
*ssl_ctx = NULL; |
327 |
|
|
|
328 |
|
|
return (-1); |
329 |
|
12 |
} |
330 |
|
|
|
331 |
|
|
static int |
332 |
|
|
tls_configure_server_sni(struct tls *ctx) |
333 |
|
|
{ |
334 |
|
|
struct tls_sni_ctx **sni_ctx; |
335 |
|
|
struct tls_keypair *kp; |
336 |
|
|
|
337 |
✓✗ |
24 |
if (ctx->config->keypair->next == NULL) |
338 |
|
12 |
return (0); |
339 |
|
|
|
340 |
|
|
/* Set up additional SSL contexts for SNI. */ |
341 |
|
|
sni_ctx = &ctx->sni_ctx; |
342 |
|
|
for (kp = ctx->config->keypair->next; kp != NULL; kp = kp->next) { |
343 |
|
|
if ((*sni_ctx = tls_sni_ctx_new()) == NULL) { |
344 |
|
|
tls_set_errorx(ctx, "out of memory"); |
345 |
|
|
goto err; |
346 |
|
|
} |
347 |
|
|
(*sni_ctx)->keypair = kp; |
348 |
|
|
if (tls_configure_server_ssl(ctx, &(*sni_ctx)->ssl_ctx, kp) == -1) |
349 |
|
|
goto err; |
350 |
|
|
if (tls_keypair_load_cert(kp, &ctx->error, |
351 |
|
|
&(*sni_ctx)->ssl_cert) == -1) |
352 |
|
|
goto err; |
353 |
|
|
sni_ctx = &(*sni_ctx)->next; |
354 |
|
|
} |
355 |
|
|
|
356 |
|
|
return (0); |
357 |
|
|
|
358 |
|
|
err: |
359 |
|
|
return (-1); |
360 |
|
12 |
} |
361 |
|
|
|
362 |
|
|
int |
363 |
|
|
tls_configure_server(struct tls *ctx) |
364 |
|
|
{ |
365 |
✓✗ |
48 |
if (tls_configure_server_ssl(ctx, &ctx->ssl_ctx, |
366 |
|
24 |
ctx->config->keypair) == -1) |
367 |
|
|
goto err; |
368 |
✓✗ |
12 |
if (tls_configure_server_sni(ctx) == -1) |
369 |
|
|
goto err; |
370 |
|
|
|
371 |
|
12 |
return (0); |
372 |
|
|
|
373 |
|
|
err: |
374 |
|
|
return (-1); |
375 |
|
12 |
} |
376 |
|
|
|
377 |
|
|
static struct tls * |
378 |
|
|
tls_accept_common(struct tls *ctx) |
379 |
|
|
{ |
380 |
|
|
struct tls *conn_ctx = NULL; |
381 |
|
|
|
382 |
✗✓ |
24 |
if ((ctx->flags & TLS_SERVER) == 0) { |
383 |
|
|
tls_set_errorx(ctx, "not a server context"); |
384 |
|
|
goto err; |
385 |
|
|
} |
386 |
|
|
|
387 |
✗✓ |
12 |
if ((conn_ctx = tls_server_conn(ctx)) == NULL) { |
388 |
|
|
tls_set_errorx(ctx, "connection context failure"); |
389 |
|
|
goto err; |
390 |
|
|
} |
391 |
|
|
|
392 |
✗✓ |
12 |
if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { |
393 |
|
|
tls_set_errorx(ctx, "ssl failure"); |
394 |
|
|
goto err; |
395 |
|
|
} |
396 |
|
|
|
397 |
✗✓ |
12 |
if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { |
398 |
|
|
tls_set_errorx(ctx, "ssl application data failure"); |
399 |
|
|
goto err; |
400 |
|
|
} |
401 |
|
|
|
402 |
|
12 |
return conn_ctx; |
403 |
|
|
|
404 |
|
|
err: |
405 |
|
|
tls_free(conn_ctx); |
406 |
|
|
|
407 |
|
|
return (NULL); |
408 |
|
12 |
} |
409 |
|
|
|
410 |
|
|
int |
411 |
|
|
tls_accept_socket(struct tls *ctx, struct tls **cctx, int s) |
412 |
|
|
{ |
413 |
|
6 |
return (tls_accept_fds(ctx, cctx, s, s)); |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
int |
417 |
|
|
tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) |
418 |
|
|
{ |
419 |
|
|
struct tls *conn_ctx; |
420 |
|
|
|
421 |
✓✗ |
12 |
if ((conn_ctx = tls_accept_common(ctx)) == NULL) |
422 |
|
|
goto err; |
423 |
|
|
|
424 |
✓✗✗✓
|
12 |
if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || |
425 |
|
6 |
SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { |
426 |
|
|
tls_set_errorx(ctx, "ssl file descriptor failure"); |
427 |
|
|
goto err; |
428 |
|
|
} |
429 |
|
|
|
430 |
|
6 |
*cctx = conn_ctx; |
431 |
|
|
|
432 |
|
6 |
return (0); |
433 |
|
|
err: |
434 |
|
|
tls_free(conn_ctx); |
435 |
|
|
*cctx = NULL; |
436 |
|
|
|
437 |
|
|
return (-1); |
438 |
|
6 |
} |
439 |
|
|
|
440 |
|
|
int |
441 |
|
|
tls_accept_cbs(struct tls *ctx, struct tls **cctx, |
442 |
|
|
tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg) |
443 |
|
|
{ |
444 |
|
|
struct tls *conn_ctx; |
445 |
|
|
|
446 |
✓✗ |
12 |
if ((conn_ctx = tls_accept_common(ctx)) == NULL) |
447 |
|
|
goto err; |
448 |
|
|
|
449 |
✓✗ |
6 |
if (tls_set_cbs(conn_ctx, read_cb, write_cb, cb_arg) != 0) |
450 |
|
|
goto err; |
451 |
|
|
|
452 |
|
6 |
*cctx = conn_ctx; |
453 |
|
|
|
454 |
|
6 |
return (0); |
455 |
|
|
err: |
456 |
|
|
tls_free(conn_ctx); |
457 |
|
|
*cctx = NULL; |
458 |
|
|
|
459 |
|
|
return (-1); |
460 |
|
6 |
} |
461 |
|
|
|
462 |
|
|
int |
463 |
|
|
tls_handshake_server(struct tls *ctx) |
464 |
|
|
{ |
465 |
|
|
int ssl_ret; |
466 |
|
|
int rv = -1; |
467 |
|
|
|
468 |
✗✓ |
72 |
if ((ctx->flags & TLS_SERVER_CONN) == 0) { |
469 |
|
|
tls_set_errorx(ctx, "not a server connection context"); |
470 |
|
|
goto err; |
471 |
|
|
} |
472 |
|
|
|
473 |
|
36 |
ctx->state |= TLS_SSL_NEEDS_SHUTDOWN; |
474 |
|
|
|
475 |
|
36 |
ERR_clear_error(); |
476 |
✓✓ |
36 |
if ((ssl_ret = SSL_accept(ctx->ssl_conn)) != 1) { |
477 |
|
24 |
rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake"); |
478 |
|
24 |
goto err; |
479 |
|
|
} |
480 |
|
|
|
481 |
|
12 |
ctx->state |= TLS_HANDSHAKE_COMPLETE; |
482 |
|
12 |
rv = 0; |
483 |
|
|
|
484 |
|
|
err: |
485 |
|
36 |
return (rv); |
486 |
|
|
} |