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

Hi Monks,

I am in need of some serious Perl help as I can't get to the bottom this issue. I have created a script using Net::SFTP::Foreign to transfer files between servers. I have to use Password authentication as we have no way of deploying Public / Private keys in the time frame that I have to get this working as a Web Application.

I have installed Expect.pm and compiled IO-Tty on Linux and all worked without an issue. Unfortunately our production environment runs HP-UX, so I have compiled IO-Tty exactly the same as I did on Linux however when using the same script, the SFTP connection drops out part way through a transfer.

It must be an issue with Expect as if Password authentication is not used the connection works fine.

Here is my test script..

use lib '../modules'; use strict; use Net::SFTP::Foreign; $|=1; print "Connecting….."; my $sftp = Net::SFTP::Foreign->new('ipaddress', user=>'user', password=>'secret'); if (not $sftp) { die("Error: No Connection:$@"); } elsif ($sftp->error) { die("Connect Failed : ".$sftp->status); } else { print "Connected!\n"; if (!$sftp->put("/source/path/to/file", "/remote/target/file ")) { print "Failed to Transfer: ".$sftp->error; } else { print "Transfer Done!!"; } print "\nFinished\n"; }
If I remove the password option and run from the command line, I get the password prompt from OpenSSH and the transfer works fine. With the password prompt the connection is opened, transfer starts but then fails before completion with the message “Connection to remote server is broken”. It’s odd because I can run ls commands, and some times they work and other times they fail half way through and some of the data is truncated. It’s as if the Expect spawned session is being closed.

I have enabled Debugging in Net:SFTP:Foreign and the following can be seen with or without password authentication.

With Password Authentication

Connecting.. # queueing msg len: 5, code:1, id:3 ... [1] # waiting for message... [1] # got it!, len:5, code:2, id:3, status: - Connected! # queueing msg len: 36, code:3, id:0 ... [1] # waiting for message... [1] # got it!, len:13, code:102, id:0, status: - # queueing msg len: 21, code:10, id:1 ... [1] # waiting for message... [1] # got it!, len:24, code:101, id:1, status: 0 # queueing msg len: 6447, code:6, id:2 ... [1] # waiting for message... [1] # queueing msg len: 13, code:4, id:3 ... [2] # waiting for message... [2] Failed to Transfer: Connection to remote server is broken

And without Password Authentication

Connecting... # queueing msg len: 5, code:1, id:3 ... [1] # waiting for message... [1] Password: # got it!, len:5, code:2, id:3, status: - Connected! # queueing msg len: 36, code:3, id:0 ... [1] # waiting for message... [1] # got it!, len:13, code:102, id:0, status: - # queueing msg len: 21, code:10, id:1 ... [1] # waiting for message... [1] # got it!, len:24, code:101, id:1, status: 0 # queueing msg len: 6447, code:6, id:2 ... [1] # waiting for message... [1] # got it!, len:24, code:101, id:2, status: 0 # queueing msg len: 13, code:4, id:3 ... [1] # waiting for message... [1] # got it!, len:24, code:101, id:3, status: 0 # queueing msg len: 36, code:9, id:4 ... [1] # waiting for message... [1] # got it!, len:24, code:101, id:4, status: 0 Transfer Done!!

I have even tried creating the Expect session my self and then passing that to Net:SFTP:Foreign but I get the same result. Below is the code and the result.

my $timeout = 50; use Expect; $Expect::Exp_Internal = 1; $Expect::Debug = 1; my $conn = Expect->new; $conn->raw_pty(1); $conn->log_user(0); $conn->spawn('/usr/bin/ssh', -l => 'USERNAME', 'IPADDRESS', -s => 'sft +p') or die "Cannot spawn : $!"; $conn->expect($timeout, "Password:") or die "Password not requested as + expected"; $conn->send("PASSWORD\n"); $conn->expect($timeout, "\n"); my $sftp = Net::SFTP::Foreign->new(transport => $conn); die "unable to stablish SSH connection: ". $sftp->error # The rest is the same as above
Result
Spawned '/usr/bin/ssh -l USERNAME IPADDRESS -s sftp' spawn id(3) Pid: 11622 Tty: /dev/pts/2 Expect::spawn('Expect=GLOB(0x4053a4dc)','/usr/bin/ssh','-l','u +sername',IPADDRESS,'-s','sftp') called at sftp.cgi line 32 expect(Expect=GLOB(0x4053a4dc) 50 Password:) called... expect(): handling param 'Password:'... expect(): exact match 'Password:'... Starting EXPECT pattern matching... Expect::expect('Expect=GLOB(0x4053a4dc)',50,'Password:') calle +d at sftp. cgi line 35 spawn id(3): beginning expect. Timeout: 50 seconds. Current time: Fri May 30 15:46:23 2008 spawn id(3): list of patterns: #1: -ex `Password:' spawn id(3): Does `' match: pattern #1: -ex `Password:'? No. Waiting for new data (50 seconds)... spawn id(3): new data. spawn id(3): read 10 byte(s). spawn id(3): Does `Password: ' match: pattern #1: -ex `Password:'? YES!! Before match string: `' Match string: `Password:' After match string: ` ' Matchlist: () Returning from expect successfully. spawn id(3): accumulator: ` ' Sending 'PASSWORD\n' to spawn id(3) Expect::print('Expect=GLOB(0x4053a4dc)','PASSWORD\x{a}') calle +d at sftp.cgi line 37 expect(Expect=GLOB(0x4053a4dc) 50 ) called... expect(): handling param ' '... expect(): exact match ' '... Starting EXPECT pattern matching... Expect::expect('Expect=GLOB(0x4053a4dc)',50,'\x{a}') called at + sftp.cgi line 38 spawn id(3): beginning expect. Timeout: 50 seconds. Current time: Fri May 30 15:46:26 2008 spawn id(3): list of patterns: #1: -ex `\n' spawn id(3): Does ` ' match: pattern #1: -ex `\n'? No. Waiting for new data (50 seconds)... spawn id(3): new data. spawn id(3): read 1 byte(s). spawn id(3): Does ` \n' match: pattern #1: -ex `\n'? YES!! Before match string: ` ' Match string: `\n' After match string: `' Matchlist: () Returning from expect successfully. spawn id(3): accumulator: `' # queueing msg len: 5, code:1, id:3 ... [1] # waiting for message... [1] # got it!, len:5, code:2, id:3, status: - Connecting Connected..... # queueing msg len: 36, code:3, id:0 ... [1] # waiting for message... [1] # got it!, len:13, code:102, id:0, status: - # queueing msg len: 21, code:10, id:1 ... [1] # waiting for message... [1] # got it!, len:24, code:101, id:1, status: 0 # queueing msg len: 6447, code:6, id:2 ... [1] # waiting for message... [1] # queueing msg len: 13, code:4, id:3 ... [2] # waiting for message... [2] Failed to Transfer: Connection to remote server is broken Closing spawn id(3). Expect::hard_close('Expect=GLOB(0x4053a4dc)') called at ../com +mon/modules/Expect.pm line 1621 Expect::DESTROY('Expect=GLOB(0x4053a4dc)') called at sftp.cgi +line 0 eval {...} called at sftp.cgi line 0 spawn id(3) closed. Pid 11622 of spawn id(3) terminated, Status: 0x8D00 # queueing msg len: 13, code:4, id:4 ... [3] # waiting for message... [3]
Dose any one have any ideas what might be causing this? I have run the Expect test script and it all checks out fine. I just cant see what is calling that close half way through the transfer which is causing Expect to kill the ssh process. The version of HP-UX is 11.11 and Perl is 5.8.0 built for PA-RISC1.1-thread-multi

Thank you!!!

Alistair

Replies are listed 'Best First'.
Re: Net::SFTP::Foreign Connections with Password Authentication
by salva (Canon) on May 30, 2008 at 21:20 UTC
    The same bug was reported last week by another person and it is already solved in the development release 1.37_07 available from CPAN (I plan to release it as stable next week if no bugs are found in the meantime).

    The bug is actually in HP-UX and it is discussed here.

      Thank you so much!! I tried some super searches but didnt find that post!

      I will try the development version tomorrow and then wait for the full version. I will let you know how I get on!

      Thank you for your help, and a great Module!!!
      Alistair

      Hi Salva,

      I have downloaded the new version of the module, but I am still having problems.

      With the changes, Expect doesn’t seem to be getting the Password prompt. The connection hangs for the timeout value and then returns "Password not requested as expected: 0".

      Any ideas as to why this could be? Its probably me being stupid but I have hit a wall again with my investigation.

      Thanks for your help!

      Alistair

        try setting the expect_log_user option on the constructor call to see the Expect interaction. And also run ssh with the verbose flag:
        my $s=Net::SFTP::Foreign->new( 'foo@bar', password=>'...', expect_log_user => 1, timeout => 8, more => '-v' ); die $sftp->error if $sftp->error;

        And BTW, is the remote system accessible from the Internet so I can run some tests against it?