我正在设置一个FTP服务器(FileZilla
),并使用netftp codeplex project
System.Net.FtpClient
通过SSL
/ TLS
使用{{}连接到它1}}。
X509Certificate2
from sourceforge。 FileZilla Server
from codeplex。我认为我已经解决了这个问题,但也许有人对基本原因有一些额外的想法。本文底部提供了一种解决方法。
调用System.Net.FtpClient v14.06.17
和client.GetListing()
时发生异常,但上传(client.GetNameListing()
)和下载(OpenWrite
)都可以正常工作。我已经测试了OpenRead
的许多版本,以确定它开始破坏的版本。
发生的异常是:
FileZilla
A call to SSPI failed, see inner exception.
导致错误的C#代码示例:
The message received was unexpected or badly formatted
在Codeplex Documentation页面上,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
写道:
您不使用pem证书,请改用p12。有关详细信息,请参阅this Stack Overflow thread。如果您获得SPPI例外 关于意外或格式错误的内部异常 消息,您可能使用了错误类型的证书。
该链接指的是jptrosclair
,而不是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)
https://netftp.codeplex.com/discussions/535815的类似讨论的链接
他的解决方法是在获得列表之前克隆连接。
解决方法:
我已针对上面列出的所有skovachev
版本测试了以下内容。修复方法是从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
为true,这会导致克隆客户端并重新连接到服务器。但是,EnableThreadSafeDataConnections
和GetListing
不会克隆连接。在GetNameListing
方法中放置断点,ActivateEncryption
将被多次调用。也许在AuthenticateAsClient
类的引擎盖下发生了一些连接池,多个SslStream
导致了问题。值得注意的是,即使AuthenticateAsClient
被调用两次,FtpClient.ValidateCertificate
事件也只被调用一次。这提供了一些缓存正在发生的证据。