From 27d1256d331d45bf68d96e9a8aa8175df2584978 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Wed, 25 Feb 2009 22:12:34 +0200 Subject: Check incoming connections using libwrap; various bugfixes. * configure.ac: Check for libwrap. * src/tcpwrap.c: New file. * src/Makefile.am (wydawca_SOURCES): Add tcpwrap.c * src/builtin.c, src/job.c, src/pidfile.c: Minor fixes. * src/config.c (assert_string_arg): Change to extern. (wydawca_kw): New block statement "tcp-wrapper" * src/net.c (wydawca_listener): Check fd using libwrap. * src/triplet.c (DECL_EXPAND_TIMER): Add missing return statement. --- configure.ac | 20 ++++++++++++++ src/Makefile.am | 1 + src/builtin.c | 1 - src/config.c | 10 +++++-- src/job.c | 29 ++++++++++++++------ src/net.c | 45 +++++++++++++++++++------------ src/pidfile.c | 4 +-- src/tcpwrap.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/triplet.c | 2 +- src/wydawca.h | 9 ++++++- 10 files changed, 172 insertions(+), 32 deletions(-) create mode 100644 src/tcpwrap.c diff --git a/configure.ac b/configure.ac index 4f6eaa0..737e2dc 100644 --- a/configure.ac +++ b/configure.ac @@ -87,6 +87,26 @@ WD_CHECK_LIB([gpgme],[main],[], [ AC_MSG_FAILURE([The requested library libgpgme is not found or is unusable])], [/usr/pkg/lib /opt/lib /sw/lib]) +# ********************** +# TCP wrappers +# ********************** +AC_ARG_WITH(tcp-wrappers, + AC_HELP_STRING([--with-tcp-wrappers], + [compile with TCP wrappers support (default)]), + [status_tcpwrap=${withval}], + [status_tcpwrap=yes]) + +if test "$status_tcpwrap" = yes; then + AC_CHECK_LIB(nsl, main) + AC_CHECK_LIB(wrap, main,, [status_tcpwrap=no]) + if test "$status_tcpwrap" = yes; then + AC_CHECK_HEADERS(tcpd.h,,[status_tcpwrap=no]) + fi +fi +if test "$status_tcpwrap" = yes; then + AC_DEFINE_UNQUOTED([WITH_LIBWRAP],1,[Defined if compiling with libwrap]) +fi + # ********************** # Preprocessor # ********************** diff --git a/src/Makefile.am b/src/Makefile.am index fcfdb78..c91669e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,6 +34,7 @@ wydawca_SOURCES=\ process.c\ sql.c\ sql.h\ + tcpwrap.c\ triplet.c\ verify.c\ wydawca.c\ diff --git a/src/builtin.c b/src/builtin.c index 90b7c2f..d70a511 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -183,7 +183,6 @@ builtin_run (struct access_method *meth, void *handle, const char *req) for (i = 0; i < meth->parmc; i++) { char *pat = meth->parmv[i]; - char *val; if (pat[0] == '/') { diff --git a/src/config.c b/src/config.c index bab1ed3..b1f339f 100644 --- a/src/config.c +++ b/src/config.c @@ -216,7 +216,7 @@ string_to_notification_target (gconf_locus_t *locus, const char *val, } -static int +int assert_string_arg (gconf_locus_t *locus, enum gconf_callback_command cmd, const gconf_value_t *value) @@ -1147,7 +1147,6 @@ cb_spool (enum gconf_callback_command cmd, struct spool *spool; void **pdata = cb_data; int rc, ec, i; - const char *ep = NULL; switch (cmd) { @@ -1247,6 +1246,13 @@ static struct gconf_keyword wydawca_kw[] = { { "listen", N_("socket"), N_("Listen on this address"), gconf_type_sockaddr, &listen_sockaddr, }, + +#ifdef WITH_LIBWRAP + { "tcp-wrapper", NULL, N_("Configure TCP wrappers"), + gconf_type_section, NULL, 0, + NULL, NULL, tcpwrapper_kw }, +#endif + { "mailer", N_("url"), N_("Set mailer URL"), gconf_type_string, &mailer, 0, cb_mailer }, { "admin-address", N_("email"), N_("Set admin email address"), diff --git a/src/job.c b/src/job.c index 2c177cb..1baa0af 100644 --- a/src/job.c +++ b/src/job.c @@ -99,7 +99,8 @@ job_start (struct job *job) } if (debug_level) - logmsg (LOG_DEBUG, _("starting job: %s, %lu"), job->spool->tag, job->uid); + logmsg (LOG_DEBUG, _("starting job: %s, %lu"), + job->spool->tag, (unsigned long)job->uid); if (single_process) { @@ -113,6 +114,14 @@ job_start (struct job *job) pid = fork (); if (pid == 0) { + int i; + signal (SIGHUP, SIG_DFL); + signal (SIGTERM, SIG_DFL); + signal (SIGQUIT, SIG_DFL); + signal (SIGINT, SIG_DFL); + signal (SIGCHLD, SIG_DFL); + for (i = getdtablesize (); i > 2; i--) + close (i); exit (wydawca_scanner (job) ? WYDAWCA_EX_AGAIN : 0); } else if (pid == -1) @@ -135,7 +144,8 @@ job_remove (struct job *job) struct job *p; if (debug_level) - logmsg (LOG_DEBUG, _("removing job: %s, %lu"), job->spool->tag, job->uid); + logmsg (LOG_DEBUG, _("removing job: %s, %lu"), + job->spool->tag, (unsigned long)job->uid); p = job->prev; if (p) p->next = job->next; @@ -169,7 +179,7 @@ job_insert (struct job *job, struct job *elt) p->prev = job; } -int +void schedule_job (const struct spool *spool, uid_t uid) { struct job *job; @@ -178,7 +188,8 @@ schedule_job (const struct spool *spool, uid_t uid) spool = &fake_spool; if (debug_level) - logmsg (LOG_DEBUG, _("scheduling job: %s, %lu"), spool->tag, uid); + logmsg (LOG_DEBUG, _("scheduling job: %s, %lu"), + spool->tag, (unsigned long)uid); job = job_locate (spool, uid); if (!job) @@ -230,22 +241,24 @@ print_status (struct job *job, int expect_term) logmsg (prio, _("%lu (%s, %s) terminated on signal %d"), - job->pid, job->spool->tag, pw->pw_name, WTERMSIG (status)); + (unsigned long)job->pid, job->spool->tag, + pw->pw_name, WTERMSIG (status)); } else if (WIFSTOPPED (status)) logmsg (LOG_NOTICE, _("%lu (%s, %s) stopped on signal %d"), - job->pid, job->spool->tag, pw->pw_name, WSTOPSIG (status)); + (unsigned long)job->pid, job->spool->tag, + pw->pw_name, WSTOPSIG (status)); #ifdef WCOREDUMP else if (WCOREDUMP (status)) logmsg (LOG_NOTICE, _("%lu (%s, %s) dumped core"), - job->pid, job->spool->tag, pw->pw_name); + (unsigned long)job->pid, job->spool->tag, pw->pw_name); #endif else logmsg (LOG_ERR, _("%lu (%s, %s) terminated with unrecognized status"), - job->pid, job->spool->tag, pw->pw_name); + (unsigned long)job->pid, job->spool->tag, pw->pw_name); } void diff --git a/src/net.c b/src/net.c index 3874827..25bb4da 100644 --- a/src/net.c +++ b/src/net.c @@ -52,8 +52,7 @@ open_listener () /* FIXME: Check permissions? */ if (!S_ISSOCK (st.st_mode)) { - logmsg (LOG_CRIT, _("%s: not a socket"), - s_un->sun_path, strerror (errno)); + logmsg (LOG_CRIT, _("%s: not a socket"), s_un->sun_path); exit (EX_OSFILE); } unlink (s_un->sun_path); @@ -94,17 +93,17 @@ trim_crlf (char *s) s[--len] = 0; } } - + void -handle_connection (FILE *fp) +handle_connection (FILE *in, FILE *out) { char *buf = NULL; size_t buflen = 0; const struct spool *spool; char *p; struct passwd *pw; - - if (getline (&buf, &buflen, fp) <= 0) + + if (getline (&buf, &buflen, in) <= 0) return; trim_crlf (buf); if (debug_level) @@ -113,20 +112,20 @@ handle_connection (FILE *fp) if (!spool) { if (all_spool_aliases && gl_list_search (all_spool_aliases, buf)) - fprintf (fp, "+ OK, all spools\r\n"); + fprintf (out, "+ OK, all spools\r\n"); else { - fprintf (fp, "- Unknown service name\r\n"); + fprintf (out, "- Unknown service name\r\n"); free (buf); return; } } else if (spool->url) - fprintf (fp, "+ OK, URL %s\r\n", spool->url); + fprintf (out, "+ OK, URL %s\r\n", spool->url); else - fprintf (fp, "+ OK, spool %s\r\n", spool->tag); - - if (getline (&buf, &buflen, fp) <= 0) + fprintf (out, "+ OK, spool %s\r\n", spool->tag); + + if (getline (&buf, &buflen, in) < 0) { logmsg (LOG_ERR, "protocol error"); free (buf); @@ -184,7 +183,7 @@ wydawca_listener () while (!terminate) { int fd; - FILE *fp; + FILE *in, *out; int rc; fd_set rset; struct timeval to, *pto; @@ -223,10 +222,22 @@ wydawca_listener () fd = accept (ctlfd, (struct sockaddr*) &addr, &len); if (fd == -1) continue; - /* FIXME: Check if the connection is allowed */ - fp = fdopen (fd, "r+"); - handle_connection (fp); - fclose (fp); + /* FIXME: Use Mailutils ACLs? */ +#ifdef WITH_LIBWRAP + if (!tcpwrap_access(fd)) + { + close(fd); + continue; + } +#endif + + in = fdopen (fd, "r"); + setlinebuf (in); + out = fdopen (fd, "w"); + setlinebuf (out); + handle_connection (in, out); + fclose (in); + fclose (out); } } diff --git a/src/pidfile.c b/src/pidfile.c index 6da84f1..afbcb87 100644 --- a/src/pidfile.c +++ b/src/pidfile.c @@ -34,7 +34,7 @@ check_pidfile () if (fp) { unsigned long pid; - if (fscanf (fp, "%ul\n", &pid) != 1) + if (fscanf (fp, "%lu\n", &pid) != 1) { logmsg (LOG_ERR, _("malformed pidfile %s"), pidfile); if (!force_startup) @@ -82,7 +82,7 @@ check_pidfile () exit (EX_UNAVAILABLE); } } - fprintf (fp, "%lu\n", getpid ()); + fprintf (fp, "%lu\n", (unsigned long) getpid ()); fclose (fp); atexit (remove_pidfile); } diff --git a/src/tcpwrap.c b/src/tcpwrap.c new file mode 100644 index 0000000..eccf21b --- /dev/null +++ b/src/tcpwrap.c @@ -0,0 +1,83 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff + + Wydawca is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or (at your + option) any later version. + + Wydawca is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with wydawca. If not, see . */ + +#include "wydawca.h" +#include + +#ifdef WITH_LIBWRAP +# include + +static int tcpwrap_enable; +static char *tcpwrap_daemon; +int deny_severity = LOG_INFO; +int allow_severity = LOG_INFO; + +static int +cb_syslog_priority (enum gconf_callback_command cmd, + gconf_locus_t *locus, + void *varptr, + gconf_value_t *value, + void *cb_data) +{ + if (assert_string_arg (locus, cmd, value)) + return 1; + + if (mu_string_to_syslog_priority (value->v.string, varptr)) + gconf_error (locus, 0, _("Unknown syslog priority `%s'"), + value->v.string); + return 0; +} + +struct gconf_keyword tcpwrapper_kw[] = { + { "enable", NULL, + N_("Enable TCP wrapper access control. Default is \"yes\"."), + gconf_type_bool, &tcpwrap_enable }, + { "daemon", N_("name"), + N_("Set daemon name for TCP wrapper lookups. Default is program name."), + gconf_type_string, &tcpwrap_daemon }, + { "allow-table", N_("file"), + N_("Use file for positive client address access control " + "(default: /etc/hosts.allow)."), + gconf_type_string, &hosts_allow_table }, + { "deny-table", N_("file"), + N_("Use file for negative client address access control " + "(default: /etc/hosts.deny)."), + gconf_type_string, &hosts_deny_table }, + { "allow-syslog-priority", N_("prio"), + N_("Log host allows at this syslog priority."), + gconf_type_string, &allow_severity, 0, cb_syslog_priority }, + { "deny-syslog-priority", N_("prio"), + N_("Log host denies at this syslog priority."), + gconf_type_string, &deny_severity, 0, cb_syslog_priority }, + { NULL } +}; + +int +tcpwrap_access(int fd) +{ + struct request_info req; + + if (!tcpwrap_enable) + return 1; + request_init(&req, + RQ_DAEMON, + tcpwrap_daemon ? tcpwrap_daemon : program_name, + RQ_FILE, fd, NULL); + fromhost(&req); + return hosts_access(&req); +} + +#endif diff --git a/src/triplet.c b/src/triplet.c index 285c831..a79d28a 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -566,7 +566,7 @@ __cat2__(expand_timer_,what) (struct metadef *def, void *data) \ { \ wydawca_timer_t t = timer_stop ((char*)def->data); \ def->storage = timer_format_time (__cat2__(timer_get_,what) (t)); \ - def->value = def->storage; \ + return def->value = def->storage; \ } DECL_EXPAND_TIMER(real) diff --git a/src/wydawca.h b/src/wydawca.h index f093504..863200f 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -437,6 +437,8 @@ int parse_time_interval (const char *str, time_t *pint, const char **endp); /* config.c */ void config_init (void); void config_help (void); +int assert_string_arg (gconf_locus_t *, enum gconf_callback_command, + const gconf_value_t *); /* vtab.c */ @@ -505,7 +507,7 @@ extern char *report_string; /* job.c */ -int schedule_job (const struct spool *spool, uid_t uid); +void schedule_job (const struct spool *spool, uid_t uid); void job_init (void); void job_queue_runner (void); @@ -529,3 +531,8 @@ char *wydawca_lockname (const char *tag); int wydawca_lock (const char *lockname); void wydawca_unlock (const char *lockname); void wydawca_lock_init (void); + + +/* tcpwrap.h */ +extern struct gconf_keyword tcpwrapper_kw[]; +int tcpwrap_access(int fd); -- cgit v1.2.1