http://www.perlmonks.org?node_id=996252

Pizentios has asked for the wisdom of the Perl Monks concerning the following question:

Good day,

I have a script here at work that logs into a ftps server and downloads some files (if there are new files to download). It's currently in production, however it lives on two different servers (thus two different installs). The script is called by a windows scheduled tast (the task part is working).

It's running on straberry perl and both servers are running Windows 2008 R2. The script runs fine on ClientA, but fails on ClientB. I have checked over all the modules that the script needs to run in my perl installs and their versions (the modules versions match up).

It should be also noted that the script works just fine (with both sets of credentials) on my development envrionment (ubuntu).

The log output of the script on ClientB is as follows:

Net-FTPSSL Version: 0.22

Perl: 5.016001 5.16.1, OS: MSWin32

Server (port): xxx.xxx.xxx (21)

Keys: (Debug), (Encryption), (Port)
Values: (1), (E), (21)

SKT <<< 220 RBCNG FTPS (Version Fri Sep 28 11:52:44 2012) server ready.
SKT >>> AUTH TLS
SKT <<< 234 Enabling TLS, awaiting negotiations.
Cannot connect to ftpssl.rbc.com: SSL connect attempt failed because of handshake problems error:00000000:lib(0):func(0):reason(0) at rbc_ftp.pl line 63.

An example of the log when the script runs fine:

Net-FTPSSL Version: 0.22

Perl: 5.016001 5.16.1, OS: MSWin32

Server (port): xxxx.xxxx.xxx (21)

Keys: (Debug), (Encryption), (Port)
Values: (1), (E), (21)

SKT <<< 220 RBCNG FTPS (Version Thu Sep 27 07:35:42 2012) server ready.
SKT >>> AUTH TLS
SKT <<< 234 Enabling TLS, awaiting negotiations.
>>> USER +++++++
<<< 331 Password required for <++++++>.
>>> PASS *******
<<< 230 User <++++++> logged in.
>>> CWD outbound/AAPA/
<<< 250 CWD Command successful.
>>> PBSZ 0
<<< 200 PBSZ Command successful.
>>> PROT P
<<< 200 PROT Command successful.
>>> PASV
<<< 227 Entering Passive Mode ()
--- Host (xxx.xxx.xxx.xxx) Port (6103)
>>> NLST
<<< 150 Opening data connection for '/bin/ls'.
<<< 226 Transfer complete.
>>> TYPE I
<<< 200 Type set to I
2012-9-27 : Found File (Seen It Already): RPT0900P.184.downloaded%WFT
2012-9-27 : Found File (Seen It Already): RPT0900P.185.downloaded%WFT
2012-9-27 : Found File (Seen It Already): RPT0900P.186.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.187.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.188.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.189.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.190.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.191.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.192.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.193.downloaded%FTPS
2012-9-27 : Found File (Seen It Already): RPT0900P.194.downloaded%FTPS
>>> QUIT
<<< 221 Goodbye.

Here's the code for the script:

###################################################################### +########################### ## Purpose: This script logs into the rbc ftp server and downloads dat +a files, then moves them ## ## to a shared folder so that they can be synced with the qui +ckbooks data. ## ## Author: Nick Peters ## ## Pre: Needs a couple of arguments at run time: + ## ## 1) What batch we want t +o run: ns (netset) or ## ## inl (inetlink). + ## ## 2) The Working Director +y we want to save the ## ## downloaded content t +oo. ## ## 3) The location of a config file containi +ng ## ## hashed user name and + passwords for the ## ## different batch runs +. ## ###################################################################### +########################### use warnings; use strict; use Net::FTPSSL; use Crypt::CBC; use Email::Send; use Email::Simple::Creator; my($day, $month, $year)=(localtime)[3,4,5]; $month = $month + 1; $year = $year + 1900; my $date = "$year-$month-$day"; my $log_name = "rbc_ftp_log_$date.log"; open (STDERR, ">>", $log_name); my $num_args = $#ARGV + 1; if ($num_args == 3) { my $batch = $ARGV[0]; my $work_dir = $ARGV[1]; my $config = $ARGV[2]; #time to read in the config file: open(CONFIG, "<$config") or die "Error Opening Config File!!!\n"; my @config_lines = <CONFIG>; close(CONFIG); my $cipher = Crypt::CBC->new( -key => 'xxxxxxxx', -cipher => 'Blow +fish',); my $user; my $pass; if ($batch eq "ns") { #we are doing a netset batch. $user = $cipher->decrypt($config_lines[0]); $pass = $cipher->decrypt($config_lines[1]); } if ($batch eq "inl") { #we are doing a inetlink batch. $user = $cipher->decrypt($config_lines[2]); $pass = $cipher->decrypt($config_lines[3]); } my $host = "xxx.xxxx.xxx"; my $ftp = Net::FTPSSL->new($host, Port => 21, Encryption => 'E', D +ebug => 1) or die "Cannot connect to $host: $@"; #connect to the ftp +server. #lets do the inl stuff first: $ftp->login($user, $pass) or die "Can't Login: ", $ftp->message; #change working directory on the remote host: $ftp->cwd("outbound/AAPA/") or die "Can't change working directory +: ", $ftp->message; my @dir_listing = $ftp->nlst() or die "Can't List Files.... ", $ft +p->message; $ftp->binary(); foreach (@dir_listing) { #loop through files in the directory and download the ones tha +t do not have downloaded in the name. if ( m/RPT0900P\.\d\d\d.downloaded/ ) { #already seen this file, output to log print STDERR "$date : Found File (Seen It Already): $_ \n" +; } else { #haven't seen this file before: print STDERR "Found File (New): $_ \n"; print STDERR "Changing Local Working Directory to: $work_d +ir\n"; chdir($work_dir) or die "Couldn't change local working dir +ectory!!!\n"; $ftp->get($_) or die "Couldn't Download New File: $_ Becau +se: ", $ftp->message; } } $ftp->quit; } else { print "Error, i need some command line arguments!!\n"; print "Usage: rbc_ftp.pl <batch> <working_directory> <config>\n"; print "<batch> is equal to what run we want to run, ie: 'ns' for N +etSet or 'inl' for I-NetLink\n"; print "<working_directory> is equal to the directory we want to sa +ve the downloaded files in.\n"; print "<config> is equal to the location of the config file.\n"; } my $mailer = Email::Send->new( { mailer => 'SMTP::TLS', mailer_args => [ Host => 'smtp.gmail.com', #Port => 587, User => 'xxx.xxxx@xxxx.xx', Password=> 'xxxxxxxx', Hello => 'localhost', ] } ); my $email = Email::Simple->create( header => [ From => 'xxxx.xxxx@xxxx.xx', To => 'xxxxxx@xxxx.xxx', Subject => 'RBC FTP Status:', ], body => 'This is a test.....', ); eval { $mailer->send($email) }; die "Error sending email: $@" if $@; close(STDERR);

Has anybody seen something like this before? I am having a hard time finding the issue that keeps this script from running on ServerB. I have a feeling that it could be a issue with one of my librarys, but i am un-sure where to look now.


Thanks in advance for any help that i get....

Edit: Fixed terminology error pointed out by Illuminatus (regarding referal of the Clients as "Servers")


Edit2: Marked topic solved as it was a firewall upstream from the client causing the issues.

Replies are listed 'Best First'.
Re: Net::FTPSSL + TLS Handshake Fail
by Illuminatus (Curate) on Sep 28, 2012 at 18:39 UTC
    caveat: I've done almost no work with TLS...

    I did find your post a little confusing, since you're using 'server' to refer to both the client systems and the system they are connecting to. I'm still not sure which one the ubuntu system is. I'd have used 'MachineA' and 'MachineB' and talk about them as the clients. ok, enough with the nits...

    It's failing on the initial TLS negotiation. As it's obviously getting to the server, it's not a network or firewall issue. That leaves either certificates or TLS library version mismatch as the most likely possible culprits. If you're able to login to ServerB (as the user the task is running under), I'd try a local ftps client there to see if it can login to your ftps-server. If you're able to make changes on the ftps-server, try bumping up the debug level on the server app. Most servers have a diagnostic level that provides detailed info on every failed session. It will likely be more informative.

    fnord

      Yes you are correct about my post being confusing...You are correct that ServerA and ServerB are both clients trying to connect to the ftps server. I refered to them wrongly as servers in this instant.

      I will give a actual ftps client a try quickly and report back with my results.

      Thanks very much for your input.
        after further testing with WinSCP on the client i am pretty sure that it's a Net::FTPSSL issue, as i can get the WinSCP client to conenct properly.

        After testing with WinSCP i uninstalled the perl install (strawberry perl) and re-installed. I now get the following output in my log:

        Net-FTPSSL Version: 0.22

        Perl: 5.016001 5.16.1, OS: MSWin32

        Server (port): xxxx.xxx.xxx (21)

        Keys: (Debug), (Encryption), (Port)
        Values: (1), (I), (21)

        Cannot connect to xxxx.xxxx.xxx: SSL connect attempt failed with unknown error error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number at rbc_ftp.pl line 63.

        Some more google searching regarding this new error message hasn't brought me much in the way of a solution....

        Does anybody have any ideas on how to fix this? I am at a loss for why this keeps failing, even though on other clients this script works just fine (including another windows 2008 r2 machine).