svn commit: trunk/busybox: include networking

vda at busybox.net vda at busybox.net
Sat Feb 2 17:54:36 UTC 2008


Author: vda
Date: 2008-02-02 09:54:35 -0800 (Sat, 02 Feb 2008)
New Revision: 20931

Log:
sendmail: fixes by Vladimir Dronnikov <dronnikov at gmail.com>



Modified:
   trunk/busybox/include/usage.h
   trunk/busybox/networking/sendmail.c


Changeset:
Modified: trunk/busybox/include/usage.h
===================================================================
--- trunk/busybox/include/usage.h	2008-02-02 16:43:51 UTC (rev 20930)
+++ trunk/busybox/include/usage.h	2008-02-02 17:54:35 UTC (rev 20931)
@@ -3135,26 +3135,28 @@
 #define selinuxenabled_full_usage
 
 #define sendmail_trivial_usage \
-       "[-d] {-t to}+ [-f from] [-n[notify]] [-s subject] [-b file]*\n" \
-       "[-a attachment]* [-c charset] [-w timeout] [-h server] [-p port] [-U user] [-P password]"
+       "{-t to}+ {-f from} [-n[notify]] [-s subject] [-b file]*\n" \
+       "[-a attachment]* [-c charset]" \
+       USE_FEATURE_SENDMAIL_NETWORK("\n" \
+       " [-d] [-w timeout] [-h server] [-p port] [-U user] [-P password]" \
+       )
 #define sendmail_full_usage \
-       "Send an email from to with subject and optional attachments.\n" \
-       "Body is read from stdin or from optional files" \
+       "Send an email <from> <to> with <subject> and optional attachments." \
        "\n\nArguments:\n" \
-       "	-d		Just dump composed message\n" \
        "	-t to		Recipient email. May be multiple\n" \
-       "	-f from		Sender email\n" \
+       "	-f from		Sender address\n" \
        "	-n[notify]	Optional notification address. If just -n given then notifies the sender\n" \
        "	-s subject	Optional subject\n" \
        "	-b filename	Optional body content file. May be multiple\n" \
        "	-a filename	Optional file attachment. May be multiple\n" \
        "	-c charset	Assumed charset for body and subject [koi8-r]" \
        USE_FEATURE_SENDMAIL_NETWORK("\n" \
+       "	-d		Just dump composed message\n" \
        "	-w timeout	Set timeout on network operations\n" \
        "	-h server	Optional mail server name or IP [127.0.0.1]\n" \
        "	-p port		Optional mail server port [25]\n" \
        "	-U username	Authenticate using AUTH LOGIN with specified username\n" \
-       "	-P password	Authenticate using AUTH LOGIN with specified password"\
+       "	-P password	Authenticate using AUTH LOGIN with specified password" \
        )
 
 #define seq_trivial_usage \

Modified: trunk/busybox/networking/sendmail.c
===================================================================
--- trunk/busybox/networking/sendmail.c	2008-02-02 16:43:51 UTC (rev 20930)
+++ trunk/busybox/networking/sendmail.c	2008-02-02 17:54:35 UTC (rev 20931)
@@ -16,47 +16,48 @@
 	DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
 };
 
-static void uuencode(const char *fname)
+static void uuencode(char *fname, const char *text)
 {
+#define src_buf text
 	int fd;
-	char src_buf[SRC_BUF_SIZE];
-	char dst_buf[1 + DST_BUF_SIZE + 1];
+#define len fd
+	char dst_buf[DST_BUF_SIZE + 1];
 
-	fd = xopen(fname, O_RDONLY);
-	fflush(stdout);
-	dst_buf[0] = '\n';
+	if (fname) {
+		fd = xopen(fname, O_RDONLY);
+		src_buf = bb_common_bufsiz1;
+	} else {
+		len = strlen(text);
+	}
+
+	fflush(stdout); // sync stdio and unistd output
 	while (1) {
-		size_t size = full_read(fd, src_buf, SRC_BUF_SIZE);
+		size_t size;
+		if (fname) {
+			size = full_read(fd, (char *)src_buf, SRC_BUF_SIZE);
+			if ((ssize_t)size < 0)
+				bb_perror_msg_and_die(bb_msg_read_error);
+		} else {
+			size = len;
+			if (len > SRC_BUF_SIZE)
+				size = SRC_BUF_SIZE;
+		}
 		if (!size)
 			break;
-		if ((ssize_t)size < 0)
-			bb_perror_msg_and_die(bb_msg_read_error);
-		/* Encode the buffer we just read in */
-		bb_uuencode(dst_buf + 1, src_buf, size, bb_uuenc_tbl_base64);
-		xwrite(STDOUT_FILENO, dst_buf, 1 + 4 * ((size + 2) / 3));
+		// Encode the buffer we just read in
+		bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
+		if (fname) {
+			xwrite(STDOUT_FILENO, "\n", 1);
+		} else {
+			src_buf += size;
+			len -= size;
+		}
+		xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3));
 	}
-	close(fd);
+	if (ENABLE_FEATURE_CLEAN_UP && fname)
+		close(fd);
 }
 
-// "inline" version
-// encodes content of given buffer instead of fd
-// used to encode subject and authentication terms
-static void uuencode_inline(const char *src_buf)
-{
-	size_t len;
-	char dst_buf[DST_BUF_SIZE + 1];
-
-	len = strlen(src_buf);
-	fflush(stdout);
-	while (len > 0) {
-		size_t chunk = (len <= SRC_BUF_SIZE) ? len : SRC_BUF_SIZE;
-		bb_uuencode(dst_buf, src_buf, chunk, bb_uuenc_tbl_base64);
-		xwrite(STDOUT_FILENO, dst_buf, 4 * ((chunk + 2) / 3));
-		src_buf += chunk;
-		len -= chunk;
-	}
-}
-
 #if ENABLE_FEATURE_SENDMAIL_NETWORK
 // generic signal handler
 static void signal_handler(int signo)
@@ -72,7 +73,7 @@
 			bb_error_msg_and_die("child exited (%d)", WEXITSTATUS(err));
 }
 
-static pid_t helper_pid = -1;
+static pid_t helper_pid;
 
 // read stdin, parses first bytes to a number, i.e. server response
 // if code = -1 then just return this number
@@ -92,7 +93,7 @@
 			return n;
 		}
 	}
-	// TODO!!!: is there more elegant way to terminate child on program failure?
+	// TODO: is there more elegant way to terminate child on program failure?
 	if (helper_pid > 0)
 		kill(helper_pid, SIGTERM);
 	if (!answer)
@@ -104,9 +105,24 @@
 
 static int puts_and_check(const char *msg, int code, const char *errmsg)
 {
-	puts(msg);
+	printf("%s\r\n", msg);
 	return check(code, errmsg);
 }
+
+// strip argument of bad chars
+static char *sane(char *str)
+{
+	char *s = str;
+	char *p = s;
+	while (*s) {
+		if (isalnum(*s) || '_' == *s || '-' == *s || '.' == *s || '@' == *s) {
+			*p++ = *s;
+		}
+		s++;
+	}
+	*p = '\0';
+	return str;
+}
 #endif
 
 int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -115,10 +131,10 @@
 	llist_t *recipients = NULL;
 	llist_t *bodies = NULL;
 	llist_t *attachments = NULL;
-	const char *from;
-	const char *notify;
+	char *from;
+	char *notify = NULL;
 	const char *subject;
-	const char *charset = "utf-8";
+	char *charset = (char*)"utf-8";
 #if ENABLE_FEATURE_SENDMAIL_NETWORK
 	const char *wsecs = "10";
 	const char *server = "127.0.0.1";
@@ -133,6 +149,7 @@
 		OPT_f = 1 << 0,         // sender
 		OPT_n = 1 << 2,         // notification
 		OPT_s = 1 << 3,         // subject given
+		OPT_c = 1 << 6,         // charset
 		OPT_d = 1 << 7,         // dry run - no networking
 		OPT_w = 1 << 8,         // network timeout
 		OPT_h = 1 << 9,         // server
@@ -152,10 +169,11 @@
 	//argc -= optind;
 	argv += optind;
 
-//printf("OPTS[%4x]\n", opts);
+	// sanitize user input
+	sane(from);
+	if (opts & OPT_c)
+		sane(charset);
 
-	// TODO!!!: strip recipients and sender from <>
-
 	// establish connection
 #if ENABLE_FEATURE_SENDMAIL_NETWORK
 	timeout = xatou(wsecs);
@@ -167,24 +185,24 @@
 				bb_error_msg_and_die("no password");
 			}
 		}
-//printf("OPTS[%4x][%s][%s]\n", opts, opt_user, opt_pass);
-//exit(0);
 		// set chat timeout
 		alarm(timeout);
 		// connect to server
 		if (argv[0]) {
 			// if connection helper given
 			// setup vanilla unidirectional pipes interchange
+			int idx;
 			int pipes[4];
 			xpipe(pipes);
 			xpipe(pipes+2);
 			helper_pid = vfork();
 			if (helper_pid < 0)
 				bb_perror_msg_and_die("vfork");
-			xdup2(pipes[(helper_pid)?0:2], STDIN_FILENO);
-			xdup2(pipes[(helper_pid)?3:1], STDOUT_FILENO);
+			idx = (!helper_pid)*2;
+			xdup2(pipes[idx], STDIN_FILENO);
+			xdup2(pipes[3-idx], STDOUT_FILENO);
 			if (ENABLE_FEATURE_CLEAN_UP)
-				for (int i = 4; --i >= 0; )
+				for (int i = 4; --i >= 0;)
 					if (pipes[i] > STDOUT_FILENO)
 						close(pipes[i]);
 			// replace child with connection helper
@@ -210,10 +228,12 @@
 			check(220, "INIT");
 		}
 		// mail user specified? try modern AUTHentication
-		if (opt_user && (334 == puts_and_check("auth login", -1, "auth login"))) {
-			uuencode_inline(opt_user);
+		if ((opts & OPT_U)
+		 && (334 == puts_and_check("auth login", -1, "auth login"))
+		) {
+			uuencode(NULL, opt_user);
 			puts_and_check("", 334, "AUTH");
-			uuencode_inline(opt_pass);
+			uuencode(NULL, opt_pass);
 			puts_and_check("", 235, "AUTH");
 		// no mail user specified or modern AUTHentication is not supported?
 		} else {
@@ -224,15 +244,15 @@
 				domain++;
 			else
 				domain = "local";
-			printf("helo %s\n", domain);
+			printf("helo %s\r\n", domain);
 			check(250, "HELO");
 		}
 
 		// set addresses
-		printf("mail from:<%s>\n", from);
+		printf("mail from:<%s>\r\n", from);
 		check(250, "MAIL FROM");
 		for (llist_t *to = recipients; to; to = to->link) {
-			printf("rcpt to:<%s>\n", to->data);
+			printf("rcpt to:<%s>\r\n", sane(to->data));
 			check(250, "RCPT TO");
 		}
 		puts_and_check("data", 354, "DATA");
@@ -243,60 +263,64 @@
 
 	// now put message
 	// put address headers
-	printf("From: %s\n", from);
+	printf("From: %s\r\n", from);
 	for (llist_t *to = recipients; to; to = to->link) {
-		printf("To: %s\n", to->data);
+		printf("To: %s\r\n", sane(to->data));
 	}
 	// put encoded subject
 	if (opts & OPT_s) {
 		printf("Subject: =?%s?B?", charset);
-		uuencode_inline(subject);
-		puts("?=");
+		uuencode(NULL, subject);
+		puts("?=\r");
 	}
 	// put notification
 	if (opts & OPT_n) {
-		const char *s = notify;
-		if (!s[0])
-			s = from; // notify sender by default
-		printf("Disposition-Notification-To: %s\n", s);
+		// -n without parameter?
+		if (!notify)
+			notify = from; // notify sender by default
+		printf("Disposition-Notification-To: %s\r\n", sane(notify));
 	}
 	// put common headers and body start
 	//srand(?);
 	boundary = xasprintf("%d-%d-%d", rand(), rand(), rand());
 	printf(
-		"X-Mailer: busybox " BB_VER " sendmail\n"
-		"X-Priority: 3\n"
-		"Message-ID: <%s>\n"
-		"Mime-Version: 1.0\n"
-		"Content-Type: multipart/mixed; boundary=\"%s\"\n"
-		"\n"
-		"--%s\n"
-		"Content-Type: text/plain; charset=%s\n"
-		"%s\n%s"
-		, boundary, boundary, boundary, charset
+		"X-Mailer: busybox " BB_VER " sendmail\r\n"
+		"Message-ID: <%s>\r\n"
+		"Mime-Version: 1.0\r\n"
+		"%smultipart/mixed; boundary=\"%s\"\r\n"
+		"\r\n"
+		"--%s\r\n"
+		"%stext/plain; charset=%s\r\n"
+		"%s\r\n%s"
+		, boundary
+		, "Content-Type: "
+		, boundary, boundary
+		, "Content-Type: "
+		, charset
 		, "Content-Disposition: inline"
-		, "Content-Transfer-Encoding: base64\n"
+		, "Content-Transfer-Encoding: base64\r\n"
 	);
 	// put body(ies)
 	for (llist_t *f = bodies; f; f = f->link) {
-		uuencode(f->data);
+		uuencode(f->data, NULL);
 	}
 	// put attachment(s)
 	for (llist_t *f = attachments; f; f = f->link) {
 		printf(
-			"\n--%s\n"
-			"Content-Type: application/octet-stream\n"
-			"%s; filename=\"%s\"\n"
+			"\r\n--%s\r\n"
+			"%sapplication/octet-stream\r\n"
+			"%s; filename=\"%s\"\r\n"
 			"%s"
 			, boundary
+			, "Content-Type: "
 			, "Content-Disposition: inline"
 			, bb_get_last_path_component_strip(f->data)
-			, "Content-Transfer-Encoding: base64\n"
+			, "Content-Transfer-Encoding: base64\r\n"
 		);
-		uuencode(f->data);
+		uuencode(f->data, NULL);
 	}
 	// put terminator
-	printf("\n--%s--\n\n", boundary);
+	printf("\r\n--%s--\r\n\r\n", boundary);
 	if (ENABLE_FEATURE_CLEAN_UP)
 		free(boundary);
 




More information about the busybox-cvs mailing list