From e969b3efc6deac4d8dee2eec02e0d69902420c9b Mon Sep 17 00:00:00 2001 From: SJ Date: Mon, 29 Oct 2012 10:22:31 +0100 Subject: [PATCH] added tcp_wrappers support to the piler daemon --- configure | 128 ++++++++++++++++++++++++++++++++++++++++++++++ configure.in | 24 +++++++++ piler-config.h.in | 2 + src/config.h | 4 +- src/defs.h | 3 ++ src/piler.c | 12 ++--- src/pilerexport.c | 10 ++-- src/reindex.c | 4 +- src/session.c | 14 +++++ src/smtpcodes.h | 1 + 10 files changed, 187 insertions(+), 15 deletions(-) diff --git a/configure b/configure index 8260b344..0859f5f1 100755 --- a/configure +++ b/configure @@ -676,6 +676,7 @@ enable_static_build enable_clamd enable_memcached enable_starttls +enable_tcpwrappers with_piler_user ' ac_precious_vars='build_alias @@ -1300,6 +1301,7 @@ Optional Features: --enable-clamd build clamd antivirus support --enable-memcached build memcached support --enable-starttls build starttls support + --enable-tcpwrappers build tcpwrappers support Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -3417,6 +3419,7 @@ have_tre="no" have_zip="no" have_zlib="no" have_starttls="no" +have_tcpwrappers="no" pdftotext="no" catdoc="no" @@ -3497,6 +3500,118 @@ fi +# Check whether --enable-tcpwrappers was given. +if test "${enable_tcpwrappers+set}" = set; then : + enableval=$enable_tcpwrappers; want_tcpwrappers=$enableval +else + want_tcpwrappers"no" +fi + + + +if test "$want_tcpwrappers" = "yes"; then + for ac_header in tcpd.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "tcpd.h" "ac_cv_header_tcpd_h" "$ac_includes_default" +if test "x$ac_cv_header_tcpd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_TCPD_H 1 +_ACEOF + have_tcpwrappers=yes +else + have_tcpwrappers=no +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hosts_access in -lwrap" >&5 +$as_echo_n "checking for hosts_access in -lwrap... " >&6; } +if ${ac_cv_lib_wrap_hosts_access+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwrap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char hosts_access (); +int +main () +{ +return hosts_access (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_wrap_hosts_access=yes +else + ac_cv_lib_wrap_hosts_access=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wrap_hosts_access" >&5 +$as_echo "$ac_cv_lib_wrap_hosts_access" >&6; } +if test "x$ac_cv_lib_wrap_hosts_access" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hosts_access in -lwrap" >&5 +$as_echo_n "checking for hosts_access in -lwrap... " >&6; } +if ${ac_cv_lib_wrap_hosts_access+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwrap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char hosts_access (); +int +main () +{ +return hosts_access (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_wrap_hosts_access=yes +else + ac_cv_lib_wrap_hosts_access=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wrap_hosts_access" >&5 +$as_echo "$ac_cv_lib_wrap_hosts_access" >&6; } +if test "x$ac_cv_lib_wrap_hosts_access" = xyes; then : + have_tcpwrappers=yes +else + echo "libwrap is not found"; have_tcpwrappers=no +fi + +fi +ac_cv_lib_wrap=ac_cv_lib_wrap_main + + if test "$have_tcpwrappers" = "no"; then + echo "can't find either tcpd.h or libwrap"; + exit 1; + fi +fi + for ac_header in math.h @@ -4361,6 +4476,19 @@ _ACEOF fi +if test "$have_tcpwrappers" = "yes"; then + echo "tcpwrappers support: yes" + +cat >>confdefs.h <<_ACEOF +#define HAVE_LIBWRAP 1 +_ACEOF + + antispam_libs="$antispam_libs -lwrap -lnsl" +else + echo "tcpwrappers support: no" +fi + + echo if test "$have_clamd" = "yes"; then diff --git a/configure.in b/configure.in index 6f8cf1f2..7a9978dd 100644 --- a/configure.in +++ b/configure.in @@ -41,6 +41,7 @@ have_tre="no" have_zip="no" have_zlib="no" have_starttls="no" +have_tcpwrappers="no" pdftotext="no" catdoc="no" @@ -104,6 +105,20 @@ AC_ARG_ENABLE(starttls, [ --enable-starttls build starttls support], have_starttls=$enableval, have_starttls="no") +AC_ARG_ENABLE(tcpwrappers, + [ --enable-tcpwrappers build tcpwrappers support], want_tcpwrappers=$enableval, want_tcpwrappers"no") + + +if test "$want_tcpwrappers" = "yes"; then + AC_CHECK_HEADERS(tcpd.h, have_tcpwrappers=yes, have_tcpwrappers=no) + AC_CHECK_LIB([wrap],[hosts_access],[AC_CHECK_LIB(wrap, hosts_access, have_tcpwrappers=yes, echo "libwrap is not found"; have_tcpwrappers=no)],[],[])ac_cv_lib_wrap=ac_cv_lib_wrap_main + + if test "$have_tcpwrappers" = "no"; then + echo "can't find either tcpd.h or libwrap"; + exit 1; + fi +fi + dnl math library @@ -289,6 +304,15 @@ if test "$have_starttls" = "yes"; then AC_DEFINE_UNQUOTED(HAVE_STARTTLS, 1, [starttls support]) fi +if test "$have_tcpwrappers" = "yes"; then + echo "tcpwrappers support: yes" + AC_DEFINE_UNQUOTED(HAVE_LIBWRAP, 1, [tcpwrappers support]) + antispam_libs="$antispam_libs -lwrap -lnsl" +else + echo "tcpwrappers support: no" +fi + + echo if test "$have_clamd" = "yes"; then diff --git a/piler-config.h.in b/piler-config.h.in index 0bbe3fa6..01cc644c 100644 --- a/piler-config.h.in +++ b/piler-config.h.in @@ -18,3 +18,5 @@ #undef HAVE_ZIP #undef HAVE_STARTTLS +#undef HAVE_LIBWRAP + diff --git a/src/config.h b/src/config.h index 82c8f23b..96324abf 100644 --- a/src/config.h +++ b/src/config.h @@ -11,9 +11,9 @@ #define PROGNAME "piler" -#define VERSION "0.1.21" +#define VERSION "0.1.22" -#define BUILD 722 +#define BUILD 723 #define HOSTID "mailarchiver" diff --git a/src/defs.h b/src/defs.h index 0ea9c7a1..0b92a80a 100644 --- a/src/defs.h +++ b/src/defs.h @@ -22,6 +22,9 @@ #include #include #endif +#ifdef HAVE_LIBWRAP + #include +#endif #include #include diff --git a/src/piler.c b/src/piler.c index d36fef7a..f29cb196 100644 --- a/src/piler.c +++ b/src/piler.c @@ -47,7 +47,7 @@ static void child_main(struct child *ptr); static pid_t child_make(struct child *ptr); int search_slot_by_pid(pid_t pid); void kill_children(int sig); -void clean_exit(); +void p_clean_exit(); void fatal(char *s); void initialise_configuration(); @@ -85,7 +85,7 @@ static void takesig(int sig){ case SIGTERM: case SIGKILL: quit = 1; - clean_exit(); + p_clean_exit(); break; case SIGCHLD: @@ -206,7 +206,7 @@ int child_pool_create(){ if(children[i].pid == -1){ syslog(LOG_PRIORITY, "error: failed to fork a child"); - clean_exit(); + p_clean_exit(); } } @@ -237,7 +237,7 @@ void kill_children(int sig){ } -void clean_exit(){ +void p_clean_exit(){ if(sd != -1) close(sd); kill_children(SIGTERM); @@ -262,7 +262,7 @@ void clean_exit(){ void fatal(char *s){ syslog(LOG_PRIORITY, "%s\n", s); - clean_exit(); + p_clean_exit(); } @@ -439,7 +439,7 @@ int main(int argc, char **argv){ for(;;){ sleep(1); } - clean_exit(); + p_clean_exit(); return 0; } diff --git a/src/pilerexport.c b/src/pilerexport.c index c0f15744..c7120025 100644 --- a/src/pilerexport.c +++ b/src/pilerexport.c @@ -41,7 +41,7 @@ void usage(){ } -void clean_exit(char *msg, int rc){ +void p_clean_exit(char *msg, int rc){ if(msg) printf("error: %s\n", msg); if(query) free(query); @@ -207,7 +207,7 @@ int main(int argc, char **argv){ if(regcomp(®exp, "^([\\+a-z0-9_\\.@\\-]+)$", REG_ICASE | REG_EXTENDED)){ - clean_exit("cannot compile rule!", 1); + p_clean_exit("cannot compile rule!", 1); } @@ -380,7 +380,7 @@ int main(int argc, char **argv){ rc += append_string_to_buffer(&query, " ORDER BY id ASC"); - if(rc) clean_exit("malloc problem building query", 1); + if(rc) p_clean_exit("malloc problem building query", 1); @@ -388,7 +388,7 @@ int main(int argc, char **argv){ cfg = read_config(configfile); - if(read_key(&cfg)) clean_exit(ERR_READING_KEY, 1); + if(read_key(&cfg)) p_clean_exit(ERR_READING_KEY, 1); init_session_data(&sdata); @@ -397,7 +397,7 @@ int main(int argc, char **argv){ mysql_init(&(sdata.mysql)); mysql_options(&(sdata.mysql), MYSQL_OPT_CONNECT_TIMEOUT, (const char*)&cfg.mysql_connect_timeout); if(mysql_real_connect(&(sdata.mysql), cfg.mysqlhost, cfg.mysqluser, cfg.mysqlpwd, cfg.mysqldb, cfg.mysqlport, cfg.mysqlsocket, 0) == 0){ - clean_exit("cannot connect to mysql server", 1); + p_clean_exit("cannot connect to mysql server", 1); } mysql_real_query(&(sdata.mysql), "SET NAMES utf8", strlen("SET NAMES utf8")); diff --git a/src/reindex.c b/src/reindex.c index 904cbbd8..fb3c2034 100644 --- a/src/reindex.c +++ b/src/reindex.c @@ -34,7 +34,7 @@ void usage(){ } -void clean_exit(char *msg, int rc){ +void p_clean_exit(char *msg, int rc){ if(msg) printf("error: %s\n", msg); exit(rc); @@ -188,7 +188,7 @@ int main(int argc, char **argv){ mysql_init(&(sdata.mysql)); mysql_options(&(sdata.mysql), MYSQL_OPT_CONNECT_TIMEOUT, (const char*)&cfg.mysql_connect_timeout); if(mysql_real_connect(&(sdata.mysql), cfg.mysqlhost, cfg.mysqluser, cfg.mysqlpwd, cfg.mysqldb, cfg.mysqlport, cfg.mysqlsocket, 0) == 0){ - clean_exit("cannot connect to mysql server", 1); + p_clean_exit("cannot connect to mysql server", 1); } mysql_real_query(&(sdata.mysql), "SET NAMES utf8", strlen("SET NAMES utf8")); diff --git a/src/session.c b/src/session.c index 5f1a9b31..4524d141 100644 --- a/src/session.c +++ b/src/session.c @@ -38,6 +38,20 @@ int handle_smtp_session(int new_sd, struct __data *data, struct __config *cfg){ char ssl_error[SMALLBUFSIZE]; #endif + +#ifdef HAVE_LIBWRAP + struct request_info req; + + request_init(&req, RQ_DAEMON, PROGNAME, RQ_FILE, new_sd, 0); + fromhost(&req); + if(!hosts_access(&req)){ + send(new_sd, SMTP_RESP_550_ERR_YOU_ARE_BANNED_BY_LOCAL_POLICY, strlen(SMTP_RESP_550_ERR_YOU_ARE_BANNED_BY_LOCAL_POLICY), 0); + syslog(LOG_PRIORITY, "denied connection from %s by tcp_wrappers", eval_client(&req)); + return 0; + } +#endif + + state = SMTP_STATE_INIT; init_session_data(&sdata); diff --git a/src/smtpcodes.h b/src/smtpcodes.h index b5c425b8..130136bb 100644 --- a/src/smtpcodes.h +++ b/src/smtpcodes.h @@ -52,6 +52,7 @@ #define SMTP_RESP_550_ERR_PREF "550 Access denied." #define SMTP_RESP_550_INVALID_RECIPIENT "550 Unknown recipient\r\n" #define SMTP_RESP_550_ERR_TOO_LONG_RCPT_TO "550 too long recipient\r\n" +#define SMTP_RESP_550_ERR_YOU_ARE_BANNED_BY_LOCAL_POLICY "550 You are banned by local policy\r\n" #define SMTP_RESP_552_ERR "552 Too many recipients\r\n"