Subject: | [+ possible solution] Password prompt matching requires colon, which may be missing |
I received a bug report as a maintainer of Fedora Net::SFTP::Foreign port. Original bug report: https://bugzilla.redhat.com/show_bug.cgi?id=1068706
Thank you for this great module and keep up the good work.
Description of problem:
Net::SFTP::Foreign's password prompt matching code goes into a permanent loop when the remote server supplies a prompt without a trailing colon.
Version-Release number of selected component (if applicable):
perl-Net-SFTP-Foreign-1.75-3.fc20.noarch.rpm
How reproducible:
When testing Net::SFTP::Foreign against an "unusual" host which supported keyboard-interactive authentication, and thus generated a server-supplied password prompt, it was found that the host in question had a prompt of the form "username's password", rather than the more usual "username@host's password: " as seen from OpenSSH client code supporting the password authentication mode.
As a consequence, the Net::SFTP::Foreign module simply sulked waiting for a colon.
Looking at the relevant /usr/share/perl5/vendor_perl/Net/SFTP/Foreign/Backend/Unix.pm code file, we find the following code fragment:
.....
debug and $debug & 65536 and _debug "looking for user/password prompt";
my $re = ( defined $password_prompt
? $password_prompt
: qr/(user|name|login)?[:?]\s*$/i );
$debug and $debug & 65536 and _debug "matching against $re";
if (substr($buffer, $at) =~ $re) {
if ($ask_for_username_at_login and
($ask_for_username_at_login ne 'auto' or defined $1)) {
$debug and $debug & 65536 and _debug "sending username";
print $pty "$user\n";
undef $ask_for_username_at_login;
}
else {
$debug and $debug & 65536 and _debug "sending password";
print $pty "$pass\n";
$password_sent = 1;
}
$at = length $buffer;
}
.....
In the absence of the $password_prompt setting, $re only matches a password prompt containing the string "password" if it contains a colon or question-mark after the word "password".
The code is also questionable in being capable of sending a password in response to a prompt which contains only a colon followed by whitespace; I feel it ought to at least see the word "password" or "passphrase".
The code also uses the $password_prompt variable to match against a potential username prompt, which is questionable.
I believe it would be better to more completely separate the user and password prompt matching with different Regex's, and avoid being able to match against the short ":" string alone, and cope with the unusual condition of a missing colon.
This recoding of the relevant block is a potential solution:
.....
$debug and $debug & 65536 and _debug "looking for user/password prompt";
my $reuser = qr/(user|name|login)([:?])?\s*$/i;
my $repass = ( defined $password_prompt ?
$password_prompt : qr/(password|passphrase)([:?])?\s*$/i );
if (substr($buffer, $at) =~ $reuser) {
$debug and $debug & 65536 and _debug "matched against $reuser";
if ($ask_for_username_at_login and
($ask_for_username_at_login ne 'auto' or defined $1)) {
$debug and $debug & 65536 and _debug "sending username";
print $pty "$user\n";
undef $ask_for_username_at_login;
}
$at = length $buffer;
} elsif (substr($buffer, $at) =~ $repass) {
$debug and $debug & 65536 and _debug "matched against $repass";
$debug and $debug & 65536 and _debug "sending password";
print $pty "$pass\n";
$password_sent = 1;
$at = length $buffer;
}
....