--- check_smtp-cvs.c 2003-07-31 19:02:23.000000000 -0500 +++ check_smtp.c 2003-07-31 19:02:07.000000000 -0500 @@ -33,6 +33,7 @@ const char *option_summary = "\ -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] [-n] [-v] [-4|-6]"; const char *options = "\ @@ -53,6 +54,12 @@ -f, --from=STRING\n\ FROM-address to include in MAIL command, required by Exchange 2000\n\ (default: '%s')\n\ + -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\ -w, --warning=INTEGER\n\ Seconds necessary to result in a warning status\n\ -c, --critical=INTEGER\n\ @@ -89,12 +96,80 @@ int smtp_use_dummycmd = 1; char *mail_command = "MAIL "; 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 = 0; +/* 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) { @@ -104,6 +179,7 @@ char buffer[MAX_INPUT_BUFFER] = ""; char *from_str = NULL; char *helocmd = NULL; + char *error_msg = NULL; struct timeval tv; if (process_arguments (argc, argv) != OK) @@ -163,7 +239,97 @@ /* 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) { + char abuf[MAX_INPUT_BUFFER]; + unsigned alen; + int ret; + do { + if (authuser == NULL) { + result = STATE_CRITICAL; + error_msg = "no authuser specified"; + break; + } + if (authpass == NULL) { + result = STATE_CRITICAL; + error_msg = "no authpass specified"; + break; + } + 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_CRITICAL; + error_msg = "recv() failed after AUTH LOGIN"; + break; + } + buffer[ret] = 0; + if (verbose == TRUE) { + printf ("received %s\n", buffer); + } + if (strncmp (buffer, "334", 3) != 0) { + result = STATE_CRITICAL; + error_msg = "invalid response received after AUTH LOGIN"; + break; + } + if (encode64 (authuser, strlen(authuser), abuf, MAX_INPUT_BUFFER, &alen) != OK) { + result = STATE_CRITICAL; + error_msg = "failed to base64-encode authuser"; + 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_CRITICAL; + error_msg = "recv() failed after sending authuser"; + break; + } + buffer[ret] = 0; + if (verbose == TRUE) { + printf ("received %s\n", buffer); + } + if (strncmp (buffer, "334", 3) != 0) { + result = STATE_CRITICAL; + error_msg = "invalid response received after authuser"; + break; + } + if (encode64 (authpass, strlen(authpass), abuf, MAX_INPUT_BUFFER, &alen) != OK) { + result = STATE_CRITICAL; + error_msg = "failed to base64-encode authpass"; + 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_CRITICAL; + error_msg = "recv() failed after sending authpass"; + break; + } + buffer[ret] = 0; + if (verbose == TRUE) { + printf ("received %s\n", buffer); + } + if (strncmp (buffer, "235", 3) != 0) { + result = STATE_CRITICAL; + error_msg = "invalid response received after authpass"; + break; + } + break; + } while (0); + } else { + result = STATE_CRITICAL; + error_msg = "only authtype LOGIN is supported"; + } + } + /* sendmail will syslog a "NOQUEUE" error if session does not attempt * to do something useful. This can be prevented by giving a command * even if syntax is illegal (MAIL requires a FROM:<...> argument) @@ -204,11 +370,21 @@ result = STATE_WARNING; if (verbose) - printf ("SMTP %s - %.3f sec. response time, %s|time=%.3f\n", - state_text (result), elapsed_time, buffer, elapsed_time); + if (error_msg == NULL) { + printf ("SMTP %s - %.3f sec. response time, %s|time=%.3f\n", + state_text (result), elapsed_time, buffer, elapsed_time); + } else { + printf ("SMTP %s - %s, %.3f sec. response time, %s|time=%.3f\n", + state_text (result), error_msg, elapsed_time, buffer, elapsed_time); + } else - printf ("SMTP %s - %.3f second response time|time=%.3f\n", - state_text (result), elapsed_time, elapsed_time); + if (error_msg == NULL) { + printf ("SMTP %s - %.3f second response time|time=%.3f\n", + state_text (result), elapsed_time, elapsed_time); + } else { + printf ("SMTP %s - %s, %.3f second response time|time=%.3f\n", + state_text (result), error_msg, elapsed_time, elapsed_time); + } return result; } @@ -233,6 +409,9 @@ {"timeout", required_argument, 0, 't'}, {"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'}, {"command", required_argument, 0, 'C'}, {"nocommand", required_argument, 0, 'n'}, {"verbose", no_argument, 0, 'v'}, @@ -256,7 +435,7 @@ } while (1) { - c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:", + c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:A:U:P:", long_options, &option_index); if (c == -1 || c == EOF) @@ -282,6 +461,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;