Archive for the ‘Ftp.dll’ Category

System.Security.Authentication.AuthenticationException

Friday, December 2nd, 2016

The token supplied to the function is invalid

Full exception looks like this:

System.Security.Authentication.AuthenticationException : A call to SSPI failed, see inner exception.
----> System.ComponentModel.Win32Exception : The token supplied to the function is invalid

Most likely your client tries to use TLS 1.2 but you are using old certificate on the server (e.g. signed using md5RSA algorithm).

There are 2 options for you:

  1. Regenerate the certificate (especially if it’s self-signed).
  2. Use older TLS/SSL version (TLS 1.1, TLS 1.0, SSL 3.0). You can force Mail.dll or Ftp.dll to use it using following code:

    using (XXX client = new XXX())
    {
        client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls11;
        //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls; // TLS 1.0
        //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Ssl3;
    
        client.ConnectSSL("host");
    
        client.Close();
    }
    
    

    Please contact your server administrator as TLS 1.1, TLS 1.0 and SSL 3.0 aren’t considered secure anymore.

The client and server cannot communicate, because they do not possess a common algorithm

Full exception looks like this:

System.Security.Authentication.AuthenticationException : A call to SSPI failed, see inner exception.
----> System.ComponentModel.Win32Exception : The client and server cannot communicate, because they do not possess a common algorithm

There are 2 possible scenarios:

  1. In most cases this means that the client is trying to use older SSL protocols like SSL 3.0, TLS 1.0 or TLS 1.1, but the remote server requires modern protocol – TLS 1.2.

    By default all our clients support TLS 1.2. Some older versions need to be told to use TLS 1.2, it is also a good practice to force TLS 1.2 only:

    using (XXX client = new XXX())
    {
        client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
    
        client.ConnectSSL("host");
    
        client.Close();
    }
    
  2. Second option is the server is not supporting TLS 1.2 – you’ll need to use older protocol (TLS 1.1, TLS 1.0, SSL 3.0):
    using (XXX client = new XXX())
    {
        client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls11;
        // client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls; // TLS 1.0
        // client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Ssl3; 
    
        client.ConnectSSL("host");
    
        client.Close();
    }
    
  3. Please contact your server administrator as TLS 1.1, TLS 1.0 and SSL 3.0 aren’t considered secure anymore.

The message received was unexpected or badly formatted

Full exception looks like this:

System.Security.Authentication.AuthenticationException : A call to SSPI failed, see inner exception.
----> System.ComponentModel.Win32Exception : The message received was unexpected or badly formatted

This error generally means that something is incorrectly configured on your machine.

What you should try:

  1. Try forcing the latest TLS version (TLS 1.2):
    using (XXX client = new XXX())
    {
        client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
    
        client.ConnectSSL("host");
    
        client.Close();
    }
    
  2. Use older TLS/SSL version (TLS 1.1, TLS 1.0, SSL 3.0). You can force Mail.dll or Ftp.dll to use it using following code:

    using (XXX client = new XXX())
    {
        client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls11;
        //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls; // TLS 1.0
        //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Ssl3;
    
        client.ConnectSSL("host");
    
        client.Close();
    }
    
    

    Please contact your server administrator as TLS 1.1, TLS 1.0 and SSL 3.0 aren’t considered secure anymore.

  3. Finally you can download IISCrypto and review “Schannel” and “Cipher Suites” tabs.

    For example we have seen clients that have TLS 1.0 turned on, but have TLS_RSA_WITH_3DES_EDE_CBC_SHA cypher suite turned off. If server requires this cypher, you’ll get this error message.

    Selecting “Best Practices” and restarting, should solve the issue.

    Please note that using TLS 1.2 and forcing your server administrator to enable TLS 1.2 is the only correct and secure way to go.

Using FTP TLS 1.2 with FTP

Friday, November 18th, 2016

By default most systems allow SSL 3.0, TLS 1.0, 1.2 and 1.2 to be used.

TLS 1.2 is the most secure version of SSL/TLS protocols. It is easy to force the connection to use it. All you need to do is to set Ftp.SSLConfiguration.EnabledSslProtocols property to SslProtocols.Tls12:

// C#

using (Ftp ftp = new Ftp())
{
    ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;

    ftp.ConnectSSL("ftps.example.com");

    ftp.Login("user","password");

    ftp.ChangeFolder("uploads");
    ftp.Upload("report.txt", @"c:\report.txt");


    ftp.Close();
}
' VB.NET

Using ftp As New Ftp()
	ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12

	ftp.ConnectSSL("ftps.example.com")

	ftp.Login("user", "password")

	ftp.ChangeFolder("uploads")
	ftp.Upload("report.txt", "c:\report.txt")


	ftp.Close()
End Using

For explicit SSL/TLS, code is almost the same. You first connect to non-secure port (21) and secure the connection using Ftp.AuthTLS command:

// C#

using (Ftp ftp = new Ftp())
{
    ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;

    ftp.Connect("ftp.example.com");
    ftp.AuthTLS();

    ftp.Login("user","password");

    ftp.ChangeFolder("uploads");
    ftp.Upload("report.txt", @"c:\report.txt");

    ftp.Close();
}
' VB.NET

Using ftp As New Ftp()
	ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12

	ftp.Connect("ftp.example.com")
	ftp.AuthTLS()

	ftp.Login("user", "password")

	ftp.ChangeFolder("uploads")
	ftp.Upload("report.txt", "c:\report.txt")

	ftp.Close()
End Using

To use TLS 1.2 .NET Framework 4.5+ must be installed on your machine and you application should target .NET 4.5+.

It is possible to use TLS 1.2 in applications targeting .NET lower than 4.5, but 4.5 must be installed on the machine. After you have .NET 4.5 installed, your 2.0-4.0 apps will use the 4.5 System.dll and you can enable TLS 1.2 using this code:

    ftp.SSLConfiguration.EnabledSslProtocols = (System.Security.Authentication.SslProtocols)3072;

Using Limilabs’ Ftp.dll with zOS Mainframes

Wednesday, December 17th, 2014

I purchased the Limilabs FTP product for FTP because I needed to send data to and from an IBM mainframe from my VB.NET program running in Windows. In particular I needed to be able to submit jobs, and receive the job output. These notes show how it’s done.

Introduction

FTP to/from IBM computers is pretty much like any other FTP except for two things.
1. IBM Mainframe and Midrange computers mostly use EBCDIC encoding rather than ASCII. With the FTP defaults your data can be garbled and useless when it arrives at the other end.
2. The SITE command is used to submit jobs to the mainframe, and get the results back.

Getting Started

I created a class called “JazzFTP” to wrap the Limilabs’ code. This was going to contain the functions that I wanted for my project, and so I started by defining the common elements that all methods would use. In my situation every FTP would be authenticated, and would be exchanging text data (not binary) with the remote computer.

Here is the initial class definition:

Imports Limilabs.FTP.Client

Public Class JazzFTP
    '   This class wraps the FTP library from Limilabs (/ftp)
    '   All methods
    '   1   Connect and logon using information from MySettings:  Sub LoginFTP
    '   2   Perform their action based on their parameters
    '   3   Close the connection
    Dim ftp As New Ftp()
    Dim response As FtpResponse
    Private Sub LoginFTP()
        ftp.Connect(My.Settings.SubmitIP)
        ftp.Login(My.Settings.Userid, My.Settings.Password)
    End Sub
    '   My functions will be written here
End Class

Basic FTP

Here is my first method, a basic function to upload a text file: –

    Function Upload(DestinationFile As String, Uploadfile As String) As String 
        LoginFTP()
        ftp.TransfersDataType = FtpDataType.Ascii
        response = ftp.Upload(DestinationFile, Uploadfile)
        ftp.Close()
        Return response.message
    End Function

FTP’s default is Binary, which is correct if you are transmitting a .JPG or other binary object, and it probably doesn’t matter if you are transmitting text to/from another Windows computer or a Unix computer. However if you are transmitting to/from an IBM mainframe or midrange computer it probably needs EBCDIC rather than ASCII characters. You must tell it that the file is Ascii text, not binary, otherwise it won’t be converted and it will be gibberish when you examine it on the mainframe.

Although this code above works, it is very fragile: the FTP server has to be up and running, you have to get the connection details exactly right, the source and destination files must exist, and so on. Since I couldn’t guarantee all of these details, I enclosed the code in Try/Catch to deal with any errors. For the time being I’ve simply used MsgBox to display the error message.

    Function Upload(DestinationFile As String, Uploadfile As String) As String
        Try
            LoginFTP()
            ftp.TransfersDataType = FtpDataType.Ascii
            response = ftp.Upload(DestinationFile, Uploadfile)
            ftp.Close()
            Return response.EndLine
        Catch ex As Exception
            MsgBox(ex.Message)
            Return ex.Message
        End Try
    End Function

Download, which is not illustrated, is similar except that you’d use ftp.Download. Again, you specify:

            ftp.TransfersDataType = FtpDataType.Ascii

Submitting Jobs and Receiving Job Output

Submitting a job is essentially an upload with a twist. Instead of uploading the file containing the job to a named file on the mainframe, you upload it to the JES (Job Entry System) input queue. Here is the basic code:

            response = ftp.Site("FILETYPE=JES")
            ftp.TransfersDataType = FtpDataType.Ascii
            response = ftp.Upload("JES", JCLFile)

The first line uses “ftp.Site”. Site means that this is a site-specific command, something that the FTP system at the other end will presumably know about. For an IBM mainframe “FILETYPE=JES” means that the data is going to and from JES.

The third line uploads the file in which we have prepared our job: in this case JCLFile is a file containing something like this: –

//IBMUSERH JOB  ,CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID,COND=(8,LT) 
//*** COPY SOURCE INTO SOURCE LIBRARY
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT2 DD DSN=IBMUSER.MANAJAZZ.SRCLIB(CRDTA1),DISP=SHR
//SYSUT1 DD *

Like any upload the FTP client syntax requires a destination file name, but because of the preceding FILETYPE=JES this will be ignored. I have written “JES” purely for documentation.

This will submit the job and it will run, appearing in the output like this:

tasks

Of course we can view the job output on the mainframe, but we may want to return it to Windows. We do this by downloading the file by naming the JobID – JOB00594 in this case – and again using the Site command. The essential code is: –

        response = ftp.Site("FILETYPE=JES")
        ftp.TransfersDataType = FtpDataType.Ascii
        ftp.Download(Jobname, LocalPath)

But how do we get the Jobname? JES returns a message with this information when the job is submitted. We need to add code to the Job Submission logic to extract this from the message. In function JobSub

       response = ftp.Upload("JES", JCLFile)

upload the job and (if all goes well) returns a message like
“It is known to JES as JOB00594″
This code extracts JOB00594” and puts it into variable JobName

       Dim TestString As String = "It is known to JES as"
       If Mid(response.Message, 1, Len(TestString)) = TestString Then  'Should be true
           Jobname = Trim(Mid(response.Message, Len(TestString) + 1))
       End If

Now, since it is logical that if we submit a job we’ll want to get it back, I coded this in the JobSub function: –

    Function JobSub(JCLFile As String, ByRef Jobname As String) As FtpResponse
        '   JCLFile is path to a .JCL file (format .txt) containing the job to be submitted
        '   If successful submission, the job name is returned in JobName
        Dim Tstring As String = ""
        Try
            Jobname = "Unknown"
            LoginFTP()
            response = ftp.Site("FILETYPE=JES")
            ftp.TransfersDataType = FtpDataType.Ascii
            response = ftp.Upload("JES", JCLFile)
            Dim TestString As String = "It is known to JES as"
            If Mid(response.Message, 1, Len(TestString)) = TestString Then  'Should be true
                Jobname = Trim(Mid(response.Message, Len(TestString) + 1))
            End If
            JobGet(Jobname, False)
            ftp.Close()
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Jazz FTP")
            Return response
        End Try
        Return response
    End Function

and I coded JobGet to accept these parameters: –

    Function JobGet(Jobname As String, Optional Login As Boolean = True) As FtpResponse
        '   Get job output, save as Jobname.txt in Jazz Program Library.  
        If Login Then
            LoginFTP()
        End If
        response = ftp.Site("FILETYPE=JES")
        ftp.TransfersDataType = FtpDataType.Ascii
        Dim LocalPath As String = My.Settings.UserCommonPath & "\" & My.Settings.Programs & "\" & Jobname & ".txt"
        Jazzworkbench.ShowBtnResults(Jobname, Jazzworkbench.ResultsStatus.Pending)
        ftp.Download(Jobname, LocalPath)
        ftp.DeleteFile(Jobname)
        Jazzworkbench.ShowBtnResults(Jobname, Jazzworkbench.ResultsStatus.JobReturned)
        ftp.Close()
        Return response
    End Function

Once the job output has been downloaded I didn’t want to leave it cluttering up my Held Job Output Queue, so after the Download

        ftp.DeleteFile(Jobname)

gets rid of it.

This all works for my test jobs (which are very quick) and provided that mainframe FTP server is available.

If you want to know any more about my project to revolutionize mainframe programming, then have a look at www.jazzsoftware.co.nz

Best wishes with your programming,
Robert Barnes.

Unblock .dll file

Wednesday, October 31st, 2012

Symptoms

You can not add .dll file as a reference in Visual Studio or SecurityException is thrown.

Solution

Most likely the problem is a protection on files coming from other computers. You just have to open file properties and click on Unblock button. Unblock the zip file first, and then extract the dll, unblock the dll if needed:

Other tricks is to copy the file to a file system that doesn’t support alternate data streams, that slices them off the file. A flash drive for example.

.chm file is not displayed correctly

Thursday, October 11th, 2012

Symptoms

When you open a .chm file, “Navigation to the webpage was canceled” is displayed in the reading pane.

Solution

Most likely the problem is a protection on files coming from other computers. You just have to open file properties and click on Unblock button: