diff options
Diffstat (limited to 'plugins/check_smtp.c')
-rw-r--r-- | plugins/check_smtp.c | 87 |
1 files changed, 52 insertions, 35 deletions
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c index 24304534..c1e92dff 100644 --- a/plugins/check_smtp.c +++ b/plugins/check_smtp.c | |||
@@ -55,14 +55,11 @@ enum { | |||
55 | #define SMTP_EXPECT "220" | 55 | #define SMTP_EXPECT "220" |
56 | #define SMTP_HELO "HELO " | 56 | #define SMTP_HELO "HELO " |
57 | #define SMTP_EHLO "EHLO " | 57 | #define SMTP_EHLO "EHLO " |
58 | #define SMTP_LHLO "LHLO " | ||
58 | #define SMTP_QUIT "QUIT\r\n" | 59 | #define SMTP_QUIT "QUIT\r\n" |
59 | #define SMTP_STARTTLS "STARTTLS\r\n" | 60 | #define SMTP_STARTTLS "STARTTLS\r\n" |
60 | #define SMTP_AUTH_LOGIN "AUTH LOGIN\r\n" | 61 | #define SMTP_AUTH_LOGIN "AUTH LOGIN\r\n" |
61 | 62 | ||
62 | #ifndef HOST_MAX_BYTES | ||
63 | #define HOST_MAX_BYTES 255 | ||
64 | #endif | ||
65 | |||
66 | #define EHLO_SUPPORTS_STARTTLS 1 | 63 | #define EHLO_SUPPORTS_STARTTLS 1 |
67 | 64 | ||
68 | int process_arguments (int, char **); | 65 | int process_arguments (int, char **); |
@@ -106,6 +103,7 @@ int check_critical_time = FALSE; | |||
106 | int verbose = 0; | 103 | int verbose = 0; |
107 | int use_ssl = FALSE; | 104 | int use_ssl = FALSE; |
108 | short use_ehlo = FALSE; | 105 | short use_ehlo = FALSE; |
106 | short use_lhlo = FALSE; | ||
109 | short ssl_established = 0; | 107 | short ssl_established = 0; |
110 | char *localhostname = NULL; | 108 | char *localhostname = NULL; |
111 | int sd; | 109 | int sd; |
@@ -128,6 +126,7 @@ main (int argc, char **argv) | |||
128 | char *cmd_str = NULL; | 126 | char *cmd_str = NULL; |
129 | char *helocmd = NULL; | 127 | char *helocmd = NULL; |
130 | char *error_msg = ""; | 128 | char *error_msg = ""; |
129 | char *server_response = NULL; | ||
131 | struct timeval tv; | 130 | struct timeval tv; |
132 | 131 | ||
133 | /* Catch pipe errors in read/write - sometimes occurs when writing QUIT */ | 132 | /* Catch pipe errors in read/write - sometimes occurs when writing QUIT */ |
@@ -155,7 +154,9 @@ main (int argc, char **argv) | |||
155 | return STATE_CRITICAL; | 154 | return STATE_CRITICAL; |
156 | } | 155 | } |
157 | } | 156 | } |
158 | if(use_ehlo) | 157 | if(use_lhlo) |
158 | xasprintf (&helocmd, "%s%s%s", SMTP_LHLO, localhostname, "\r\n"); | ||
159 | else if(use_ehlo) | ||
159 | xasprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n"); | 160 | xasprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n"); |
160 | else | 161 | else |
161 | xasprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n"); | 162 | xasprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n"); |
@@ -189,21 +190,9 @@ main (int argc, char **argv) | |||
189 | printf (_("recv() failed\n")); | 190 | printf (_("recv() failed\n")); |
190 | return STATE_WARNING; | 191 | return STATE_WARNING; |
191 | } | 192 | } |
192 | else { | 193 | |
193 | if (verbose) | 194 | /* save connect return (220 hostname ..) for later use */ |
194 | printf ("%s", buffer); | 195 | xasprintf(&server_response, "%s", buffer); |
195 | /* strip the buffer of carriage returns */ | ||
196 | strip (buffer); | ||
197 | /* make sure we find the response we are looking for */ | ||
198 | if (!strstr (buffer, server_expect)) { | ||
199 | if (server_port == SMTP_PORT) | ||
200 | printf (_("Invalid SMTP response received from host: %s\n"), buffer); | ||
201 | else | ||
202 | printf (_("Invalid SMTP response received from host on port %d: %s\n"), | ||
203 | server_port, buffer); | ||
204 | return STATE_WARNING; | ||
205 | } | ||
206 | } | ||
207 | 196 | ||
208 | /* send the HELO/EHLO command */ | 197 | /* send the HELO/EHLO command */ |
209 | send(sd, helocmd, strlen(helocmd), 0); | 198 | send(sd, helocmd, strlen(helocmd), 0); |
@@ -212,7 +201,7 @@ main (int argc, char **argv) | |||
212 | if (recvlines(buffer, MAX_INPUT_BUFFER) <= 0) { | 201 | if (recvlines(buffer, MAX_INPUT_BUFFER) <= 0) { |
213 | printf (_("recv() failed\n")); | 202 | printf (_("recv() failed\n")); |
214 | return STATE_WARNING; | 203 | return STATE_WARNING; |
215 | } else if(use_ehlo){ | 204 | } else if(use_ehlo || use_lhlo){ |
216 | if(strstr(buffer, "250 STARTTLS") != NULL || | 205 | if(strstr(buffer, "250 STARTTLS") != NULL || |
217 | strstr(buffer, "250-STARTTLS") != NULL){ | 206 | strstr(buffer, "250-STARTTLS") != NULL){ |
218 | supports_tls=TRUE; | 207 | supports_tls=TRUE; |
@@ -231,7 +220,7 @@ main (int argc, char **argv) | |||
231 | send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0); | 220 | send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0); |
232 | 221 | ||
233 | recvlines(buffer, MAX_INPUT_BUFFER); /* wait for it */ | 222 | recvlines(buffer, MAX_INPUT_BUFFER); /* wait for it */ |
234 | if (!strstr (buffer, server_expect)) { | 223 | if (!strstr (buffer, SMTP_EXPECT)) { |
235 | printf (_("Server does not support STARTTLS\n")); | 224 | printf (_("Server does not support STARTTLS\n")); |
236 | smtp_quit(); | 225 | smtp_quit(); |
237 | return STATE_UNKNOWN; | 226 | return STATE_UNKNOWN; |
@@ -239,8 +228,8 @@ main (int argc, char **argv) | |||
239 | result = np_net_ssl_init(sd); | 228 | result = np_net_ssl_init(sd); |
240 | if(result != STATE_OK) { | 229 | if(result != STATE_OK) { |
241 | printf (_("CRITICAL - Cannot create SSL context.\n")); | 230 | printf (_("CRITICAL - Cannot create SSL context.\n")); |
242 | np_net_ssl_cleanup(); | ||
243 | close(sd); | 231 | close(sd); |
232 | np_net_ssl_cleanup(); | ||
244 | return STATE_CRITICAL; | 233 | return STATE_CRITICAL; |
245 | } else { | 234 | } else { |
246 | ssl_established = 1; | 235 | ssl_established = 1; |
@@ -276,6 +265,7 @@ main (int argc, char **argv) | |||
276 | # ifdef USE_OPENSSL | 265 | # ifdef USE_OPENSSL |
277 | if ( check_cert ) { | 266 | if ( check_cert ) { |
278 | result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); | 267 | result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); |
268 | smtp_quit(); | ||
279 | my_close(); | 269 | my_close(); |
280 | return result; | 270 | return result; |
281 | } | 271 | } |
@@ -283,12 +273,31 @@ main (int argc, char **argv) | |||
283 | } | 273 | } |
284 | #endif | 274 | #endif |
285 | 275 | ||
276 | if (verbose) | ||
277 | printf ("%s", buffer); | ||
278 | |||
279 | /* save buffer for later use */ | ||
280 | xasprintf(&server_response, "%s%s", server_response, buffer); | ||
281 | /* strip the buffer of carriage returns */ | ||
282 | strip (server_response); | ||
283 | |||
284 | /* make sure we find the droids we are looking for */ | ||
285 | if (!strstr (server_response, server_expect)) { | ||
286 | if (server_port == SMTP_PORT) | ||
287 | printf (_("Invalid SMTP response received from host: %s\n"), server_response); | ||
288 | else | ||
289 | printf (_("Invalid SMTP response received from host on port %d: %s\n"), | ||
290 | server_port, server_response); | ||
291 | return STATE_WARNING; | ||
292 | } | ||
293 | |||
286 | if (send_mail_from) { | 294 | if (send_mail_from) { |
287 | my_send(cmd_str, strlen(cmd_str)); | 295 | my_send(cmd_str, strlen(cmd_str)); |
288 | if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose) | 296 | if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose) |
289 | printf("%s", buffer); | 297 | printf("%s", buffer); |
290 | } | 298 | } |
291 | 299 | ||
300 | n = 0; | ||
292 | while (n < ncommands) { | 301 | while (n < ncommands) { |
293 | xasprintf (&cmd_str, "%s%s", commands[n], "\r\n"); | 302 | xasprintf (&cmd_str, "%s%s", commands[n], "\r\n"); |
294 | my_send(cmd_str, strlen(cmd_str)); | 303 | my_send(cmd_str, strlen(cmd_str)); |
@@ -465,6 +474,7 @@ process_arguments (int argc, char **argv) | |||
465 | {"use-ipv4", no_argument, 0, '4'}, | 474 | {"use-ipv4", no_argument, 0, '4'}, |
466 | {"use-ipv6", no_argument, 0, '6'}, | 475 | {"use-ipv6", no_argument, 0, '6'}, |
467 | {"help", no_argument, 0, 'h'}, | 476 | {"help", no_argument, 0, 'h'}, |
477 | {"lmtp", no_argument, 0, 'L'}, | ||
468 | {"starttls",no_argument,0,'S'}, | 478 | {"starttls",no_argument,0,'S'}, |
469 | {"certificate",required_argument,0,'D'}, | 479 | {"certificate",required_argument,0,'D'}, |
470 | {"ignore-quit-failure",no_argument,0,'q'}, | 480 | {"ignore-quit-failure",no_argument,0,'q'}, |
@@ -484,7 +494,7 @@ process_arguments (int argc, char **argv) | |||
484 | } | 494 | } |
485 | 495 | ||
486 | while (1) { | 496 | while (1) { |
487 | c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:R:SD:F:A:U:P:q", | 497 | c = getopt_long (argc, argv, "+hVv46Lt:p:f:e:c:w:H:C:R:SD:F:A:U:P:q", |
488 | longopts, &option); | 498 | longopts, &option); |
489 | 499 | ||
490 | if (c == -1 || c == EOF) | 500 | if (c == -1 || c == EOF) |
@@ -581,11 +591,6 @@ process_arguments (int argc, char **argv) | |||
581 | usage4 (_("Timeout interval must be a positive integer")); | 591 | usage4 (_("Timeout interval must be a positive integer")); |
582 | } | 592 | } |
583 | break; | 593 | break; |
584 | case 'S': | ||
585 | /* starttls */ | ||
586 | use_ssl = TRUE; | ||
587 | use_ehlo = TRUE; | ||
588 | break; | ||
589 | case 'D': | 594 | case 'D': |
590 | /* Check SSL cert validity */ | 595 | /* Check SSL cert validity */ |
591 | #ifdef USE_OPENSSL | 596 | #ifdef USE_OPENSSL |
@@ -607,9 +612,17 @@ process_arguments (int argc, char **argv) | |||
607 | days_till_exp_warn = atoi (optarg); | 612 | days_till_exp_warn = atoi (optarg); |
608 | } | 613 | } |
609 | check_cert = TRUE; | 614 | check_cert = TRUE; |
615 | ignore_send_quit_failure = TRUE; | ||
610 | #else | 616 | #else |
611 | usage (_("SSL support not available - install OpenSSL and recompile")); | 617 | usage (_("SSL support not available - install OpenSSL and recompile")); |
612 | #endif | 618 | #endif |
619 | case 'S': | ||
620 | /* starttls */ | ||
621 | use_ssl = TRUE; | ||
622 | use_ehlo = TRUE; | ||
623 | break; | ||
624 | case 'L': | ||
625 | use_lhlo = TRUE; | ||
613 | break; | 626 | break; |
614 | case '4': | 627 | case '4': |
615 | address_family = AF_INET; | 628 | address_family = AF_INET; |
@@ -623,10 +636,10 @@ process_arguments (int argc, char **argv) | |||
623 | break; | 636 | break; |
624 | case 'V': /* version */ | 637 | case 'V': /* version */ |
625 | print_revision (progname, NP_VERSION); | 638 | print_revision (progname, NP_VERSION); |
626 | exit (STATE_OK); | 639 | exit (STATE_UNKNOWN); |
627 | case 'h': /* help */ | 640 | case 'h': /* help */ |
628 | print_help (); | 641 | print_help (); |
629 | exit (STATE_OK); | 642 | exit (STATE_UNKNOWN); |
630 | case '?': /* help */ | 643 | case '?': /* help */ |
631 | usage5 (); | 644 | usage5 (); |
632 | } | 645 | } |
@@ -763,10 +776,12 @@ recvlines(char *buf, size_t bufsize) | |||
763 | int | 776 | int |
764 | my_close (void) | 777 | my_close (void) |
765 | { | 778 | { |
779 | int result; | ||
780 | result = close(sd); | ||
766 | #ifdef HAVE_SSL | 781 | #ifdef HAVE_SSL |
767 | np_net_ssl_cleanup(); | 782 | np_net_ssl_cleanup(); |
768 | #endif | 783 | #endif |
769 | return close(sd); | 784 | return result; |
770 | } | 785 | } |
771 | 786 | ||
772 | 787 | ||
@@ -817,6 +832,8 @@ print_help (void) | |||
817 | printf (" %s\n", _("SMTP AUTH username")); | 832 | printf (" %s\n", _("SMTP AUTH username")); |
818 | printf (" %s\n", "-P, --authpass=STRING"); | 833 | printf (" %s\n", "-P, --authpass=STRING"); |
819 | printf (" %s\n", _("SMTP AUTH password")); | 834 | printf (" %s\n", _("SMTP AUTH password")); |
835 | printf (" %s\n", "-L, --lmtp"); | ||
836 | printf (" %s\n", _("Send LHLO instead of HELO/EHLO")); | ||
820 | printf (" %s\n", "-q, --ignore-quit-failure"); | 837 | printf (" %s\n", "-q, --ignore-quit-failure"); |
821 | printf (" %s\n", _("Ignore failure when sending QUIT command to server")); | 838 | printf (" %s\n", _("Ignore failure when sending QUIT command to server")); |
822 | 839 | ||
@@ -829,7 +846,7 @@ print_help (void) | |||
829 | printf("\n"); | 846 | printf("\n"); |
830 | printf ("%s\n", _("Successul connects return STATE_OK, refusals and timeouts return")); | 847 | printf ("%s\n", _("Successul connects return STATE_OK, refusals and timeouts return")); |
831 | printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful")); | 848 | printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful")); |
832 | printf ("%s\n", _("connects, but incorrect reponse messages from the host result in")); | 849 | printf ("%s\n", _("connects, but incorrect response messages from the host result in")); |
833 | printf ("%s\n", _("STATE_WARNING return values.")); | 850 | printf ("%s\n", _("STATE_WARNING return values.")); |
834 | 851 | ||
835 | printf (UT_SUPPORT); | 852 | printf (UT_SUPPORT); |
@@ -843,6 +860,6 @@ print_usage (void) | |||
843 | printf ("%s\n", _("Usage:")); | 860 | printf ("%s\n", _("Usage:")); |
844 | printf ("%s -H host [-p port] [-4|-6] [-e expect] [-C command] [-R response] [-f from addr]\n", progname); | 861 | printf ("%s -H host [-p port] [-4|-6] [-e expect] [-C command] [-R response] [-f from addr]\n", progname); |
845 | printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout] [-q]\n"); | 862 | printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout] [-q]\n"); |
846 | printf ("[-F fqdn] [-S] [-D warn days cert expire[,crit days cert expire]] [-v] \n"); | 863 | printf ("[-F fqdn] [-S] [-L] [-D warn days cert expire[,crit days cert expire]] [-v] \n"); |
847 | } | 864 | } |
848 | 865 | ||