diff options
author | Holger Weiss <holger@zedat.fu-berlin.de> | 2013-09-30 00:03:24 +0200 |
---|---|---|
committer | Holger Weiss <holger@zedat.fu-berlin.de> | 2013-09-30 00:03:24 +0200 |
commit | 0b6423f9c99d9edf8c96fefd0f6c453859395aa1 (patch) | |
tree | 1c2b6b21704a294940f87c7892676998d8371707 /web/attachments/127924-check_smtp.c | |
download | site-0b6423f9c99d9edf8c96fefd0f6c453859395aa1.tar.gz |
Import Nagios Plugins site
Import the Nagios Plugins web site, Cronjobs, infrastructure scripts,
and configuration files.
Diffstat (limited to 'web/attachments/127924-check_smtp.c')
-rw-r--r-- | web/attachments/127924-check_smtp.c | 739 |
1 files changed, 739 insertions, 0 deletions
diff --git a/web/attachments/127924-check_smtp.c b/web/attachments/127924-check_smtp.c new file mode 100644 index 0000000..f86a119 --- /dev/null +++ b/web/attachments/127924-check_smtp.c | |||
@@ -0,0 +1,739 @@ | |||
1 | /****************************************************************************** | ||
2 | |||
3 | This program is free software; you can redistribute it and/or modify | ||
4 | it under the terms of the GNU General Public License as published by | ||
5 | the Free Software Foundation; either version 2 of the License, or | ||
6 | (at your option) any later version. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | GNU General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License | ||
14 | along with this program; if not, write to the Free Software | ||
15 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
16 | |||
17 | $Id: check_smtp.c,v 1.43 2005/01/01 16:15:39 tonvoon Exp $ | ||
18 | |||
19 | ******************************************************************************/ | ||
20 | |||
21 | const char *progname = "check_smtp"; | ||
22 | const char *revision = "$Revision: 1.43 $"; | ||
23 | const char *copyright = "2000-2004"; | ||
24 | const char *email = "nagiosplug-devel@lists.sourceforge.net"; | ||
25 | |||
26 | #include "common.h" | ||
27 | #include "netutils.h" | ||
28 | #include "utils.h" | ||
29 | |||
30 | #ifdef HAVE_SSL_H | ||
31 | # include <rsa.h> | ||
32 | # include <crypto.h> | ||
33 | # include <x509.h> | ||
34 | # include <pem.h> | ||
35 | # include <ssl.h> | ||
36 | # include <err.h> | ||
37 | #else | ||
38 | # ifdef HAVE_OPENSSL_SSL_H | ||
39 | # include <openssl/rsa.h> | ||
40 | # include <openssl/crypto.h> | ||
41 | # include <openssl/x509.h> | ||
42 | # include <openssl/pem.h> | ||
43 | # include <openssl/ssl.h> | ||
44 | # include <openssl/err.h> | ||
45 | # endif | ||
46 | #endif | ||
47 | |||
48 | #ifdef HAVE_SSL | ||
49 | |||
50 | int check_cert = FALSE; | ||
51 | int days_till_exp; | ||
52 | SSL_CTX *ctx; | ||
53 | SSL *ssl; | ||
54 | X509 *server_cert; | ||
55 | int connect_STARTTLS (void); | ||
56 | int check_certificate (X509 **); | ||
57 | #endif | ||
58 | |||
59 | enum { | ||
60 | SMTP_PORT = 25 | ||
61 | }; | ||
62 | const char *SMTP_EXPECT = "220"; | ||
63 | const char *SMTP_HELO = "HELO "; | ||
64 | const char *SMTP_QUIT = "QUIT\r\n"; | ||
65 | const char *SMTP_STARTTLS = "STARTTLS\r\n"; | ||
66 | |||
67 | int process_arguments (int, char **); | ||
68 | int validate_arguments (void); | ||
69 | void print_help (void); | ||
70 | void print_usage (void); | ||
71 | int myrecv(void); | ||
72 | int my_close(void); | ||
73 | |||
74 | #ifdef HAVE_REGEX_H | ||
75 | #include <regex.h> | ||
76 | char regex_expect[MAX_INPUT_BUFFER] = ""; | ||
77 | regex_t preg; | ||
78 | regmatch_t pmatch[10]; | ||
79 | char timestamp[10] = ""; | ||
80 | char errbuf[MAX_INPUT_BUFFER]; | ||
81 | int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; | ||
82 | int eflags = 0; | ||
83 | int errcode, excode; | ||
84 | #endif | ||
85 | |||
86 | int server_port = SMTP_PORT; | ||
87 | char *server_address = NULL; | ||
88 | char *server_expect = NULL; | ||
89 | int smtp_use_dummycmd = 0; | ||
90 | char *mail_command = NULL; | ||
91 | char *from_arg = NULL; | ||
92 | int ncommands=0; | ||
93 | int command_size=0; | ||
94 | int nresponses=0; | ||
95 | int response_size=0; | ||
96 | char **commands = NULL; | ||
97 | char **responses = NULL; | ||
98 | int warning_time = 0; | ||
99 | int check_warning_time = FALSE; | ||
100 | int critical_time = 0; | ||
101 | int check_critical_time = FALSE; | ||
102 | int verbose = 0; | ||
103 | int use_ssl = FALSE; | ||
104 | int sd; | ||
105 | char buffer[MAX_INPUT_BUFFER]; | ||
106 | enum { | ||
107 | TCP_PROTOCOL = 1, | ||
108 | UDP_PROTOCOL = 2, | ||
109 | MAXBUF = 1024 | ||
110 | }; | ||
111 | |||
112 | int | ||
113 | main (int argc, char **argv) | ||
114 | { | ||
115 | |||
116 | int n = 0; | ||
117 | double elapsed_time; | ||
118 | long microsec; | ||
119 | int result = STATE_UNKNOWN; | ||
120 | char *cmd_str = NULL; | ||
121 | char *helocmd = NULL; | ||
122 | struct timeval tv; | ||
123 | |||
124 | setlocale (LC_ALL, ""); | ||
125 | bindtextdomain (PACKAGE, LOCALEDIR); | ||
126 | textdomain (PACKAGE); | ||
127 | |||
128 | if (process_arguments (argc, argv) == ERROR) | ||
129 | usage4 (_("Could not parse arguments")); | ||
130 | |||
131 | /* initialize the HELO command with the localhostname */ | ||
132 | #ifndef HOST_MAX_BYTES | ||
133 | #define HOST_MAX_BYTES 255 | ||
134 | #endif | ||
135 | helocmd = malloc (HOST_MAX_BYTES); | ||
136 | gethostname(helocmd, HOST_MAX_BYTES); | ||
137 | asprintf (&helocmd, "%s%s%s", SMTP_HELO, helocmd, "\r\n"); | ||
138 | |||
139 | /* initialize the MAIL command with optional FROM command */ | ||
140 | asprintf (&cmd_str, "%sFROM: %s%s", mail_command, from_arg, "\r\n"); | ||
141 | |||
142 | if (verbose && smtp_use_dummycmd) | ||
143 | printf ("FROM CMD: %s", cmd_str); | ||
144 | |||
145 | /* initialize alarm signal handling */ | ||
146 | (void) signal (SIGALRM, socket_timeout_alarm_handler); | ||
147 | |||
148 | /* set socket timeout */ | ||
149 | (void) alarm (socket_timeout); | ||
150 | |||
151 | /* start timer */ | ||
152 | gettimeofday (&tv, NULL); | ||
153 | |||
154 | /* try to connect to the host at the given port number */ | ||
155 | result = my_tcp_connect (server_address, server_port, &sd); | ||
156 | |||
157 | if (result == STATE_OK) { /* we connected */ | ||
158 | |||
159 | /* watch for the SMTP connection string and */ | ||
160 | /* return a WARNING status if we couldn't read any data */ | ||
161 | if (recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0) == -1) { | ||
162 | printf (_("recv() failed\n")); | ||
163 | result = STATE_WARNING; | ||
164 | } | ||
165 | else { | ||
166 | if (verbose) | ||
167 | printf ("%s", buffer); | ||
168 | /* strip the buffer of carriage returns */ | ||
169 | strip (buffer); | ||
170 | /* make sure we find the response we are looking for */ | ||
171 | if (!strstr (buffer, server_expect)) { | ||
172 | if (server_port == SMTP_PORT) | ||
173 | printf (_("Invalid SMTP response received from host\n")); | ||
174 | else | ||
175 | printf (_("Invalid SMTP response received from host on port %d\n"), | ||
176 | server_port); | ||
177 | result = STATE_WARNING; | ||
178 | } | ||
179 | } | ||
180 | #ifdef HAVE_SSL | ||
181 | if(use_ssl) { | ||
182 | |||
183 | send(sd, helocmd, strlen(helocmd), 0); | ||
184 | recv(sd,buffer, MAX_INPUT_BUFFER-1, 0); // wait for it | ||
185 | /* send the STARTTLS command */ | ||
186 | send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0); | ||
187 | |||
188 | recv(sd,buffer, MAX_INPUT_BUFFER-1, 0); // wait for it | ||
189 | if (!strstr (buffer, server_expect)) { | ||
190 | printf (_("Server does not support STARTTLS : %s \n"),buffer); | ||
191 | return STATE_UNKNOWN; | ||
192 | } | ||
193 | if(connect_STARTTLS() != OK) { | ||
194 | printf (_("CRITICAL - Cannot create SSL context.: %s \n"),buffer); | ||
195 | return STATE_CRITICAL; | ||
196 | } | ||
197 | if ( check_cert ) { | ||
198 | if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) { | ||
199 | result = check_certificate (&server_cert); | ||
200 | X509_free(server_cert); | ||
201 | } | ||
202 | else { | ||
203 | printf (_("CRITICAL - Cannot retrieve server certificate.: %s \n"),buffer); | ||
204 | result = STATE_CRITICAL; | ||
205 | |||
206 | } | ||
207 | my_close(); | ||
208 | return result; | ||
209 | } | ||
210 | } | ||
211 | #endif | ||
212 | /* send the HELO command */ | ||
213 | #ifdef HAVE_SSL | ||
214 | if (use_ssl) | ||
215 | SSL_write(ssl, helocmd, strlen(helocmd)); | ||
216 | else | ||
217 | #endif | ||
218 | send(sd, helocmd, strlen(helocmd), 0); | ||
219 | |||
220 | /* allow for response to helo command to reach us */ | ||
221 | myrecv(); | ||
222 | |||
223 | /* sendmail will syslog a "NOQUEUE" error if session does not attempt | ||
224 | * to do something useful. This can be prevented by giving a command | ||
225 | * even if syntax is illegal (MAIL requires a FROM:<...> argument) | ||
226 | * | ||
227 | * According to rfc821 you can include a null reversepath in the from command | ||
228 | * - but a log message is generated on the smtp server. | ||
229 | * | ||
230 | * You can disable sending mail_command with '--nocommand' | ||
231 | * Use the -f option to provide a FROM address | ||
232 | */ | ||
233 | if (smtp_use_dummycmd) { | ||
234 | #ifdef HAVE_SSL | ||
235 | if (use_ssl) | ||
236 | SSL_write(ssl, cmd_str, strlen(cmd_str)); | ||
237 | else | ||
238 | #endif | ||
239 | send(sd, cmd_str, strlen(cmd_str), 0); | ||
240 | myrecv(); | ||
241 | if (verbose) | ||
242 | printf("%s", buffer); | ||
243 | } | ||
244 | |||
245 | while (n < ncommands) { | ||
246 | asprintf (&cmd_str, "%s%s", commands[n], "\r\n"); | ||
247 | #ifdef HAVE_SSL | ||
248 | if (use_ssl) | ||
249 | SSL_write(ssl,cmd_str, strlen(cmd_str)); | ||
250 | else | ||
251 | #endif | ||
252 | send(sd, cmd_str, strlen(cmd_str), 0); | ||
253 | myrecv(); | ||
254 | if (verbose) | ||
255 | printf("%s", buffer); | ||
256 | strip (buffer); | ||
257 | if (n < nresponses) { | ||
258 | #ifdef HAVE_REGEX_H | ||
259 | cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; | ||
260 | //strncpy (regex_expect, responses[n], sizeof (regex_expect) - 1); | ||
261 | //regex_expect[sizeof (regex_expect) - 1] = '\0'; | ||
262 | errcode = regcomp (&preg, responses[n], cflags); | ||
263 | if (errcode != 0) { | ||
264 | regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); | ||
265 | printf (_("Could Not Compile Regular Expression")); | ||
266 | return ERROR; | ||
267 | } | ||
268 | excode = regexec (&preg, buffer, 10, pmatch, eflags); | ||
269 | if (excode == 0) { | ||
270 | result = STATE_OK; | ||
271 | } | ||
272 | else if (excode == REG_NOMATCH) { | ||
273 | result = STATE_WARNING; | ||
274 | printf (_("SMTP %s - Invalid response '%s' to command '%s'\n"), state_text (result), buffer, commands[n]); | ||
275 | } | ||
276 | else { | ||
277 | regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER); | ||
278 | printf (_("Execute Error: %s\n"), errbuf); | ||
279 | result = STATE_UNKNOWN; | ||
280 | } | ||
281 | #else | ||
282 | if (strstr(buffer, responses[n])!=buffer) { | ||
283 | result = STATE_WARNING; | ||
284 | printf (_("SMTP %s - Invalid response '%s' to command '%s'\n"), state_text (result), buffer, commands[n]); | ||
285 | } | ||
286 | #endif | ||
287 | } | ||
288 | n++; | ||
289 | } | ||
290 | |||
291 | /* tell the server we're done */ | ||
292 | #ifdef HAVE_SSL | ||
293 | if (use_ssl) | ||
294 | SSL_write(ssl,SMTP_QUIT, strlen (SMTP_QUIT)); | ||
295 | else | ||
296 | #endif | ||
297 | send (sd, SMTP_QUIT, strlen (SMTP_QUIT), 0); | ||
298 | |||
299 | /* finally close the connection */ | ||
300 | close (sd); | ||
301 | } | ||
302 | |||
303 | /* reset the alarm */ | ||
304 | alarm (0); | ||
305 | |||
306 | microsec = deltime (tv); | ||
307 | elapsed_time = (double)microsec / 1.0e6; | ||
308 | |||
309 | if (result == STATE_OK) { | ||
310 | if (check_critical_time && elapsed_time > (double) critical_time) | ||
311 | result = STATE_CRITICAL; | ||
312 | else if (check_warning_time && elapsed_time > (double) warning_time) | ||
313 | result = STATE_WARNING; | ||
314 | } | ||
315 | |||
316 | printf (_("SMTP %s - %.3f sec. response time%s%s|%s\n"), | ||
317 | state_text (result), elapsed_time, | ||
318 | verbose?", ":"", verbose?buffer:"", | ||
319 | fperfdata ("time", elapsed_time, "s", | ||
320 | (int)check_warning_time, warning_time, | ||
321 | (int)check_critical_time, critical_time, | ||
322 | TRUE, 0, FALSE, 0)); | ||
323 | |||
324 | return result; | ||
325 | } | ||
326 | |||
327 | |||
328 | |||
329 | /* process command-line arguments */ | ||
330 | int | ||
331 | process_arguments (int argc, char **argv) | ||
332 | { | ||
333 | int c; | ||
334 | |||
335 | int option = 0; | ||
336 | static struct option longopts[] = { | ||
337 | {"hostname", required_argument, 0, 'H'}, | ||
338 | {"expect", required_argument, 0, 'e'}, | ||
339 | {"critical", required_argument, 0, 'c'}, | ||
340 | {"warning", required_argument, 0, 'w'}, | ||
341 | {"timeout", required_argument, 0, 't'}, | ||
342 | {"port", required_argument, 0, 'p'}, | ||
343 | {"from", required_argument, 0, 'f'}, | ||
344 | {"command", required_argument, 0, 'C'}, | ||
345 | {"response", required_argument, 0, 'R'}, | ||
346 | {"nocommand", required_argument, 0, 'n'}, | ||
347 | {"verbose", no_argument, 0, 'v'}, | ||
348 | {"version", no_argument, 0, 'V'}, | ||
349 | {"use-ipv4", no_argument, 0, '4'}, | ||
350 | {"use-ipv6", no_argument, 0, '6'}, | ||
351 | {"help", no_argument, 0, 'h'}, | ||
352 | {"starttls",no_argument,0,'S'}, | ||
353 | {"certificate",required_argument,0,'D'}, | ||
354 | {0, 0, 0, 0} | ||
355 | }; | ||
356 | |||
357 | if (argc < 2) | ||
358 | return ERROR; | ||
359 | |||
360 | for (c = 1; c < argc; c++) { | ||
361 | if (strcmp ("-to", argv[c]) == 0) | ||
362 | strcpy (argv[c], "-t"); | ||
363 | else if (strcmp ("-wt", argv[c]) == 0) | ||
364 | strcpy (argv[c], "-w"); | ||
365 | else if (strcmp ("-ct", argv[c]) == 0) | ||
366 | strcpy (argv[c], "-c"); | ||
367 | } | ||
368 | |||
369 | while (1) { | ||
370 | c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:R:SD:", | ||
371 | longopts, &option); | ||
372 | |||
373 | if (c == -1 || c == EOF) | ||
374 | break; | ||
375 | |||
376 | switch (c) { | ||
377 | case 'H': /* hostname */ | ||
378 | if (is_host (optarg)) { | ||
379 | server_address = optarg; | ||
380 | } | ||
381 | else { | ||
382 | usage2 (_("Invalid hostname/address"), optarg); | ||
383 | } | ||
384 | break; | ||
385 | case 'p': /* port */ | ||
386 | if (is_intpos (optarg)) | ||
387 | server_port = atoi (optarg); | ||
388 | else | ||
389 | usage4 (_("Port must be a positive integer")); | ||
390 | break; | ||
391 | case 'f': /* from argument */ | ||
392 | from_arg = optarg; | ||
393 | smtp_use_dummycmd = 1; | ||
394 | break; | ||
395 | case 'e': /* server expect string on 220 */ | ||
396 | server_expect = optarg; | ||
397 | break; | ||
398 | case 'C': /* commands */ | ||
399 | if (ncommands >= command_size) { | ||
400 | commands = realloc (commands, command_size+8); | ||
401 | if (commands == NULL) | ||
402 | die (STATE_UNKNOWN, | ||
403 | _("Could not realloc() units [%d]\n"), ncommands); | ||
404 | } | ||
405 | commands[ncommands] = optarg; | ||
406 | ncommands++; | ||
407 | break; | ||
408 | case 'R': /* server responses */ | ||
409 | if (nresponses >= response_size) { | ||
410 | responses = realloc (responses, response_size+8); | ||
411 | if (responses == NULL) | ||
412 | die (STATE_UNKNOWN, | ||
413 | _("Could not realloc() units [%d]\n"), nresponses); | ||
414 | } | ||
415 | responses[nresponses] = optarg; | ||
416 | nresponses++; | ||
417 | break; | ||
418 | case 'c': /* critical time threshold */ | ||
419 | if (is_intnonneg (optarg)) { | ||
420 | critical_time = atoi (optarg); | ||
421 | check_critical_time = TRUE; | ||
422 | } | ||
423 | else { | ||
424 | usage4 (_("Critical time must be a positive integer")); | ||
425 | } | ||
426 | break; | ||
427 | case 'w': /* warning time threshold */ | ||
428 | if (is_intnonneg (optarg)) { | ||
429 | warning_time = atoi (optarg); | ||
430 | check_warning_time = TRUE; | ||
431 | } | ||
432 | else { | ||
433 | usage4 (_("Warning time must be a positive integer")); | ||
434 | } | ||
435 | break; | ||
436 | case 'v': /* verbose */ | ||
437 | verbose++; | ||
438 | break; | ||
439 | case 't': /* timeout */ | ||
440 | if (is_intnonneg (optarg)) { | ||
441 | socket_timeout = atoi (optarg); | ||
442 | } | ||
443 | else { | ||
444 | usage4 (_("Timeout interval must be a positive integer")); | ||
445 | } | ||
446 | break; | ||
447 | case 'S': | ||
448 | /* starttls */ | ||
449 | use_ssl = TRUE; | ||
450 | break; | ||
451 | case 'D': | ||
452 | /* Check SSL cert validity */ | ||
453 | #ifdef HAVE_SSL | ||
454 | if (!is_intnonneg (optarg)) | ||
455 | usage2 ("Invalid certificate expiration period",optarg); | ||
456 | days_till_exp = atoi (optarg); | ||
457 | check_cert = TRUE; | ||
458 | #else | ||
459 | usage (_("SSL support not available - install OpenSSL and recompile")); | ||
460 | #endif | ||
461 | break; | ||
462 | case '4': | ||
463 | address_family = AF_INET; | ||
464 | break; | ||
465 | case '6': | ||
466 | #ifdef USE_IPV6 | ||
467 | address_family = AF_INET6; | ||
468 | #else | ||
469 | usage4 (_("IPv6 support not available")); | ||
470 | #endif | ||
471 | break; | ||
472 | case 'V': /* version */ | ||
473 | print_revision (progname, revision); | ||
474 | exit (STATE_OK); | ||
475 | case 'h': /* help */ | ||
476 | print_help (); | ||
477 | exit (STATE_OK); | ||
478 | case '?': /* help */ | ||
479 | usage2 (_("Unknown argument"), optarg); | ||
480 | } | ||
481 | } | ||
482 | |||
483 | c = optind; | ||
484 | if (server_address == NULL) { | ||
485 | if (argv[c]) { | ||
486 | if (is_host (argv[c])) | ||
487 | server_address = argv[c]; | ||
488 | else | ||
489 | usage2 (_("Invalid hostname/address"), argv[c]); | ||
490 | } | ||
491 | else { | ||
492 | asprintf (&server_address, "127.0.0.1"); | ||
493 | } | ||
494 | } | ||
495 | |||
496 | if (server_expect == NULL) | ||
497 | server_expect = strdup (SMTP_EXPECT); | ||
498 | |||
499 | if (mail_command == NULL) | ||
500 | mail_command = strdup("MAIL "); | ||
501 | |||
502 | if (from_arg==NULL) | ||
503 | from_arg = strdup(" "); | ||
504 | |||
505 | return validate_arguments (); | ||
506 | } | ||
507 | |||
508 | |||
509 | |||
510 | int | ||
511 | validate_arguments (void) | ||
512 | { | ||
513 | return OK; | ||
514 | } | ||
515 | |||
516 | |||
517 | |||
518 | void | ||
519 | print_help (void) | ||
520 | { | ||
521 | char *myport; | ||
522 | asprintf (&myport, "%d", SMTP_PORT); | ||
523 | |||
524 | print_revision (progname, revision); | ||
525 | |||
526 | printf ("Copyright (c) 1999-2001 Ethan Galstad <nagios@nagios.org>\n"); | ||
527 | printf (COPYRIGHT, copyright, email); | ||
528 | |||
529 | printf(_("This plugin will attempt to open an SMTP connection with the host.\n\n")); | ||
530 | |||
531 | print_usage (); | ||
532 | |||
533 | printf (_(UT_HELP_VRSN)); | ||
534 | |||
535 | printf (_(UT_HOST_PORT), 'p', myport); | ||
536 | |||
537 | printf (_(UT_IPv46)); | ||
538 | |||
539 | printf (_("\ | ||
540 | -e, --expect=STRING\n\ | ||
541 | String to expect in first line of server response (default: '%s')\n\ | ||
542 | -n, nocommand\n\ | ||
543 | Suppress SMTP command\n\ | ||
544 | -C, --command=STRING\n\ | ||
545 | SMTP command (may be used repeatedly)\n\ | ||
546 | -R, --command=STRING\n\ | ||
547 | Expected response to command (may be used repeatedly)\n\ | ||
548 | -f, --from=STRING\n\ | ||
549 | FROM-address to include in MAIL command, required by Exchange 2000\n"), | ||
550 | SMTP_EXPECT); | ||
551 | #ifdef HAVE_SSL | ||
552 | printf (_("\ | ||
553 | -D, --certificate=INTEGER\n\ | ||
554 | Minimum number of days a certificate has to be valid.\n\ | ||
555 | -S, --starttls\n\ | ||
556 | Use STARTTLS for the connection.\n")); | ||
557 | #endif | ||
558 | |||
559 | printf (_(UT_WARN_CRIT)); | ||
560 | |||
561 | printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); | ||
562 | |||
563 | printf (_(UT_VERBOSE)); | ||
564 | |||
565 | printf(_("\n\ | ||
566 | Successul connects return STATE_OK, refusals and timeouts return\n\ | ||
567 | STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful\n\ | ||
568 | connects, but incorrect reponse messages from the host result in\n\ | ||
569 | STATE_WARNING return values.\n")); | ||
570 | |||
571 | printf (_(UT_SUPPORT)); | ||
572 | } | ||
573 | |||
574 | |||
575 | |||
576 | void | ||
577 | print_usage (void) | ||
578 | { | ||
579 | printf ("\ | ||
580 | Usage: %s -H host [-p port] [-e expect] [-C command] [-f from addr]\n\ | ||
581 | [-w warn] [-c crit] [-t timeout] [-S] [-D days] [-n] [-v] [-4|-6]\n", progname); | ||
582 | } | ||
583 | |||
584 | #ifdef HAVE_SSL | ||
585 | int | ||
586 | connect_STARTTLS (void) | ||
587 | { | ||
588 | SSL_METHOD *meth; | ||
589 | |||
590 | /* Initialize SSL context */ | ||
591 | SSLeay_add_ssl_algorithms (); | ||
592 | meth = SSLv2_client_method (); | ||
593 | SSL_load_error_strings (); | ||
594 | if ((ctx = SSL_CTX_new (meth)) == NULL) | ||
595 | { | ||
596 | printf(_("CRITICAL - Cannot create SSL context.\n")); | ||
597 | return STATE_CRITICAL; | ||
598 | } | ||
599 | /* do the SSL handshake */ | ||
600 | if ((ssl = SSL_new (ctx)) != NULL) | ||
601 | { | ||
602 | SSL_set_fd (ssl, sd); | ||
603 | /* original version checked for -1 | ||
604 | I look for success instead (1) */ | ||
605 | if (SSL_connect (ssl) == 1) | ||
606 | return OK; | ||
607 | ERR_print_errors_fp (stderr); | ||
608 | } | ||
609 | else | ||
610 | { | ||
611 | printf (_("CRITICAL - Cannot initiate SSL handshake.\n")); | ||
612 | } | ||
613 | /* this causes a seg faul | ||
614 | not sure why, being sloppy | ||
615 | and commenting it out */ | ||
616 | // SSL_free (ssl); | ||
617 | SSL_CTX_free(ctx); | ||
618 | my_close(); | ||
619 | |||
620 | return STATE_CRITICAL; | ||
621 | } | ||
622 | |||
623 | int | ||
624 | check_certificate (X509 ** certificate) | ||
625 | { | ||
626 | ASN1_STRING *tm; | ||
627 | int offset; | ||
628 | struct tm stamp; | ||
629 | int days_left; | ||
630 | |||
631 | /* Retrieve timestamp of certificate */ | ||
632 | tm = X509_get_notAfter (*certificate); | ||
633 | |||
634 | /* Generate tm structure to process timestamp */ | ||
635 | if (tm->type == V_ASN1_UTCTIME) { | ||
636 | if (tm->length < 10) { | ||
637 | printf (_("CRITICAL - Wrong time format in certificate.\n")); | ||
638 | return STATE_CRITICAL; | ||
639 | } | ||
640 | else { | ||
641 | stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0'); | ||
642 | if (stamp.tm_year < 50) | ||
643 | stamp.tm_year += 100; | ||
644 | offset = 0; | ||
645 | } | ||
646 | } | ||
647 | else { | ||
648 | if (tm->length < 12) { | ||
649 | printf (_("CRITICAL - Wrong time format in certificate.\n")); | ||
650 | return STATE_CRITICAL; | ||
651 | } | ||
652 | else { | ||
653 | stamp.tm_year = | ||
654 | (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 + | ||
655 | (tm->data[2] - '0') * 10 + (tm->data[3] - '0'); | ||
656 | stamp.tm_year -= 1900; | ||
657 | offset = 2; | ||
658 | } | ||
659 | } | ||
660 | stamp.tm_mon = | ||
661 | (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1; | ||
662 | stamp.tm_mday = | ||
663 | (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0'); | ||
664 | stamp.tm_hour = | ||
665 | (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0'); | ||
666 | stamp.tm_min = | ||
667 | (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0'); | ||
668 | stamp.tm_sec = 0; | ||
669 | stamp.tm_isdst = -1; | ||
670 | |||
671 | days_left = (mktime (&stamp) - time (NULL)) / 86400; | ||
672 | snprintf | ||
673 | (timestamp, 16, "%02d/%02d/%04d %02d:%02d", | ||
674 | stamp.tm_mon + 1, | ||
675 | stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min); | ||
676 | |||
677 | if (days_left > 0 && days_left <= days_till_exp) { | ||
678 | printf ("Certificate expires in %d day(s) (%s).\n", days_left, timestamp); | ||
679 | return STATE_WARNING; | ||
680 | } | ||
681 | if (days_left < 0) { | ||
682 | printf ("Certificate expired on %s.\n", timestamp); | ||
683 | return STATE_CRITICAL; | ||
684 | } | ||
685 | |||
686 | if (days_left == 0) { | ||
687 | printf ("Certificate expires today (%s).\n", timestamp); | ||
688 | return STATE_WARNING; | ||
689 | } | ||
690 | |||
691 | printf ("Certificate will expire on %s.\n", timestamp); | ||
692 | |||
693 | return STATE_OK; | ||
694 | } | ||
695 | #endif | ||
696 | |||
697 | int | ||
698 | myrecv (void) | ||
699 | { | ||
700 | int i; | ||
701 | |||
702 | #ifdef HAVE_SSL | ||
703 | if (use_ssl) { | ||
704 | i = SSL_read (ssl, buffer, MAXBUF - 1); | ||
705 | } | ||
706 | else { | ||
707 | #endif | ||
708 | i = read (sd, buffer, MAXBUF - 1); | ||
709 | #ifdef HAVE_SSL | ||
710 | } | ||
711 | #endif | ||
712 | return i; | ||
713 | } | ||
714 | |||
715 | int | ||
716 | myrecv_norm (void) | ||
717 | { | ||
718 | int i; | ||
719 | i = read (sd, buffer, MAXBUF - 1); | ||
720 | return i; | ||
721 | } | ||
722 | |||
723 | int | ||
724 | my_close (void) | ||
725 | { | ||
726 | #ifdef HAVE_SSL | ||
727 | if (use_ssl == TRUE) { | ||
728 | SSL_shutdown (ssl); | ||
729 | SSL_free (ssl); | ||
730 | SSL_CTX_free (ctx); | ||
731 | return 0; | ||
732 | } | ||
733 | else { | ||
734 | #endif | ||
735 | return close(sd); | ||
736 | #ifdef HAVE_SSL | ||
737 | } | ||
738 | #endif | ||
739 | } | ||