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.c87
1 files changed, 52 insertions, 35 deletions
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index 2430453..c1e92df 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
68int process_arguments (int, char **); 65int process_arguments (int, char **);
@@ -106,6 +103,7 @@ int check_critical_time = FALSE;
106int verbose = 0; 103int verbose = 0;
107int use_ssl = FALSE; 104int use_ssl = FALSE;
108short use_ehlo = FALSE; 105short use_ehlo = FALSE;
106short use_lhlo = FALSE;
109short ssl_established = 0; 107short ssl_established = 0;
110char *localhostname = NULL; 108char *localhostname = NULL;
111int sd; 109int 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)
763int 776int
764my_close (void) 777my_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