Ошибка вызова SSPI, см. Внутреннее исключение, используя FileZilla Server и System.Net.FtpClient
Я настраиваю FTP-сервер (FileZilla
) и используя netftp codeplex project
System.Net.FtpClient
подключиться к нему через SSL
/TLS
используя X509Certificate2
,
- Я скачал
FileZilla Server
от sourceforge. - Я скачал
System.Net.FtpClient v14.06.17
из кодекса
Я думаю, что я выделил проблему, но, возможно, у кого-то есть некоторые дополнительные мысли относительно основной причины. Обходной путь представлен в нижней части этого поста.
Происходит исключение вызова 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
называется дважды. Это дает некоторое свидетельство того, что кеширование происходит.