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 | ||
