Проверка/установка сертификата для FTPS (SSL)?

Я использую FileZilla в качестве сервера и службы DNS, поэтому мне не пришлось бы использовать IP-адрес моего локального компьютера (но я пробовал следующие методы на обоих).

Попробовав System.Net.FtpWebRequest для работы, я прочитал (включая несколько сообщений о SO) и обнаружил, что поддержка SSL не очень адекватна этой библиотеке. Он работал с обычным FTP, но когда я попытался принудительно использовать SSL, я получил сообщение об ошибке проверки сертификата: The remote certificate is invalid according to the validation procedure.

Итак, я немного поискал и нашел библиотеку Alex FTPS Client. Вот код, который я написал:

class FTPSWorker
    {
        public static void UploadFile(string sourceFile, string targetFile, string ftpIP, string ftpUser, string ftpPass)
        {
            try
            {
                using (FTPSClient client = new FTPSClient())
                {
                    client.Connect(ftpIP, new NetworkCredential(ftpUser, ftpPass),
                                   ESSLSupportMode.CredentialsRequired | ESSLSupportMode.DataChannelRequested);
                    client.SetTransferMode(ETransferMode.Binary);
                    client.PutFile(sourceFile, targetFile);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

К сожалению, я получал ту же самую ошибку сертификата. Однако я могу отлично получить доступ к FTP-серверу с помощью клиента FileZilla. Итак, я подумал, что должна быть проблема с сертификатом.

Я должен отметить, что мой сервер показывал следующие записи журнала:

Welcome Message
AUTH TLS
234 Using authentication type TLS
SSL connection established
disconnected

Пока клиент (приложение С# WPF) получал эту ошибку:

The remote certificate is invalid according to the validation procedure.

Это абсолютно такая же ошибка, если я использую библиотеку .NET и код MSDN.

Я провел больше исследований и нашел решения, подобные этим:

Удаленный сертификат недействителен в соответствии с процедурой проверки

Удаленный сертификат недействителен в соответствии с процедурой проверки . с помощью SMTP-сервера Gmail

Но они просто кажутся рискованными хаками ... И хотя они действительно работают, есть ли способ, чтобы информация о сертификации отображалась и, возможно, пользователь проверял ее / устанавливал ее помимо основного Да / Нет, который он использует в настоящее время?

Мой код прямо сейчас (я отказался от библиотеки Алекса и вернулся к .NET по умолчанию):

ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(FTPWorker.ValidateServerCertificate);

public class FTPWorker
{
    public static void UploadFile(string sourceFile, string targetFile, string ftpIP, string ftpUser, string ftpPass)
    {
        try
        {
            string filename = "ftp://" + ftpIP + "/test/" + targetFile;
            FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
            ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
            ftpReq.Credentials = new NetworkCredential(ftpUser, ftpPass);
            ftpReq.UsePassive = true;
            ftpReq.EnableSsl = true;
            ftpReq.UseBinary = true;
            ftpReq.KeepAlive = false;

            byte[] b = File.ReadAllBytes(sourceFile);

            ftpReq.ContentLength = b.Length;

            using (Stream s = ftpReq.GetRequestStream())
            {
                s.Write(b, 0, b.Length);
            }

            FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();

            if (ftpResp != null)
            {
                MessageBox.Show(ftpResp.StatusDescription);
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
    }

    public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;
        else
        {
            if (System.Windows.Forms.MessageBox.Show("The server certificate is not valid.\nAccept?", 
                   "Certificate Validation", System.Windows.Forms.MessageBoxButtons.YesNo,
                   System.Windows.Forms.MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                return true;
            else
                return false;
        }
    }
}

person B.K.    schedule 11.10.2013    source источник
comment
Ваш код может абсолютно точно представить сертификат пользователю для проверки и, вероятно, ДОЛЖЕН показать конкретную проблему с проверкой сертификата, которая возвращается вашему коду в обратном вызове проверки.   -  person EricLaw    schedule 24.07.2015


Ответы (2)


Итак, для всех, у кого была такая же проблема, я просто дал пользователю предупреждение о сертификате и возможность принять или отклонить на основе ссылки, которую я предоставил в своем исходном сообщении. Чтобы сертификат прошел проверку, он должен быть реальным, а не локально созданным. Итак, это единственный обходной путь, который есть на данный момент.

person B.K.    schedule 15.10.2013

Alex ftps выполнит ту же проверку сертификата, если вы укажете это. В вашем client.connect добавьте обратный вызов remotecertificatevalidation, чтобы принять сертификат

client.Connect(ftpIP, new NetworkCredential(ftpUser, ftpPass),
                               ESSLSupportMode.CredentialsRequired | ESSLSupportMode.DataChannelRequested, 
                           new RemoteCertificateValidationCallback(ValidateTestServerCertificate));

Потом ниже.

private static bool ValidateTestServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        // Accept any certificate
        return true;
    }

Я хотел использовать .net по умолчанию. но я застрял при подключении к серверу, который использует неявный. :(

person Prescient    schedule 01.04.2015
comment
Да я и не говорил, что его библиотека не подойдет, просто мне она была не нужна, так как библиотека, предоставленная .NET, работала точно так же, в той конкретной ситуации. Ссылки, которые я предоставил в своем исходном сообщении, относятся к тем же решениям, которые вы предоставили. Просто они мне не понравились, потому что молча приняли аттестат. Очевидно, вы все еще можете уведомить пользователя, но тогда это просто дополнительная работа, чтобы начать с обратного вызова. В любом случае вы принимаете сертификат, созданный локально, а не фактически подписанный. Однако использование его библиотеки — более короткий путь. - person B.K.; 02.04.2015