summaryrefslogtreecommitdiffstats
path: root/plugins/check_ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_ssh.c')
-rw-r--r--plugins/check_ssh.c188
1 files changed, 132 insertions, 56 deletions
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
index 4eb746c..34ef37b 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -1,39 +1,39 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2*
3* Monitoring check_ssh plugin 3* Monitoring check_ssh plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6* Copyright (c) 2000-2007 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
10* This file contains the check_ssh plugin 10* This file contains the check_ssh plugin
11* 11*
12* Try to connect to an SSH server at specified server and port 12* Try to connect to an SSH server at specified server and port
13* 13*
14* 14*
15* This program is free software: you can redistribute it and/or modify 15* This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16* it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17* the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18* (at your option) any later version.
19* 19*
20* This program is distributed in the hope that it will be useful, 20* This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21* but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23* GNU General Public License for more details.
24* 24*
25* You should have received a copy of the GNU General Public License 25* You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26* along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27*
28* 28*
29*****************************************************************************/ 29*****************************************************************************/
30 30
31const char *progname = "check_ssh"; 31const char *progname = "check_ssh";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2007";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "./common.h"
36#include "netutils.h" 36#include "./netutils.h"
37#include "utils.h" 37#include "utils.h"
38 38
39#ifndef MSG_DONTWAIT 39#ifndef MSG_DONTWAIT
@@ -105,7 +105,7 @@ process_arguments (int argc, char **argv)
105 {"timeout", required_argument, 0, 't'}, 105 {"timeout", required_argument, 0, 't'},
106 {"verbose", no_argument, 0, 'v'}, 106 {"verbose", no_argument, 0, 'v'},
107 {"remote-version", required_argument, 0, 'r'}, 107 {"remote-version", required_argument, 0, 'r'},
108 {"remote-protcol", required_argument, 0, 'P'}, 108 {"remote-protocol", required_argument, 0, 'P'},
109 {0, 0, 0, 0} 109 {0, 0, 0, 0}
110 }; 110 };
111 111
@@ -214,7 +214,9 @@ ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol
214{ 214{
215 int sd; 215 int sd;
216 int result; 216 int result;
217 char *output = NULL; 217 int len = 0;
218 ssize_t recv_ret = 0;
219 char *version_control_string = NULL;
218 char *buffer = NULL; 220 char *buffer = NULL;
219 char *ssh_proto = NULL; 221 char *ssh_proto = NULL;
220 char *ssh_server = NULL; 222 char *ssh_server = NULL;
@@ -229,52 +231,126 @@ ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol
229 if (result != STATE_OK) 231 if (result != STATE_OK)
230 return result; 232 return result;
231 233
232 output = (char *) malloc (BUFF_SZ + 1); 234 char *output = (char *) calloc (BUFF_SZ + 1, sizeof(char));
233 memset (output, 0, BUFF_SZ + 1); 235
234 recv (sd, output, BUFF_SZ, 0); 236 unsigned int iteration = 0;
235 if (strncmp (output, "SSH", 3)) { 237 ssize_t byte_offset = 0;
236 printf (_("Server answer: %s"), output); 238
237 close(sd); 239 while ((version_control_string == NULL) && (recv_ret = recv(sd, output+byte_offset, BUFF_SZ - byte_offset, 0) > 0)) {
240
241 if (strchr(output, '\n')) { /* we've got at least one full line, start parsing*/
242 byte_offset = 0;
243
244 char *index = NULL;
245 while ((index = strchr(output+byte_offset, '\n')) != NULL) {
246 /*Partition the buffer so that this line is a separate string,
247 * by replacing the newline with NUL*/
248 output[(index - output)] = '\0';
249 len = strlen(output + byte_offset);
250
251 if ((len >= 4) && (strncmp (output+byte_offset, "SSH-", 4) == 0)) {
252 /*if the string starts with SSH-, this _should_ be a valid version control string*/
253 version_control_string = output+byte_offset;
254 break;
255 }
256
257 /*the start of the next line (if one exists) will be after the current one (+ NUL)*/
258 byte_offset += (len + 1);
259 }
260
261 if(version_control_string == NULL) {
262 /* move unconsumed data to beginning of buffer, null rest */
263 memmove((void *)output, (void *)output+byte_offset+1, BUFF_SZ - len+1);
264 memset(output+byte_offset+1, 0, BUFF_SZ-byte_offset+1);
265
266 /*start reading from end of current line chunk on next recv*/
267 byte_offset = strlen(output);
268 }
269 } else {
270 byte_offset += recv_ret;
271 }
272 }
273
274 if (recv_ret < 0) {
275 printf("SSH CRITICAL - %s", strerror(errno));
276 exit(STATE_CRITICAL);
277 }
278
279 if (version_control_string == NULL) {
280 printf("SSH CRITICAL - No version control string received");
281 exit(STATE_CRITICAL);
282 }
283 /*
284 * "When the connection has been established, both sides MUST send an
285 * identification string. This identification string MUST be
286 *
287 * SSH-protoversion-softwareversion SP comments CR LF"
288 * - RFC 4253:4.2
289 */
290 strip (version_control_string);
291 if (verbose)
292 printf ("%s\n", version_control_string);
293 ssh_proto = version_control_string + 4;
294
295 /*
296 * We assume the protoversion is of the form Major.Minor, although
297 * this is not _strictly_ required. See
298 *
299 * "Both the 'protoversion' and 'softwareversion' strings MUST consist of
300 * printable US-ASCII characters, with the exception of whitespace
301 * characters and the minus sign (-)"
302 * - RFC 4253:4.2
303 * and,
304 *
305 * "As stated earlier, the 'protoversion' specified for this protocol is
306 * "2.0". Earlier versions of this protocol have not been formally
307 * documented, but it is widely known that they use 'protoversion' of
308 * "1.x" (e.g., "1.5" or "1.3")."
309 * - RFC 4253:5
310 */
311 ssh_server = ssh_proto + strspn (ssh_proto, "0123456789.") + 1; /* (+1 for the '-' separating protoversion from softwareversion) */
312
313 /* If there's a space in the version string, whatever's after the space is a comment
314 * (which is NOT part of the server name/version)*/
315 char *tmp = strchr(ssh_server, ' ');
316 if (tmp) {
317 ssh_server[tmp - ssh_server] = '\0';
318 }
319 if (strlen(ssh_proto) == 0 || strlen(ssh_server) == 0) {
320 printf(_("SSH CRITICAL - Invalid protocol version control string %s\n"), version_control_string);
238 exit (STATE_CRITICAL); 321 exit (STATE_CRITICAL);
239 } 322 }
240 else { 323 ssh_proto[strspn (ssh_proto, "0123456789. ")] = 0;
241 strip (output);
242 if (verbose)
243 printf ("%s\n", output);
244 ssh_proto = output + 4;
245 ssh_server = ssh_proto + strspn (ssh_proto, "-0123456789. ");
246 ssh_proto[strspn (ssh_proto, "0123456789. ")] = 0;
247
248 xasprintf (&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no);
249 send (sd, buffer, strlen (buffer), MSG_DONTWAIT);
250 if (verbose)
251 printf ("%s\n", buffer);
252
253 if (remote_version && strcmp(remote_version, ssh_server)) {
254 printf
255 (_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"),
256 ssh_server, ssh_proto, remote_version);
257 close(sd);
258 exit (STATE_CRITICAL);
259 }
260 324
261 if (remote_protocol && strcmp(remote_protocol, ssh_proto)) { 325 xasprintf (&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no);
262 printf 326 send (sd, buffer, strlen (buffer), MSG_DONTWAIT);
263 (_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s'\n"), 327 if (verbose)
264 ssh_server, ssh_proto, remote_protocol); 328 printf ("%s\n", buffer);
265 close(sd);
266 exit (STATE_CRITICAL);
267 }
268 329
269 elapsed_time = (double)deltime(tv) / 1.0e6; 330 if (remote_version && strcmp(remote_version, ssh_server)) {
331 printf
332 (_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"),
333 ssh_server, ssh_proto, remote_version);
334 close(sd);
335 exit (STATE_CRITICAL);
336 }
270 337
338 if (remote_protocol && strcmp(remote_protocol, ssh_proto)) {
271 printf 339 printf
272 (_("SSH OK - %s (protocol %s) | %s\n"), 340 (_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s' | %s\n"),
273 ssh_server, ssh_proto, fperfdata("time", elapsed_time, "s", 341 ssh_server, ssh_proto, remote_protocol, fperfdata("time", elapsed_time, "s",
274 false, 0, false, 0, true, 0, true, (int)socket_timeout)); 342 false, 0, false, 0, true, 0, true, (int)socket_timeout));
275 close(sd); 343 close(sd);
276 exit (STATE_OK); 344 exit (STATE_CRITICAL);
277 } 345 }
346 elapsed_time = (double)deltime(tv) / 1.0e6;
347
348 printf
349 (_("SSH OK - %s (protocol %s) | %s\n"),
350 ssh_server, ssh_proto, fperfdata("time", elapsed_time, "s",
351 false, 0, false, 0, true, 0, true, (int)socket_timeout));
352 close(sd);
353 exit (STATE_OK);
278} 354}
279 355
280 356
@@ -292,7 +368,7 @@ print_help (void)
292 368
293 printf ("%s\n", _("Try to connect to an SSH server at specified server and port")); 369 printf ("%s\n", _("Try to connect to an SSH server at specified server and port"));
294 370
295 printf ("\n\n"); 371 printf ("\n\n");
296 372
297 print_usage (); 373 print_usage ();
298 374
@@ -306,10 +382,10 @@ print_help (void)
306 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 382 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
307 383
308 printf (" %s\n", "-r, --remote-version=STRING"); 384 printf (" %s\n", "-r, --remote-version=STRING");
309 printf (" %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)")); 385 printf (" %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
310 386
311 printf (" %s\n", "-P, --remote-protocol=STRING"); 387 printf (" %s\n", "-P, --remote-protocol=STRING");
312 printf (" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)")); 388 printf (" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)"));
313 389
314 printf (UT_VERBOSE); 390 printf (UT_VERBOSE);
315 391
@@ -321,7 +397,7 @@ print_help (void)
321void 397void
322print_usage (void) 398print_usage (void)
323{ 399{
324 printf ("%s\n", _("Usage:")); 400 printf ("%s\n", _("Usage:"));
325 printf ("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname); 401 printf ("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname);
326} 402}
327 403