Ошибка вызова SSPI, см. Внутреннее исключение, используя FileZilla Server и System.Net.FtpClient

Я настраиваю FTP-сервер (FileZilla) и используя netftp codeplex projectSystem.Net.FtpClient подключиться к нему через SSL/TLS используя X509Certificate2,

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

Происходит исключение вызова client.GetListing() а также client.GetNameListing()Тем не менее, загрузка (OpenWrite) и скачивание (OpenRead) оба работают нормально. Я проверил много версий FileZilla чтобы изолировать какую версию он начал ломать.

  • 0.9.42 работы (2013-12-16)
  • 0.9.43 плохо (2014-01-02)
  • 0.9.46 плохо (2014-08-03)
  • 0.9.50 плохо (2015-03-19) - текущий

Возникает исключение:

  • внешнее сообщение: A call to SSPI failed, see inner exception.
  • внутреннее сообщение: The message received was unexpected or badly formatted

Пример кода C#, который вызывает ошибку:

FtpClient client = new FtpClient();
client.Credentials = new NetworkCredential("blah", "blah123");
client.Host = "127.0.0.1";
client.Port = 21;
client.DataConnectionEncryption = true;
client.EncryptionMode = FtpEncryptionMode.Explicit;
//client.ClientCertificates.Add(cert); // tried both with and without
client.ValidateCertificate += (cli, e) => { e.Accept = true; };
client.Connect();
var list = client.GetNameListing(); // exception on this line

На странице документации Codeplex jptrosclair писал:

Вы не используете сертификаты pem, вместо этого используйте p12. См. Этот поток переполнения стека для получения дополнительной информации. Если вы получаете исключения SPPI с внутренним исключением в отношении неожиданного или плохо отформатированного сообщения, возможно, вы используете неправильный тип сертификата.

Ссылка относится к asp.netне FileZilla, Я думаю, что IIS не поддерживает PEM и, скорее всего, посылал кучу тарабарщины через ручей. Однако если вы используете формат сертификата, который поддерживает ваш сервер, то проблем быть не должно. Насколько я прочитал, FileZilla только поддерживает PEM формат (или CRT/CER которые все еще PEM формат).

Кроме того, это не объясняет, почему OpenRead а также OpenWrite преуспеть, но GetListing а также GetNameListing потерпеть поражение.

Несмотря на это, я все еще тестировал несколько различных инструментов генерации сертификатов, в том числе FileZilla's встроенный генератор, C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\makecert.exe, а также OpenSSL (windows), Проблема все еще сохраняется.

Вот ссылка на аналогичное обсуждение от skovachev https://netftp.codeplex.com/discussions/535815 Его обходной путь заключался в клонировании соединения перед получением списка.

Временное решение:

Я проверил следующее со всеми FileZilla версии, перечисленные выше. Исправление заключается в загрузке System.Net.FtpClient исходный код от codeplex и в FtpSocketStream.csКласс редактировать следующий метод:

public void ActivateEncryption(string targethost, X509CertificateCollection clientCerts)

менять:

m_sslStream.AuthenticateAsClient(targethost, clientCerts, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true);

чтобы:

m_sslStream.AuthenticateAsClient(targethost, clientCerts, SslProtocols.Tls | SslProtocols.Ssl3, true);

(В основном просто удалитьSsl2флаг).

Я думаю, что-то изменилось в FileZilla v0.9.43 когда Ssl2 флаг устанавливается при подключении к серверу. Странно, что первый раз AuthenticateAsClient называется это удастся, но во второй раз это не удастся.

Что касается выгрузки и загрузки успешно, по умолчанию EnableThreadSafeDataConnections Значение true, что приводит к клонированию клиента и повторному подключению к серверу. Тем не мение, GetListing а также GetNameListing не клонируйте соединение. Ставить точку останова в ActivateEncryption метод, AuthenticateAsClient будет вызываться несколько раз. Может быть, есть некоторое объединение соединений, происходящее под капотом в SslStream класс и несколько AuthenticateAsClient вызывают проблемы. Стоит отметить, что FtpClient.ValidateCertificate событие вызывается только один раз, хотя AuthenticateAsClient называется дважды. Это дает некоторое свидетельство того, что кеширование происходит.

0 ответов

Другие вопросы по тегам