1

我正在设置一个 FTP 服务器( FileZilla)netftp codeplex project System.Net.FtpClient并使用.SSLTLSX509Certificate2

我想我已经隔离了这个问题,但也许有人对根本原因有一些额外的想法。本文底部提供了一种解决方法。

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。有关更多信息,请参阅此 Stack Overflow 线程。如果您收到 SPPI 异常以及有关意外或格式错误的消息的内部异常,则您可能使用了错误类型的证书。

链接是指asp.net,不是FileZilla。我的猜测是IIS不支持PEM并且很可能通过流发送一堆乱码。但是,如果您使用您的服务器支持的证书格式,那么应该没有问题。据我所知,FileZilla仅支持PEM格式(或CRT/CER仍然是PEM格式)。

此外,这并不能解释为什么OpenReadOpenWrite成功,而是GetListingGetNameListing失败。

无论如何,我仍然测试了多种不同的证书生成工具,包括FileZilla's内置生成器C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\makecert.exeOpenSSL (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调用了两次,该事件也只调用了一次。这提供了一些缓存正在发生的证据。

4

0 回答 0