1 /*****************************************************************************
3 * Monitoring check_ssh plugin
6 * Copyright (c) 2000-2007 Monitoring Plugins Development Team
10 * This file contains the check_ssh plugin
12 * Try to connect to an SSH server at specified server and port
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
17 * the Free Software Foundation, either version 3 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
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/>.
29 *****************************************************************************/
31 const char *progname
= "check_ssh";
32 const char *copyright
= "2000-2007";
33 const char *email
= "devel@monitoring-plugins.org";
40 #define MSG_DONTWAIT 0
43 #define SSH_DFL_PORT 22
47 char *server_name
= NULL
;
48 char *remote_version
= NULL
;
49 char *remote_protocol
= NULL
;
52 int process_arguments (int, char **);
53 int validate_arguments (void);
54 void print_help (void);
55 void print_usage (void);
57 int ssh_connect (char *haddr
, int hport
, char *remote_version
, char *remote_protocol
);
62 main (int argc
, char **argv
)
64 int result
= STATE_UNKNOWN
;
66 setlocale (LC_ALL
, "");
67 bindtextdomain (PACKAGE
, LOCALEDIR
);
70 /* Parse extra opts if any */
71 argv
=np_extra_opts (&argc
, argv
, progname
);
73 if (process_arguments (argc
, argv
) == ERROR
)
74 usage4 (_("Could not parse arguments"));
76 /* initialize alarm signal handling */
77 signal (SIGALRM
, socket_timeout_alarm_handler
);
79 alarm (socket_timeout
);
81 /* ssh_connect exits if error is found */
82 result
= ssh_connect (server_name
, port
, remote_version
, remote_protocol
);
91 /* process command-line arguments */
93 process_arguments (int argc
, char **argv
)
98 static struct option longopts
[] = {
99 {"help", no_argument
, 0, 'h'},
100 {"version", no_argument
, 0, 'V'},
101 {"host", required_argument
, 0, 'H'}, /* backward compatibility */
102 {"hostname", required_argument
, 0, 'H'},
103 {"port", required_argument
, 0, 'p'},
104 {"use-ipv4", no_argument
, 0, '4'},
105 {"use-ipv6", no_argument
, 0, '6'},
106 {"timeout", required_argument
, 0, 't'},
107 {"verbose", no_argument
, 0, 'v'},
108 {"remote-version", required_argument
, 0, 'r'},
109 {"remote-protcol", required_argument
, 0, 'P'},
116 for (c
= 1; c
< argc
; c
++)
117 if (strcmp ("-to", argv
[c
]) == 0)
118 strcpy (argv
[c
], "-t");
121 c
= getopt_long (argc
, argv
, "+Vhv46t:r:H:p:P:", longopts
, &option
);
123 if (c
== -1 || c
== EOF
)
129 case 'V': /* version */
130 print_revision (progname
, NP_VERSION
);
131 exit (STATE_UNKNOWN
);
134 exit (STATE_UNKNOWN
);
135 case 'v': /* verbose */
138 case 't': /* timeout period */
139 if (!is_integer (optarg
))
140 usage2 (_("Timeout interval must be a positive integer"), optarg
);
142 socket_timeout
= atoi (optarg
);
145 address_family
= AF_INET
;
149 address_family
= AF_INET6
;
151 usage4 (_("IPv6 support not available"));
154 case 'r': /* remote version */
155 remote_version
= optarg
;
157 case 'P': /* remote version */
158 remote_protocol
= optarg
;
161 if (is_host (optarg
) == FALSE
)
162 usage2 (_("Invalid hostname/address"), optarg
);
163 server_name
= optarg
;
166 if (is_intpos (optarg
)) {
167 port
= atoi (optarg
);
170 usage2 (_("Port number must be a positive integer"), optarg
);
176 if (server_name
== NULL
&& c
< argc
) {
177 if (is_host (argv
[c
])) {
178 server_name
= argv
[c
++];
182 if (port
== -1 && c
< argc
) {
183 if (is_intpos (argv
[c
])) {
184 port
= atoi (argv
[c
++]);
188 exit (STATE_UNKNOWN
);
192 return validate_arguments ();
196 validate_arguments (void)
198 if (server_name
== NULL
)
200 if (port
== -1) /* funky, but allows -p to override stray integer in args */
206 /************************************************************************
208 * Try to connect to SSH server at specified server and port
210 *-----------------------------------------------------------------------*/
214 ssh_connect (char *haddr
, int hport
, char *remote_version
, char *remote_protocol
)
220 char *ssh_proto
= NULL
;
221 char *ssh_server
= NULL
;
222 static char *rev_no
= VERSION
;
226 gettimeofday(&tv
, NULL
);
228 result
= my_tcp_connect (haddr
, hport
, &sd
);
230 if (result
!= STATE_OK
)
233 output
= (char *) malloc (BUFF_SZ
+ 1);
234 memset (output
, 0, BUFF_SZ
+ 1);
235 recv (sd
, output
, BUFF_SZ
, 0);
236 if (strncmp (output
, "SSH", 3)) {
237 printf (_("Server answer: %s"), output
);
239 exit (STATE_CRITICAL
);
244 printf ("%s\n", output
);
245 ssh_proto
= output
+ 4;
246 ssh_server
= ssh_proto
+ strspn (ssh_proto
, "-0123456789. ");
247 ssh_proto
[strspn (ssh_proto
, "0123456789. ")] = 0;
249 xasprintf (&buffer
, "SSH-%s-check_ssh_%s\r\n", ssh_proto
, rev_no
);
250 send (sd
, buffer
, strlen (buffer
), MSG_DONTWAIT
);
252 printf ("%s\n", buffer
);
254 if (remote_version
&& strcmp(remote_version
, ssh_server
)) {
256 (_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"),
257 ssh_server
, ssh_proto
, remote_version
);
259 exit (STATE_CRITICAL
);
262 if (remote_protocol
&& strcmp(remote_protocol
, ssh_proto
)) {
264 (_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s'\n"),
265 ssh_server
, ssh_proto
, remote_protocol
);
267 exit (STATE_CRITICAL
);
270 elapsed_time
= (double)deltime(tv
) / 1.0e6
;
273 (_("SSH OK - %s (protocol %s) | %s\n"),
274 ssh_server
, ssh_proto
, fperfdata("time", elapsed_time
, "s",
275 FALSE
, 0, FALSE
, 0, TRUE
, 0, TRUE
, (int)socket_timeout
));
287 xasprintf (&myport
, "%d", SSH_DFL_PORT
);
289 print_revision (progname
, NP_VERSION
);
291 printf ("Copyright (c) 1999 Remi Paulmier <remi@sinfomic.fr>\n");
292 printf (COPYRIGHT
, copyright
, email
);
294 printf ("%s\n", _("Try to connect to an SSH server at specified server and port"));
300 printf (UT_HELP_VRSN
);
301 printf (UT_EXTRA_OPTS
);
303 printf (UT_HOST_PORT
, 'p', myport
);
307 printf (UT_CONN_TIMEOUT
, DEFAULT_SOCKET_TIMEOUT
);
309 printf (" %s\n", "-r, --remote-version=STRING");
310 printf (" %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
312 printf (" %s\n", "-P, --remote-protocol=STRING");
313 printf (" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)"));
325 printf ("%s\n", _("Usage:"));
326 printf ("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname
);