FTP über SSL mit FtpWebRequest.EnableSsl

  • VB.NET

    FTP über SSL mit FtpWebRequest.EnableSsl

    Hallo zusammen,

    ich habe hier ein Beispielprogramm, an dem ich ein Problem verdeutlichen möchte, was auftritt, wenn ich versuche, eine FTPS-Verbindung zu einem FTP-Server aufzubauen, der dies unterstützt. Der FTP-Server unterstützt zum Einen eine unverschlüsselte Verbindung über Port 21 und eine Verbindung mittels "FTPS – FTP über impliziertes TLS/SSL" über Port 990. Ich habe nun folgendes Beispiel-Konsolenprogramm, was sich an dem Server anmelden und eine Beispieldatei hochladen soll. Das Programm enthält einige STOP-Anweisungen, die natürlich nur zu Debuggingzwecken enthalten sind, und ich lasse das Programm direkt über die Entwicklungsumgebung im Debugging laufen.

    VB.NET-Quellcode

    1. Module Module1
    2. Private Const USER = "USER"
    3. Private Const PASSWORD = "PASSWORD"
    4. Private Const ADDRESS = "ftp://server.domain:990/test.txt"
    5. Private Const FILE = "C:\Temp\test.txt"
    6. Sub Main()
    7. Try
    8. Dim credentials As New Net.NetworkCredential(USER, PASSWORD)
    9. Dim ftpWebRequest As Net.FtpWebRequest
    10. ftpWebRequest = Net.FtpWebRequest.Create(ADDRESS)
    11. ftpWebRequest.EnableSsl = True
    12. ftpWebRequest.Credentials = credentials
    13. ftpWebRequest.Method = Net.WebRequestMethods.Ftp.UploadFile
    14. Net.ServicePointManager.ServerCertificateValidationCallback = New Net.Security.RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
    15. Dim requestStream As IO.Stream = ftpWebRequest.GetRequestStream()
    16. Dim fileStream As IO.Stream = IO.File.OpenRead(FILE)
    17. Const bufferLength As Integer = 2048
    18. Dim buffer(bufferLength) As Byte
    19. Dim count As Integer = 0
    20. Dim readBytes As Integer = 0
    21. Do
    22. readBytes = fileStream.Read(buffer, 0, bufferLength)
    23. requestStream.Write(buffer, 0, readBytes)
    24. count += readBytes
    25. Loop While readBytes <> 0
    26. requestStream.Close()
    27. fileStream.Close()
    28. Catch ex As Net.WebException
    29. Dim response As Net.FtpWebResponse = ex.Response
    30. Stop
    31. Catch ex As Exception
    32. Stop
    33. End Try
    34. End Sub
    35. Public Function ValidateServerCertificate( _
    36. ByVal sender As Object, _
    37. ByVal certificate As Security.Cryptography.X509Certificates.X509Certificate, _
    38. ByVal chain As System.Security.Cryptography.X509Certificates.X509Chain, _
    39. ByVal sslPolicyErrors As System.Net.Security.SslPolicyErrors _
    40. ) As Boolean
    41. If sslPolicyErrors = Net.Security.SslPolicyErrors.None Then
    42. Return True
    43. End If
    44. Console.WriteLine("Certificate error {0}", sslPolicyErrors)
    45. Return False
    46. End Function
    47. End Module


    Den Port habe ich innerhalb der ADDRESS-Konstante um URI hinterlegt - ich weiß nicht, ob dies so korrekt ist, allerdings sind die Auswirkungen etwas anders, wenn ich hier den Port 990 angebe, im Gegensatz dazu, wenn ich keinen Port mit angebe.

    Lasse ich das Beispielprogramm nun laufen, tritt bei der Zeile...

    Dim requestStream As IO.Stream = ftpWebRequest.GetRequestStream()

    ...nach einer Zeit eine WebException "Timeout" auf:

    Timeout für den Vorgang wurde überschritten.

    Innerhalb der Exception steht ein WebResponse-Objekt über die Eigenschaft "Response" zur Verfügung, was in ein Objekt vom Typ "FtpWebResponse" gecastet werden kann. Dies enthält aber leider keinerlei weitere Angaben in den Eigenschaften.

    Lasse ich das Programm ohne Angabe eines Ports laufen, erhalte ich bei oben genannter Zeile sofort eine WebException:

    Der Remoteserver hat einen Fehler zurückgegeben: (530) Nicht angemeldet.

    Das WebResponse-Objekt in der Ausnahme zeigt dann Folgendes:

    {System.Net.FtpWebResponse}
    BannerMessage: "220 FTP-Server ready "
    ContentLength: 0
    ContentType: {"Die Eigenschaft wird von der Klasse nicht implementiert."}
    ExitMessage: ""
    Headers: {System.Net.WebHeaderCollection}
    IsFromCache: False
    IsMutuallyAuthenticated: False
    LastModified: #12:00:00 AM#
    ResponseUri: {System.Uri}
    StatusCode: NotLoggedIn {530}
    StatusDescription: "530 Please login with USER and PASS. "
    WelcomeMessage: ""


    Hat jemand eine Idee, was hier falsch ist, und wie ich mich an diesen FTP-Server mittels eines impliziten FTP over SSL anmelden kann?

    Vielen Dank im Voraus für Eure Hilfe!

    Gruß

    Harry