Net-OpenSSH-More

 view release on metacpan or  search on metacpan

lib/Net/OpenSSH/More.pm  view on Meta::CPAN

package Net::OpenSSH::More;
$Net::OpenSSH::More::VERSION = '1.01';
#ABSTRACT: Net::OpenSSH submodule with many useful features

use strict;
use warnings;

use parent 'Net::OpenSSH';

use Data::UUID         ();
use Expect             ();
use File::HomeDir      ();
use File::Temp         ();
use Fcntl              ();
use IO::Pty            ();
use IO::Socket::INET   ();
use IO::Socket::INET6  ();
use IO::Stty           ();
use List::Util         qw{first};
use Net::DNS::Resolver ();
use Net::IP            ();
use Time::HiRes        ();
use Term::ANSIColor    ();


my %defaults = (
    'user'                 => $ENV{'USER'} || getpwuid($>),
    'port'                 => 22,
    'use_persistent_shell' => 0,
    'output_prefix'        => '',
    'home'                 => File::HomeDir->my_home,
    'retry_interval'       => 6,
    'retry_max'            => 10,
);

our %cache;
our $disable_destructor = 0;

###################
# PRIVATE METHODS #
###################

my $die_no_trace = sub {
    my ( $full_msg, $summary ) = @_;
    $summary ||= 'FATAL';
    my $carp = $INC{'Carp/Always.pm'} ? '' : ' - Use Carp::Always for full trace.';
    die "[$summary] ${full_msg}${carp}";
};

my $check_local_perms = sub {
    my ( $path, $expected_mode, $is_dir ) = @_;
    $is_dir //= 0;
    my @stat = stat($path);
    $die_no_trace->(qq{"$path" must be a directory that exists}) unless !$is_dir ^ -d _;
    $die_no_trace->(qq{"$path" must be a file that exists})      unless $is_dir ^ -f _;
    $die_no_trace->(qq{"$path" could not be read})               unless -r _;

    my $actual_mode = $stat[2] & 07777;
    $die_no_trace->( sprintf( qq{Permissions on "$path" are not correct: got=0%o, expected=0%o}, $actual_mode, $expected_mode ) ) unless $expected_mode eq $actual_mode;
    return 1;
};

my $resolve_login_method = sub {
    my ($opts) = @_;

    my $chosen = first { $opts->{$_} } qw{key_path password};
    $chosen //= '';
    undef $chosen          if $chosen eq 'key_path' && !$check_local_perms->( $opts->{'key_path'}, 0600 );
    return $chosen         if $chosen;
    return 'SSH_AUTH_SOCK' if $ENV{'SSH_AUTH_SOCK'};
    my $fallback_path = "$opts->{'home'}/.ssh/id";
    my $key_type      = first { -s "${fallback_path}_$_" } qw{ed25519 ecdsa rsa dsa};
    $opts->{'key_path'} = "${fallback_path}_${key_type}" if defined $key_type;

    $die_no_trace->('No key_path or password specified and no active SSH agent; cannot connect') if !$opts->{'key_path'};
    $check_local_perms->( $opts->{'key_path'}, 0600 )                                            if $opts->{'key_path'};

    return $opts->{'key_path'};
};

my $get_dns_record_from_hostname = sub {
    my ( $hostname, $record_type ) = @_;
    $record_type ||= 'A';

    my $reply = Net::DNS::Resolver->new()->search( $hostname, $record_type );
    return unless $reply;
    return { map { $_->type() => $_->address() } grep { $_->type eq $record_type } ( $reply->answer() ) };



( run in 2.653 seconds using v1.01-cache-2.11-cpan-995e09ba956 )