Выключение SSLEngine

В документации SSLEngine указано, как правильно закрыть соединение SSL. В частности, он дает инструкции о том, как обращаться с разорванным соединением:

В дополнение к обычным отключениям также могут быть неупорядоченные отключения, при которых транспортный канал разрывается до обмена сообщениями о закрытии. В предыдущих примерах приложение могло получить -1 при попытке чтения или записи в неблокирующий SocketChannel. Когда вы дойдете до конца ваших входных данных, вы должны вызвать engine.closeInbound(), который проверит с помощью SSLEngine, что удаленный одноранговый узел закрылся правильно с точки зрения SSL/TLS, а затем приложение все еще должно попытаться завершить работу корректно. с помощью описанной выше процедуры.

По сути, если ссылка разорвана, следует вызвать engine.closeInbound(). Однако документация этого closeInbound() указывает, что он вызовет исключение, если он будет вызван до получения надлежащего закрывающего сообщения от однорангового узла. Мне кажется, что если соединение разорвано, это сообщение close_notify никогда не будет получено, поэтому этот метод всегда будет выдавать это исключение.

Я сделал тест, сделал простую процедуру выключения, где socketChannel.read() возвращает -1, я вызываю engine.closeInbound() и действительно получаю следующее исключение:

javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?

Что мне не хватает? Разве эти 2 части документации не противоречат друг другу?


person J_D    schedule 16.04.2014    source источник


Ответы (2)


Я не думаю, что эти две части документации противоречат друг другу.

Когда вы дойдете до конца ваших входных данных, вы должны вызвать engine.closeInbound()

Это относится как к чисто закрытым, так и к разорванным соединениям. Когда соединение будет разорвано, будет выдано исключение (т.е. если вы вызовете его до получения close_notify). Если было получено close_notify (или если соединение вообще не началось), это исключение не будет сгенерировано.

Я не совсем уверен, как вы сделали свой простой тест на выключение, но вы должны были сначала отправить close_notify с другого конца (например, с closeOutbound()). В этом случае вы не должны были получить -1 от socketChannel.read() до получения close_notify (и тогда вы не получили бы исключения).

(На всякий случай, если это интересно, недавно был похожий вопрос на SSLSocket.)

person Bruno    schedule 16.04.2014
comment
+1 Спасибо за разъяснение и за очень хорошо документированный ответ по предоставленной вами ссылке. Хотел бы я принять как ваш ответ, так и ответ EJP, так как оба мне в равной степени помогли. Я принял твое, потому что оно было первым. - person J_D; 17.04.2014

Вы неправильно это прочитали.

В основном, если ссылка разорвана, следует вызвать closeInbound().

Это вовсе не говорит об этом.

В нем говорится, что метод closeInbound() должен всегда вызываться, когда вы дойдете до конца ваших входных данных, и тогда он обнаружит любое разорванное соединение.

Если close_notify не получено, будет выдано исключение.

person user207421    schedule 16.04.2014
comment
+1 Спасибо за разъяснение и за четкое указание, что closeInbound обнаружит разорванное соединение, подтверждая, что исключение не является неожиданным. - person J_D; 17.04.2014