Кажется, моя проблема проистекает из того факта, что openssl не имеет стиля передачи продолжения для обратных вызовов, таких как указание имени сервера (SNI), но я пытаюсь заставить его использовать его.
Я хочу не блокировать рабочий поток при чтении SSL-сообщений клиентов и не блокировать рабочий поток, пока я отказываюсь возвращать обратный вызов SNI, ожидая завершения рукопожатия ssl-сервера (поэтому я могу заново подписать сертификат сервера).
Для asio
bsaed повторная подпись SSL-прокси с использованием boost::asio::ssl::stream
обертка для openssl.
я использую SSL_CTX_set_tlsext_servername_*
помощники, чтобы получить обратный вызов во время согласования SSL с клиентом.
В настоящее время убедитесь, что я использую сопрограмму и рукопожатие внутри лямбда от boost::asio::spawn
на strand
, Я использую обратный вызов с указанием имени сервера (соответствующим образом завернутый), чтобы я мог заблокировать клиентское рукопожатие во время серверного рукопожатия, но без блокировки рабочего потока (совместная подпрограмма будет приостановлена.
boost::asio::spawn(strand_, [=](boost::asio::yield_context yield){
boost::system::error_code ec;
boost::system::error_code ec_server;
sni_callback = [=,&ec](std::string server_name) {
server_->ssl_connection->ssl_socket.async_handshake(boost::asio::ssl::stream_base::client, yield[ec_server]);
/* Todo: sign the server certificate and replace the ssl_socket SSL_CTX here */
};
ssl_connection->ssl_socket.handshake(boost::asio::ssl:stream_base::server, ec);
if (! ec) ec = ec_server;
handler(ec);
});
Но я понимаю, что рукопожатие ssl с клиентом заблокирует рабочий поток, когда он завершит работу.
Я попытался Asyc рукопожатие с клиентом:
ssl_connection->ssl_socket.async_handshake(boost::asio::ssl:stream_base::server, yield[ec]);
но программа выдает ошибку в yield во время оболочки обработчика SNI.
Несомненно, это потому, что неблокирующее рукопожатие не вызывает обработчик SNI в сопрограмме — и единственный способ, которым он может это сделать (без блокировки рабочего потока), — это если все его внутренние обработчики вызываются в сопрограмме, но Я знаю, что он использует внутреннюю прядь для своей работы.
Со всеми загруженными символами совместно используемой библиотеки (даже для libstdc ++ и т. Д.) Трассировка стека:
.#0 0x000000000000000c in ?? ()
.#1 0x00007f8200000000 in ?? ()
.#2 0x00007f829e15043d in CRYPTO_free (str=0x7f828c054640) at mem.c:401
.#3 0x00007f829e1faba5 in ASN1_primitive_free (pval=<optimized out>, it=<optimized out>) at tasn_fre.c:261
.#4 0x00007f828c052250 in ?? ()
.#5 0x0000000000000005 in ?? ()
.#6 0x00007f828c0524f0 in ?? ()
.#7 0x0000000000000005 in ?? ()
.#8 0x00007f829d30c560 in ?? ()
.#9 0x00007f829d30c710 in ?? ()
.#10 0x000000000000000c in ?? ()
.#11 0x00007f828c0180b4 in ?? ()
.#12 0x00007f829e15043d in CRYPTO_free (str=0x7f828c052250) at mem.c:401
.#13 0x00007f829e1eb2cf in EVP_PKEY_CTX_free (ctx=<optimized out>) at pmeth_lib.c:381
.#14 0x00007f829e1de1e2 in EVP_MD_CTX_cleanup (ctx=0x7f829d30c590) at digest.c:394
.#15 0x00007f829e5041c1 in tls1_PRF (digest_mask=262400, seed1=0x7f829e5213fb, seed1_len=15, seed2=0x7f829d30c720, seed2_len=-1639094656, seed3=0x0,
seed3_len=-1657747584, seed4=0x23635fe, seed4_len=-1657747600, sec=0x7f82a0035df0 "\321\365M\236\202\177", slen=<optimized out>, out1=0x7f82a0035178 "d\356@",
out2=0x7f82a0038508 "", olen=4247053, seed5_len=0, seed5=0x0) at t1_enc.c:272
.#16 0x00007f829e4dbb18 in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
.#17 0x00007f829d30c780 in ?? ()
.#18 0x00000000023635fe in ?? ()
.#19 0x00007f829d30c770 in ?? ()
.#20 0x00007f82a0035df0 in ?? ()
.#21 0x0000000000000000 in ?? ()
Я ожидаю, что это трассировка стека во время очистки от ошибки.
Чтобы вызвать обработчик SNI в той же сопрограмме, я думаю, что мне нужно, чтобы все промежуточные обратные вызовы ssl :: stream выполнялись в этой сопрограмме.
Есть ли прямой способ сделать это?
Интересно, может ли boost :: ssl вызывать свои обработчики в своей собственной цепочке, но все еще в стеке сопрограмм, это единственное исправление, но я не знаю, достаточно ли у магии asio_handler_invoke с обработчиком магии, чтобы это произошло, даже если это было возможно. Как вы можете вложить asio_handler_invoke для запуска на сопрограмме (strand-y сама по себе) И через внутреннюю цепочку.
Также я должен использовать asio_invoke_handler в последней строке моего примера?
Задача ещё не решена.
Других решений пока нет …