1

The following code is able to connect to a FTP server using TLS:

private FtpClient getFtpsClient(System.Uri uri) {
    if (uri.Scheme != "ftps") {
        throw new NotImplementedException("Only ftps is implementent");
    }
    var userInfo = uri.UserInfo.Split(":");
    FtpClient client = new FtpClient(uri.Host, userInfo[0], userInfo[1]);
    client.EncryptionMode = FtpEncryptionMode.Explicit;
    client.SslProtocols = SslProtocols.Tls;
    client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);
    client.Connect();

    void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e) {
        var cert2 = new X509Certificate2(e.Certificate);
        e.Accept = cert2.Verify();
    }
    return client;
}

As library I use FluentFTP. I wonder, if the method X509Certificate2.Verify() is enough to prevent security issues.

What exactly does X509Certificate2.Verify() do? The referenced documentation is very short on information.

Would it fail on a man-in-the-middle attack?

jww
  • 97,681
  • 90
  • 411
  • 885
Adrian Dymorz
  • 875
  • 8
  • 25
  • There's no telling based on what you provided. You need to provide FluentFTP's implementation. You might also be interested in [How to verify chain in RemoteCertificateValidationCallback?](https://stackoverflow.com/q/22518525/608639) – jww Oct 06 '19 at 04:29

1 Answers1

0

The documentation got updated 3 month ago and now anwers the question.

Method 1: Connect if the SSL certificate has no errors.

client.ValidateCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidationEventArgs e) {
    if (e.PolicyErrors != System.Net.Security.SslPolicyErrors.None){
        e.Accept = false;
    }else{
        e.Accept = true;
    }
});

Method 2: Connect if the certificate matches a whitelisted certificate.

First you must discover the string of the valid certificate. Use this code to save the valid certificate string to a file:

client.ValidateCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidationEventArgs e) {
    File.WriteAllText(@"C:\cert.txt", e.Certificate.GetRawCertDataString());
});

Then finally use this code to check if the received certificate matches the one you trust:

string ValidCert = "<insert contents of cert.txt>";
client.ValidateCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidationEventArgs e) {
    if (e.PolicyErrors == SslPolicyErrors.None || e.Certificate.GetRawCertDataString() == ValidCert) {
        e.Accept = true;
    }else{
        throw new Exception("Invalid certificate : " + e.PolicyErrors);
    }
});
Adrian Dymorz
  • 875
  • 8
  • 25