| 568 | } |
| 569 | |
| 570 | SSL_CTX* CreateServerSSLContext(const std::string& certificate, |
| 571 | const std::string& private_key, |
| 572 | const ServerSSLOptions& options, |
| 573 | const std::string* alpns, |
| 574 | std::vector<std::string>* hostnames) { |
| 575 | std::unique_ptr<SSL_CTX, FreeSSLCTX> ssl_ctx( |
| 576 | SSL_CTX_new(SSLv23_server_method())); |
| 577 | if (!ssl_ctx) { |
| 578 | LOG(ERROR) << "Fail to new SSL_CTX: " << SSLError(ERR_get_error()); |
| 579 | return NULL; |
| 580 | } |
| 581 | MaybeSetKeyLogCallback(ssl_ctx.get()); |
| 582 | |
| 583 | if (LoadCertificate(ssl_ctx.get(), certificate, |
| 584 | private_key, hostnames) != 0) { |
| 585 | return NULL; |
| 586 | } |
| 587 | |
| 588 | int protocols = TLSv1 | TLSv1_1 | TLSv1_2; |
| 589 | if (!options.disable_ssl3) { |
| 590 | protocols |= SSLv3; |
| 591 | } |
| 592 | if (SetSSLOptions(ssl_ctx.get(), options.ciphers, |
| 593 | protocols, options.verify) != 0) { |
| 594 | return NULL; |
| 595 | } |
| 596 | |
| 597 | #ifdef SSL_MODE_RELEASE_BUFFERS |
| 598 | if (options.release_buffer) { |
| 599 | long sslmode = SSL_CTX_get_mode(ssl_ctx.get()); |
| 600 | sslmode |= SSL_MODE_RELEASE_BUFFERS; |
| 601 | SSL_CTX_set_mode(ssl_ctx.get(), sslmode); |
| 602 | } |
| 603 | #endif // SSL_MODE_RELEASE_BUFFERS |
| 604 | |
| 605 | SSL_CTX_set_timeout(ssl_ctx.get(), options.session_lifetime_s); |
| 606 | SSL_CTX_sess_set_cache_size(ssl_ctx.get(), options.session_cache_size); |
| 607 | |
| 608 | #ifndef OPENSSL_NO_DH |
| 609 | SSL_CTX_set_tmp_dh_callback(ssl_ctx.get(), SSLGetDHCallback); |
| 610 | |
| 611 | #if !defined(OPENSSL_NO_ECDH) && defined(SSL_CTX_set_tmp_ecdh) |
| 612 | EC_KEY* ecdh = NULL; |
| 613 | int i = OBJ_sn2nid(options.ecdhe_curve_name.c_str()); |
| 614 | if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) { |
| 615 | LOG(ERROR) << "Fail to find ECDHE named curve=" |
| 616 | << options.ecdhe_curve_name |
| 617 | << ": " << SSLError(ERR_get_error()); |
| 618 | return NULL; |
| 619 | } |
| 620 | SSL_CTX_set_tmp_ecdh(ssl_ctx.get(), ecdh); |
| 621 | EC_KEY_free(ecdh); |
| 622 | #endif |
| 623 | |
| 624 | #endif // OPENSSL_NO_DH |
| 625 | |
| 626 | // Set ALPN callback to choose application protocol when alpns is not empty. |
| 627 | if (alpns != nullptr && !alpns->empty()) { |