Net-SSH2
view release on metacpan or search on metacpan
lib/Net/SSH2.pm view on Meta::CPAN
},
'hostbased' => {
ssh => 'hostbased',
method => \&auth_hostbased,
params => [qw(username publickey privatekey
hostname local_username? passphrase?)],
},
'publickey' => {
ssh => 'publickey',
method => \&auth_publickey,
params => [qw(username publickey? privatekey passphrase?)],
},
'keyboard' => {
ssh => 'keyboard-interactive',
method => \&auth_keyboard,
params => [qw(_interact _fallback username cb_keyboard?)]
},
'keyboard-auto' => {
ssh => 'keyboard-interactive',
method => \&auth_keyboard,
params => [qw(username password)],
},
'password' => {
ssh => 'password',
method => \&auth_password,
params => [qw(username password cb_password?)],
},
'password-interact' => {
ssh => 'password',
method => \&auth_password_interact,
params => [qw(_interact _fallback username cb_password?)],
},
'none' => {
ssh => 'none',
method => \&auth_password,
params => [qw(username)],
},
};
}
my @rank_default = qw(hostbased publickey keyboard-auto password agent keyboard password-interact none);
sub _auth_rank {
my ($self, $rank) = @_;
$rank ||= \@rank_default;
my $libver = ($self->version)[1] || 0;
return @$rank if $libver > 0x010203;
return grep { $_ ne 'agent' } @$rank;
}
sub _local_user {
for (qw(USER LOGNAME)) {
return $ENV{$_} if defined $ENV{$_}
}
local ($@, $SIG{__DIE__}, $SIG{__WARN__});
my $u = eval { getlogin };
return $u if defined $u;
eval { getpwuid $< }
}
my $password_when_you_mean_passphrase_warned;
sub auth {
my ($self, %p) = @_;
$self->_set_error(LIBSSH2_ERROR_AUTHENTICATION_FAILED(),
"Authentication failed"); # default error
$p{username} = _local_user unless defined $p{username};
my @rank = $self->_auth_rank(delete $p{rank});
my $remote_rank;
$remote_rank = { map { $_ => 1 } $self->auth_list($p{username}) }
if defined $p{username};
# if fallback is set, interact with the user even when a password
# is given
$p{fallback} = 1 unless defined $p{password} or defined $p{passphrase};
TYPE: for my $type (@rank) {
my $data = $self->_auth_methods->{$type};
unless ($data) {
carp "unknown authentication method '$type'";
next;
}
next if $remote_rank and !$remote_rank->{$data->{ssh}};
# do we have the required parameters?
my @pass;
for my $param(@{$data->{params}}) {
my $p = $param;
my $opt = $p =~ s/\?$//;
my $pseudo = $p =~ s/^_//;
if ($p eq 'passphrase' and not exists $p{$p} and defined $p{password}) {
$p = 'password';
$password_when_you_mean_passphrase_warned++
or carp "Using the key 'password' to refer to a passphrase is deprecated. Use 'passphrase' instead";
}
if ($pseudo) {
next TYPE unless $p{$p};
}
else {
next TYPE unless $opt or defined $p{$p};
push @pass, $p{$p}; # if it's optional, store undef
}
}
# invoke the authentication method
return $type if $data->{method}->($self, @pass) and $self->auth_ok;
}
return 'none' if $self->auth_ok;
$self->_set_error(LIBSSH2_ERROR_AUTHENTICATION_FAILED(),
"All authentication methods failed");
return; # failure
}
lib/Net/SSH2.pm view on Meta::CPAN
my $term_readkey_unavailable_warned;
my $term_readkey_loaded;
sub _load_term_readkey {
return 1 if $term_readkey_loaded ||= do {
local ($@, $!, $SIG{__DIE__}, $SIG{__WARN__});
eval { require Term::ReadKey; 1 }
};
carp "Unable to load Term::ReadKey, will not ask for passwords at the console!"
unless $term_readkey_unavailable_warned++;
return;
}
sub _print_stderr {
my $self = shift;
my $ofh = select STDERR; local $|= 1; select $ofh;
print STDERR $_ for @_;
}
sub _ask_user {
my ($self, $prompt, $echo) = @_;
my $timeout;
if (($self->version)[1] >= 0x10209) {
$timeout = $self->timeout || 0;
$timeout = ($timeout + 999) / 1000;
}
_load_term_readkey or return;
$self->_print_stderr($prompt);
Term::ReadKey::ReadMode('noecho') unless $echo;
my $reply = Term::ReadKey::ReadLine($timeout);
Term::ReadKey::ReadMode('normal') unless $echo;
$self->_print_stderr("\n")
unless $echo and defined $reply;
if (defined $reply) {
chomp $reply
}
else {
$self->_set_error(LIBSSH2_ERROR_SOCKET_TIMEOUT(),
"Timeout waiting for user response!");
}
return $reply;
}
sub auth_password_interact {
my ($self, $username, $cb) = @_;
_load_term_readkey or return;
my $rc;
for (0..2) {
my $password = $self->_ask_user("${username}'s password? ", 0);
$rc = $self->auth_password($username, $password, $cb);
last if $rc or $self->error != LIBSSH2_ERROR_AUTHENTICATION_FAILED();
my $ofh = select STDERR; local $|= 1; select $ofh;
$self->_print_stderr("Password authentication failed!\n");
}
return $rc;
}
sub _local_home {
return $ENV{HOME} if defined $ENV{HOME};
local ($@, $SIG{__DIE__}, $SIG{__WARN__});
my $home = eval { (getpwuid($<))[7] };
return $home;
}
my $check_hostkey_void_ctx_warned;
sub check_hostkey {
my ($self, $policy, $path, $comment) = @_;
defined wantarray or $check_hostkey_void_ctx_warned++ or
warnings::warnif($self, "Calling check_hostkey in void context is useless");
my $cb;
if (not defined $policy) {
$policy = LIBSSH2_HOSTKEY_POLICY_STRICT();
}
elsif (ref $policy eq 'CODE') {
$cb = $policy;
}
else {
$policy = _parse_constant(HOSTKEY_POLICY => $policy);
}
my $hostname = $self->hostname;
croak("hostname unknown: in order to use check_hostkey the peer host name ".
"must be given (or discoverable) at connect time")
unless defined $hostname;
unless (defined $path) {
my $home = _local_home;
unless (defined $home) {
$self->_set_error(LIBSSH2_ERROR_FILE(), "Unable to determine known_hosts location");
return;
}
require File::Spec;
$path = File::Spec->catfile($home, '.ssh', 'known_hosts');
}
my ($check, $key, $type, $flags);
my $kh = $self->known_hosts;
if ($kh and defined $kh->readfile($path)) {
($key, $type) = $self->remote_hostkey;
$flags = ( LIBSSH2_KNOWNHOST_TYPE_PLAIN() |
LIBSSH2_KNOWNHOST_KEYENC_RAW() |
(($type + 1) << LIBSSH2_KNOWNHOST_KEY_SHIFT()) );
$check = $kh->check($hostname, $self->port, $key, $flags);
$check == LIBSSH2_KNOWNHOST_CHECK_MATCH() and return "00";
}
else {
$check = LIBSSH2_KNOWNHOST_CHECK_FAILURE();
}
if ($cb) {
my $ok = $cb->($self, $check, $comment);
$ok or $self->_set_error(LIBSSH2_ERROR_KNOWN_HOSTS(), 'Host key verification failed');
return $ok;
}
return $check
if $policy == LIBSSH2_HOSTKEY_POLICY_ADVISORY(); # user doesn't care!
( run in 0.760 second using v1.01-cache-2.11-cpan-39bf76dae61 )