1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package probes::SSH;
=head1 301 Moved Permanently
This is a Smokeping probe module. Please use the command
C<smokeping -man probes::SSH>
to view the documentation or the command
C<smokeping -makepod probes::SSH>
to generate the POD document.
=cut
use strict;
use base qw(probes::basefork);
use IPC::Open3;
use Symbol;
use Carp;
use POSIX;
sub pod_hash {
return {
name => <<DOC,
probes::SSH - Secure Shell Probe for SmokePing
DOC
description => <<DOC,
Integrates ssh-keyscan as a probe into smokeping. The variable B<binary> must
point to your copy of the ssh-keyscan program. If it is not installed on
your system yet, you should install openssh >= 3.8p1
The Probe asks the given host n-times for it's public key. Where n is
the amount specified in the config File.
DOC
authors => <<'DOC',
Christian Recktenwald <smokeping-contact@citecs.de>
DOC
}
}
my $ssh_re=qr/^# \S+ SSH-/i;
sub new($$$)
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new(@_);
# no need for this if we run as a cgi
unless ( $ENV{SERVER_SOFTWARE} ) {
my $call = "$self->{properties}{binary} -t rsa localhost";
my $return = `$call 2>&1`;
if ($return =~ m/$ssh_re/s){
$self->{pingfactor} = 10;
print "### parsing ssh-keyscan output...OK\n";
} else {
croak "ERROR: output of '$call' does not match $ssh_re\n";
}
};
return $self;
}
sub ProbeDesc($){
my $self = shift;
return "SSH requests";
}
sub pingone ($){
my $self = shift;
my $target = shift;
my $inh = gensym;
my $outh = gensym;
my $errh = gensym;
my $host = $target->{addr};
my $query = "$self->{properties}{binary} -t rsa $host";
my @times;
# get the user and system times before and after the test
$self->do_debug("query=$query\n");
for (my $run = 0; $run < $self->pings; $run++) {
my @times1 = POSIX::times;
my $pid = open3($inh,$outh,$errh, $query);
while (<$outh>) {
if (/$ssh_re/i) {
last;
}
}
waitpid $pid,0;
close $errh;
close $inh;
close $outh;
my @times2 = POSIX::times;
push @times, $times2[0]-$times1[0];
}
@times = map {sprintf "%.10e", $_ / $self->{pingfactor}} sort {$a <=> $b} grep {$_ ne "-"} @times;
# $self->do_debug("time=@times\n");
return @times;
}
sub probevars {
my $class = shift;
return $class->_makevars($class->SUPER::probevars, {
_mandatory => [ 'binary' ],
binary => {
_doc => "The location of your ssh-keyscan binary.",
_example => '/usr/bin/ssh-keyscan',
_sub => sub {
my $val = shift;
-x $val or return "ERROR: binary '$val' is not executable";
return undef;
},
},
})
}
1;
|