File Coverage

blib/lib/Net/Prober/ssh.pm
Criterion Covered Total %
statement 34 40 85.0
branch 4 10 40.0
condition 1 3 33.3
subroutine 8 8 100.0
pod 0 2 0.0
total 47 63 74.6


line stmt bran cond sub pod time code
1             package Net::Prober::ssh;
2             $Net::Prober::ssh::VERSION = '0.17';
3 1     1   6 use strict;
  1         1  
  1         22  
4 1     1   4 use warnings;
  1         2  
  1         21  
5 1     1   4 use base 'Net::Prober::Probe::TCP';
  1         2  
  1         330  
6              
7 1     1   6 use Carp ();
  1         2  
  1         344  
8              
9             sub defaults {
10 2     2 0 3 my ($self) = @_;
11              
12 2         8 my $defaults = $self->SUPER::defaults();
13 2         3 $defaults->{port} = 22;
14              
15 2         5 return $defaults;
16             }
17              
18             sub probe {
19 1     1 0 2 my ($self, $args) = @_;
20              
21 1         6 my ($host, $port, $timeout, $username, $password) =
22             $self->parse_args($args, qw(host port timeout username password));
23              
24 1         6 my $t0 = $self->time_now();
25              
26 1         6 my $sock = $self->open_socket($args);
27 1 50       1373264 if (! $sock) {
28 0         0 return $self->probe_failed(
29             reason => qq{Couldn't connect to SSH server $host:$port},
30             );
31             }
32              
33 1         8 chomp (my $ssh_banner = $self->_get_reply($sock));
34              
35 1 50       9 if (! $ssh_banner) {
36 0         0 return $self->probe_failed(
37             reason => qq{Couldn't get SSH banner from $host:$port}
38             );
39             }
40              
41             # SSH-protoversion-softwareversion SP comments CR LF
42 1 50       33 if ($ssh_banner !~ qr{^SSH-
43             (? [^\-]+) -
44             (? [^\s]+) \s?
45             (? .*)? $}x) {
46 0         0 return $self->probe_failed(
47             reason => qq{Non-RFC compliant SSH banner from $host:$port? ($ssh_banner)},
48             );
49             }
50              
51             my %ssh_info = (
52             protoversion => $+{protoversion},
53             softwareversion => $+{softwareversion},
54             comments => $+{comments},
55 1         36 banner => $ssh_banner,
56             );
57              
58             # We can't try to login if we haven't got credentials
59 1 50 33     17 if ($username && $password) {
60 0         0 $self->_send_command($sock, $username . "\n" . $password . "\n");
61 0 0       0 if (! $self->_get_reply($sock)) {
62 0         0 return $self->probe_failed(
63             reason => qq{Couldn't login to ssh $host:$port with user $username},
64             );
65             }
66             }
67              
68             # Say goodbye
69 1         9 $self->_send_command($sock, 'exit');
70              
71 1         159 return $self->probe_ok(%ssh_info);
72             }
73              
74             sub _send_command {
75 1     1   5 my ($self, $sock, $text_input) = @_;
76 1         18 return $sock->send($text_input);
77             }
78              
79             sub _get_reply {
80 1     1   5 my ($self, $sock) = @_;
81 1         18 $sock->recv(my $reply, 1024);
82 1         231853 $reply =~ s{\s+$}{};
83 1         11 return $reply;
84             }
85              
86             1;
87              
88             __END__