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.c95
1 files changed, 50 insertions, 45 deletions
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index 494bc2c..a861a71 100644
--- a/plugins/check_smtp.c
+++ b/plugins/check_smtp.c
@@ -41,7 +41,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
41 41
42#ifdef HAVE_SSL 42#ifdef HAVE_SSL
43int check_cert = FALSE; 43int check_cert = FALSE;
44int days_till_exp; 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_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_ssl && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
47#else /* ifndef HAVE_SSL */ 47#else /* ifndef HAVE_SSL */
@@ -87,9 +87,9 @@ int errcode, excode;
87int server_port = SMTP_PORT; 87int server_port = SMTP_PORT;
88char *server_address = NULL; 88char *server_address = NULL;
89char *server_expect = NULL; 89char *server_expect = NULL;
90int smtp_use_dummycmd = 0;
91char *mail_command = NULL; 90char *mail_command = NULL;
92char *from_arg = NULL; 91char *from_arg = NULL;
92int send_mail_from=0;
93int ncommands=0; 93int ncommands=0;
94int command_size=0; 94int command_size=0;
95int nresponses=0; 95int nresponses=0;
@@ -156,17 +156,17 @@ main (int argc, char **argv)
156 } 156 }
157 } 157 }
158 if(use_ehlo) 158 if(use_ehlo)
159 asprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n"); 159 xasprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n");
160 else 160 else
161 asprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n"); 161 xasprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n");
162 162
163 if (verbose) 163 if (verbose)
164 printf("HELOCMD: %s", helocmd); 164 printf("HELOCMD: %s", helocmd);
165 165
166 /* initialize the MAIL command with optional FROM command */ 166 /* initialize the MAIL command with optional FROM command */
167 asprintf (&cmd_str, "%sFROM: %s%s", mail_command, from_arg, "\r\n"); 167 xasprintf (&cmd_str, "%sFROM:<%s>%s", mail_command, from_arg, "\r\n");
168 168
169 if (verbose && smtp_use_dummycmd) 169 if (verbose && send_mail_from)
170 printf ("FROM CMD: %s", cmd_str); 170 printf ("FROM CMD: %s", cmd_str);
171 171
172 /* initialize alarm signal handling */ 172 /* initialize alarm signal handling */
@@ -275,7 +275,7 @@ main (int argc, char **argv)
275 275
276# ifdef USE_OPENSSL 276# ifdef USE_OPENSSL
277 if ( check_cert ) { 277 if ( check_cert ) {
278 result = np_net_ssl_check_cert(days_till_exp); 278 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
279 my_close(); 279 my_close();
280 return result; 280 return result;
281 } 281 }
@@ -283,23 +283,14 @@ main (int argc, char **argv)
283 } 283 }
284#endif 284#endif
285 285
286 /* sendmail will syslog a "NOQUEUE" error if session does not attempt 286 if (send_mail_from) {
287 * to do something useful. This can be prevented by giving a command
288 * even if syntax is illegal (MAIL requires a FROM:<...> argument)
289 *
290 * According to rfc821 you can include a null reversepath in the from command
291 * - but a log message is generated on the smtp server.
292 *
293 * Use the -f option to provide a FROM address
294 */
295 if (smtp_use_dummycmd) {
296 my_send(cmd_str, strlen(cmd_str)); 287 my_send(cmd_str, strlen(cmd_str));
297 if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose) 288 if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose)
298 printf("%s", buffer); 289 printf("%s", buffer);
299 } 290 }
300 291
301 while (n < ncommands) { 292 while (n < ncommands) {
302 asprintf (&cmd_str, "%s%s", commands[n], "\r\n"); 293 xasprintf (&cmd_str, "%s%s", commands[n], "\r\n");
303 my_send(cmd_str, strlen(cmd_str)); 294 my_send(cmd_str, strlen(cmd_str));
304 if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose) 295 if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose)
305 printf("%s", buffer); 296 printf("%s", buffer);
@@ -336,12 +327,12 @@ main (int argc, char **argv)
336 do { 327 do {
337 if (authuser == NULL) { 328 if (authuser == NULL) {
338 result = STATE_CRITICAL; 329 result = STATE_CRITICAL;
339 asprintf(&error_msg, _("no authuser specified, ")); 330 xasprintf(&error_msg, _("no authuser specified, "));
340 break; 331 break;
341 } 332 }
342 if (authpass == NULL) { 333 if (authpass == NULL) {
343 result = STATE_CRITICAL; 334 result = STATE_CRITICAL;
344 asprintf(&error_msg, _("no authpass specified, ")); 335 xasprintf(&error_msg, _("no authpass specified, "));
345 break; 336 break;
346 } 337 }
347 338
@@ -351,7 +342,7 @@ main (int argc, char **argv)
351 printf (_("sent %s\n"), "AUTH LOGIN"); 342 printf (_("sent %s\n"), "AUTH LOGIN");
352 343
353 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) { 344 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) {
354 asprintf(&error_msg, _("recv() failed after AUTH LOGIN, ")); 345 xasprintf(&error_msg, _("recv() failed after AUTH LOGIN, "));
355 result = STATE_WARNING; 346 result = STATE_WARNING;
356 break; 347 break;
357 } 348 }
@@ -360,21 +351,20 @@ main (int argc, char **argv)
360 351
361 if (strncmp (buffer, "334", 3) != 0) { 352 if (strncmp (buffer, "334", 3) != 0) {
362 result = STATE_CRITICAL; 353 result = STATE_CRITICAL;
363 asprintf(&error_msg, _("invalid response received after AUTH LOGIN, ")); 354 xasprintf(&error_msg, _("invalid response received after AUTH LOGIN, "));
364 break; 355 break;
365 } 356 }
366 357
367 /* encode authuser with base64 */ 358 /* encode authuser with base64 */
368 base64_encode_alloc (authuser, strlen(authuser), &abuf); 359 base64_encode_alloc (authuser, strlen(authuser), &abuf);
369 /* FIXME: abuf shouldn't have enough space to strcat a '\r\n' into it. */ 360 xasprintf(&abuf, "%s\r\n", abuf);
370 strcat (abuf, "\r\n");
371 my_send(abuf, strlen(abuf)); 361 my_send(abuf, strlen(abuf));
372 if (verbose) 362 if (verbose)
373 printf (_("sent %s\n"), abuf); 363 printf (_("sent %s\n"), abuf);
374 364
375 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) { 365 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) {
376 result = STATE_CRITICAL; 366 result = STATE_CRITICAL;
377 asprintf(&error_msg, _("recv() failed after sending authuser, ")); 367 xasprintf(&error_msg, _("recv() failed after sending authuser, "));
378 break; 368 break;
379 } 369 }
380 if (verbose) { 370 if (verbose) {
@@ -382,20 +372,19 @@ main (int argc, char **argv)
382 } 372 }
383 if (strncmp (buffer, "334", 3) != 0) { 373 if (strncmp (buffer, "334", 3) != 0) {
384 result = STATE_CRITICAL; 374 result = STATE_CRITICAL;
385 asprintf(&error_msg, _("invalid response received after authuser, ")); 375 xasprintf(&error_msg, _("invalid response received after authuser, "));
386 break; 376 break;
387 } 377 }
388 /* encode authpass with base64 */ 378 /* encode authpass with base64 */
389 base64_encode_alloc (authpass, strlen(authpass), &abuf); 379 base64_encode_alloc (authpass, strlen(authpass), &abuf);
390 /* FIXME: abuf shouldn't have enough space to strcat a '\r\n' into it. */ 380 xasprintf(&abuf, "%s\r\n", abuf);
391 strcat (abuf, "\r\n");
392 my_send(abuf, strlen(abuf)); 381 my_send(abuf, strlen(abuf));
393 if (verbose) { 382 if (verbose) {
394 printf (_("sent %s\n"), abuf); 383 printf (_("sent %s\n"), abuf);
395 } 384 }
396 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) { 385 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) {
397 result = STATE_CRITICAL; 386 result = STATE_CRITICAL;
398 asprintf(&error_msg, _("recv() failed after sending authpass, ")); 387 xasprintf(&error_msg, _("recv() failed after sending authpass, "));
399 break; 388 break;
400 } 389 }
401 if (verbose) { 390 if (verbose) {
@@ -403,14 +392,14 @@ main (int argc, char **argv)
403 } 392 }
404 if (strncmp (buffer, "235", 3) != 0) { 393 if (strncmp (buffer, "235", 3) != 0) {
405 result = STATE_CRITICAL; 394 result = STATE_CRITICAL;
406 asprintf(&error_msg, _("invalid response received after authpass, ")); 395 xasprintf(&error_msg, _("invalid response received after authpass, "));
407 break; 396 break;
408 } 397 }
409 break; 398 break;
410 } while (0); 399 } while (0);
411 } else { 400 } else {
412 result = STATE_CRITICAL; 401 result = STATE_CRITICAL;
413 asprintf(&error_msg, _("only authtype LOGIN is supported, ")); 402 xasprintf(&error_msg, _("only authtype LOGIN is supported, "));
414 } 403 }
415 } 404 }
416 405
@@ -454,6 +443,7 @@ int
454process_arguments (int argc, char **argv) 443process_arguments (int argc, char **argv)
455{ 444{
456 int c; 445 int c;
446 char* temp;
457 447
458 int option = 0; 448 int option = 0;
459 static struct option longopts[] = { 449 static struct option longopts[] = {
@@ -520,8 +510,9 @@ process_arguments (int argc, char **argv)
520 localhostname = strdup(optarg); 510 localhostname = strdup(optarg);
521 break; 511 break;
522 case 'f': /* from argument */ 512 case 'f': /* from argument */
523 from_arg = optarg; 513 from_arg = optarg + strspn(optarg, "<");
524 smtp_use_dummycmd = 1; 514 from_arg = strndup(from_arg, strcspn(from_arg, ">"));
515 send_mail_from = 1;
525 break; 516 break;
526 case 'A': 517 case 'A':
527 authtype = optarg; 518 authtype = optarg;
@@ -600,12 +591,26 @@ process_arguments (int argc, char **argv)
600 case 'D': 591 case 'D':
601 /* Check SSL cert validity */ 592 /* Check SSL cert validity */
602#ifdef USE_OPENSSL 593#ifdef USE_OPENSSL
603 if (!is_intnonneg (optarg)) 594 if ((temp=strchr(optarg,','))!=NULL) {
604 usage2 ("Invalid certificate expiration period",optarg); 595 *temp='\0';
605 days_till_exp = atoi (optarg); 596 if (!is_intnonneg (temp))
606 check_cert = TRUE; 597 usage2 ("Invalid certificate expiration period", optarg);
598 days_till_exp_warn = atoi(optarg);
599 *temp=',';
600 temp++;
601 if (!is_intnonneg (temp))
602 usage2 (_("Invalid certificate expiration period"), temp);
603 days_till_exp_crit = atoi (temp);
604 }
605 else {
606 days_till_exp_crit=0;
607 if (!is_intnonneg (optarg))
608 usage2 ("Invalid certificate expiration period", optarg);
609 days_till_exp_warn = atoi (optarg);
610 }
611 check_cert = TRUE;
607#else 612#else
608 usage (_("SSL support not available - install OpenSSL and recompile")); 613 usage (_("SSL support not available - install OpenSSL and recompile"));
609#endif 614#endif
610 break; 615 break;
611 case '4': 616 case '4':
@@ -638,7 +643,7 @@ process_arguments (int argc, char **argv)
638 usage2 (_("Invalid hostname/address"), argv[c]); 643 usage2 (_("Invalid hostname/address"), argv[c]);
639 } 644 }
640 else { 645 else {
641 asprintf (&server_address, "127.0.0.1"); 646 xasprintf (&server_address, "127.0.0.1");
642 } 647 }
643 } 648 }
644 649
@@ -771,7 +776,7 @@ void
771print_help (void) 776print_help (void)
772{ 777{
773 char *myport; 778 char *myport;
774 asprintf (&myport, "%d", SMTP_PORT); 779 xasprintf (&myport, "%d", SMTP_PORT);
775 780
776 print_revision (progname, NP_VERSION); 781 print_revision (progname, NP_VERSION);
777 782
@@ -795,14 +800,14 @@ print_help (void)
795 printf (_(" String to expect in first line of server response (default: '%s')\n"), SMTP_EXPECT); 800 printf (_(" String to expect in first line of server response (default: '%s')\n"), SMTP_EXPECT);
796 printf (" %s\n", "-C, --command=STRING"); 801 printf (" %s\n", "-C, --command=STRING");
797 printf (" %s\n", _("SMTP command (may be used repeatedly)")); 802 printf (" %s\n", _("SMTP command (may be used repeatedly)"));
798 printf (" %s\n", "-R, --command=STRING"); 803 printf (" %s\n", "-R, --response=STRING");
799 printf (" %s\n", _("Expected response to command (may be used repeatedly)")); 804 printf (" %s\n", _("Expected response to command (may be used repeatedly)"));
800 printf (" %s\n", "-f, --from=STRING"); 805 printf (" %s\n", "-f, --from=STRING");
801 printf (" %s\n", _("FROM-address to include in MAIL command, required by Exchange 2000")), 806 printf (" %s\n", _("FROM-address to include in MAIL command, required by Exchange 2000")),
802 printf (" %s\n", "-F, --fqdn=STRING"); 807 printf (" %s\n", "-F, --fqdn=STRING");
803 printf (" %s\n", _("FQDN used for HELO")); 808 printf (" %s\n", _("FQDN used for HELO"));
804#ifdef HAVE_SSL 809#ifdef HAVE_SSL
805 printf (" %s\n", "-D, --certificate=INTEGER"); 810 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]");
806 printf (" %s\n", _("Minimum number of days a certificate has to be valid.")); 811 printf (" %s\n", _("Minimum number of days a certificate has to be valid."));
807 printf (" %s\n", "-S, --starttls"); 812 printf (" %s\n", "-S, --starttls");
808 printf (" %s\n", _("Use STARTTLS for the connection.")); 813 printf (" %s\n", _("Use STARTTLS for the connection."));
@@ -838,8 +843,8 @@ void
838print_usage (void) 843print_usage (void)
839{ 844{
840 printf ("%s\n", _("Usage:")); 845 printf ("%s\n", _("Usage:"));
841 printf ("%s -H host [-p port] [-e expect] [-C command] [-f from addr]", progname); 846 printf ("%s -H host [-p port] [-4|-6] [-e expect] [-C command] [-R response] [-f from addr]\n", progname);
842 printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout]\n"); 847 printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout] [-q]\n");
843 printf ("[-F fqdn] [-S] [-D days] [-v] [-4|-6] [-q]\n"); 848 printf ("[-F fqdn] [-S] [-D warn days cert expire[,crit days cert expire]] [-v] \n");
844} 849}
845 850