Tuesday, June 18, 2013

Windows Forms Application in C# for transferring files between Linux and Windows machines, via SFTP, Port 22, using WinSCP

Why was it required to implement this tool?

At present I am working on a project in Oracle's Imaging and Process Management tool (Oracle's I/ PM). My organization had developed a suite of 2 Windows Forms applications to facilitate migration of images and indexes from MarkView system at Boral to Oracle's I/ PM

Images and indexes that need to be migrated are related to invoices entered in Oracle’s Enterprise Business Suite (EBS).  This tool extracts images and index data from existing MarkView170  system and Oracle’s EBS and formats them for consumption into Oracle’s I/ PM system via Oracle’s I/ PM Input Agent. This tool also generates xml file containing annotations and markup data

Once images and index data have been ingested into Oracle’s I/ PM, tool also updates image attachments for invoice transactions in Oracle’s EBS. This functionality was originally implemented to download files from Linux source location to user’s Windows desktop and upload these to I/ PM Input Agent folder on Linux using FTP. Client requirement was to files transferred via SFTP

About this application:

This Windows-based application is ready-to-use tool with source code for SFTP file transfers between Windows and Linux machines. Tool has been developed using Microsoft Visual Studio 2008. It will also work with .NET Framework 2.0 as I have set Target Framework to .NET Framework 2.0. This can be changed - my project required .NET Framework 2.0. For any other requirement, use source code provided towards end of this article to handle download, upload events

WinSCP:

WinSCP .NET assembly winscp.dll is .NET wrapper around WinSCP’s scripting interface that allows your code to connect to remote machine and manipulate remote files over SFTP, SCP, and FTP sessions from .NET languages, such as C#, VB.NET, PowerShell and others, or from environments supporting .NET add ons, such as SQL Server Integration Services (SSIS)

GPL License:

WinSCP is free software. You can use it, redistribute it and/ or modify it under terms of GNU General Public License as published by Free Software Foundation, either version 3 of License, or (at your option) any later version. Please visit below link for more information

SFTP v/ s SCP:


SCP lets you remotely copy file to or from SSH server. Generally, people only use SCP if they are going to recusively upload folder or upload just one file. There is also fact that since SCP is one-liner


SFTP is interactive program that let's you upload files to/ from SSH server. advantage of using SFTP over SCP is that if you need to do multiple uploads from or to different directories, you can do it in one session
SFTP is interactive program used by human in shell session SCP is mostly one-liner used in scripts to transfer/ copy files



In nutshell, SCP can only be used for transferring files, and it is non-interactive (i.e., everything has to be specified on command line). SFTP is more elaborate, and allows interactive commands to do things like creating directories, deleting directories and files (all subject to system permissions, of course), etc



Compared to earlier SCP protocol, which allows only file transfers, SFTP protocol allows for range of operations on remote files – it is more like remote file system protocol.  SFTP client's extra capabilities compared to SCP client include resuming interrupted transfers, directory listings, and remote file removal. For these reasons it is relatively simple to implement GUI SFTP client compared with GUI SCP client



Although both SCP and SFTP utilize same SSH encryption during file transfer with same general level of overhead, SCP is usually much faster than  SFTP at transferring files, especially on high latency networks. This happens because SCP implements more efficient transfer algorithm, one which does not require waiting for packet confirmations. This leads to faster speed but comes at expense of not being able to interrupt transfer, so unlike SFTP, SCP transfer cannot be canceled without terminating session

How to get server's rsa2 key fingerprint? (There are 2 methods to get this):

In order to run this application, server's rsa2 key is required, there are 2 methods to get it

Method 1:
Run WinSCP.exe

Type following details in WinSCP Login prompt
Host name:
Port number: 22
Username:
Password: 

Click Login

If you are using WinSCP to connect to server for first time, dialog is displayed, which displays server's rsa2 key fingerprint is available. Click Copy Key to copy it to clipboard

Method 2:
Run WinSCP.exe 


Type following details in WinSCP Login prompt
Host name:
Port number: 22
Username:
Password:

After logging in, under Commands menu, select Open in PuTTY. server's rsa2 key fingerprint is displayed in PuTTY Security Alert pop up

Server's rsa2 key fingerprint looks like
ssh-rsa 1024 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
or
ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx 



This is feature of  SSH protocol. It is designed to protect you against network attack known as spoofing: secretly redirecting your connection to  different computer, so that you send your password to  wrong machine. Using this technique, an attacker would be able to learn password that guards your login account, and could then log in as if they were you and use  account for their own purposes


To prevent this attack, each server has unique identifying code, called host key. These keys prevent server from forging another server’s key. If you connect to server and you receive an unexpected host key, WinSCP can warn you that server may have been switched and that  spoofing attack might be underway



WinSCP records host key for each server you connect to, in configuration storage. Every time you connect to server, it compares server’s host key to host key you received  last time you connected. If keys differ, you will receive warning and chance to abandon your connection before you enter any private information such as  password



However, when you connect to server for  first time, WinSCP has no way of telling whether  host key is  right one or not. So it gives warning shown above, and asks you whether you want to trust this host key or not 

How to use this application:

Download application from http://www.4shared.com/account/dir/kfjS4FIX/_online.html?&rnd=21#dir=kfjS4FIX. After running program, Click SFTP File Operation and select required operation viz. Download/ Upload. Appropriate form opens up. You will require following details:Host name:
Port number: 22
Username:
Password:
server's rsa2 key fingerprint:

Main form:

Download form:

Upload form:

 

Steps to implement application:

1) Create a Windows Forms Application using Visual Studio

2) Application requires WinSCP.exe. Copy it from attached downloadable application and paste it to your <YOUR_APPLICATION_FOLDER>\bin\Debug and Release folders i.e. where .exe of your application gets generated

3) Create lib folder under your project in application. Copy WinSCP.dll from lib folder of attached downloadable application and paste it to you lib folder. Add reference to your WinSCP.dll in your project. Right click References > Add Reference... > Browse > lib > WinSCP.dll > OK 
4) Add reference to WinSCP.dll to your Windows Forms Application
5) Paste WinSCP.exe to where .exe of your application gets generated viz. <YOUR_APPLICATION_FOLDER>\bin\Debug folder while developing and also to Release folder before packaging for software release
6) Implement download, upload methods using APIs provided by WinSCP.dll. Return boolean variable true/ false as per success/ failure of upload/ download. Pass string parameters as source path, destination path to both methods

 Source code:

To download file:
On click event of 'Download' button, type below code
private void btnDownload_Click(object sender, EventArgs e)
{
    btnDownload.Enabled = false;
    lblStatusMessage.Text = "";

    try
    {

        // Setup session options
        SessionOptions sessionOptions = new SessionOptions
        {
            Protocol = Protocol.Sftp,
            HostName = txtDownloadServer.Text.Trim(),
            UserName = txtDownloadUsername.Text.Trim(),
            Password = txtDownloadPassword.Text.Trim(),
            SshHostKeyFingerprint = txtDownloadSHHostKeyFingerprint.Text.Trim()
        };

        using (Session session = new Session())
        {
            // Connect
            session.Open(sessionOptions);

            // Download files
            TransferOptions transferOptions = new TransferOptions();
            transferOptions.TransferMode = TransferMode.Binary;

            TransferOperationResult transferResult;
            transferResult = session.GetFiles(txtSourcePath.Text.Trim(), txtDestinationPath.Text.Trim(), false, null);

            // Throw error
            transferResult.Check();

            // Print results
            foreach (TransferEventArgs transfer in transferResult.Transfers)
            {
                lblStatusMessage.Text = "Download of " + transfer.FileName + " succeeded";
            }
        }
    }
    catch (Exception ex)
    {
        lblStatusMessage.Text = "Exception: " + ex.Message;
    }

    btnDownload.Enabled = true;
}

To upload file:
On click event of 'Upload' button type below code
private void btnUpload_Click(object sender, EventArgs e)
{
    btnUpload.Enabled = false;
    lblStatusMessage.Text = "";

    try
    {
        // Setup session options
        SessionOptions sessionOptions = new SessionOptions
        {
            Protocol = Protocol.Sftp,
            HostName = txtUploadServer.Text.Trim(),
            UserName = txtUploadUsername.Text.Trim(),
            Password = txtUploadPassword.Text.Trim(),
            SshHostKeyFingerprint = txtUploadSSHHostKeyFingerprint.Text.Trim()
        };

        using (Session session = new Session())
        {
            // Connect
            session.Open(sessionOptions);

            // Upload files
            TransferOptions transferOptions = new TransferOptions();
            transferOptions.TransferMode = TransferMode.Binary;

            TransferOperationResult transferResult;
            transferResult = session.PutFiles(txtSourcePath.Text.Trim(), txtDestinationPath.Text.Trim(), false, transferOptions);

            // Throw error
            transferResult.Check();

            // Print results
            foreach (TransferEventArgs transfer in transferResult.Transfers)
            {
                lblStatusMessage.Text = "Upload of " + transfer.FileName + " succeeded";
            }
        }

        //return 0;
    }
    catch (Exception ex)
    {
        lblStatusMessage.Text = "Exception: " + ex.Message;
    }

    btnUpload.Enabled = true;


Download application:

http://www.4shared.com/account/dir/kfjS4FIX/_online.html?&rnd=21#dir=kfjS4FIX

References: