Skip Menu |

This queue is for tickets about the Net-SSH-Perl CPAN distribution.

Report information
The Basics
Id: 23947
Status: resolved
Priority: 0/
Queue: Net-SSH-Perl

People
Owner: Nobody in particular
Requestors: toddr [...] cpanel.net
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.29
Fixed in: (no value)



Subject: Net::SSH::Perl::Auth::KeyboardInt should offer non-interactive option.
With the below minor change, keyboard-interactive mode can be done in batch mode. I'm guessing a decision was made to stay true to the openssh model. Is this why it was not done? I'd be really appreciative if this mod made it into the next release... < for (1..$prompts) { < my $res = _prompt($packet->get_str, undef, $packet- Show quoted text
>get_int8);
--- Show quoted text
> my $username_passed = $ssh->config->get('user'); > my $password_passed = $ssh->config->get('pass'); > for (1..$prompts) { > my $string = $packet->get_str; > my $res; > if(defined $password_passed && $string =~ m/
${username_passed}\'s Password:/) { Show quoted text
> $res = $password_passed; > } else { > my $res = _prompt($string, undef, $packet->get_int8); > }
68c76 < }); --- Show quoted text
> });
Subject: KeyboardInt.pm.html

Message body is not shown because it is too large.

From: todd.e.rinaldo [...] jpmorgan.com
My Bad. Minor mod on the diff < for (1..$prompts) { < my $res = _prompt($packet->get_str, undef, $packet- Show quoted text
>get_int8);
--- Show quoted text
> my $username_passed = $ssh->config->get('user'); > my $password_passed = $ssh->config->get('pass'); > for (1..$prompts) { > my $string = $packet->get_str; > my $res; > if(defined $password_passed && $password_passed =~ m/\S/ &&
$string =~ m/${username_passed}\'s Password:/) { Show quoted text
> $res = $password_passed; > } else { > $res = _prompt($string, undef, $packet->get_int8); > }
I do appreciate the diff, but it doesn't have any context information. Please provide a unified diff (-u) showing which file was changed ("diff -u old new" should suffice, and attach the result). In general I'm not fixing non-critical Net::SSH::Perl errors, but given that there's a diff, if this passes tests I'll fix it given a unified diff.
(The reason I'm not fixing non-critical Net::SSH::Perl errors is that it's been mostly superseded by Net::SSH2, which has less dependencies, and is based on a C library libssh2 which makes it much faster.)
From: todd.e.rinaldo [...] jpmorgan.com
Unified Diff --- KeyboardInt.pm.133.pm Wed Nov 05 14:04:57 2008 +++ KeyboardInt.pm.mod Wed Nov 05 14:04:57 2008 @@ -60,12 +60,22 @@ my $prompts = $packet->get_int32; my $pres = $ssh->packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); $pres->put_int32($prompts); + my $username_passed = $ssh->config->get('user'); + my $password_passed = $ssh->config->get('pass'); for (1..$prompts) { - my $res = _prompt($packet->get_str, undef, $packet- Show quoted text
>get_int8);
+ my $string = $packet->get_str; + my $res; + if(defined $password_passed + && $password_passed =~ m/\S/ + && $string =~ m/${username_passed}\'s Password:/) { + $res = $password_passed; + } else { + $res = _prompt($string, undef, $packet->get_int8); + } $pres->put_str($res); } $pres->send; - }); +}); return 1; }
From: todd.e.rinaldo [...] jpmorgan.com
Changed code to die if automatic KB int is attempted twice --- KeyboardInt.pm.133.pm Wed Nov 05 16:08:56 2008 +++ KeyboardInt.pm.mod Wed Nov 05 16:08:56 2008 @@ -60,12 +60,26 @@ my $prompts = $packet->get_int32; my $pres = $ssh->packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); $pres->put_int32($prompts); - for (1..$prompts) { - my $res = _prompt($packet->get_str, undef, $packet- Show quoted text
>get_int8);
+ my $username_passed = $ssh->config->get('user'); + my $password_passed = $ssh->config->get('pass'); + for (1..$prompts) { + my $string = $packet->get_str; + my $res; + if($password_passed && $string =~ m/${username_passed}\'s Password:/) { + $ssh->debug("Attempting keyboard-interactive with passed password from login()"); + if($ssh->config->get('interactive_attempted')) { # Die if we've tried this before. + die("Interactive KB attempted once already"); + } + $res = $password_passed; + $ssh->config->set('interactive_attempted', 1); # Assure keyboard int won't re-try. + } else { + $res = _prompt($string, undef, $packet->get_int8); + } + # Modification Ends. $pres->put_str($res); } $pres->send; - }); +}); return 1; }
From: todd.e.rinaldo [...] jpmorgan.com
Net::SSH2 is far from offering all of the features this version has. I would humbly request this patch be considered.
On Wed Nov 05 17:12:56 2008, todd_rinaldo wrote: Show quoted text
> Net::SSH2 is far from offering all of the features this version has. I > would humbly request this patch be considered.
I would as well. I used Net::SSH::Perl in a context in which I ask for the password once and use it for a multitude of servers, and they only support keyboard-interactive. Being required to insert the same password all the times... is simply not Perl :) My code change was even simpler: --- KeyboardInt.pm 2008-10-21 19:54:23.000000000 +0200 +++ /opt/perl/lib/site_perl/5.8.8/Net/SSH/Perl/Auth/KeyboardInt.pm 2008-10-22 10:13:07.000000000 +0200 @@ -61,7 +61,7 @@ my $pres = $ssh->packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); $pres->put_int32($prompts); for (1..$prompts) { - my $res = _prompt($packet->get_str, undef, $packet->get_int8); + my $res = $ssh->config->get('pass') || _prompt($packet->get_str, undef, $packet->get_int8); $pres->put_str($res); } $pres->send; but, of course, is slightly wrong (does not work if the password is '0') and lacks all the checks of the proposed change.
From: todd.e.rinaldo [...] jpmorgan.com
The big enhancement my solution offers over yours is that in my environment, it's critical that login fail if the password is wrong. In previous attempts on this patch, I failed to think of this and on more than one occasion locked my account out.
From: jamie [...] audible.transient.net
On Mon Dec 15 10:49:26 2008, todd_rinaldo wrote: Show quoted text
> The big enhancement my solution offers over yours is that in my > environment, it's critical that login fail if the password is wrong. In > previous attempts on this patch, I failed to think of this and on more > than one occasion locked my account out.
I've written a replacement for KeyboardInt.pm that both facilitates what it is you want to do (try the password in $ssh->config->get('pass')) but doesn't get in they way of compliance with RFC 4256, or impose any limitations on any other users of this package that may not enjoy a change in existing behavior. What I haven't written is any documentation for it (yet). If there's a chance that my replacement could just become the default keyboard-interactive authentication method implementation for Net::SSH::Perl, then I'd happily write up some pod too, but here's the basic feature list and how it differs from KeyboardInt.pm: 1) isn't limited to interactive mode Incidentally, despite the name "keyboard-interactive", a completely legitimate userauth info request may include a request with empty strings for the name, and instruction fields and 0 num-prompts, the correct response for which is handled entirely without any user interaction. Given that the SSH authentication protocol allows for multi-method authentication sequences, it's completely possible for such a request to be part of a such a sequence, and it would be silly to not support it just because the client hadn't been configured as "interactive." I consider the current package to be buggy in this regard. 2) includes debugging Figuring out where and why authentication is failing can be tricky. I just used the existing debugging framework and added some appropriate debug calls. 3) implements control character filtering Client's shouldn't blindly trust the text servers give them to be safe for display, so I rip out any control characters per RFC 4251 section 9.2. 4) includes the ability to register info request handlers Want to introspect the userauth info request and send an automated reply to it if the request matches some set of heuristics? This the feature that lets you do that. If you don't register any handlers, this module acts pretty much the same as KeyboardInt.pm acts now (modulo the above 3 features anyway). I've attached my replacement package. As an example of how you might use it to go about installing a one-shot automatic password handler that will only be triggered if the name and instruction strings in the userauth info request message are empty, num-prompts is 1, the prompt looks like the word "password" and we have a stored password for the current user... use Net::SSH::Perl; use Net::SSH::Perl::Auth::KeyboardInteractive qw(add_kbdint_handler); my $ssh = new Net::SSH::Perl->new($host, 'protocol' => 2); add_kbdint_handler($ssh, sub { my ($auth, $name, $instruction, $lang, $prompts) = @_; return defined($auth->{'ssh'}->config->get('pass')) && $name eq '' && $instruction eq '' && @$prompts == 1 && $prompts->[0]->[0] =~ /\Apassword\W*\z/i; }, sub { my ($auth, $name, $instruction, $lang, $prompt, $echo) = @_; $auth->del_handler; return $auth->{'ssh'}->config->get('pass'); } ); $ssh-login(...
package Net::SSH::Perl::Auth::KeyboardInteractive; use strict; use warnings; use Exporter qw(import); use Net::SSH::Perl::Constants qw(:msg2); use Net::SSH::Perl::Util qw(_prompt); use Scalar::Util qw(weaken); use base qw(Net::SSH::Perl::Auth); our @EXPORT_OK = qw(add_kbdint_handler del_kbdint_handler); sub add_kbdint_handler { my ($ssh, $handles, $handler, $pos) = @_; my $handlers = $ssh->config->get('auth_kbd_interactive_handlers') || []; $pos = @$handlers unless (defined $pos); splice @$handlers, $pos, 0, {'handler' => $handler, 'handles' => $handles}; $ssh->config->set('auth_kbd_interactive_handlers', $handlers); return $pos; } sub del_kbdint_handler { my ($ssh, $pos) = @_; my $handlers = $ssh->config->get('auth_kbd_interactive_handlers') or return; $pos = -1 unless (defined $pos); splice @$handlers, $pos, 1; return $pos; } sub _dispatch { my ($auth, $name, $instruction, $lang, $prompts) = @_; foreach (@{$auth->{'_handlers'}}) { return $_->{'handler'} if ($_->{'handles'}($auth, $name, $instruction, $lang, $prompts)); } return; } sub new { my ($class, $ssh) = @_; my $auth = bless {'ssh' => $ssh}, $class; weaken($auth->{'ssh'}); my $handlers = $ssh->config->get('auth_kbd_interactive_handlers') || []; @{$auth->{'_handlers'}} = map { {%$_} } @$handlers; # 1 level deep copy $auth->enabled($ssh->config->get('auth_kbd_interactive')); return $auth; } sub enabled { my $self = shift; $self->{'enabled'} = shift if (@_); return $self->{'enabled'}; } sub add_handler { my ($self, $handles, $handler, $pos) = @_; $pos = @{$self->{'_handlers'}} unless (defined $pos); splice @{$self->{'_handlers'}}, $pos, 0, { 'handler' => $handler, 'handles' => $handles }; return $pos; } sub del_handler { my ($self, $pos) = @_; return unless (@{$self->{'_handlers'}}); $pos = -1 unless (defined $pos); splice @{$self->{'_handlers'}}, $pos, 1; return $pos; } sub authenticate { my $self = shift; my $ssh = $self->{'ssh'}; return unless ($self->enabled); $self->mgr->register_handler(SSH2_MSG_USERAUTH_INFO_REQUEST, sub { my ($amgr, $pkt) = @_; $ssh->debug('auth keyboard-interactive: rcvd info req'); my ($name, $instruction, $lang, $n_prompts) = ($pkt->get_str, $pkt->get_str, $pkt->get_str, $pkt->get_int32); $ssh->debug("auth info req: name='$name' instruction='$instruction' " . "language='$lang' prompts=$n_prompts"); my @prompts = map { [$pkt->get_str, $pkt->get_int8] } (1 .. $n_prompts); my $r_pkt = $ssh->packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); $r_pkt->put_int32($n_prompts); if (my $h = _dispatch($self, $name, $instruction, $lang, \@prompts)) { $r_pkt->put_str(&$h($self, $name, $instruction, $lang, @$_)) for (@prompts); } elsif ($ssh->config->get('interactive')) { print map { s/[[:cntrl:]]+//g; "$_\n" } grep { length } ($name, $instruction); $r_pkt->put_str(_prompt($_->[0], undef, $_->[1])) for (@prompts); } elsif ($n_prompts != 0) { $ssh->debug('auth keyboard-interactive: cannot handle info req'); # We're not in interactive mode so we can't prompt anybody # and we don't have a handler for this request, so we mark # ourselves disabled, and abandon the current info request # by sending a new, "none" method, auth request. $self->enabled(0); $r_pkt = $ssh->packet_start(SSH2_MSG_USERAUTH_REQUEST); $r_pkt->put_str($ssh->config->get('user')); # user $r_pkt->put_str('ssh-connection'); # service name $r_pkt->put_str('none'); # method name } $r_pkt->send; }); $ssh->debug('auth keyboard-interactive: send req'); my $packet = $ssh->packet_start(SSH2_MSG_USERAUTH_REQUEST); $packet->put_str($ssh->config->get('user')); # user $packet->put_str('ssh-connection'); # service name $packet->put_str('keyboard-interactive'); # method name $packet->put_str(''); # language $packet->put_str(''); # submethods $packet->send; return 1; } 1;
Show quoted text
> If there's a chance that my replacement > could just become the default keyboard-interactive authentication method > implementation for Net::SSH::Perl, then I'd happily write up some pod > too
There is definitely a chance, so POD would be very welcome.
On Sun Jan 25 20:16:20 2009, TURNSTEP wrote: Show quoted text
> > If there's a chance that my replacement > > could just become the default keyboard-interactive authentication method > > implementation for Net::SSH::Perl, then I'd happily write up some pod > > too
> > There is definitely a chance, so POD would be very welcome.
The patch is now in its own branch here: https://github.com/renormalist/Net-SSH-Perl/tree/keyboardinteractive Kind regards, Steffen -- Steffen Schwigon <ss5@renormalist.net> Dresden Perl Mongers <http://dresden-pm.org/>
Branch maintenance. It's now here: https://github.com/renormalist/Net-SSH-Perl/tree/rt23947-keyboard-interactive Steffen -- Steffen Schwigon <ss5@renormalist.net> Dresden Perl Mongers <http://dresden-pm.org/>
On Mon Dec 10 06:16:30 2012, SCHWIGON wrote: Show quoted text
> Branch maintenance. It's now here: > > > https://github.com/renormalist/Net-SSH-Perl/tree/rt23947-keyboard- > interactive
Now part of v1.36, just uploaded to CPAN. Steffen -- Steffen Schwigon <ss5@renormalist.net> Dresden Perl Mongers <http://dresden-pm.org/>