diff options
| author | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
|---|---|---|
| committer | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
| commit | b1ddde874c215cc8891531ed92876f091b7eb83e (patch) | |
| tree | edb6da6af7e865d488dc1a29309f1e1ec226e603 /src/lib/libtls/tls_server.c | |
| parent | f0a36529837a161734c802ae4c42e84e42347be2 (diff) | |
| download | openbsd-tb_20250414.tar.gz openbsd-tb_20250414.tar.bz2 openbsd-tb_20250414.zip | |
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/lib/libtls/tls_server.c')
| -rw-r--r-- | src/lib/libtls/tls_server.c | 483 |
1 files changed, 0 insertions, 483 deletions
diff --git a/src/lib/libtls/tls_server.c b/src/lib/libtls/tls_server.c deleted file mode 100644 index a94b4221ed..0000000000 --- a/src/lib/libtls/tls_server.c +++ /dev/null | |||
| @@ -1,483 +0,0 @@ | |||
| 1 | /* $OpenBSD: tls_server.c,v 1.51 2024/03/26 08:54:48 joshua 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 <string.h> | ||
| 23 | |||
| 24 | #include <openssl/ec.h> | ||
| 25 | #include <openssl/err.h> | ||
| 26 | #include <openssl/ssl.h> | ||
| 27 | |||
| 28 | #include <tls.h> | ||
| 29 | #include "tls_internal.h" | ||
| 30 | |||
| 31 | struct tls * | ||
| 32 | tls_server(void) | ||
| 33 | { | ||
| 34 | struct tls *ctx; | ||
| 35 | |||
| 36 | if (tls_init() == -1) | ||
| 37 | return (NULL); | ||
| 38 | |||
| 39 | if ((ctx = tls_new()) == NULL) | ||
| 40 | return (NULL); | ||
| 41 | |||
| 42 | ctx->flags |= TLS_SERVER; | ||
| 43 | |||
| 44 | return (ctx); | ||
| 45 | } | ||
| 46 | |||
| 47 | struct tls * | ||
| 48 | tls_server_conn(struct tls *ctx) | ||
| 49 | { | ||
| 50 | struct tls *conn_ctx; | ||
| 51 | |||
| 52 | if ((conn_ctx = tls_new()) == NULL) | ||
| 53 | return (NULL); | ||
| 54 | |||
| 55 | conn_ctx->flags |= TLS_SERVER_CONN; | ||
| 56 | |||
| 57 | pthread_mutex_lock(&ctx->config->mutex); | ||
| 58 | ctx->config->refcount++; | ||
| 59 | pthread_mutex_unlock(&ctx->config->mutex); | ||
| 60 | |||
| 61 | conn_ctx->config = ctx->config; | ||
| 62 | conn_ctx->keypair = ctx->config->keypair; | ||
| 63 | |||
| 64 | return (conn_ctx); | ||
| 65 | } | ||
| 66 | |||
| 67 | static int | ||
| 68 | tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, | ||
| 69 | const unsigned char *in, unsigned int inlen, void *arg) | ||
| 70 | { | ||
| 71 | struct tls *ctx = arg; | ||
| 72 | |||
| 73 | if (SSL_select_next_proto((unsigned char**)out, outlen, | ||
| 74 | ctx->config->alpn, ctx->config->alpn_len, in, inlen) == | ||
| 75 | OPENSSL_NPN_NEGOTIATED) | ||
| 76 | return (SSL_TLSEXT_ERR_OK); | ||
| 77 | |||
| 78 | return (SSL_TLSEXT_ERR_NOACK); | ||
| 79 | } | ||
| 80 | |||
| 81 | static int | ||
| 82 | tls_servername_cb(SSL *ssl, int *al, void *arg) | ||
| 83 | { | ||
| 84 | struct tls *ctx = (struct tls *)arg; | ||
| 85 | struct tls_sni_ctx *sni_ctx; | ||
| 86 | union tls_addr addrbuf; | ||
| 87 | struct tls *conn_ctx; | ||
| 88 | const char *name; | ||
| 89 | int match; | ||
| 90 | |||
| 91 | if ((conn_ctx = SSL_get_app_data(ssl)) == NULL) | ||
| 92 | goto err; | ||
| 93 | |||
| 94 | if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) == | ||
| 95 | NULL) { | ||
| 96 | /* | ||
| 97 | * The servername callback gets called even when there is no | ||
| 98 | * TLS servername extension provided by the client. Sigh! | ||
| 99 | */ | ||
| 100 | return (SSL_TLSEXT_ERR_NOACK); | ||
| 101 | } | ||
| 102 | |||
| 103 | /* | ||
| 104 | * Per RFC 6066 section 3: ensure that name is not an IP literal. | ||
| 105 | * | ||
| 106 | * While we should treat this as an error, a number of clients | ||
| 107 | * (Python, Ruby and Safari) are not RFC compliant. To avoid handshake | ||
| 108 | * failures, pretend that we did not receive the extension. | ||
| 109 | */ | ||
| 110 | if (inet_pton(AF_INET, name, &addrbuf) == 1 || | ||
| 111 | inet_pton(AF_INET6, name, &addrbuf) == 1) | ||
| 112 | return (SSL_TLSEXT_ERR_NOACK); | ||
| 113 | |||
| 114 | free(conn_ctx->servername); | ||
| 115 | if ((conn_ctx->servername = strdup(name)) == NULL) | ||
| 116 | goto err; | ||
| 117 | |||
| 118 | /* Find appropriate SSL context for requested servername. */ | ||
| 119 | for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) { | ||
| 120 | if (tls_check_name(ctx, sni_ctx->ssl_cert, name, | ||
| 121 | &match) == -1) | ||
| 122 | goto err; | ||
| 123 | if (match) { | ||
| 124 | conn_ctx->keypair = sni_ctx->keypair; | ||
| 125 | SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx); | ||
| 126 | return (SSL_TLSEXT_ERR_OK); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | /* No match, use the existing context/certificate. */ | ||
| 131 | return (SSL_TLSEXT_ERR_OK); | ||
| 132 | |||
| 133 | err: | ||
| 134 | /* | ||
| 135 | * There is no way to tell libssl that an internal failure occurred. | ||
| 136 | * The only option we have is to return a fatal alert. | ||
| 137 | */ | ||
| 138 | *al = SSL_AD_INTERNAL_ERROR; | ||
| 139 | return (SSL_TLSEXT_ERR_ALERT_FATAL); | ||
| 140 | } | ||
| 141 | |||
| 142 | static struct tls_ticket_key * | ||
| 143 | tls_server_ticket_key(struct tls_config *config, unsigned char *keyname) | ||
| 144 | { | ||
| 145 | struct tls_ticket_key *key = NULL; | ||
| 146 | time_t now; | ||
| 147 | int i; | ||
| 148 | |||
| 149 | now = time(NULL); | ||
| 150 | if (config->ticket_autorekey == 1) { | ||
| 151 | if (now - 3 * (config->session_lifetime / 4) > | ||
| 152 | config->ticket_keys[0].time) { | ||
| 153 | if (tls_config_ticket_autorekey(config) == -1) | ||
| 154 | return (NULL); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | for (i = 0; i < TLS_NUM_TICKETS; i++) { | ||
| 158 | struct tls_ticket_key *tk = &config->ticket_keys[i]; | ||
| 159 | if (now - config->session_lifetime > tk->time) | ||
| 160 | continue; | ||
| 161 | if (keyname == NULL || timingsafe_memcmp(keyname, | ||
| 162 | tk->key_name, sizeof(tk->key_name)) == 0) { | ||
| 163 | key = tk; | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | return (key); | ||
| 168 | } | ||
| 169 | |||
| 170 | static int | ||
| 171 | tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, | ||
| 172 | EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode) | ||
| 173 | { | ||
| 174 | struct tls_ticket_key *key; | ||
| 175 | struct tls *tls_ctx; | ||
| 176 | |||
| 177 | if ((tls_ctx = SSL_get_app_data(ssl)) == NULL) | ||
| 178 | return (-1); | ||
| 179 | |||
| 180 | if (mode == 1) { | ||
| 181 | /* create new session */ | ||
| 182 | key = tls_server_ticket_key(tls_ctx->config, NULL); | ||
| 183 | if (key == NULL) { | ||
| 184 | tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, | ||
| 185 | "no valid ticket key found"); | ||
| 186 | return (-1); | ||
| 187 | } | ||
| 188 | |||
| 189 | memcpy(keyname, key->key_name, sizeof(key->key_name)); | ||
| 190 | arc4random_buf(iv, EVP_MAX_IV_LENGTH); | ||
| 191 | if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, | ||
| 192 | key->aes_key, iv)) { | ||
| 193 | tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, | ||
| 194 | "failed to init encrypt"); | ||
| 195 | return (-1); | ||
| 196 | } | ||
| 197 | if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), | ||
| 198 | EVP_sha256(), NULL)) { | ||
| 199 | tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, | ||
| 200 | "failed to init hmac"); | ||
| 201 | return (-1); | ||
| 202 | } | ||
| 203 | return (0); | ||
| 204 | } else { | ||
| 205 | /* get key by name */ | ||
| 206 | key = tls_server_ticket_key(tls_ctx->config, keyname); | ||
| 207 | if (key == NULL) | ||
| 208 | return (0); | ||
| 209 | |||
| 210 | if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, | ||
| 211 | key->aes_key, iv)) { | ||
| 212 | tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, | ||
| 213 | "failed to init decrypt"); | ||
| 214 | return (-1); | ||
| 215 | } | ||
| 216 | if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), | ||
| 217 | EVP_sha256(), NULL)) { | ||
| 218 | tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, | ||
| 219 | "failed to init hmac"); | ||
| 220 | return (-1); | ||
| 221 | } | ||
| 222 | |||
| 223 | /* time to renew the ticket? is it the primary key? */ | ||
| 224 | if (key != &tls_ctx->config->ticket_keys[0]) | ||
| 225 | return (2); | ||
| 226 | return (1); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 230 | static int | ||
| 231 | tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, | ||
| 232 | struct tls_keypair *keypair) | ||
| 233 | { | ||
| 234 | SSL_CTX_free(*ssl_ctx); | ||
| 235 | |||
| 236 | if ((*ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { | ||
| 237 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl context failure"); | ||
| 238 | goto err; | ||
| 239 | } | ||
| 240 | |||
| 241 | SSL_CTX_set_options(*ssl_ctx, SSL_OP_NO_CLIENT_RENEGOTIATION); | ||
| 242 | |||
| 243 | if (SSL_CTX_set_tlsext_servername_callback(*ssl_ctx, | ||
| 244 | tls_servername_cb) != 1) { | ||
| 245 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, | ||
| 246 | "failed to set servername callback"); | ||
| 247 | goto err; | ||
| 248 | } | ||
| 249 | if (SSL_CTX_set_tlsext_servername_arg(*ssl_ctx, ctx) != 1) { | ||
| 250 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, | ||
| 251 | "failed to set servername callback arg"); | ||
| 252 | goto err; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (tls_configure_ssl(ctx, *ssl_ctx) != 0) | ||
| 256 | goto err; | ||
| 257 | if (tls_configure_ssl_keypair(ctx, *ssl_ctx, keypair, 1) != 0) | ||
| 258 | goto err; | ||
| 259 | if (ctx->config->verify_client != 0) { | ||
| 260 | int verify = SSL_VERIFY_PEER; | ||
| 261 | if (ctx->config->verify_client == 1) | ||
| 262 | verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; | ||
| 263 | if (tls_configure_ssl_verify(ctx, *ssl_ctx, verify) == -1) | ||
| 264 | goto err; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (ctx->config->alpn != NULL) | ||
| 268 | SSL_CTX_set_alpn_select_cb(*ssl_ctx, tls_server_alpn_cb, | ||
| 269 | ctx); | ||
| 270 | |||
| 271 | if (ctx->config->dheparams == -1) | ||
| 272 | SSL_CTX_set_dh_auto(*ssl_ctx, 1); | ||
| 273 | else if (ctx->config->dheparams == 1024) | ||
| 274 | SSL_CTX_set_dh_auto(*ssl_ctx, 2); | ||
| 275 | |||
| 276 | if (ctx->config->ecdhecurves != NULL) { | ||
| 277 | SSL_CTX_set_ecdh_auto(*ssl_ctx, 1); | ||
| 278 | if (SSL_CTX_set1_groups(*ssl_ctx, ctx->config->ecdhecurves, | ||
| 279 | ctx->config->ecdhecurves_len) != 1) { | ||
| 280 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | ||
| 281 | "failed to set ecdhe curves"); | ||
| 282 | goto err; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | if (ctx->config->ciphers_server == 1) | ||
| 287 | SSL_CTX_set_options(*ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); | ||
| 288 | |||
| 289 | if (SSL_CTX_set_tlsext_status_cb(*ssl_ctx, tls_ocsp_stapling_cb) != 1) { | ||
| 290 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | ||
| 291 | "failed to add OCSP stapling callback"); | ||
| 292 | goto err; | ||
| 293 | } | ||
| 294 | |||
| 295 | if (ctx->config->session_lifetime > 0) { | ||
| 296 | /* set the session lifetime and enable tickets */ | ||
| 297 | SSL_CTX_set_timeout(*ssl_ctx, ctx->config->session_lifetime); | ||
| 298 | SSL_CTX_clear_options(*ssl_ctx, SSL_OP_NO_TICKET); | ||
| 299 | if (!SSL_CTX_set_tlsext_ticket_key_cb(*ssl_ctx, | ||
| 300 | tls_server_ticket_cb)) { | ||
| 301 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, | ||
| 302 | "failed to set the TLS ticket callback"); | ||
| 303 | goto err; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | if (SSL_CTX_set_session_id_context(*ssl_ctx, ctx->config->session_id, | ||
| 308 | sizeof(ctx->config->session_id)) != 1) { | ||
| 309 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, | ||
| 310 | "failed to set session id context"); | ||
| 311 | goto err; | ||
| 312 | } | ||
| 313 | |||
| 314 | return (0); | ||
| 315 | |||
| 316 | err: | ||
| 317 | SSL_CTX_free(*ssl_ctx); | ||
| 318 | *ssl_ctx = NULL; | ||
| 319 | |||
| 320 | return (-1); | ||
| 321 | } | ||
| 322 | |||
| 323 | static int | ||
| 324 | tls_configure_server_sni(struct tls *ctx) | ||
| 325 | { | ||
| 326 | struct tls_sni_ctx **sni_ctx; | ||
| 327 | struct tls_keypair *kp; | ||
| 328 | |||
| 329 | if (ctx->config->keypair->next == NULL) | ||
| 330 | return (0); | ||
| 331 | |||
| 332 | /* Set up additional SSL contexts for SNI. */ | ||
| 333 | sni_ctx = &ctx->sni_ctx; | ||
| 334 | for (kp = ctx->config->keypair->next; kp != NULL; kp = kp->next) { | ||
| 335 | if ((*sni_ctx = tls_sni_ctx_new()) == NULL) { | ||
| 336 | tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); | ||
| 337 | goto err; | ||
| 338 | } | ||
| 339 | (*sni_ctx)->keypair = kp; | ||
| 340 | if (tls_configure_server_ssl(ctx, &(*sni_ctx)->ssl_ctx, kp) == -1) | ||
| 341 | goto err; | ||
| 342 | if (tls_keypair_load_cert(kp, &ctx->error, | ||
| 343 | &(*sni_ctx)->ssl_cert) == -1) | ||
| 344 | goto err; | ||
| 345 | sni_ctx = &(*sni_ctx)->next; | ||
| 346 | } | ||
| 347 | |||
| 348 | return (0); | ||
| 349 | |||
| 350 | err: | ||
| 351 | return (-1); | ||
| 352 | } | ||
| 353 | |||
| 354 | int | ||
| 355 | tls_configure_server(struct tls *ctx) | ||
| 356 | { | ||
| 357 | if (tls_configure_server_ssl(ctx, &ctx->ssl_ctx, | ||
| 358 | ctx->config->keypair) == -1) | ||
| 359 | goto err; | ||
| 360 | if (tls_configure_server_sni(ctx) == -1) | ||
| 361 | goto err; | ||
| 362 | |||
| 363 | return (0); | ||
| 364 | |||
| 365 | err: | ||
| 366 | return (-1); | ||
| 367 | } | ||
| 368 | |||
| 369 | static struct tls * | ||
| 370 | tls_accept_common(struct tls *ctx) | ||
| 371 | { | ||
| 372 | struct tls *conn_ctx = NULL; | ||
| 373 | |||
| 374 | if ((ctx->flags & TLS_SERVER) == 0) { | ||
| 375 | tls_set_errorx(ctx, TLS_ERROR_INVALID_CONTEXT, | ||
| 376 | "not a server context"); | ||
| 377 | goto err; | ||
| 378 | } | ||
| 379 | |||
| 380 | if ((conn_ctx = tls_server_conn(ctx)) == NULL) { | ||
| 381 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | ||
| 382 | "connection context failure"); | ||
| 383 | goto err; | ||
| 384 | } | ||
| 385 | |||
| 386 | if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { | ||
| 387 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl failure"); | ||
| 388 | goto err; | ||
| 389 | } | ||
| 390 | |||
| 391 | if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { | ||
| 392 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | ||
| 393 | "ssl application data failure"); | ||
| 394 | goto err; | ||
| 395 | } | ||
| 396 | |||
| 397 | return conn_ctx; | ||
| 398 | |||
| 399 | err: | ||
| 400 | tls_free(conn_ctx); | ||
| 401 | |||
| 402 | return (NULL); | ||
| 403 | } | ||
| 404 | |||
| 405 | int | ||
| 406 | tls_accept_socket(struct tls *ctx, struct tls **cctx, int s) | ||
| 407 | { | ||
| 408 | return (tls_accept_fds(ctx, cctx, s, s)); | ||
| 409 | } | ||
| 410 | |||
| 411 | int | ||
| 412 | tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) | ||
| 413 | { | ||
| 414 | struct tls *conn_ctx; | ||
| 415 | |||
| 416 | if ((conn_ctx = tls_accept_common(ctx)) == NULL) | ||
| 417 | goto err; | ||
| 418 | |||
| 419 | if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || | ||
| 420 | SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { | ||
| 421 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | ||
| 422 | "ssl file descriptor failure"); | ||
| 423 | goto err; | ||
| 424 | } | ||
| 425 | |||
| 426 | *cctx = conn_ctx; | ||
| 427 | |||
| 428 | return (0); | ||
| 429 | err: | ||
| 430 | tls_free(conn_ctx); | ||
| 431 | *cctx = NULL; | ||
| 432 | |||
| 433 | return (-1); | ||
| 434 | } | ||
| 435 | |||
| 436 | int | ||
| 437 | tls_accept_cbs(struct tls *ctx, struct tls **cctx, | ||
| 438 | tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg) | ||
| 439 | { | ||
| 440 | struct tls *conn_ctx; | ||
| 441 | |||
| 442 | if ((conn_ctx = tls_accept_common(ctx)) == NULL) | ||
| 443 | goto err; | ||
| 444 | |||
| 445 | if (tls_set_cbs(conn_ctx, read_cb, write_cb, cb_arg) != 0) | ||
| 446 | goto err; | ||
| 447 | |||
| 448 | *cctx = conn_ctx; | ||
| 449 | |||
| 450 | return (0); | ||
| 451 | err: | ||
| 452 | tls_free(conn_ctx); | ||
| 453 | *cctx = NULL; | ||
| 454 | |||
| 455 | return (-1); | ||
| 456 | } | ||
| 457 | |||
| 458 | int | ||
| 459 | tls_handshake_server(struct tls *ctx) | ||
| 460 | { | ||
| 461 | int ssl_ret; | ||
| 462 | int rv = -1; | ||
| 463 | |||
| 464 | if ((ctx->flags & TLS_SERVER_CONN) == 0) { | ||
| 465 | tls_set_errorx(ctx, TLS_ERROR_INVALID_CONTEXT, | ||
| 466 | "not a server connection context"); | ||
| 467 | goto err; | ||
| 468 | } | ||
| 469 | |||
| 470 | ctx->state |= TLS_SSL_NEEDS_SHUTDOWN; | ||
| 471 | |||
| 472 | ERR_clear_error(); | ||
| 473 | if ((ssl_ret = SSL_accept(ctx->ssl_conn)) != 1) { | ||
| 474 | rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake"); | ||
| 475 | goto err; | ||
| 476 | } | ||
| 477 | |||
| 478 | ctx->state |= TLS_HANDSHAKE_COMPLETE; | ||
| 479 | rv = 0; | ||
| 480 | |||
| 481 | err: | ||
| 482 | return (rv); | ||
| 483 | } | ||
