Index: check_smtp.c =================================================================== RCS file: /usr/local/cvs/root/nagios-plugins/plugins/check_smtp.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- check_smtp.c 3 Jul 2003 23:27:44 -0000 1.1.1.1 +++ check_smtp.c 3 Jul 2003 23:35:52 -0000 1.2 @@ -69,12 +69,80 @@ char *server_address = NULL; char *server_expect = NULL; char *from_arg = " "; +char *authtype = NULL; +char *authuser = NULL; +char *authpass = NULL; int warning_time = 0; int check_warning_time = FALSE; int critical_time = 0; int check_critical_time = FALSE; int verbose = FALSE; +/* encode64 routine from http://www.experts-exchange.com/Programming/Programming_Languages/C/Q_20245582.html */ + +/* #define OK (0) */ +/* #define FAIL (-1) */ +#define BUFOVER (-2) +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) +static char basis_64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????"; +static char index_64[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 +}; + +static int +encode64(const char *_in, unsigned inlen, char *_out, unsigned outmax, unsigned *outlen) +{ + + const unsigned char *in = (const unsigned char *) _in; + unsigned char *out = (unsigned char *) _out; + unsigned char oval; + char *blah; + unsigned olen; + + olen = (inlen + 2) / 3 * 4; + if (outlen) + *outlen = olen; + if (outmax < olen) + return BUFOVER; + + blah = (char *) out; + while (inlen >= 3) + { +/* user provided max buffer size; make sure we don't go over it */ + *out++ = basis_64[in[0] >> 2]; + *out++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)]; + *out++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; + *out++ = basis_64[in[2] & 0x3f]; + in += 3; + inlen -= 3; + } + if (inlen > 0) + { +/* user provided max buffer size; make sure we don't go over it */ + *out++ = basis_64[in[0] >> 2]; + oval = (in[0] << 4) & 0x30; + if (inlen > 1) + oval |= in[1] >> 4; + *out++ = basis_64[oval]; + *out++ = (inlen < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c]; + *out++ = '='; + } + + if (olen < outmax) + *out = '\0'; + + return OK; + +} + int main (int argc, char **argv) { @@ -151,14 +219,19 @@ && (end_time - start_time) > warning_time) result = STATE_WARNING; - if (verbose == TRUE) - printf ("SMTP %s - %d sec. response time, %s\n", + if (authtype == NULL) { + if (verbose == TRUE) + printf ("SMTP %s - %d sec. response time, %s\n", state_text (result), (int) (end_time - start_time), buffer); - else - printf ("SMTP %s - %d second response time\n", state_text (result), + else + printf ("SMTP %s - %d second response time\n", state_text (result), (int) (end_time - start_time)); + } } } + } + + if (result == STATE_OK) { /* close the connection */ @@ -168,6 +241,112 @@ /* allow for response to helo command to reach us */ recv(sd, buffer, MAX_INPUT_BUFFER-1, 0); + if (authtype != NULL) { + if (strcmp (authtype, "LOGIN") == 0) { + if (authuser == NULL) { + result = STATE_CRITICAL; + printf ("SMTP %s - no authuser specified\n", state_text (result)); + } else if (authpass == NULL) { + result = STATE_CRITICAL; + printf ("SMTP %s - no authpass specified\n", state_text (result)); + } else { + char abuf[MAX_INPUT_BUFFER]; + unsigned alen; + int ret; + do { + send(sd, "AUTH LOGIN\r\n", strlen("AUTH LOGIN\r\n"), 0); + if (verbose == TRUE) { + printf ("sent AUTH LOGIN\n"); + } + if ((ret = recv(sd, buffer, MAX_INPUT_BUFFER-1, 0)) == -1) { + result = STATE_WARNING; + printf ("SMTP %s - recv() failed after AUTH LOGIN\n", + state_text (result)); + break; + } + buffer[ret] = 0; + if (verbose == TRUE) { + printf ("received %s\n", buffer); + } + if (strncmp (buffer, "334", 3) != 0) { + result = STATE_CRITICAL; + printf ("SMTP %s - Invalid response received from host after AUTH LOGIN\n", + state_text (result)); + break; + } + if (encode64 (authuser, strlen(authuser), abuf, MAX_INPUT_BUFFER, &alen) != OK) { + result = STATE_WARNING; + printf ("SMTP %s - Failed to base64-encode authuser\n", + state_text (result)); + break; + } + strcat (abuf, "\r\n"); + send(sd, abuf, strlen(abuf), 0); + if (verbose == TRUE) { + printf ("sent %s\n", abuf); + } + if ((ret = recv(sd, buffer, MAX_INPUT_BUFFER-1, 0)) == -1) { + result = STATE_WARNING; + printf ("SMTP %s - recv() failed after sending authuser\n", + state_text (result)); + break; + } + buffer[ret] = 0; + if (verbose == TRUE) { + printf ("received %s\n", buffer); + } + if (strncmp (buffer, "334", 3) != 0) { + result = STATE_CRITICAL; + printf ("SMTP %s - Invalid response received from host after authuser\n", + state_text (result)); + break; + } + if (encode64 (authpass, strlen(authpass), abuf, MAX_INPUT_BUFFER, &alen) != OK) { + result = STATE_WARNING; + printf ("SMTP %s - Failed to base64-encode authpass\n", + state_text (result)); + break; + } + strcat (abuf, "\r\n"); + send(sd, abuf, strlen(abuf), 0); + if (verbose == TRUE) { + printf ("sent %s\n", abuf); + } + if ((ret = recv(sd, buffer, MAX_INPUT_BUFFER-1, 0)) == -1) { + result = STATE_WARNING; + printf ("SMTP %s - recv() failed after sending authpass\n", + state_text (result)); + break; + } + buffer[ret] = 0; + if (verbose == TRUE) { + printf ("received %s\n", buffer); + } + if (strncmp (buffer, "235", 3) != 0) { + result = STATE_CRITICAL; + printf ("SMTP %s - Invalid response received from host after authpass\n", + state_text (result)); + break; + } + break; + } while (0); + if (result == STATE_OK) { + if (verbose == TRUE) + printf ("SMTP %s - %d sec. response time, %s\n", + state_text (result), (int) (end_time - start_time), buffer); + else + printf ("SMTP %s - %d second response time\n", state_text (result), + (int) (end_time - start_time)); + } + } + } else { + result = STATE_CRITICAL; + printf ("SMTP %s - authtype %s is not supported\n", state_text (result), authtype); + } + } + } + + if (result == STATE_OK) { #ifdef SMTP_USE_DUMMYCMD send(sd, from_str, strlen(from_str), 0); @@ -211,6 +390,9 @@ {"warning", required_argument, 0, 'w'}, {"port", required_argument, 0, 'p'}, {"from", required_argument, 0, 'f'}, + {"authtype", required_argument, 0, 'A'}, + {"authuser", required_argument, 0, 'U'}, + {"authpass", required_argument, 0, 'P'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, @@ -233,10 +415,10 @@ while (1) { #ifdef HAVE_GETOPT_H c = - getopt_long (argc, argv, "+hVvt:p:f:e:c:w:H:", long_options, + getopt_long (argc, argv, "+hVvt:p:f:e:c:w:H:A:U:P:", long_options, &option_index); #else - c = getopt (argc, argv, "+?hVvt:p:f:e:c:w:H:"); + c = getopt (argc, argv, "+?hVvt:p:f:e:c:w:H:A:U:P:"); #endif if (c == -1 || c == EOF) break; @@ -261,6 +443,15 @@ case 'f': /* from argument */ from_arg = optarg; break; + case 'A': + authtype = optarg; + break; + case 'U': + authuser = optarg; + break; + case 'P': + authpass = optarg; + break; case 'e': /* server expect string on 220 */ server_expect = optarg; break; @@ -355,6 +546,12 @@ " String to expect in first line of server response (default: %s)\n" " -f, --from=STRING\n" " from address to include in MAIL command (default NULL, Exchange2000 requires one)\n" + " -A, --authtype=STRING\n" + " SMTP AUTH type to check (default NULL, only LOGIN supported)\n" + " -U, --authuser=STRING\n" + " SMTP AUTH username\n" + " -P, --authpass=STRING\n" + " SMTP AUTH password\n" " -w, --warning=INTEGER\n" " Seconds necessary to result in a warning status\n" " -c, --critical=INTEGER\n" @@ -379,7 +576,7 @@ print_usage (void) { printf - ("Usage: %s -H host [-e expect] [-p port] [-f from addr] [-w warn] [-c crit] [-t timeout] [-v]\n" + ("Usage: %s -H host [-e expect] [-p port] [-A authtype -U authuser -P authpass] [-f from addr] [-w warn] [-c crit] [-t timeout] [-v]\n" " %s --help\n" " %s --version\n", progname, progname, progname); }