LINUX.ORG.RU

OpenSSL graceful завершение соединения, включая одностороннее

 


0

2

Я не удивлюсь, если там в библиотеке фундаментальный дефект на этот счёт, но возможно это просто непонятные маны.

Исходные данные:

1) есть функция int SSL_shutdown(SSL *ssl);

Краткое содержание мана: функция отправляет «close notify alert» и иногда ещё и принимает ответ на него (тоже «close notify alert») от той стороны. Возвращает: -1 если произошла ошибка либо нужно ждать читаемости/записываемости сокета, 0 если «close notify alert» отправлен успешно, но ответный ещё не получен, и 1, если и отправлен и получен.

Касательно возврата 0 там есть три пояснения:

а) если мы планируем закрывать сокет то можно этим и ограничиться и ответ не ждать

б) есть рекомендация вызвать SSL_shutdown() повторно чтобы принять ответ

в) есть рекомендация вызвать SSL_read() повторно чтобы принять ответ - да, в том же мане 4 абзацами ниже предыдущего утверждения, которому оно немного противоречит (подозреваю речь идет про SSL_ERROR_ZERO_RETURN, см. ниже, но это догадка)

2) есть ошибка SSL_ERROR_ZERO_RETURN, в мане к SSL_get_error описанная так: та сторона закрыла соединение для записи, отправив «close notify alert», читать данные больше нельзя (и уточнение что речь не идёт о сокете, а только об ssl-сессии).

Описание очень похоже на описание нуля, возвращённого из recv() для обычных BSD-сокетов, однако в инете я нашёл ряд репортов про получение этой ошибки от SSL_write(), так что кажется её может делать и он. Тут непонятно: ман говорит что нельзя больше читать, а оказывается что и запись тоже блокируется? В SSL/TLS вообще есть такое явление как наполовину закрытый поток, когда одна сторона завершила отправку и уведомила об этом, а потом только принимает ответ?

В мане какие-то мутные намёки на то, как будто оно есть, но не уточнено как с ним обращаться. Например, как известно, TLS иногда шлёт какие-то служебные данные, которые в итоге прозрачно обрабатываются во время вызова SSL_read/SSL_write. Пока соединение полностью открыто, с ними всё просто: узнаём что на уровне сокетов что-то пришло, вызывает SSL_read(), тот уже либо выяснит что это полезные данные и выдаст нам их, либо примет и обработает служебные и скажет что пользовательских пока нет. Если же та сторона сделала shutdown и нам SSL_read возвращает только SSL_ERROR_ZERO_RETURN, то кем читать пришедшие байты? SSL_write не годится, если мы пока что не хотим ничего записывать, а оставлять их в сокете тоже нельзя - они будут постоянно триггерить select() или его аналоги. Убирать сокет из select-а тоже нельзя - тогда мы не узнаем если он вдруг закроется уже на уровне tcp.

Или, может быть, всё проще, и SSL_ERROR_ZERO_RETURN следует считать как «соединение умерло, закрываем всё что осталось», а в мане просто враньё? Смущает фраза из мана SSL_shutdown: «the peer is still allowed to send data after receiving the close_notify event», и рядом ещё ода рекомендация использовать именно SSL_read вместо повторного SSL_shutdown.

★★★★★
Ответ на: комментарий от seiken

Во варианте а) проблем нет. Это я просто написал существенные аспекты, которые из манов понятны, чтобы был контекст.

Проблема главным образом такая: та сторона сделала shutdown, мы подозреваем что она всё ещё ждёт чего-то от нас, а не просто хочет закрыть коннект - такое может быть? Маны вроде бы такое не запрещают и пишут что shutdown закрывает только исходящую половину канала, а приём может продолжаться. Но как обрабатывать такое полузакрытое соединение не совсем понятно.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

мы подозреваем что она всё ещё ждёт чего-то от нас

Но как обрабатывать такое полузакрытое соединение не совсем понятно.

по идее, это должно быть ясно из протокола более высокого уровня. Если нужно писать в полузакрытое состояние - пиши.

seiken ★★★★★
()

Как-то натыкался на проблемы с этим. Но, кажись, писатели RFC, разработчики SSL/TLS (и с TCP надо было считаться) хорошенько запутали всё:

gag ★★★★★
()
Ответ на: комментарий от gag

Не, по ссылкам немного другое: они закрывают TCP-сокет вслед за TLS-записью. Такое делать нельзя, и не только в TLS1.3 но и в более ранних версиях, и об этом вполне прозрачно сказано в манах к SSL_read/SSL_write: обе этих функции могут захотеть, помимо чисто приёма/отправки полезной нагрузки, обменяться с пиром какими-то служебными данными в любую сторону. Кажется, в TLS1.2 и раньше, тем не менее, это нарушение спецификации почти всегда прокатывало т.к. служебные данные слались реже.

Я же про другое: сокет мы не закрываем ни в одну из сторон, то есть openssl может свободно им пользоваться. Закрываем только одно из направлений ssl-канала с помощью SSL_shutdown. И пользуемся после закрытия второй половиной канала, которая осталась. Пример:

// клиент
SSL_connect();
while(...) SSL_send();
SSL_shutdown();
while(...) SSL_recv();
SSL_free();
close();

// сервер
SSL_accept();
while(...) SSL_recv();
// получили ZERO_RETURN от SSL_shutdown, вызванного на клиенте
while(...) {
  // some code
  if(...) SSL_send();
}
SSL_shutdown();
SSL_free();
close();

Отмечу, что ситуация выше вполне может соответствовать работе обычного https-сервера/клиента, при условии что не используется keep-alive: клиент отослал запрос, закрыл свою отправку, и потом читает ответ. Сервер прочитал запрос, получил «конец данных» от клиента, приступил к обработке запроса (допустим он длинный и асинхронный) и иногда шлёт какие-то части ответа. Проблема в том, как серверу теперь узнавать об изменениях состояния SSL-сессии в те моменты, когда ему не требуется делать SSL_send(). Вдруг клиент её уже закрыл, а сервер зря продолжает свои асинхронные обработки. Да, ничего совсем страшного не случится, сервер об этом узнает когда попытается сделать SSL_send(), но по-нормальному это должно становиться известно сразу же.

firkax ★★★★★
() автор топика

возможно это просто непонятные маны.

Маны-то как раз предельно простые и понятные. Непонятно, как ты их не понял.

Тут непонятно: ман говорит что нельзя больше читать, а оказывается что и запись тоже блокируется?

Тут всё предельно понятно:

SSL_shutdown() only closes the write direction. It is not possible to call SSL_write() after calling SSL_shutdown().

Смущает фраза из мана SSL_shutdown: «the peer is still allowed to send data after receiving the close_notify event», и рядом ещё ода рекомендация использовать именно SSL_read вместо повторного SSL_shutdown.

Тут нечего "смущаться" - ты закрываешь соединение со своей стороны через SSL_shutdown() и ждёшь через SSL_read(), когда другая сторона закроет его. SSL_read() в этом случае в какой-то момент должен вернуть тебе ошибку чтения. Это полностью совпадает по механике работы с tcp-сокетами или чтением из сокета / pipe’а, и рекомендуется делать именно так:

it is possible to call SSL_shutdown() again to wait for the peer’s close_notify alert. SSL_shutdown() will return 1 in that case. However, it is recommended to wait for it using SSL_read() instead.

В этом месте API разработан как прозрачная замена обычным сокетам.

Отмечу, что ситуация выше вполне может соответствовать работе обычного https-сервера/клиента, при условии что не используется keep-alive:

Верно, поэтому и рекомендуется дожидаться ошибки через SSL_read() - так ты выберешь все данные и корректно закроешь текущую сессию, которая потом может быть переиспользована.

как серверу теперь узнавать об изменениях состояния SSL-сессии в те моменты, когда ему не требуется делать SSL_send().

Ничем не отличается от send() / write() для сокета. Если тебе не требуется - ты и не спрашиваешь. Когда требуется - либо отправляешь, либо закрываешь.

Вдруг клиент её уже закрыл, а сервер зря продолжает свои асинхронные обработки.

Если клиент закрыл сокет, ты получишь ошибку записи.

сервер об этом узнает когда попытается сделать SSL_send()

Подожди, а о каких "асинхронных обработках" шла речь, если кроме сенда и шатдауна ты ничего и сделать-то больше не можешь?

по-нормальному это должно становиться известно сразу же.

Это и "становится известно сразу же" как только ты спросишь. А если не спросишь - будет дальше не известно. Никакой разницы с обычным tcp.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Подожди, а о каких «асинхронных обработках» шла речь, если кроме сенда и шатдауна ты ничего и сделать-то больше не можешь?

О таких, что работа сервера не ограничивается пересылкой данных клиенту, он может ещё делать какие-то расчёты, или ждать ответа от диска, или ждать ответа от проксированного бекэнда. Если он вовремя (а не только при попытке отослать ответ) узнает что клиенту уже ничего не нужно, он может сэкономить свои ресурсы.

Это и «становится известно сразу же» как только ты спросишь. А если не спросишь - будет дальше не известно.

Вот и вопрос - как спросить, не отсылая никаких байтов?

Аналогия с сокетами понятна, но она не совсем правильная. TLS сам по себе вполне позволяет узнать о закрытой сессии не пытаясь в неё ничего записать (открытая сессия требует открытого двустороннего tcp, соответственно как только tcp закрывается хотя бы в одну сторону - tls-сессию можно считать полностью закрытой), но вот соответствующего апи в openssl я что-то не вижу. Опрашивать сокет напрямую тоже не годится - в него могут прийти данные, которые надо обработать openssl-ем, но опять же функции «прими что там прислали служебное» я не вижу, она есть только в неявном виде как часть SSL_write.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

работа сервера не ограничивается пересылкой данных клиенту, он может ещё делать

Это не имеет отношения к SSL, и ничем не отличается от обычных сокетов.

Аналогия с сокетами понятна, но она не совсем правильная.

Полностью правильная.

TLS сам по себе вполне позволяет узнать о закрытой сессии не пытаясь в неё ничего записать (открытая сессия требует открытого двустороннего tcp, соответственно как только tcp закрывается хотя бы в одну сторону - tls-сессию можно считать полностью закрытой),

Ты делаешь очень много допущений о том, что и как работает уровнем ниже. Оно может работать так, а может и по другому (в зависимости от выбранных протоколов шифрования к примеру). Тебе предоставлен публичный API, имеющий одинаковую семантику с TCP. То есть, ты можешь прозрачно перенести логику работы с нешифрованным tcp-сокетом на шифрованный.

функции «прими что там прислали служебное» я не вижу

Если тебя обуревает ОКР вместо решения практической задачи, то к твоим услугам SSL_get_shutdown(), которая вернёт тебе SSL_RECEIVED_SHUTDOWN, если тебе за каким-то рожном надо обработать именно это событие от удалённой стороны. Но если за ним сразу будет следовать SSL_read() - это будет просто тупо.

Что же касается

прими что там прислали служебное

то в ssl-коде пока ещё нет телепатов узнавать, что же именно прислали - только ли служебное или не только.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Это не имеет отношения к SSL

И что? Ты как-то странно читаешь что я пишу, додумываешь каике-то заявления которых я не делал.

Ты делаешь очень много допущений о том, что и как работает уровнем ниже. Оно может работать так, а может и по другому (в зависимости от выбранных протоколов шифрования к примеру).

Это не допущения.

Тебе предоставлен публичный API, имеющий одинаковую семантику с TCP. То есть, ты можешь прозрачно перенести логику работы с нешифрованным tcp-сокетом на шифрованный.

Во-первых, не путай: TCP то не апи а протокол. Апи это сокеты. И так вот, семантика не одинаковая. У сокетов есть возможность заранее распознать закрывание на той стороне, например см. man epoll_ctl,

EPOLLERR
Error condition happened on the associated file descriptor.  This event is also reported for the write end of a pipe when the read end has been closed.

то к твоим услугам SSL_get_shutdown(), которая вернёт тебе SSL_RECEIVED_SHUTDOWN

Ты читать не умеешь или как? Принятый шатдаун я вижу и без этого, от SSL_read, я об этом уже три раза писал. Только вот он не означает, что та сторона завершила приём данных, а интересует именно это.

то в ssl-коде пока ещё нет телепатов узнавать, что же именно прислали - только ли служебное или не только.

Причём тут телепаты? Приняли, распарсили и узнали.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

додумываешь каике-то заявления которых я не делал.

Где? Какие?

Это не допущения.

Это допущения. Ты понятия не имеешь ни малейшего какой именно механизм шифрования и обмена данных будет использован в конкретной сессии. Это решается хэндшейком и переговорами с обоих сторон.

Это не имеет отношения к SSL

И что?

И то, что SSL тут не при чём. Если тебя интересует вопрос про сокеты - спрашивай про сокеты.

Только вот он не означает, что та сторона завершила приём данных, а интересует именно это.

Так никакой протокол без подтверждения данных не означает, что та сторона завершила приём. Опять же причём тут SSL ? Чем твой вопрос будет отличаться, если его задать про tcp?

У сокетов есть возможность заранее распознать закрывание на той стороне, например см. man epoll_ctl,

Чем тебе SSL_get_shutdown() с SSL_RECEIVED_SHUTDOWN не заменяет EPOLLERR?

функции «прими что там прислали служебное» я не вижу
Причём тут телепаты? Приняли, распарсили и узнали.
Ты читать не умеешь или как?

А ты писать умеешь или как? Нужная тебе функция "Приняли, распарсили и узнали." - это SSL_read() , но она почему-то тебе не нужна.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

По имение и неимения отношения - хватит флудить, прочти нормально вопрос, там всё нормально написано.

Чем тебе SSL_get_shutdown() с SSL_RECEIVED_SHUTDOWN не заменяет EPOLLERR?

Тем, что это всё про завершение отправки на той стороне (в терминах epoll это EPOLLHUP/EPOLLRDHUP), а я про завершение приёма.

Нужная тебе функция «Приняли, распарсили и узнали.» - это SSL_read() , но она почему-то тебе не нужна.

Насколько я понял, SSL_read перестаёт работать после того как оттуда шатдаун прислали, и начинает возвращать ZERO_RETURN сходу. Это не так?

Так никакой протокол без подтверждения данных не означает, что та сторона завершила приём. Опять же причём тут SSL ? Чем твой вопрос будет отличаться, если его задать про tcp?

Да, есть такое, но в большинстве случаев после завершения приёма та сторона закроет и сокет на своей стороне. Чтобы узнать про закрытый сокет, надо сначала прочитать возможно присланные перед закрытием данные. Во время чтения данных мы ещё не знаем, будет ли после них закрываться сокет или же нет, поэтому просто выкинуть их нельзя, их надо именно заставить прочесть openssl.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

нормально вопрос, там всё нормально написано

Да через жопу там всё описано - хрен поймёшь, чего тебе надо.

а я про завершение приёма.

Ты хочешь определить сценарий, когда удалённая сторона заблокировала от тебя приём данных, тогда как ты со своей стороны ещё не отправлял SSL_shutdown() ? Такого механизма в SSL нет. Разрабы не захотели придумывать специальную хитрожопую логику на экзотический сценарий, когда оба конца выполнят на своей стороне условные shutdown(sock, SHUT_RD). Потому что интуитивно кажется, что читать данные после этого уже не надо, но SSL ещё нужно корректно завершить сессию, что требует обмена пакетами. Кроме того, SSL может без полезной нагрузки произвести обмен служебными пакетами, поэтому блокировать передачу уровнем ниже нельзя.

И да, твой ОП-пост вообще не про это, а про коды возврата из уже вызванного SSL_shutdown(), еслишто.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Ты хочешь определить сценарий, когда удалённая сторона заблокировала от тебя приём данных, тогда как ты со своей стороны ещё не отправлял SSL_shutdown() ? Такого механизма в SSL нет.

Я выше описал как это делается и чего не хватает с openssl (именно в библиотеке а не в протоколе) для этого.

Разрабы не захотели придумывать специальную хитрожопую логику на экзотический сценарий, когда оба конца выполнят на своей стороне условные shutdown(sock, SHUT_RD).

Всё проще - одна из сторон сделала close(), и сценарий это самый обычный.

Кроме того, SSL может без полезной нагрузки произвести обмен служебными пакетами, поэтому блокировать передачу уровнем ниже нельзя.

В том и дело. Пока передача не заблокирована - одностороннее соединение есть, когда она заблокирована - значит его нет.

И да, твой ОП-пост вообще не про это, а про коды возврата из уже вызванного SSL_shutdown(), еслишто.

Надо читать до уконца всё а не наискокок. Ты прочитал только введение где описана логика работы шатдауна, а до вопроса не дошёл.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

Я выше описал как это делается

А я выше, но ниже твоего описания, описал, почему это так не делается.

Надо читать до уконца всё а не наискокок. Ты прочитал только введение где описана логика работы шатдауна, а до вопроса не дошёл.

Ну, давай разберём по частям тобою написанное:

  1. Тут непонятно: ман говорит что нельзя больше читать, а оказывается что и запись тоже блокируется?
  2. В SSL/TLS вообще есть такое явление как наполовину закрытый поток, когда одна сторона завершила отправку и уведомила об этом, а потом только принимает ответ?
  3. Если же та сторона сделала shutdown и нам SSL_read возвращает только SSL_ERROR_ZERO_RETURN, то кем читать пришедшие байты?
  4. Или, может быть, всё проще, и SSL_ERROR_ZERO_RETURN следует считать как «соединение умерло, закрываем всё что осталось», а в мане просто враньё?

У тебя тут четыре (прописью - четыре) вопроса.

Тут непонятно: ман говорит что нельзя больше читать, а оказывается что и запись тоже блокируется?

На этот я тебе ответил первым постом.

В SSL/TLS вообще есть такое явление как наполовину закрытый поток, когда одна сторона завершила отправку и уведомила об этом, а потом только принимает ответ?

На этот у тебя есть ответ в твоём собственном ОП-посте:

the peer is still allowed to send data after receiving the close_notify event

Я кажется понял, на каком месте ты заблудился в трёх соснах.

Или, может быть, всё проще, и SSL_ERROR_ZERO_RETURN следует считать как «соединение умерло, закрываем всё что осталось», а в мане просто враньё?

См.:

When the underlying connection shall be used for more communications, the complete shutdown procedure (bidirectional «close notify» alerts) must be performed, so that the peers stay synchronized.

Note that in this case SSL_ERROR_ZERO_RETURN does not necessarily indicate that the underlying transport has been closed.

В случае tcp-сокета SSL_ERROR_ZERO_RETURN означает, что ты можешь продолжать обмен данными по сокету теперь без шифрования. Так к примеру работает FTP(s). В т.ч. по этому сам сокет надо потом закрывать руками самому.

Если же та сторона сделала shutdown и нам SSL_read возвращает только SSL_ERROR_ZERO_RETURN, то кем читать пришедшие байты?

Любым read()’ом / recv()’ом. Это теперь обычные не шифрованные данные.

Всё проще - одна из сторон сделала close(), и сценарий это самый обычный.

Без шатдауна этот сценарий не обычный, но если одна из сторон сделала close() на свой конец, то другая будет получать ошибку на любую операцию с ssl-хэндлом, включая SSL_shutdown().

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Ну что такое, ты опять надёргал каких-то отрывков и отвечаешь на них полностью забыв о контексте и местами переврав вопросы. Неужели так сложно принять простой вопрос?

Без шатдауна этот сценарий не обычный,

Никто не говорит про «без шатдауна».

но если одна из сторон сделала close() на свой конец, то другая будет получать ошибку на любую операцию с ssl-хэндлом, включая SSL_shutdown().

Какую операцию то? SSL_shutdown мы вызывать не хотим т.к. возможно ещё что-то отправим (иначе бы и проблемы не возникло), SSL_write - пока слать нечего, а SSL_read и так выдаёт ошибку без close.

Ещё раз повторю суть беседы, постарайся её принять целиком не вытаскивая из неё отдельные утверждения:

1) есть два пира A и B, они успешно настроили SSL сессию (SSL_connect/SSL_accept) и как-то её пользуются

2) в какой-то момент пир A вызывает SSL_shutdown, после чего пир B получает SSL_ERROR_ZERO_RETURN, но на данный момент у пира B нет уверенности в том, что он больше ничего не хочет слать пиру A, впрочем данных для отправки прямо сейчас у него тоже нет

Дальнейшее развитие событий может произойти тремя способами:

3а) пир A после этого вызывает ещё close()

3б) пир A после этого начинает цикл SSL_read()

3в) пир A после этого начинает цикл SSL_read(), но в какой-то момент всё-таки делает close()

Вопрос такой: как пиру B узнать про close(), сделанный пиром A до того, как у пира B появятся данные для отправки? Портить состояние SSL-сессии (читать данные из сокета в обход openssl) при этом нельзя.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 3)
Ответ на: комментарий от firkax

Ещё раз повторю суть беседы,

Вот в таком формате надо было сделать ОП-пост.

3б) и 3в) - это одно и тоже, если шатдаун не пропущен. В любом случае сокет надо будет закрыть.

а SSL_read и так выдаёт ошибку без close.

SSL_read() + SSL_get_error() возвращающий тебе SSL_ERROR_ZERO_RETURN означает, что у тебя есть рабочая SSL-сессия, но нет данных для чтения. Когда удалённая сторона закроет сокет со свой стороны, SSL_read() / SSL_get_error() вернёт тебе другую ошибку (SSL_ERROR_SYSCALL).

Т.е. для тебя порядок и логика вызвов функций во всех трёх случаях (3а - 3в) одни и те же.

LamerOk ★★★★★
()
Последнее исправление: LamerOk (всего исправлений: 3)
Ответ на: комментарий от LamerOk

Когда удалённая сторона закроет сокет со свой стороны, SSL_read() / SSL_get_error() вернёт тебе другую ошибку (SSL_ERROR_SYSCALL).

Это так, только если удалённая сторона SSL_shutdown перед этим не сделала.

В зависимости от её действий (слева) получаются такие результаты SSL_read на другой стороне (справа):

1) ничего не делать - WANT_READ

2) close - SSL_shutdown - SYSCALL, errno=ECONNRESET

4) shutdown(SHUT_WR)+close - SYSCALL, errno=0

5) SSL_shutdown - ZERO_RETURN

6) SSL_shutdown+close - ZERO_RETURN

7) SSL_shutdown+shutdown(SHUT_WR)+close - ZERO_RETURN

То есть, как я и ожидал, если SSL_read принял с той стороны шатдаун то дальше он работать полностью перестаёт и на изменение состояния сокета не реагирует. Единственное, чего я не проверил - что будет если ему в этот сокет прислать служебные пакеты, но я не знаю как это организовать.

Если после этого SSL_read ZERO_RETURN сделать SSL_write - то уже разное поведение: с незакрытым сокетом (вариант 5) он выполняется успешно, с закрытым (варианты 6 и 7) - тоже возвращает ZERO_RETURN. Но, повторюсь, чтобы вызывать SSL_write, надо иметь данные для отправки, а они есть не всегда.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от LamerOk

Опять по кругу начнём? Я выше писал почему через селект нельзя. Там могут быть служебные пакеты tls и их оттуда над прочитать чтобы выявить конец tcp-соединения. А читать нечем.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

Там могут быть служебные пакеты

После SSL_read() + SSL_get_error() возвращающий тебе SSL_ERROR_ZERO_RETURN уже не могут.

tls и их оттуда над прочитать чтобы выявить конец tcp-соединения

Не tcp-соединения, а ssl-сессии. Еще раз - после закрытия ssl-сессии само соединение остаётся открытым.

LamerOk ★★★★★
()
Последнее исправление: LamerOk (всего исправлений: 1)
Ответ на: комментарий от LamerOk

После SSL_read() + SSL_get_error() возвращающий тебе SSL_ERROR_ZERO_RETURN уже не могут.

С чего это не могут? Обновления сессионных ключей по таймауту какие-нить например. Мы ж запись в сокет не закрывали.

Не tcp-соединения, а ssl-сессии. Еще раз - после закрытия ssl-сессии само соединение остаётся открытым.

Нет, речь про соединение. Ты опять контекст теряешь? Та сторона могла сделать close после SSL_shutdown а могла и не делать. Если второе - могла присылать службные пакеты, могла не присылать.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

С чего это не могут?

С того, что на сокете на другом конеце был вызвал SSL_shutdown(). После этого других ssl-пакетов по этому каналу уйти не может:

Whether the operation succeeds or not, the SSL_SENT_SHUTDOWN flag is set and a currently open session is considered closed …

После обработки ушедших к тебе ssl-пакетов на твоём конце, тебе в вечном цикле будет выдавать SSL_ERROR_ZERO_RETURN, пока ты не закроешь сокет:

Обновления сессионных ключей по таймауту какие-нить например.

Не будет. Сессия закрыта, все ушли на фронт. Если таймаут чего-нибудь протухнет, то ты получишь ошибку крипотграфии, но более вероятно, что вообще ничего работать не будет.

LamerOk ★★★★★
()
Ответ на: комментарий от firkax

Нет, речь про соединение. Ты опять контекст теряешь?

Нетты. Еще раз - close() будет обработан как SSL_ERROR_SYSCALL.

после SSL_shutdown а могла и не делать. Если второе - могла присылать службные пакеты

Нет, не могла прислать.

SSL_shutdown() only closes the write direction.

Служебный пакет, который к тебе придёт от SSL_shutdown() - последний пакет в сессии с того конца, после него SSL-пакетов не будет. Как только он обработан на твоём конце, тебе прилетит SSL_ERROR_ZERO_RETURN. Это значит, что SSL-сессия окончена для той стороны.

LamerOk ★★★★★
()
Последнее исправление: LamerOk (всего исправлений: 2)
Ответ на: комментарий от LamerOk

После обработки ушедших к тебе ssl-пакетов на твоём конце, тебе в вечном цикле будет выдавать SSL_ERROR_ZERO_RETURN, пока ты не закроешь сокет:

Опять... Да, закрыто одно направление, второе осталось и работает - слать пакеты можно.

firkax ★★★★★
() автор топика
Ответ на: комментарий от LamerOk

Нетты. Еще раз - close() будет обработан как SSL_ERROR_SYSCALL.

Нет, не будет, я тебе уже показывал что там ZERO_RETURN вместо этого.

Служебный пакет, который к тебе придёт от SSL_shutdown() - последний пакет в сессии с того конца, после него SSL-пакетов не будет.

Это противоречит заявлению в мане о том, что SSL_write может WANT_READ. Пакеты не только могут приходить, они могут ещё и требоваться для успешной отправки данных.

firkax ★★★★★
() автор топика
Ответ на: комментарий от LamerOk

Попробуй, отправь себе что-нибудь.

Прекращай опять выдумки, я ничего не писал про приём полезных данных. Писал про служебные, а они могут приниматься в целях отправки полезных.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

Писал про служебные, а они могут приниматься в целях отправки полезных.
Это противоречит заявлению в мане о том, что SSL_write может WANT_READ.

Это не противоречит, потому что эта схема с закрытым с одной стороны концом работать не будет. Попробуй добиться, чтобы после SSL_ERROR_ZERO_RETURN тебе пришёл WANT_READ и прочитать что-нибудь. Накидай с другого конца с таймаутами - у тебя где-то всё свалится к херам.

LamerOk ★★★★★
()
Последнее исправление: LamerOk (всего исправлений: 2)
Ответ на: комментарий от firkax

Попробуй, отправь себе что-нибудь.

Прекращай опять выдумки, я ничего не писал про приём полезных данных.

Ну, не себе, в другую сторону - в ту, которую еще не закрыл.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Прекрасно всё шлётся в другую сторону. То есть SSL_shutdown + while(1) SSL_read читает SSL_write-ы другой стороны, делающиеся в таком же цикле.

Попробуй добиться, чтобы после SSL_ERROR_ZERO_RETURN тебе пришёл WANT_READ

Я не знаю как этого добиться, у меня SSL_write вообще никакие WANT не делает.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

SSL_shutdown + while(1) SSL_read читает SSL_write-ы другой стороны

И кто-нибудь из них вернул WANT_READ ? Попробуй выставить через SSL_CTX_set_timeout() какое-нибудь малое значение сессии и посмотри, как оно себя поведёт.

LamerOk ★★★★★
()
Ответ на: комментарий от firkax

у меня SSL_write вообще никакие WANT не делает.

У тебя в рамках сессии сессионые синхронные ключи после хендшейка, пока они действуют, ты можешь шитпостить. Как протухнут потребуется новый хендшейк. Я ставлю на то, что после шатдауна он не сработает.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Как узнать что он случился? Поставил SSL_CTX_set_timeout(10), SSL_get_timeout() показывает его же, а вот SSL_get_time() хранит время начала и никуда не меняется через 10 секунд. SSL_write никаких WANT_READ тоже не делает.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

Попробуй через SSL_get_session() получить саму сессию, через SSL_SESSION_get_timeout() - таймаут сессии, изменить его с помощью SSL_SESSION_set_timeout(), а потом через SSL_SESSION_get_time_ex() и SSL_SESSION_set_time_ex() сменить время создания сессии так, чтобы таймаут протух.

LamerOk ★★★★★
()