[nagios-plugins] check_ssh using libssh to verify host ...
Git Repository
git at nagios-plugins.org
Fri Oct 4 00:10:06 CEST 2013
Module: nagios-plugins
Branch: pu
Commit: 776f03beaad1595502c3ccbf5532568e64c90c9d
Author: hjanuschka <helmut at januschka.com>
Committer: Thomas Guyot-Sionnest <dermoth at aei.ca>
Date: Tue Dec 4 13:29:40 2012 +0100
URL: https://www.nagios-plugins.org/repositories/nagios-plugins.git/?/commit/?id=776f03b
check_ssh using libssh to verify host fingerprint and openssh version
if libssh is not found, the fingerprint / openssh-version-detection functions are not compiled in.
for backward compatibility the parameters of original check_ssh stay untouched
for checking the fingerprint && || the openssh version use -f and or -o
to check against known_hosts file use -f known_host
sample calls:
#checks if SSH fingerprint is stored in local known hosts
./check_ssh -f known_hosts localhost
#checks if SSH fingerprint is stored in local known hosts, and version is >= 5.5
./check_ssh -f known_hosts -o 5.5 localhost
#checks if SSH fingerprint is equal the print supplied with -f
./check_ssh -f a2:47:e8:83:d9:8b:f5:c4:19:23:47:0d:e0:bf:a8:26 localhost
#checks if SSH fingerprint is equal the print supplied with -f and version is >= 5.5
./check_ssh -f a2:47:e8:83:d9:8b:f5:c4:19:23:47:0d:e0:bf:a8:26 -o 5.5 localhost
#check for SSH version
./check_ssh -o 5.5 localhost
---
configure.in | 14 ++++
plugins/Makefile.am | 2 +-
plugins/check_ssh.c | 206 ++++++++++++++++++++++++++++++++++++++-------------
3 files changed, 170 insertions(+), 52 deletions(-)
diff --git a/configure.in b/configure.in
index 1d4ed00..a951d39 100644
--- a/configure.in
+++ b/configure.in
@@ -204,6 +204,20 @@ if test "$enable_extra_opts" = "yes" ; then
fi
fi
+
+dnl Check for ssh libraries
+
+AC_CHECK_LIB(ssh,ssh_connect)
+if test "$ac_cv_lib_ssh_ssh_connect" = "yes"; then
+ SSHLIB="-lssh"
+ AC_SUBST(SSHLIB)
+ AC_DEFINE(HAVE_SSH,1,[Define if SSL libraries are found])
+else
+ AC_MSG_WARN([Skipping check_ssh plugin])
+ AC_MSG_WARN([install ssh libs to compile this plugin (see REQUIREMENTS).])
+fi
+
+
dnl Check for PostgreSQL libraries
_SAVEDLIBS="$LIBS"
_SAVEDCPPFLAGS="$CPPFLAGS"
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 0eb0255..7cea40c 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -96,7 +96,7 @@ check_radius_LDADD = $(NETLIBS) $(RADIUSLIBS)
check_real_LDADD = $(NETLIBS)
check_snmp_LDADD = $(BASEOBJS)
check_smtp_LDADD = $(SSLOBJS) $(NETLIBS) $(SSLLIBS)
-check_ssh_LDADD = $(NETLIBS)
+check_ssh_LDADD = $(NETLIBS) $(SSHLIB)
check_swap_LDADD = $(MATHLIBS) $(BASEOBJS) popen.o
check_tcp_LDADD = $(SSLOBJS) $(NETLIBS) $(SSLLIBS)
check_time_LDADD = $(NETLIBS)
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
index 6e8a5fc..c3526c9 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -36,6 +36,10 @@ const char *email = "nagiosplug-devel at lists.sourceforge.net";
#include "netutils.h"
#include "utils.h"
+#ifdef HAVE_SSH
+#include <libssh/libssh.h>
+#endif
+
#ifndef MSG_DONTWAIT
#define MSG_DONTWAIT 0
#endif
@@ -46,15 +50,17 @@ const char *email = "nagiosplug-devel at lists.sourceforge.net";
int port = -1;
char *server_name = NULL;
char *remote_version = NULL;
+char *remote_fingerprint = NULL;
int verbose = FALSE;
+char * remote_openssh_version = NULL;
int process_arguments (int, char **);
int validate_arguments (void);
void print_help (void);
void print_usage (void);
-int ssh_connect (char *haddr, int hport, char *remote_version);
-
+int ssh_connect_p (char *haddr, int hport, char *remote_version, char *remote_fingerprint);
+int ssh_connect_wo_lib (char *haddr, int hport, char *remote_version);
int
@@ -78,14 +84,80 @@ main (int argc, char **argv)
alarm (socket_timeout);
/* ssh_connect exits if error is found */
- result = ssh_connect (server_name, port, remote_version);
+ #ifdef HAVE_SSH
+ if(remote_openssh_version != NULL || remote_fingerprint != NULL) {
+ result = ssh_connect_p (server_name, port, remote_openssh_version, remote_fingerprint);
+ } else {
+ result = ssh_connect_wo_lib(server_name, port, remote_version);
+ }
+ #else
+ result = ssh_connect_wo_lib(server_name, port, remote_version);
+ #endif
alarm (0);
return (result);
}
+int
+ssh_connect_wo_lib (char *haddr, int hport, char *remote_version)
+{
+ int sd;
+ int result;
+ char *output = NULL;
+ char *buffer = NULL;
+ char *ssh_proto = NULL;
+ char *ssh_server = NULL;
+ static char *rev_no = VERSION;
+ struct timeval tv;
+ double elapsed_time;
+ gettimeofday(&tv, NULL);
+
+ result = my_tcp_connect (haddr, hport, &sd);
+
+ if (result != STATE_OK)
+ return result;
+
+ output = (char *) malloc (BUFF_SZ + 1);
+ memset (output, 0, BUFF_SZ + 1);
+ recv (sd, output, BUFF_SZ, 0);
+ if (strncmp (output, "SSH", 3)) {
+ printf (_("Server answer: %s"), output);
+ close(sd);
+ exit (STATE_CRITICAL);
+ }
+ else {
+ strip (output);
+ if (verbose)
+ printf ("%s\n", output);
+ ssh_proto = output + 4;
+ ssh_server = ssh_proto + strspn (ssh_proto, "-0123456789. ");
+ ssh_proto[strspn (ssh_proto, "0123456789. ")] = 0;
+
+ xasprintf (&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no);
+ send (sd, buffer, strlen (buffer), MSG_DONTWAIT);
+ if (verbose)
+ printf ("%s\n", buffer);
+
+ if (remote_version && strcmp(remote_version, ssh_server)) {
+ printf
+ (_("SSH WARNING - %s (protocol %s) version mismatch, expected '%s'\n"),
+ ssh_server, ssh_proto, remote_version);
+ close(sd);
+ exit (STATE_WARNING);
+ }
+
+ elapsed_time = (double)deltime(tv) / 1.0e6;
+
+ printf
+ (_("SSH OK - %s (protocol %s) | %s\n"),
+ ssh_server, ssh_proto, fperfdata("time", elapsed_time, "s",
+ FALSE, 0, FALSE, 0, TRUE, 0, TRUE, (int)socket_timeout));
+ close(sd);
+ exit (STATE_OK);
+ }
+}
/* process command-line arguments */
int
@@ -105,6 +177,8 @@ process_arguments (int argc, char **argv)
{"timeout", required_argument, 0, 't'},
{"verbose", no_argument, 0, 'v'},
{"remote-version", required_argument, 0, 'r'},
+ {"fingerprint", required_argument, 0, 'f'},
+ {"remote-openssh-version", required_argument, 0, 'o'},
{0, 0, 0, 0}
};
@@ -116,7 +190,7 @@ process_arguments (int argc, char **argv)
strcpy (argv[c], "-t");
while (1) {
- c = getopt_long (argc, argv, "+Vhv46t:r:H:p:", longopts, &option);
+ c = getopt_long (argc, argv, "+Vhv46t:r:f:H:o:p:", longopts, &option);
if (c == -1 || c == EOF)
break;
@@ -152,6 +226,12 @@ process_arguments (int argc, char **argv)
case 'r': /* remote version */
remote_version = optarg;
break;
+ case 'o':
+ remote_openssh_version = optarg;
+ break;
+ case 'f': /* remote version */
+ remote_fingerprint = optarg;
+ break;
case 'H': /* host */
if (is_host (optarg) == FALSE)
usage2 (_("Invalid hostname/address"), optarg);
@@ -204,66 +284,82 @@ validate_arguments (void)
*
*-----------------------------------------------------------------------*/
-
+#ifdef HAVE_SSH
int
-ssh_connect (char *haddr, int hport, char *remote_version)
+ssh_connect_p (char *haddr, int hport, char *remote_version, char * remote_fingerprint)
{
- int sd;
- int result;
- char *output = NULL;
- char *buffer = NULL;
- char *ssh_proto = NULL;
- char *ssh_server = NULL;
- static char *rev_no = VERSION;
struct timeval tv;
double elapsed_time;
+ ssh_session my_ssh_session;
+ int version;
+ int myversion;
+ int hlen;
+ int rc;
+ int state;
+ int i;
+ unsigned char *hash = NULL;
+ char * fingerprint;
+ int in_known_host;
+
+ int sshv1,sshv2,sshv3;
+
gettimeofday(&tv, NULL);
- result = my_tcp_connect (haddr, hport, &sd);
+ my_ssh_session = ssh_new();
- if (result != STATE_OK)
- return result;
+ if (my_ssh_session == NULL)
+ return STATE_CRITICAL;
- output = (char *) malloc (BUFF_SZ + 1);
- memset (output, 0, BUFF_SZ + 1);
- recv (sd, output, BUFF_SZ, 0);
- if (strncmp (output, "SSH", 3)) {
- printf (_("Server answer: %s"), output);
- close(sd);
+ ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, haddr);
+ ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &hport);
+ rc = ssh_connect(my_ssh_session);
+ if (rc != SSH_OK) {
+ printf ("Connect to Server failed\n");
exit (STATE_CRITICAL);
}
- else {
- strip (output);
- if (verbose)
- printf ("%s\n", output);
- ssh_proto = output + 4;
- ssh_server = ssh_proto + strspn (ssh_proto, "-0123456789. ");
- ssh_proto[strspn (ssh_proto, "0123456789. ")] = 0;
+ in_known_host=-1;
+ state = ssh_is_server_known(my_ssh_session);
+ hlen = ssh_get_pubkey_hash(my_ssh_session, &hash);
+
+ /* Get the finger print as a string */
+ fingerprint = ssh_get_hexa(hash, hlen);
+ if(remote_fingerprint && strcmp(remote_fingerprint, "known_host") == NULL) {
+ if(state != SSH_SERVER_KNOWN_OK) {
+ printf ("SSH CRITICAL - Fingerprint (%s) checked in known_hosts failed\n", remote_fingerprint,fingerprint);
+ exit(STATE_CRITICAL);
+ } else {
+ in_known_host=1;
+ }
+ }
- xasprintf (&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no);
- send (sd, buffer, strlen (buffer), MSG_DONTWAIT);
- if (verbose)
- printf ("%s\n", buffer);
+ /* FIXME: This alwats eval to false... */
+ if(remote_fingerprint && strcmp(remote_fingerprint, "known_host") && strcmp(remote_fingerprint, fingerprint)) {
+ printf ("SSH CRITICAL - Fingerprint (%s) mismatched %s\n", remote_fingerprint,fingerprint);
+ free(fingerprint);
+ exit(STATE_CRITICAL);
+ }
- if (remote_version && strcmp(remote_version, ssh_server)) {
- printf
- (_("SSH WARNING - %s (protocol %s) version mismatch, expected '%s'\n"),
- ssh_server, ssh_proto, remote_version);
- close(sd);
- exit (STATE_WARNING);
+ version = ssh_get_openssh_version(my_ssh_session);
+ if(remote_version && sscanf(remote_version, "%d.%d.%d", &sshv1, &sshv2, &sshv3)) {
+ myversion = SSH_VERSION_INT(sshv1, sshv2, sshv3);
+ if(version < myversion) {
+ printf ("SSH WARNING version on server is below %s\n", remote_version);
+ exit(STATE_CRITICAL);
}
+ }
- elapsed_time = (double)deltime(tv) / 1.0e6;
+ elapsed_time = (double)deltime(tv) / 1.0e6;
- printf
- (_("SSH OK - %s (protocol %s) | %s\n"),
- ssh_server, ssh_proto, fperfdata("time", elapsed_time, "s",
- FALSE, 0, FALSE, 0, TRUE, 0, TRUE, (int)socket_timeout));
- close(sd);
- exit (STATE_OK);
- }
+ printf (_("SSH OK - fingerprint: %s (Version %d) known_host_check:%d | %s\n"),
+ fingerprint, version,in_known_host, fperfdata("time", elapsed_time, "s",
+ FALSE, 0, FALSE, 0, TRUE, 0, TRUE, (int)socket_timeout));
+ free(fingerprint);
+ ssh_disconnect(my_ssh_session);
+ ssh_free(my_ssh_session);
+ exit(STATE_OK);
}
+#endif
@@ -280,7 +376,7 @@ print_help (void)
printf ("%s\n", _("Try to connect to an SSH server at specified server and port"));
- printf ("\n\n");
+ printf ("\n\n");
print_usage ();
@@ -294,7 +390,15 @@ print_help (void)
printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
printf (" %s\n", "-r, --remote-version=STRING");
- printf (" %s\n", _("Warn if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
+ printf (" %s\n", _("Warn if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
+
+#ifdef HAVE_SSH
+ printf (" %s\n", "-o, --remote-openssh-version=STRING");
+ printf (" %s\n", _("Warn if Remote Openssh version is lower than STRING"));
+#endif
+
+ printf (" %s\n", "-f, --fingerprint=STRING (e.g.: a247e883d98bf5c41923470de0bfa826)");
+ printf (" %s\n", _("Critical if remote fingerprint is not equal to supplied"));
printf (UT_VERBOSE);
@@ -306,7 +410,7 @@ print_help (void)
void
print_usage (void)
{
- printf ("%s\n", _("Usage:"));
- printf ("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname);
+ printf ("%s\n", _("Usage:"));
+ printf ("%s [-4|-6] [-t <timeout>] [-f <fingerprint>] [-r <remote version>] [-o <remote openssh version>] [-p <port>] <host>\n", progname);
}
More information about the Commits
mailing list