summaryrefslogtreecommitdiffstats
path: root/plugins/check_smtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_smtp.c')
-rw-r--r--plugins/check_smtp.c104
1 files changed, 89 insertions, 15 deletions
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index d37c57c..fc0ae2c 100644
--- a/plugins/check_smtp.c
+++ b/plugins/check_smtp.c
@@ -3,7 +3,7 @@
3* Monitoring check_smtp plugin 3* Monitoring check_smtp plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6* Copyright (c) 2000-2023 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -42,19 +42,22 @@ const char *email = "devel@monitoring-plugins.org";
42#ifdef HAVE_SSL 42#ifdef HAVE_SSL
43int check_cert = FALSE; 43int check_cert = FALSE;
44int days_till_exp_warn, days_till_exp_crit; 44int days_till_exp_warn, days_till_exp_crit;
45# define my_recv(buf, len) ((use_ssl && ssl_established) ? np_net_ssl_read(buf, len) : read(sd, buf, len)) 45# define my_recv(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
46# define my_send(buf, len) ((use_ssl && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0)) 46# define my_send(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
47#else /* ifndef HAVE_SSL */ 47#else /* ifndef HAVE_SSL */
48# define my_recv(buf, len) read(sd, buf, len) 48# define my_recv(buf, len) read(sd, buf, len)
49# define my_send(buf, len) send(sd, buf, len, 0) 49# define my_send(buf, len) send(sd, buf, len, 0)
50#endif 50#endif
51 51
52enum { 52enum {
53 SMTP_PORT = 25 53 SMTP_PORT = 25,
54 SMTPS_PORT = 465
54}; 55};
56#define PROXY_PREFIX "PROXY TCP4 0.0.0.0 0.0.0.0 25 25\r\n"
55#define SMTP_EXPECT "220" 57#define SMTP_EXPECT "220"
56#define SMTP_HELO "HELO " 58#define SMTP_HELO "HELO "
57#define SMTP_EHLO "EHLO " 59#define SMTP_EHLO "EHLO "
60#define SMTP_LHLO "LHLO "
58#define SMTP_QUIT "QUIT\r\n" 61#define SMTP_QUIT "QUIT\r\n"
59#define SMTP_STARTTLS "STARTTLS\r\n" 62#define SMTP_STARTTLS "STARTTLS\r\n"
60#define SMTP_AUTH_LOGIN "AUTH LOGIN\r\n" 63#define SMTP_AUTH_LOGIN "AUTH LOGIN\r\n"
@@ -81,6 +84,7 @@ int eflags = 0;
81int errcode, excode; 84int errcode, excode;
82 85
83int server_port = SMTP_PORT; 86int server_port = SMTP_PORT;
87int server_port_option = 0;
84char *server_address = NULL; 88char *server_address = NULL;
85char *server_expect = NULL; 89char *server_expect = NULL;
86char *mail_command = NULL; 90char *mail_command = NULL;
@@ -101,7 +105,11 @@ double critical_time = 0;
101int check_critical_time = FALSE; 105int check_critical_time = FALSE;
102int verbose = 0; 106int verbose = 0;
103int use_ssl = FALSE; 107int use_ssl = FALSE;
108int use_starttls = FALSE;
109int use_sni = FALSE;
110short use_proxy_prefix = FALSE;
104short use_ehlo = FALSE; 111short use_ehlo = FALSE;
112short use_lhlo = FALSE;
105short ssl_established = 0; 113short ssl_established = 0;
106char *localhostname = NULL; 114char *localhostname = NULL;
107int sd; 115int sd;
@@ -152,7 +160,9 @@ main (int argc, char **argv)
152 return STATE_CRITICAL; 160 return STATE_CRITICAL;
153 } 161 }
154 } 162 }
155 if(use_ehlo) 163 if(use_lhlo)
164 xasprintf (&helocmd, "%s%s%s", SMTP_LHLO, localhostname, "\r\n");
165 else if(use_ehlo)
156 xasprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n"); 166 xasprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n");
157 else 167 else
158 xasprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n"); 168 xasprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n");
@@ -179,6 +189,26 @@ main (int argc, char **argv)
179 result = my_tcp_connect (server_address, server_port, &sd); 189 result = my_tcp_connect (server_address, server_port, &sd);
180 190
181 if (result == STATE_OK) { /* we connected */ 191 if (result == STATE_OK) { /* we connected */
192 /* If requested, send PROXY header */
193 if (use_proxy_prefix) {
194 if (verbose)
195 printf ("Sending header %s\n", PROXY_PREFIX);
196 my_send(PROXY_PREFIX, strlen(PROXY_PREFIX));
197 }
198
199#ifdef HAVE_SSL
200 if (use_ssl) {
201 result = np_net_ssl_init_with_hostname(sd, (use_sni ? server_address : NULL));
202 if (result != STATE_OK) {
203 printf (_("CRITICAL - Cannot create SSL context.\n"));
204 close(sd);
205 np_net_ssl_cleanup();
206 return STATE_CRITICAL;
207 } else {
208 ssl_established = 1;
209 }
210 }
211#endif
182 212
183 /* watch for the SMTP connection string and */ 213 /* watch for the SMTP connection string and */
184 /* return a WARNING status if we couldn't read any data */ 214 /* return a WARNING status if we couldn't read any data */
@@ -191,27 +221,27 @@ main (int argc, char **argv)
191 xasprintf(&server_response, "%s", buffer); 221 xasprintf(&server_response, "%s", buffer);
192 222
193 /* send the HELO/EHLO command */ 223 /* send the HELO/EHLO command */
194 send(sd, helocmd, strlen(helocmd), 0); 224 my_send(helocmd, strlen(helocmd));
195 225
196 /* allow for response to helo command to reach us */ 226 /* allow for response to helo command to reach us */
197 if (recvlines(buffer, MAX_INPUT_BUFFER) <= 0) { 227 if (recvlines(buffer, MAX_INPUT_BUFFER) <= 0) {
198 printf (_("recv() failed\n")); 228 printf (_("recv() failed\n"));
199 return STATE_WARNING; 229 return STATE_WARNING;
200 } else if(use_ehlo){ 230 } else if(use_ehlo || use_lhlo){
201 if(strstr(buffer, "250 STARTTLS") != NULL || 231 if(strstr(buffer, "250 STARTTLS") != NULL ||
202 strstr(buffer, "250-STARTTLS") != NULL){ 232 strstr(buffer, "250-STARTTLS") != NULL){
203 supports_tls=TRUE; 233 supports_tls=TRUE;
204 } 234 }
205 } 235 }
206 236
207 if(use_ssl && ! supports_tls){ 237 if(use_starttls && ! supports_tls){
208 printf(_("WARNING - TLS not supported by server\n")); 238 printf(_("WARNING - TLS not supported by server\n"));
209 smtp_quit(); 239 smtp_quit();
210 return STATE_WARNING; 240 return STATE_WARNING;
211 } 241 }
212 242
213#ifdef HAVE_SSL 243#ifdef HAVE_SSL
214 if(use_ssl) { 244 if(use_starttls) {
215 /* send the STARTTLS command */ 245 /* send the STARTTLS command */
216 send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0); 246 send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0);
217 247
@@ -221,7 +251,7 @@ main (int argc, char **argv)
221 smtp_quit(); 251 smtp_quit();
222 return STATE_UNKNOWN; 252 return STATE_UNKNOWN;
223 } 253 }
224 result = np_net_ssl_init(sd); 254 result = np_net_ssl_init_with_hostname(sd, (use_sni ? server_address : NULL));
225 if(result != STATE_OK) { 255 if(result != STATE_OK) {
226 printf (_("CRITICAL - Cannot create SSL context.\n")); 256 printf (_("CRITICAL - Cannot create SSL context.\n"));
227 close(sd); 257 close(sd);
@@ -450,6 +480,10 @@ process_arguments (int argc, char **argv)
450 int c; 480 int c;
451 char* temp; 481 char* temp;
452 482
483 enum {
484 SNI_OPTION
485 };
486
453 int option = 0; 487 int option = 0;
454 static struct option longopts[] = { 488 static struct option longopts[] = {
455 {"hostname", required_argument, 0, 'H'}, 489 {"hostname", required_argument, 0, 'H'},
@@ -470,9 +504,14 @@ process_arguments (int argc, char **argv)
470 {"use-ipv4", no_argument, 0, '4'}, 504 {"use-ipv4", no_argument, 0, '4'},
471 {"use-ipv6", no_argument, 0, '6'}, 505 {"use-ipv6", no_argument, 0, '6'},
472 {"help", no_argument, 0, 'h'}, 506 {"help", no_argument, 0, 'h'},
507 {"lmtp", no_argument, 0, 'L'},
508 {"ssl", no_argument, 0, 's'},
509 {"tls", no_argument, 0, 's'},
473 {"starttls",no_argument,0,'S'}, 510 {"starttls",no_argument,0,'S'},
511 {"sni", no_argument, 0, SNI_OPTION},
474 {"certificate",required_argument,0,'D'}, 512 {"certificate",required_argument,0,'D'},
475 {"ignore-quit-failure",no_argument,0,'q'}, 513 {"ignore-quit-failure",no_argument,0,'q'},
514 {"proxy",no_argument,0,'r'},
476 {0, 0, 0, 0} 515 {0, 0, 0, 0}
477 }; 516 };
478 517
@@ -489,7 +528,7 @@ process_arguments (int argc, char **argv)
489 } 528 }
490 529
491 while (1) { 530 while (1) {
492 c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:R:SD:F:A:U:P:q", 531 c = getopt_long (argc, argv, "+hVv46Lrt:p:f:e:c:w:H:C:R:sSD:F:A:U:P:q",
493 longopts, &option); 532 longopts, &option);
494 533
495 if (c == -1 || c == EOF) 534 if (c == -1 || c == EOF)
@@ -506,7 +545,7 @@ process_arguments (int argc, char **argv)
506 break; 545 break;
507 case 'p': /* port */ 546 case 'p': /* port */
508 if (is_intpos (optarg)) 547 if (is_intpos (optarg))
509 server_port = atoi (optarg); 548 server_port_option = atoi (optarg);
510 else 549 else
511 usage4 (_("Port must be a positive integer")); 550 usage4 (_("Port must be a positive integer"));
512 break; 551 break;
@@ -611,11 +650,29 @@ process_arguments (int argc, char **argv)
611#else 650#else
612 usage (_("SSL support not available - install OpenSSL and recompile")); 651 usage (_("SSL support not available - install OpenSSL and recompile"));
613#endif 652#endif
653 case 's':
654 /* ssl */
655 use_ssl = TRUE;
656 server_port = SMTPS_PORT;
657 break;
614 case 'S': 658 case 'S':
615 /* starttls */ 659 /* starttls */
616 use_ssl = TRUE; 660 use_starttls = TRUE;
617 use_ehlo = TRUE; 661 use_ehlo = TRUE;
618 break; 662 break;
663 case SNI_OPTION:
664#ifdef HAVE_SSL
665 use_sni = TRUE;
666#else
667 usage (_("SSL support not available - install OpenSSL and recompile"));
668#endif
669 break;
670 case 'r':
671 use_proxy_prefix = TRUE;
672 break;
673 case 'L':
674 use_lhlo = TRUE;
675 break;
619 case '4': 676 case '4':
620 address_family = AF_INET; 677 address_family = AF_INET;
621 break; 678 break;
@@ -659,6 +716,14 @@ process_arguments (int argc, char **argv)
659 if (from_arg==NULL) 716 if (from_arg==NULL)
660 from_arg = strdup(" "); 717 from_arg = strdup(" ");
661 718
719 if (use_starttls && use_ssl) {
720 usage4 (_("Set either -s/--ssl/--tls or -S/--starttls"));
721 }
722
723 if (server_port_option != 0) {
724 server_port = server_port_option;
725 }
726
662 return validate_arguments (); 727 return validate_arguments ();
663} 728}
664 729
@@ -811,11 +876,18 @@ print_help (void)
811 printf (" %s\n", _("FROM-address to include in MAIL command, required by Exchange 2000")), 876 printf (" %s\n", _("FROM-address to include in MAIL command, required by Exchange 2000")),
812 printf (" %s\n", "-F, --fqdn=STRING"); 877 printf (" %s\n", "-F, --fqdn=STRING");
813 printf (" %s\n", _("FQDN used for HELO")); 878 printf (" %s\n", _("FQDN used for HELO"));
879 printf (" %s\n", "-r, --proxy");
880 printf (" %s\n", _("Use PROXY protocol prefix for the connection."));
814#ifdef HAVE_SSL 881#ifdef HAVE_SSL
815 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]"); 882 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]");
816 printf (" %s\n", _("Minimum number of days a certificate has to be valid.")); 883 printf (" %s\n", _("Minimum number of days a certificate has to be valid."));
884 printf (" %s\n", "-s, --ssl, --tls");
885 printf (" %s\n", _("Use SSL/TLS for the connection."));
886 printf (_(" Sets default port to %d.\n"), SMTPS_PORT);
817 printf (" %s\n", "-S, --starttls"); 887 printf (" %s\n", "-S, --starttls");
818 printf (" %s\n", _("Use STARTTLS for the connection.")); 888 printf (" %s\n", _("Use STARTTLS for the connection."));
889 printf (" %s\n", "--sni");
890 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
819#endif 891#endif
820 892
821 printf (" %s\n", "-A, --authtype=STRING"); 893 printf (" %s\n", "-A, --authtype=STRING");
@@ -824,6 +896,8 @@ print_help (void)
824 printf (" %s\n", _("SMTP AUTH username")); 896 printf (" %s\n", _("SMTP AUTH username"));
825 printf (" %s\n", "-P, --authpass=STRING"); 897 printf (" %s\n", "-P, --authpass=STRING");
826 printf (" %s\n", _("SMTP AUTH password")); 898 printf (" %s\n", _("SMTP AUTH password"));
899 printf (" %s\n", "-L, --lmtp");
900 printf (" %s\n", _("Send LHLO instead of HELO/EHLO"));
827 printf (" %s\n", "-q, --ignore-quit-failure"); 901 printf (" %s\n", "-q, --ignore-quit-failure");
828 printf (" %s\n", _("Ignore failure when sending QUIT command to server")); 902 printf (" %s\n", _("Ignore failure when sending QUIT command to server"));
829 903
@@ -834,7 +908,7 @@ print_help (void)
834 printf (UT_VERBOSE); 908 printf (UT_VERBOSE);
835 909
836 printf("\n"); 910 printf("\n");
837 printf ("%s\n", _("Successul connects return STATE_OK, refusals and timeouts return")); 911 printf ("%s\n", _("Successful connects return STATE_OK, refusals and timeouts return"));
838 printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful")); 912 printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful"));
839 printf ("%s\n", _("connects, but incorrect response messages from the host result in")); 913 printf ("%s\n", _("connects, but incorrect response messages from the host result in"));
840 printf ("%s\n", _("STATE_WARNING return values.")); 914 printf ("%s\n", _("STATE_WARNING return values."));
@@ -850,6 +924,6 @@ print_usage (void)
850 printf ("%s\n", _("Usage:")); 924 printf ("%s\n", _("Usage:"));
851 printf ("%s -H host [-p port] [-4|-6] [-e expect] [-C command] [-R response] [-f from addr]\n", progname); 925 printf ("%s -H host [-p port] [-4|-6] [-e expect] [-C command] [-R response] [-f from addr]\n", progname);
852 printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout] [-q]\n"); 926 printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout] [-q]\n");
853 printf ("[-F fqdn] [-S] [-D warn days cert expire[,crit days cert expire]] [-v] \n"); 927 printf ("[-F fqdn] [-S] [-L] [-D warn days cert expire[,crit days cert expire]] [-r] [--sni] [-v] \n");
854} 928}
855 929