Index: ChangeLog
===================================================================
--- ChangeLog	(revision 2331)
+++ ChangeLog	(working copy)
@@ -1,3 +1,12 @@
+2006-10-18  Rob Buis <r.buis@ic-s.nl>
+
+	* misc.h, misc.c:
+	Backport dm_shellesc function from 2.1.
+
+	* forward.c:
+	Use dm_shellesc to escape the from and to strings that are being
+	fed to sendmail using popen.
+
 2006-10-06  Aaron Stone  <aaron@serendipity.cx>
 
 	* dbsearch.c:
Index: forward.c
===================================================================
--- forward.c	(revision 2331)
+++ forward.c	(working copy)
@@ -48,6 +48,8 @@
 {
 	struct element *target = NULL;
 	char *command = NULL;
+	char *escaped_from = NULL;
+	char *escaped_to = NULL;
 	size_t command_len = 0;
 	FILE *pipe = NULL;
 	int err;
@@ -95,10 +97,24 @@
 			/* skip the pipe (|) sign */
 			strncpy(command, (char *) (target->data) + 1, command_len);
 		} else {
+			escaped_from = dm_shellesc(from);
+			if (!escaped_from) {
+				trace(TRACE_ERROR,
+				      "%s,%s: out of memory",
+				      __FILE__, __func__);
+				return -1;
+			}
+			escaped_to = dm_shellesc((char *) (target->data));
+			if (!escaped_to) {
+				trace(TRACE_ERROR,
+				      "%s,%s: out of memory",
+				      __FILE__, __func__);
+				return -1;
+			}
 			/* pipe to sendmail */
 			command_len = strlen(sendmail) + strlen(" -f ") +
-				strlen(from) + strlen (" ") +
-				strlen((char *) (target->data)) + 1;
+				strlen(escaped_from) + strlen (" ") +
+				strlen(escaped_to) + 1;
 			command = dm_malloc(command_len * sizeof(char));
 			if (!command) {
 				trace(TRACE_ERROR,
@@ -110,8 +126,7 @@
 			trace(TRACE_DEBUG,
 			      "%s,%s: allocated memory for external "
 			      "command call", __FILE__, __func__);
-			snprintf(command, command_len, "%s -f %s %s", sendmail, from, 
-				(char *) (target->data));
+			snprintf(command, command_len, "%s -f %s %s", sendmail, escaped_from, escaped_to);
 		}
 
 		trace(TRACE_INFO, "%s,%s: opening pipe to command %s",
Index: misc.c
===================================================================
--- misc.c	(revision 2331)
+++ misc.c	(working copy)
@@ -491,3 +491,64 @@
 		return 0;
 	}
 }
+
+/* Following the advice of:
+ * "Secure Programming for Linux and Unix HOWTO"
+ * Chapter 8: Carefully Call Out to Other Resources */
+char *dm_shellesc(const char * command)
+{
+        char *safe_command; 
+        int pos, end, len;
+
+        // These are the potentially unsafe characters:
+        // & ; ` ' \ " | * ? ~ < > ^ ( ) [ ] { } $ \n \r
+        // # ! \t \ (space)
+
+        len = strlen(command);
+        if (!(safe_command = dm_calloc((len + 1) * 2 + 1, sizeof(char))))
+                return NULL;
+
+        for (pos = end = 0; pos < len; pos++) {
+                switch (command[pos]) {
+                case '&':
+                case ';':
+                case '`':
+                case '\'':
+case '\\':
+                case '"':
+                case '|':
+                case '*':
+                case '?':
+                case '~':
+                case '<':
+                case '>':
+                case '^':
+                case '(':
+                case ')':
+                case '[':
+                case ']':
+                case '{':
+                case '}':
+                case '$':
+                case '\n':
+                case '\r':
+                case '\t':
+                case ' ':
+                case '#':
+                case '!':
+                        // Add an escape before the offending char.
+                        safe_command[end++] = '\\';
+                default:
+                        // And then put in the character itself.
+                        safe_command[end++] = command[pos];
+                        break;
+                }
+        }
+
+        /* The string is already initialized,
+         * but let's be extra double sure. */
+        safe_command[end] = '\0';
+
+        return safe_command;
+}
+
Index: misc.h
===================================================================
--- misc.h	(revision 2331)
+++ misc.h	(working copy)
@@ -107,5 +107,6 @@
 		 size_t * retsize, size_t * retlast);
 int base64_grow_ret(char ***inchar, size_t ** inint, size_t newcount,
 		    size_t newchar);
+char *dm_shellesc(const char * command);
 
 #endif
