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);
 }