Я разрабатываю простой клиент FTPS на C ++. Связь через канал управления работает по протоколу SSL, но у меня проблемы с получением списка файлов. В настоящее время я делаю следующую последовательность:
open control connection
AUTH TLS
do handshake on control connection
USER username
PASS password
PBSZ 0
PROT P
EPSV
open data connection
TYPE A
LIST
read data connection
Если я пытаюсь напрямую создать ssl-соединение (в фазе открытого соединения для передачи данных), создание соединения завершается неудачно. Если я создаю соединение, но выполняю квитирование только после отправки команды LIST, квитирование будет успешным, но клиент не получит никаких данных с сервера. Это моя логика открытия подключения к данным (1 для прямого ssl, 2 для рукопожатия по требованию):
SSL* ssl;
BIO* bioSsl;
int err;
SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
1) err = BIO_new_ssl_connect(ctx);
2) err = BIO_new_connect(host.c_str());
err = BIO_do_connect(bio);
2) bioSsl = BIO_new_ssl(ctx, 1);
2) bio = BIO_push(bioSsl, bio);
BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
Подключение для чтения данных осуществляется с помощью функции BIO_read (). Всегда возвращает 0 (примечание: я могу читать управляющий сокет и получать данные таким образом). Существующие клиенты могут получать список файлов с сервера, поэтому проблема не на стороне сервера. Может кто-нибудь объяснить, что происходит, я делаю что-то не так в последовательности? Почему происходит сбой рукопожатия при подключении к данным, если оно инициировано перед командой LIST? Любой другой совет также приветствуется!
Я нашел ответ. Проблема заключалась в том, что сервер требовал повторного использования ssl-сессий между управлением и подключением к данным. Сработало после добавления (псевдокод)
SSL_SESSION s = SSL_get_session(controlSsl);
dataSsl = BIO_get_ssl(dataBio);
SSL_set_session(dataSsl, s);
Других решений пока нет …