[Mimedefang] Useful patch ? [PATCH] tcpwrappers support for mimedefang

Martin Blapp mb at imp.ch
Sun Jul 18 02:33:11 EDT 2004


Hi all,

We else is using mimedefang on a different server than the running
sendmail ? Is this patch useful for you ? Please mail to the list
if you definitly want this :-)

Martin

-----------------------------------------------------------------------
Add tcpwrappers support:

Fix a security problem which is present in ALL other milters
using tcpwrappers ! If the hostname or the adress of the
remote sendmail are retrieved via sendmail macros if_name/if_addr
or via milter callback, we may get a local configured IP back which
is not official. Everybody can then set up a internal ipalias which
can be abused to gain access to the milter.

To get the remote IP-adresses of the caller we have to use the
filedescriptor of the connection. All other attempts can simply
be spoofed. fromhost() calls getpeername() and get's the ip back.
This saves us a call to gethostbyname() too, which is not yet threadsafe
in FreeBSD.

--- configure.in.orig	Thu Jul 15 19:30:04 2004
+++ configure.in	Sat Jul 17 00:24:27 2004
@@ -256,6 +256,62 @@
     fi
 fi

+# tcpwrappers support
+# rules from http://ma.ph-freiburg.de/tng/tng-technical/2002-01/msg00094.html
+AC_ARG_WITH(tcpwrappers,
+[  --with-tcpwrappers      Support hosts.allow / hosts.deny (default=auto)],
+[ case "$withval" in
+  yes|no) tcpw="$withval" ;;
+  *)      AC_MSG_ERROR([--with-tcpwrappers does not take an argument]) ;;
+  esac],
+[ tcpw=auto ])
+
+if test $tcpw != no ; then
+        AC_CHECK_HEADERS(tcpd.h,[
+                AC_MSG_CHECKING([for TCP wrappers library])
+                save_LIBS="$LIBS"
+                LIBS="$LIBS -lwrap"
+                AC_TRY_LINK([
+#include <tcpd.h>
+int allow_severity = 0;
+int deny_severity  = 0;
+
+struct request_info *req;
+                ],[
+hosts_access(req)
+                ],[AC_MSG_RESULT([-lwrap])
+                have_wrappers=yes
+                LIBS="$save_LIBS"
+                LIBS="$LIBS -lwrap"],[
+                dnl try with -lnsl
+                LIBS="$LIBS -lnsl"
+                AC_TRY_LINK([
+#include <tcpd.h>
+int allow_severity = 0;
+int deny_severity  = 0;
+
+struct request_info *req;
+                ],[
+hosts_access(req)
+                ],[AC_MSG_RESULT([-lwrap -lnsl])
+                have_wrappers=yes
+                LIBS="$LIBS -lwrap"],[
+                AC_MSG_RESULT(no)
+                have_wrappers=no
+                LIBS=$save_LIBS])],[
+                have_wrappers=no])],[have_wrappers=no])
+
+        if test $have_wrappers = yes ; then
+		OLDCFLAGS="$CFLAGS"
+                AC_DEFINE(WITH_TCPWRAP,1, [tcpwrappers support])
+		CFLAGS="$CFLAGS -DWITH_TCPWRAP"
+        elif test $tcpw = yes ; then
+                AC_MSG_ERROR([could not find TCP wrappers])
+        else
+                AC_MSG_WARN([could not find TCP wrappers, support disabled])
+        fi
+fi
+
 dnl Check if "setlogsock('unix')" works
 AC_MSG_CHECKING([if setlogsock('unix') works])
 echo "use Sys::Syslog qw(:DEFAULT setlogsock); exit(0) if (defined(setlogsock('unix'))); exit(1);" | $PERL > /dev/null 2>&1
--- mimedefang.c.orig	Wed Jun 23 14:38:43 2004
+++ mimedefang.c	Sun Jul 18 01:29:35 2004
@@ -79,6 +79,14 @@
 #define DEBUG(x) (void) 0
 #endif

+#ifdef  WITH_TCPWRAP
+#include <tcpd.h>
+
+int     allow_severity = LOG_DEBUG;
+int     deny_severity = LOG_NOTICE;
+
+#endif
+
 extern int find_syslog_facility(char const *facility_name);

 #define DEBUG_ENTER(func, line) DEBUG(syslog(LOG_DEBUG, "Entering %s (line %d)", func, line))
@@ -138,6 +146,18 @@
     unsigned char filterFailed; /* Filter failed */
 };

+#ifdef WITH_TCPWRAP
+/*
+ * These are hidden structs from milter.h which is not public
+ * available. We only need access to ctx_sd, so we skip the rest.
+ */
+struct smfi_str
+{
+        pthread_t       ctx_id;         /* thread id */
+        int		ctx_sd;         /* socket descriptor */
+};
+#endif /* WITH_TCPWRAP */
+
 static void write_macro_value(SMFICTX *ctx,
 			      char *macro);

@@ -164,6 +184,9 @@
 /* Mutex to protect mkdir() calls */
 static pthread_mutex_t MkdirMutex = PTHREAD_MUTEX_INITIALIZER;

+/* Mutex to protect hosts_allow() calls */
+static pthread_mutex_t AllowMutex = PTHREAD_MUTEX_INITIALIZER;
+
 /* Do relay check? */
 static int doRelayCheck = 0;

@@ -362,6 +385,34 @@
 #endif

     DEBUG_ENTER("mfconnect", __LINE__);
+
+#ifdef WITH_TCPWRAP
+/*
+ * Support for TCP-wrappers by mb at imp.ch 2004
+ *
+ * To get the remote IP-adresses of the caller we
+ * have to use the filedescriptor of the connection. All
+ * other attempts can simply be spoofed. fromhost() calls
+ * getpeername() and get's the ip back. This saves us a
+ * call to gethostbyname() too, which is not yet threadsafe
+ * in FreeBSD.
+ */
+    {
+	struct request_info req;
+	int sd;
+
+	sd = ctx->ctx_sd;
+	request_init(&req, RQ_DAEMON, "mimedefang", RQ_FILE, sd, 0);
+        pthread_mutex_lock(&AllowMutex);
+	fromhost(&req);
+	if (!hosts_access(&req)) {
+		pthread_mutex_unlock(&AllowMutex);
+		syslog(LOG_WARNING, "Access denied by tcp wrapper");
+		return SMFIS_TEMPFAIL;
+	}
+    	pthread_mutex_unlock(&AllowMutex);
+    }
+#endif

     /* Delete any existing context data */
     mfclose(ctx);



More information about the MIMEDefang mailing list