--- 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 +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 +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 Mon Nov 29 17:10:43 2004 +++ mimedefang.c Mon Nov 29 17:11:31 2004 @@ -85,6 +85,12 @@ #endif extern int find_syslog_facility(char const *facility_name); +#ifdef WITH_TCPWRAP +#include +int allow_severity = LOG_DEBUG; +int deny_severity = LOG_NOTICE; +#endif + #define DEBUG_ENTER(func, line) DEBUG(syslog(LOG_DEBUG, "Entering %s (line %d)", func, line)) #define DEBUG_EXIT(func, line, ret) DEBUG(syslog(LOG_DEBUG, "Exiting %s (line %d) ret=%s", func, line, ret)) @@ -148,6 +154,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); @@ -174,6 +192,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; @@ -375,6 +396,35 @@ #endif DEBUG_ENTER("mfconnect", __LINE__); + +#ifdef WITH_TCPWRAP +/* + * Support for TCP-wrappers by mb@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"); + mfclose(ctx); + return SMFIS_TEMPFAIL; + } + pthread_mutex_unlock(&AllowMutex); + } +#endif /* Delete any existing context data */ mfclose(ctx);