void TcpServer::AsyncSecureAccept() { auto errorHandler = std::bind(&TcpServer::ErrorHandler, this, std::placeholders::_1, std::placeholders::_2); auto context = boost::asio::ssl::context(boost::asio::ssl::context::sslv23); auto optionsMask = boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use; if (_securityOptions.VerifyClient) { auto verifyCallback = [](bool preverified, boost::asio::ssl::verify_context& ctx) { std::cout << "Verifying certificate, pre-verified: " << std::string(preverified ? "true" : "false"); char subject_name[256]; X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle()); X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); LOG() << "Verifying, subject: " << subject_name << "\n"; char issuer_name[256]; X509_NAME_oneline(X509_get_issuer_name(cert), issuer_name, 256); LOG() << "Verifying, issuer: " << issuer_name << "\n"; return preverified; }; context.set_verify_mode(boost::asio::ssl::context::verify_fail_if_no_peer_cert | boost::asio::ssl::verify_peer); context.set_verify_callback(verifyCallback); context.load_verify_file(_securityOptions.ClientVerifyFile); } context.set_options(optionsMask); context.set_password_callback(std::bind(&TcpServer::GetPassword, this)); context.use_certificate_chain_file(_securityOptions.CertificateFilename); context.use_rsa_private_key_file(_securityOptions.PrivKeyFilename, boost::asio::ssl::context::pem); context.use_tmp_dh_file(_securityOptions.DHExchangeFilename); auto conn = std::make_shared<TcpSslConnection>(_ioService, std::move(context), std::move(errorHandler)); auto acceptor = std::bind(&TcpServer::SecureAcceptHandler, this, conn, std::placeholders::_1); // Async accept does not block and takes references to the socket and end point of the connection. // The connection smart pointer is kept alive by being bound to the acceptor callback. _acceptor->async_accept(conn->PeerSocket, conn->PeerEndPoint, std::move(acceptor)); }
std::shared_ptr<ssl_context> WSService::make_ssl_ctx() { auto ssl_ctx_ptr = std::make_shared<ssl_context>(ssl_context::tlsv12); // SSL settings ssl_ctx_ptr->set_options( ssl_context::default_workarounds | ssl_context::single_dh_use | ssl_context::no_sslv2 | ssl_context::no_sslv3 | ssl_context::no_tlsv1 | ssl_context::no_tlsv1_1 ); ssl_ctx_ptr->set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert); ssl_ctx_ptr->use_certificate_file(Config::get()->paths().cert_path.string(std::codecvt_utf8_utf16<wchar_t>()), ssl_context::pem); ssl_ctx_ptr->use_private_key_file(Config::get()->paths().key_path.string(std::codecvt_utf8_utf16<wchar_t>()), ssl_context::pem); SSL_CTX_set_cipher_list(ssl_ctx_ptr->native_handle(), "ECDH-ECDSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-SHA256"); return ssl_ctx_ptr; }
client connect(const uri& uri) { static asio::io_service service; if (uri.scheme() == "http") { auto socket = std::make_unique<http_socket_t>(service); connect(uri, socket); return std::make_shared<client_impl<http_socket_t>>(std::move(socket), uri.host()); } else { ssl::context context(ssl::context::sslv23_client); context.set_default_verify_paths(); auto socket = std::make_unique<https_socket_t>(service, context); connect(uri, socket); socket->set_verify_mode(ssl::verify_peer); socket->set_verify_callback(ssl::rfc2818_verification(uri.host())); socket->handshake(ssl::stream_base::client); return std::make_shared<client_impl<https_socket_t>>(std::move(socket), uri.host()); } }
/** * This function may be used to configure the peer verification mode used by * the stream. The new mode will override the mode inherited from the context. * * @param v A bitmask of peer verification modes. See @ref verify_mode for * available values. * * @throws boost::system::system_error Thrown on failure. * * @note Calls @c SSL_set_verify. */ void set_verify_mode(verify_mode v) { boost::system::error_code ec; set_verify_mode(v, ec); boost::asio::detail::throw_error(ec, "set_verify_mode"); }
/** * This function may be used to configure the peer verification mode used by * the stream. The new mode will override the mode inherited from the context. * * @param v A bitmask of peer verification modes. See @ref verify_mode for * available values. * * @throws asio::system_error Thrown on failure. * * @note Calls @c SSL_set_verify. */ void set_verify_mode(verify_mode v) { asio::error_code ec; set_verify_mode(v, ec); asio::detail::throw_error(ec, "set_verify_mode"); }