SSL_Read () возвращает SSL_ERROR_ZERO_RETURN, но ERR_get_error () равен 0

Я пишу неблокирующий клиент Websocket и использую OpenSSL для уровня TLS. Я могу подключиться к удаленному серверу, выполнить квитирование TLS, отправить запрос на обновление, получить ответ, подтверждающий обновление, и получить реальный ответ через веб-сокет, прежде чем уровень TLS отключится с помощью SSL_ERROR_ZERO_RETURN,

SSL_get_error(...) возвращает: 6 // SSL_ERROR_ZERO_RETURN

ERR_error_string(ERR_get_error(), nullptr) возвращает: error:00000000:lib(0):func(0):reason(0)

Из моего понимания, ERR_get_error() должен появиться и вернуть первую ошибку в очередь ошибок, и SSL_get_error() возвращает последнюю ошибку SSL_* функция. я не понимаю почему SSL_get_error() вернет значение ошибки, но ERR_get_error() не. Согласно этому предыдущему Вопрос переполнения стека, SSL_get_error() НЕ звонит ERR_get_error(),

Следующий код вызывается повторно (так как это неблокирующий сокет):

ERR_clear_error();
int ret = SSL_read(...);
if (ret > 0) {
// read bytes from socket
} else {
int err_code = SSL_get_error(ssl_session_, ret);
if (err_code == SSL_ERROR_ZERO_RETURN || err_code == SSL_ERROR_SYSCALL || err_code == SSL_ERROR_SSL) {
sprintf("Disconnected: %d %s", err_code, ERR_error_string(ERR_get_error(), nullptr));
// Disconnect Code
}
}

У меня есть два вопроса:

  1. Почему я не получаю значение ошибки для ERR_get_error ()?

  2. Почему я так быстро отключаюсь после установления сеанса TLS и Websocket?

РЕДАКТИРОВАТЬ 1

Я использовал wireshark для захвата пакетов между клиентом и сервером. Я подтвердил, что квитирование TLS, обновление websocket и первоначальный ответ сервера были успешными. Я заметил, что после первоначального ответа сервера мой клиент получает Encrypted Alert 21 с сервера, который, по моему мнению, является фатальной ошибкой и объясняет, почему сеанс TLS завершается немедленно, а моя очередь ошибок SSL пуста (хотя это, вероятно, проблема на стороне клиента, я не думаю, что это результат недавнего действия), и вид объясняет SSL_ERROR_ZERO_RETURN значение, которое я получаю после SSL_Read,

Я не уверен, что Encrypted Alert 21 влечет за собой. Это может быть сертификат, который я использую (самоподписанный). Нужно расследовать дальше.

0

Решение

Хорошо, коренная причина проблемы была определена, но было прыгнуто много обручей, и время было потрачено, чтобы добраться туда. Я смог расшифровать трафик SSL, взяв главный ключ, используя метод OpenSSL, SSL_SESSION_get_master_key (), и случайное значение Hello клиента с помощью wireshark.

Соответствующий код для вывода мастер-ключа после SSL_Connect:

ERR_clear_error();
int ret = SSL_connect(ssl_ptr);
if (ret > 0) {
SSL_SESSION * ssl_session = SSL_get_session(ssl_ptr);
if(ssl_session != NULL) {
unsigned char master_key_buf[256];
size_t outlen = sizeof(master_key_buf);
size_t buf_size = SSL_SESSION_get_master_key(ssl_session, master_key_buf, outlen);
if(outlen > 0) {
char hex_encoded_master_buf[513];
// hex encode the master key
for(size_t i = 0; i < buf_size; ++i) {
sprintf(&hex_encoded_master_buf[2*i], "%02x", master_key_buf[i]);
}
hex_encoded_master_buf[(2*buf_size)] = '\0';
// log out the hex-encoded master key in master buf here
}
}
}

С использованием Журнал ключей NSS CLIENT_RANDOM Формат в Wireshark для расшифровки захваченного трафика SSL, я смог изучить вышеупомянутые Encrypted Alert 21 который в итоге оказался просто WebSocket FIN и close_notify.

Оказывается, основной причиной было то, что во время рукопожатия мое сообщение с запросом на обновление WSS действительно содержало правильные заголовки, но я фактически отправлял полезную нагрузку вместе с ним. Это был случай установки размера с помощью sizeof буфера сообщений вместо strlen при отправке сообщения. Сервер отлично бы проанализировал сообщение Upgrade и успешно завершил рукопожатие, но в следующий раз, когда он проверял свой сокет, он считывал мусор, когда ожидал сообщение WSS. Это вызвало внезапное закрытие соединения websocket.

В заключение, чтобы ответить на мои оригинальные два вопроса:

  1. Почему я не получаю значение ошибки для ERR_get_error ()?

Соединение прерывается на стороне сервера, а очередь ошибок будет содержать ошибки на стороне клиента, которых нет, по крайней мере на уровне SSL / TLS.

  1. Почему я так быстро отключаюсь после установления сеанса TLS и Websocket?

Мой начальный запрос на обновление содержал действительный запрос на обновление Websocket, за которым следовали данные мусора. Сервер проанализировал запрос на обновление Websocket, подтвердил обновление и начал отправлять данные обратно. В следующий раз, когда сервер проверил свой сокет, у него все еще были значения мусора, которые были отправлены с оригинальным Запросом на обновление Websocket. Поскольку сервер не распознал его как допустимое сообщение Websocket или что-либо еще в этом отношении, он решил разорвать соединение с close_notify,

-1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]