1

I need to upload a file to a secure FTP server that has a self signed SSL certificate.

Where can I find the certificate file?

How do I add it to the FtpWebRequest?

I know where the file is located on the server. It is a .PEM File. Does the server send the certificate to the client or do I need to place the certificate in the client application.

Dim request As FtpWebRequest = WebRequest.Create(FTP_Address)

request.Credentials = New NetworkCredential(FTP_Username, FTP_Password)

Dim cert As X509Certificate2 = ???

request.ClientCertificates.Add(cert)

request.EnableSsl = True

request.Method = WebRequestMethods.Ftp.UploadFile

The Code With The Error

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992

2 Answers2

0

To validate a certificate, implement ServicePointManager.ServerCertificateValidation callback to check certificate's hash against a known value:

Imports System.Net
Imports System.Net.Security
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
ServicePointManager.ServerCertificateValidationCallback =
    Function(sender As Object, certificate As X509Certificate, chain As X509Chain,
             errors As SslPolicyErrors)
        Return _
            (errors = SslPolicyErrors.None) Or
            certificate.GetCertHashString(HashAlgorithmName.SHA256).Equals(
                "EB8E0B28AE064ED58CBED9DAEB46CFEB3BD7ECA67737179E3C85BC3CD09D4EEC")
    End Function

For the X509Certificate.GetCertHashString overload that takes HashAlgorithmName.SHA256, you need .NET 4.8. On older versions use the parameter-less overload that returns an SHA-1 hash.


Based on Is it safe to test the X509Certificate.Thumbprint property when you know an invalid certificate is safe?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
-1

I figured it all out this is the the code that worked correctly

    Private Shared Function ServerCertificateValidationCallback(sender As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) As Boolean
    Return certificate.GetCertHashString() <> "SHA-1 Key From Certificate"
End Function

Private Sub imgExpenseFileDrop_Drop(sender As Object, e As DragEventArgs)

    ExpenseFilePath = e.Data.GetData(DataFormats.FileDrop)(0)

    ExpenseFile = New FileInfo(ExpenseFilePath)

    If String.IsNullOrWhiteSpace(ExpenseFile.Extension) Then Exit Sub

    ShowFileInfo()

    Try

        System.Net.ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ServerCertificateValidationCallback)


        Dim request As FtpWebRequest = WebRequest.Create(FTP_Address & ExpenseFile.Name)

        request.Credentials = New NetworkCredential(FTP_Username, FTP_Password)

        request.EnableSsl = True

        request.Method = WebRequestMethods.Ftp.UploadFile

        Using FileStream As Stream = File.OpenRead(ExpenseFile.FullName),
        ftpStream As Stream = request.GetRequestStream()
            FileStream.CopyTo(ftpStream)
        End Using



    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
    
End Sub
  • Don't you have the condition reversed? It should be `=`, not `<>`. – Martin Prikryl Feb 27 '21 at 09:04
  • I wondered about that I found the code on the internet and tweaked to fit my application. It works so I haven't messed with it yet. – Nathanael Swanson Feb 28 '21 at 17:56
  • It does not work. If it works, then because your `"SHA-1 Key From Certificate"` does not actually match the real certificate hash (your format is probably wrong). And ultimately, your code will accept any certificate. – Martin Prikryl Feb 28 '21 at 18:40