Subject: | On redhat linux ftps session hangs afte USER xxx command is sent |
While testing on redhat linux my ftps session consistantly hangs after
the "USER xxx" command is sent. The error condition is 100% reproduceable.
On the server side, the "331 Enter password" response has already been
sent. On the client side, the Net::FTPSSL module is stuck in sysread in
sub response.
Since the same sysread works just a moment before, against the same
socket in clear text, I suspect the clear-to-ssl switch has something to
do with it, and the fault lies not in Net::FTPSSL, but one of the
underlying SSL modules.
I have found a workaround in Net::FTPSSL, by having Net::FTPSSL read the
server response one character at a time. Although this workaround seems
to solve the problem, I am hesitate to call it a patch, because it may
not be fixing the real thing. In any case, I am attaching the workaround
for your review. (Although you can't apply this workaround and the patch
for bug 16751 at the same time, this workaround also handles long,
multi-line response correctly.)
Oddly enough, the data channels, which are also SSL, continue to be read
chunks at a time, and yet I never run into any hung situation...
Here is the details of my test environment:
perl version: 5.8.4
$IO::Socket::SSL:VERSION = 0.97
$Net::SSLeay::VERSION = 1.25
$Net::FTPSSL::VERSION = 0.04
openssl library version: 0.9.7
The client and server are on different hosts, on the same network, with
the same OS type/revision.
sysinfo output of client host:
G E N E R A L I N F O R M A T I O N
Host Name is pi119c2n13
Host Address(es) is 144.14.14.73
Host ID is 0e90490e
Serial Number is KPGPZ36
Manufacturer is IBM
Manufacturer (Short) is IBM
Manufacturer (Full) is IBM
System Model is eServer BladeCenter HS20 -[88323EX]-
Main Memory is 8.0 GB
Virtual Memory is 12 GB
Number of CPUs (Physical) is 2
Number of CPUs (Virtual) is 4
Number of CPUs Online is 4
CPU Type is i686
CPU Model is Xeon
CPU Speed is 3.1 GHz
App Architecture is x86
Kernel Architecture is i686
Kernel Bit Size is 32
OS Name is Linux
OS Version is 2.4.21-32.0.1.ELhugemem
OS Distribution is Red Hat Enterprise Linux AS release 3
(Taroon Update 4)
OS Distribution Name is Red Hat Enterprise Linux
OS Distribution Short Name is rhel
OS Distribution Version is 3
Libc Version is 2.3.2
Kernel Version is Linux version 2.4.21-32.0.1.ELhugemem
(bhcompile@bugs.build.redhat.com) (gcc version 3.2.3 20030502 (Red Hat
Linux 3.2.3-52)) #1 SMP Tue May 17 17:43:22 EDT 2005
Boot Time is Sat Jul 16 23:56:29 2005 EDT
Current Time is Thu Feb 9 09:20:59 2006 EST
Time Zone is EST
Primary User Login is dong
Primary User Name is Dong Yan
sysinfo output of server host is very similar (difference being
hostname, ip address, etc).
Subject: | workaround.txt |
--- FTPSSL.pm.ORIG 2006-02-08 15:01:01.000000000 -0500
+++ FTPSSL.pm.PATCH 2006-02-09 09:19:39.000000000 -0500
@@ -657,29 +657,31 @@
my $self = shift;
my ( $data, $code );
- my $read = sysread( $self, $data, 4096);
- unless( defined $read ) {
- croak "Can't read on socket: $!";
- }
-
- my @lines = split( "\015\012", $data );
-
- foreach my $line ( @lines ) {
-
-# $data = $self->getline();
-# $data =~ m/^(\d+)(\-?)(.*)$/s;
- $line =~ m/^(\d+)(\-?)(.*)$/s;
-
- $code = $1;
- print STDERR "<<< " . $line ."\n"
- if ref($self) eq "Net::FTPSSL" && ${*$self}{'debug'};
-
- if ( ref($self) eq "Net::FTPSSL" ) {
- ${*$self}{'last_ftp_msg'} = $line;
+ $code = '000';
+ my $line = '';
+ my $all_lines = '';
+ while (1) {
+ my $read = sysread( $self, $data, 1 );
+ unless( defined $read ) {
+ next if $! == EINTR;
+ croak "Can't read on socket: $!";
}
+ $line .= $data;
+ if ($data eq "\012" ) {
+ $line =~ s/\015//g;
+ $all_lines .= $line;
+ print STDERR "<<< " . $line
+ if ref($self) eq "Net::FTPSSL" && ${*$self}{'debug'};
+ if ( $line =~ /^\d{3} / ) {
+ $code = substr( $line, 0, 3 );
+ last;
+ }
+ $line = '';
+ }
+ }
- last if $2 ne '-';
-
+ if ( ref($self) eq "Net::FTPSSL" ) {
+ ${*$self}{'last_ftp_msg'} = $all_lines;
}
return substr( $code, 0, 1 );