| Net-SSH-Perl documentation | Contained in the Net-SSH-Perl distribution. |
Net::SSH::Perl::AuthMgr - Authentication manager/context for SSH-2
use Net::SSH::Perl::AuthMgr;
my $amgr = Net::SSH::Perl::AuthMgr->new($ssh);
$amgr->authenticate;
Net::SSH::Perl::AuthMgr manages authentication methods and auth context for the SSH-2 authentication process. At its heart is a dispatch mechanism that waits for incoming packets and responds as necessary, based on a handler table that maps packet types to code references.
You should never need to use AuthMgr directly, as it will be automatically invoked when you call login.
Please see the Net::SSH::Perl manpage for author, copyright, and license information.
| Net-SSH-Perl documentation | Contained in the Net-SSH-Perl distribution. |
# $Id: AuthMgr.pm,v 1.7 2008/10/02 20:46:17 turnstep Exp $ package Net::SSH::Perl::AuthMgr; use strict; use Carp qw( croak ); use Net::SSH::Perl::Agent; use Net::SSH::Perl::Auth; use Net::SSH::Perl::Constants qw( SSH2_MSG_SERVICE_REQUEST SSH2_MSG_SERVICE_ACCEPT SSH2_MSG_USERAUTH_BANNER SSH2_MSG_USERAUTH_REQUEST SSH2_MSG_USERAUTH_SUCCESS SSH2_MSG_USERAUTH_FAILURE ); use Scalar::Util qw(weaken); use vars qw( %AUTH_MAP ); %AUTH_MAP = ( password => 'Password', publickey => 'PublicKey', 'keyboard-interactive' => 'KeyboardInt', ); sub new { my $class = shift; my $ssh = shift; my $amgr = bless { ssh => $ssh }, $class; weaken $amgr->{ssh}; $amgr->init(@_); } sub init { my $amgr = shift; my $ssh = $amgr->{ssh}; my($packet); $ssh->debug("Sending request for user-authentication service."); $packet = $ssh->packet_start(SSH2_MSG_SERVICE_REQUEST); $packet->put_str("ssh-userauth"); $packet->send; $packet = Net::SSH::Perl::Packet->read($ssh); croak "Server denied SSH2_MSG_SERVICE_ACCEPT: ", $packet->type unless $packet->type == SSH2_MSG_SERVICE_ACCEPT; $ssh->debug("Service accepted: " . $packet->get_str . "."); $amgr->{agent} = Net::SSH::Perl::Agent->new(2); $amgr->{service} = "ssh-connection"; $amgr->send_auth_none; $amgr; } sub agent { $_[0]->{agent} } sub send_auth_none { my $amgr = shift; my $ssh = $amgr->{ssh}; $ssh->debug("Trying empty user-authentication request."); my $packet = $ssh->packet_start(SSH2_MSG_USERAUTH_REQUEST); $packet->put_str($ssh->config->get('user')); $packet->put_str("ssh-connection"); $packet->put_str("none"); $packet->send; } sub authenticate { my $amgr = shift; my $ssh = $amgr->{ssh}; my($packet); my $valid = 0; $amgr->{_done} = 0; $amgr->register_handler(SSH2_MSG_USERAUTH_SUCCESS, sub { $valid++; $amgr->{_done}++ }); $amgr->register_handler(SSH2_MSG_USERAUTH_BANNER, sub { my $amgr = shift; my($packet) = @_; if ($amgr->{ssh}->config->get('interactive')) { print $packet->get_str, "\n"; } }); $amgr->register_handler(SSH2_MSG_USERAUTH_FAILURE, \&auth_failure); $amgr->register_error( sub { croak "userauth error: bad message during auth" } ); $amgr->run( \$amgr->{_done} ); $amgr->{agent}->close_socket if $amgr->{agent}; $valid; } sub auth_failure { my $amgr = shift; my($packet) = @_; my $ssh = $amgr->{ssh}; my $authlist = $packet->get_str; my $partial = $packet->get_int8; $ssh->debug("Authentication methods that can continue: $authlist."); my($found); for my $meth ( split /,/, $authlist ) { $found = 0; next if !exists $AUTH_MAP{$meth}; my $auth = $amgr->{_auth_objects}{$meth}; unless ($auth) { $auth = $amgr->{_auth_objects}{$meth} = Net::SSH::Perl::Auth->new($AUTH_MAP{$meth}, $ssh); $auth->mgr($amgr); } next unless $auth->enabled; $ssh->debug("Next method to try is $meth."); $found++; if ($auth->authenticate($amgr->{_auth_tried}{$meth}++)) { last; } else { $auth->enabled(0); delete $amgr->{_auth_objects}{$meth}; $found = 0; } } $amgr->{_done} = 1 unless $found; } sub register_handler { $_[0]->{__handlers}{$_[1]} = $_[2] } sub remove_handler { delete $_[0]->{__handlers}{$_[1]} } sub register_error { $_[0]->{__error_handler} = $_[1] } sub handler_for { $_[0]->{__handlers}{$_[1]} } sub error_handler { $_[0]->{__error_handler} } sub run { my $amgr = shift; my($end, @args) = @_; until ($$end) { my $packet = Net::SSH::Perl::Packet->read($amgr->{ssh}); my $code = $amgr->handler_for($packet->type); unless (defined $code) { $code = $amgr->error_handler || sub { croak "Protocol error: received type ", $packet->type }; } $code->($amgr, $packet, @args); } } 1; __END__