1 /*****************************************************************************
3 * Nagios check_ssh plugin
6 * Copyright (c) 2000-2007 Nagios 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
= "nagiosplug-devel@lists.sourceforge.net";
40 #define MSG_DONTWAIT 0
43 #define SSH_DFL_PORT 22
47 char *server_name
= NULL
;
48 char *remote_version
= NULL
;
51 int process_arguments (int, char **);
52 int validate_arguments (void);
53 void print_help (void);
54 void print_usage (void);
56 int ssh_connect (char *haddr
, int hport
, char *remote_version
);
61 main (int argc
, char **argv
)
63 int result
= STATE_UNKNOWN
;
65 setlocale (LC_ALL
, "");
66 bindtextdomain (PACKAGE
, LOCALEDIR
);
69 /* Parse extra opts if any */
70 argv
=np_extra_opts (&argc
, argv
, progname
);
72 if (process_arguments (argc
, argv
) == ERROR
)
73 usage4 (_("Could not parse arguments"));
75 /* initialize alarm signal handling */
76 signal (SIGALRM
, socket_timeout_alarm_handler
);
78 alarm (socket_timeout
);
80 /* ssh_connect exits if error is found */
81 result
= ssh_connect (server_name
, port
, remote_version
);
90 /* process command-line arguments */
92 process_arguments (int argc
, char **argv
)
97 static struct option longopts
[] = {
98 {"help", no_argument
, 0, 'h'},
99 {"version", no_argument
, 0, 'V'},
100 {"host", required_argument
, 0, 'H'}, /* backward compatibility */
101 {"hostname", required_argument
, 0, 'H'},
102 {"port", required_argument
, 0, 'p'},
103 {"use-ipv4", no_argument
, 0, '4'},
104 {"use-ipv6", no_argument
, 0, '6'},
105 {"timeout", required_argument
, 0, 't'},
106 {"verbose", no_argument
, 0, 'v'},
107 {"remote-version", required_argument
, 0, 'r'},
114 for (c
= 1; c
< argc
; c
++)
115 if (strcmp ("-to", argv
[c
]) == 0)
116 strcpy (argv
[c
], "-t");
119 c
= getopt_long (argc
, argv
, "+Vhv46t:r:H:p:", longopts
, &option
);
121 if (c
== -1 || c
== EOF
)
127 case 'V': /* version */
128 print_revision (progname
, NP_VERSION
);
133 case 'v': /* verbose */
136 case 't': /* timeout period */
137 if (!is_integer (optarg
))
138 usage2 (_("Timeout interval must be a positive integer"), optarg
);
140 socket_timeout
= atoi (optarg
);
143 address_family
= AF_INET
;
147 address_family
= AF_INET6
;
149 usage4 (_("IPv6 support not available"));
152 case 'r': /* remote version */
153 remote_version
= optarg
;
156 if (is_host (optarg
) == FALSE
)
157 usage2 (_("Invalid hostname/address"), optarg
);
158 server_name
= optarg
;
161 if (is_intpos (optarg
)) {
162 port
= atoi (optarg
);
165 usage2 (_("Port number must be a positive integer"), optarg
);
171 if (server_name
== NULL
&& c
< argc
) {
172 if (is_host (argv
[c
])) {
173 server_name
= argv
[c
++];
177 if (port
== -1 && c
< argc
) {
178 if (is_intpos (argv
[c
])) {
179 port
= atoi (argv
[c
++]);
183 exit (STATE_UNKNOWN
);
187 return validate_arguments ();
191 validate_arguments (void)
193 if (server_name
== NULL
)
195 if (port
== -1) /* funky, but allows -p to override stray integer in args */
201 /************************************************************************
203 * Try to connect to SSH server at specified server and port
205 *-----------------------------------------------------------------------*/
209 ssh_connect (char *haddr
, int hport
, char *remote_version
)
215 char *ssh_proto
= NULL
;
216 char *ssh_server
= NULL
;
217 static char *rev_no
= VERSION
;
219 result
= my_tcp_connect (haddr
, hport
, &sd
);
221 if (result
!= STATE_OK
)
224 output
= (char *) malloc (BUFF_SZ
+ 1);
225 memset (output
, 0, BUFF_SZ
+ 1);
226 recv (sd
, output
, BUFF_SZ
, 0);
227 if (strncmp (output
, "SSH", 3)) {
228 printf (_("Server answer: %s"), output
);
230 exit (STATE_CRITICAL
);
235 printf ("%s\n", output
);
236 ssh_proto
= output
+ 4;
237 ssh_server
= ssh_proto
+ strspn (ssh_proto
, "-0123456789. ");
238 ssh_proto
[strspn (ssh_proto
, "0123456789. ")] = 0;
240 asprintf (&buffer
, "SSH-%s-check_ssh_%s\r\n", ssh_proto
, rev_no
);
241 send (sd
, buffer
, strlen (buffer
), MSG_DONTWAIT
);
243 printf ("%s\n", buffer
);
245 if (remote_version
&& strcmp(remote_version
, ssh_server
)) {
247 (_("SSH WARNING - %s (protocol %s) version mismatch, expected '%s'\n"),
248 ssh_server
, ssh_proto
, remote_version
);
250 exit (STATE_WARNING
);
254 (_("SSH OK - %s (protocol %s)\n"),
255 ssh_server
, ssh_proto
);
267 asprintf (&myport
, "%d", SSH_DFL_PORT
);
269 print_revision (progname
, NP_VERSION
);
271 printf ("Copyright (c) 1999 Remi Paulmier <remi@sinfomic.fr>\n");
272 printf (COPYRIGHT
, copyright
, email
);
274 printf ("%s\n", _("Try to connect to an SSH server at specified server and port"));
280 printf (UT_HELP_VRSN
);
281 printf (UT_EXTRA_OPTS
);
283 printf (UT_HOST_PORT
, 'p', myport
);
287 printf (UT_TIMEOUT
, DEFAULT_SOCKET_TIMEOUT
);
289 printf (" %s\n", "-r, --remote-version=STRING");
290 printf (" %s\n", _("Warn if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
302 printf ("%s\n", _("Usage:"));
303 printf ("%s [-46] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname
);