X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=plugins%2Fcheck_smtp.c;h=a7a07838f9b10f5d08063467045b5f27f0aeaf25;hb=c134205981203c7a6908f5ae1e3ca297bac83876;hp=e99f0675f86e0a175d9e6c6e5a2089eabedb7580;hpb=b51ab1c0696fb6abdd1c8f5d2c47bba9ae4118b2;p=nagiosplug.git diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c index e99f067..a7a0783 100644 --- a/plugins/check_smtp.c +++ b/plugins/check_smtp.c @@ -1,26 +1,43 @@ /****************************************************************************** - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ - +* +* Nagios check_smtp plugin +* +* License: GPL +* Copyright (c) 1999-2006 nagios-plugins team +* +* Last Modified: $Date$ +* +* Description: +* +* This file contains the check_smtp plugin +* +* This plugin will attempt to open an SMTP connection with the host. +* +* +* License Information: +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* +* $Id$ +* ******************************************************************************/ const char *progname = "check_smtp"; const char *revision = "$Revision$"; -const char *copyright = "2000-2004"; +const char *copyright = "2000-2006"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" @@ -59,8 +76,7 @@ void print_help (void); void print_usage (void); int my_close(void); -#ifdef HAVE_REGEX_H -#include +#include "regex.h" char regex_expect[MAX_INPUT_BUFFER] = ""; regex_t preg; regmatch_t pmatch[10]; @@ -69,7 +85,6 @@ char errbuf[MAX_INPUT_BUFFER]; int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; int eflags = 0; int errcode, excode; -#endif int server_port = SMTP_PORT; char *server_address = NULL; @@ -154,9 +169,8 @@ main (int argc, char **argv) int result = STATE_UNKNOWN; char *cmd_str = NULL; char *helocmd = NULL; - char *error_msg = NULL; + char *error_msg = ""; struct timeval tv; - struct hostent *hp; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -165,7 +179,7 @@ main (int argc, char **argv) if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); - /* initialize the HELO command with the localhostname */ + /* If localhostname not set on command line, use gethostname to set */ if(! localhostname){ localhostname = malloc (HOST_MAX_BYTES); if(!localhostname){ @@ -176,16 +190,14 @@ main (int argc, char **argv) printf(_("gethostname() failed!\n")); return STATE_CRITICAL; } - hp = gethostbyname(localhostname); - if(!hp) helocmd = localhostname; - else helocmd = hp->h_name; - } else { - helocmd = localhostname; } if(use_ehlo) - asprintf (&helocmd, "%s%s%s", SMTP_EHLO, helocmd, "\r\n"); + asprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n"); else - asprintf (&helocmd, "%s%s%s", SMTP_HELO, helocmd, "\r\n"); + asprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n"); + + if (verbose) + printf("HELOCMD: %s", helocmd); /* initialize the MAIL command with optional FROM command */ asprintf (&cmd_str, "%sFROM: %s%s", mail_command, from_arg, "\r\n"); @@ -270,11 +282,40 @@ main (int argc, char **argv) } else { ssl_established = 1; } + + /* + * Resend the EHLO command. + * + * RFC 3207 (4.2) says: ``The client MUST discard any knowledge + * obtained from the server, such as the list of SMTP service + * extensions, which was not obtained from the TLS negotiation + * itself. The client SHOULD send an EHLO command as the first + * command after a successful TLS negotiation.'' For this + * reason, some MTAs will not allow an AUTH LOGIN command before + * we resent EHLO via TLS. + */ + if (my_send(helocmd, strlen(helocmd)) <= 0) { + printf("%s\n", _("SMTP UNKNOWN - Cannot send EHLO command via TLS.")); + my_close(); + return STATE_UNKNOWN; + } + if (verbose) + printf(_("sent %s"), helocmd); + if ((n = my_recv(buffer, MAX_INPUT_BUFFER - 1)) <= 0) { + printf("%s\n", _("SMTP UNKNOWN - Cannot read EHLO response via TLS.")); + my_close(); + return STATE_UNKNOWN; + } + if (verbose) { + buffer[n] = '\0'; + printf("%s", buffer); + } + # ifdef USE_OPENSSL if ( check_cert ) { result = np_net_ssl_check_cert(days_till_exp); if(result != STATE_OK){ - printf (_("CRITICAL - Cannot retrieve server certificate.\n")); + printf ("%s\n", _("CRITICAL - Cannot retrieve server certificate.")); } my_close(); return result; @@ -308,7 +349,6 @@ main (int argc, char **argv) printf("%s", buffer); strip (buffer); if (n < nresponses) { -#ifdef HAVE_REGEX_H cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; errcode = regcomp (&preg, responses[n], cflags); if (errcode != 0) { @@ -329,12 +369,6 @@ main (int argc, char **argv) printf (_("Execute Error: %s\n"), errbuf); result = STATE_UNKNOWN; } -#else - if (strstr(buffer, responses[n])!=buffer) { - result = STATE_WARNING; - printf (_("SMTP %s - Invalid response '%s' to command '%s'\n"), state_text (result), buffer, commands[n]); - } -#endif } n++; } @@ -346,12 +380,12 @@ main (int argc, char **argv) do { if (authuser == NULL) { result = STATE_CRITICAL; - error_msg = _("no authuser specified, "); + asprintf(&error_msg, _("no authuser specified, ")); break; } if (authpass == NULL) { result = STATE_CRITICAL; - error_msg = _("no authpass specified, "); + asprintf(&error_msg, _("no authpass specified, ")); break; } @@ -361,7 +395,7 @@ main (int argc, char **argv) printf (_("sent %s\n"), "AUTH LOGIN"); if((ret = my_recv(buffer, MAXBUF - 1)) < 0){ - error_msg = _("recv() failed after AUTH LOGIN, \n"); + asprintf(&error_msg, _("recv() failed after AUTH LOGIN, ")); result = STATE_WARNING; break; } @@ -371,7 +405,7 @@ main (int argc, char **argv) if (strncmp (buffer, "334", 3) != 0) { result = STATE_CRITICAL; - error_msg = _("invalid response received after AUTH LOGIN, "); + asprintf(&error_msg, _("invalid response received after AUTH LOGIN, ")); break; } @@ -384,7 +418,7 @@ main (int argc, char **argv) if ((ret = my_recv(buffer, MAX_INPUT_BUFFER-1)) == -1) { result = STATE_CRITICAL; - error_msg = _("recv() failed after sending authuser, "); + asprintf(&error_msg, _("recv() failed after sending authuser, ")); break; } buffer[ret] = 0; @@ -393,7 +427,7 @@ main (int argc, char **argv) } if (strncmp (buffer, "334", 3) != 0) { result = STATE_CRITICAL; - error_msg = _("invalid response received after authuser, "); + asprintf(&error_msg, _("invalid response received after authuser, ")); break; } /* encode authpass with base64 */ @@ -405,7 +439,7 @@ main (int argc, char **argv) } if ((ret = my_recv(buffer, MAX_INPUT_BUFFER-1)) == -1) { result = STATE_CRITICAL; - error_msg = _("recv() failed after sending authpass, "); + asprintf(&error_msg, _("recv() failed after sending authpass, ")); break; } buffer[ret] = 0; @@ -414,14 +448,14 @@ main (int argc, char **argv) } if (strncmp (buffer, "235", 3) != 0) { result = STATE_CRITICAL; - error_msg = _("invalid response received after authpass, "); + asprintf(&error_msg, _("invalid response received after authpass, ")); break; } break; } while (0); } else { result = STATE_CRITICAL; - error_msg = _("only authtype LOGIN is supported, "); + asprintf(&error_msg, _("only authtype LOGIN is supported, ")); } } @@ -447,7 +481,7 @@ main (int argc, char **argv) printf (_("SMTP %s - %s%.3f sec. response time%s%s|%s\n"), state_text (result), - (error_msg == NULL ? "" : error_msg), + error_msg, elapsed_time, verbose?", ":"", verbose?buffer:"", fperfdata ("time", elapsed_time, "s", @@ -548,22 +582,26 @@ process_arguments (int argc, char **argv) break; case 'C': /* commands */ if (ncommands >= command_size) { - commands = realloc (commands, command_size+8); + command_size+=8; + commands = realloc (commands, sizeof(char *) * command_size); if (commands == NULL) die (STATE_UNKNOWN, _("Could not realloc() units [%d]\n"), ncommands); } - commands[ncommands] = optarg; + commands[ncommands] = (char *) malloc (sizeof(char) * 255); + strncpy (commands[ncommands], optarg, 255); ncommands++; break; case 'R': /* server responses */ if (nresponses >= response_size) { - responses = realloc (responses, response_size+8); + response_size += 8; + responses = realloc (responses, sizeof(char *) * response_size); if (responses == NULL) die (STATE_UNKNOWN, _("Could not realloc() units [%d]\n"), nresponses); } - responses[nresponses] = optarg; + responses[nresponses] = (char *) malloc (sizeof(char) * 255); + strncpy (responses[nresponses], optarg, 255); nresponses++; break; case 'c': /* critical time threshold */ @@ -628,7 +666,7 @@ process_arguments (int argc, char **argv) print_help (); exit (STATE_OK); case '?': /* help */ - usage2 (_("Unknown argument"), optarg); + usage5 (); } } @@ -666,6 +704,15 @@ validate_arguments (void) } +int +my_close (void) +{ +#ifdef HAVE_SSL + np_net_ssl_cleanup(); +#endif + return close(sd); +} + void print_help (void) @@ -678,7 +725,9 @@ print_help (void) printf ("Copyright (c) 1999-2001 Ethan Galstad \n"); printf (COPYRIGHT, copyright, email); - printf(_("This plugin will attempt to open an SMTP connection with the host.\n\n")); + printf("%s\n", _("This plugin will attempt to open an SMTP connection with the host.")); + + printf ("\n\n"); print_usage (); @@ -688,34 +737,29 @@ print_help (void) printf (_(UT_IPv46)); - printf (_("\ - -e, --expect=STRING\n\ - String to expect in first line of server response (default: '%s')\n\ - -n, nocommand\n\ - Suppress SMTP command\n\ - -C, --command=STRING\n\ - SMTP command (may be used repeatedly)\n\ - -R, --command=STRING\n\ - Expected response to command (may be used repeatedly)\n\ - -f, --from=STRING\n\ - FROM-address to include in MAIL command, required by Exchange 2000\n"), - SMTP_EXPECT); + printf (" %s\n", "-e, --expect=STRING"); + printf (_(" String to expect in first line of server response (default: '%s')\n"), SMTP_EXPECT); + printf (" %s\n", "-n, nocommand"); + printf (" %s\n", _("Suppress SMTP command")); + printf (" %s\n", "-C, --command=STRING"); + printf (" %s\n", _("SMTP command (may be used repeatedly)")); + printf (" %s\n", "-R, --command=STRING"); + printf (" %s\n", _("Expected response to command (may be used repeatedly)")); + printf (" %s\n", "-f, --from=STRING"); + printf (" %s\n", _("FROM-address to include in MAIL command, required by Exchange 2000")), #ifdef HAVE_SSL - printf (_("\ - -D, --certificate=INTEGER\n\ - Minimum number of days a certificate has to be valid.\n\ - -S, --starttls\n\ - Use STARTTLS for the connection.\n")); + printf (" %s\n", "-D, --certificate=INTEGER"); + printf (" %s\n", _("Minimum number of days a certificate has to be valid.")); + printf (" %s\n", "-S, --starttls"); + printf (" %s\n", _("Use STARTTLS for the connection.")); #endif - printf("\ - -A, --authtype=STRING\n\ - SMTP AUTH type to check (default none, only LOGIN supported)\n\ - -U, --authuser=STRING\n\ - SMTP AUTH username\n\ - -P, --authpass=STRING\n\ - SMTP AUTH password\n\ - "); + printf (" %s\n", "-A, --authtype=STRING"); + printf (" %s\n", _("SMTP AUTH type to check (default none, only LOGIN supported)")); + printf (" %s\n", "-U, --authuser=STRING"); + printf (" %s\n", _("SMTP AUTH username")); + printf (" %s\n", "-P, --authpass=STRING"); + printf (" %s\n", _("SMTP AUTH password")); printf (_(UT_WARN_CRIT)); @@ -723,11 +767,11 @@ print_help (void) printf (_(UT_VERBOSE)); - printf(_("\n\ -Successul connects return STATE_OK, refusals and timeouts return\n\ -STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful\n\ -connects, but incorrect reponse messages from the host result in\n\ -STATE_WARNING return values.\n")); + printf("\n"); + printf ("%s\n", _("Successul connects return STATE_OK, refusals and timeouts return")); + printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful")); + printf ("%s\n", _("connects, but incorrect reponse messages from the host result in")); + printf ("%s\n", _("STATE_WARNING return values.")); printf (_(UT_SUPPORT)); } @@ -737,17 +781,9 @@ STATE_WARNING return values.\n")); void print_usage (void) { - printf ("\ -Usage: %s -H host [-p port] [-e expect] [-C command] [-f from addr]\n\ - [-A authtype -U authuser -P authpass]\n\ - [-w warn] [-c crit] [-t timeout] [-S] [-D days] [-n] [-v] [-4|-6]\n", progname); + printf (_("Usage:")); + printf ("%s -H host [-p port] [-e expect] [-C command] [-f from addr]", progname); + printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout]\n"); + printf ("[-S] [-D days] [-n] [-v] [-4|-6]\n"); } -int -my_close (void) -{ -#ifdef HAVE_SSL - np_net_ssl_cleanup(); -#endif - return close(sd); -}