diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-25 22:12:34 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-25 22:12:34 +0200 |
commit | 27d1256d331d45bf68d96e9a8aa8175df2584978 (patch) | |
tree | d4e28ce067fa001b7aff5a470c146a6d04eead96 | |
parent | c9178a6fef0184baed0e8456bb6c6d4091b4997c (diff) | |
download | wydawca-27d1256d331d45bf68d96e9a8aa8175df2584978.tar.gz wydawca-27d1256d331d45bf68d96e9a8aa8175df2584978.tar.bz2 |
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.
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/builtin.c | 1 | ||||
-rw-r--r-- | src/config.c | 10 | ||||
-rw-r--r-- | src/job.c | 29 | ||||
-rw-r--r-- | src/net.c | 45 | ||||
-rw-r--r-- | src/pidfile.c | 4 | ||||
-rw-r--r-- | src/tcpwrap.c | 83 | ||||
-rw-r--r-- | src/triplet.c | 2 | ||||
-rw-r--r-- | src/wydawca.h | 9 |
10 files changed, 172 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac index 4f6eaa0..737e2dc 100644 --- a/configure.ac +++ b/configure.ac @@ -85,12 +85,32 @@ WD_CHECK_LIB([gpgme],[main],[], [GPGMELIB="$wd_cv_lib_gpgme" AC_DEFINE(HAVE_GPGME) ], [ 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 # ********************** AC_ARG_WITH([preprocessor], AC_HELP_STRING([--without-preprocessor], [do not use external preprocessor]), [ diff --git a/src/Makefile.am b/src/Makefile.am index fcfdb78..c91669e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,12 +31,13 @@ wydawca_SOURCES=\ method.c\ net.c\ pidfile.c\ process.c\ sql.c\ sql.h\ + tcpwrap.c\ triplet.c\ verify.c\ wydawca.c\ wydawca.h\ mail.h\ mail.c\ diff --git a/src/builtin.c b/src/builtin.c index 90b7c2f..d70a511 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -180,13 +180,12 @@ builtin_run (struct access_method *meth, void *handle, const char *req) obstack_init (&stk); for (i = 0; i < meth->parmc; i++) { char *pat = meth->parmv[i]; - char *val; if (pat[0] == '/') { pat++; if (*pat != '/' && parse_cmp_type (pat, &cmpfn, &flags) == 0) continue; diff --git a/src/config.c b/src/config.c index bab1ed3..b1f339f 100644 --- a/src/config.c +++ b/src/config.c @@ -213,13 +213,13 @@ string_to_notification_target (gconf_locus_t *locus, const char *val, locus); *pret = res; return rc; } -static int +int assert_string_arg (gconf_locus_t *locus, enum gconf_callback_command cmd, const gconf_value_t *value) { if (cmd != gconf_callback_set_value) { @@ -1144,13 +1144,12 @@ cb_spool (enum gconf_callback_command cmd, gconf_value_t *value, void *cb_data) { struct spool *spool; void **pdata = cb_data; int rc, ec, i; - const char *ep = NULL; switch (cmd) { case gconf_callback_section_begin: if (!value || value->type != GCONF_TYPE_STRING) { @@ -1244,12 +1243,19 @@ static struct gconf_keyword wydawca_kw[] = { gconf_type_string, &lockdir }, { "lock-expire-time", N_("interval"), N_("Define lock expiration interval"), gconf_type_string, &lock_expire_time, 0, cb_interval }, { "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"), gconf_type_string, &admin_address, 0, cb_email_address }, { "from-address", N_("email"), N_("Set sender email address"), gconf_type_string, &from_address, 0, cb_email_address }, @@ -96,13 +96,14 @@ job_start (struct job *job) { logmsg (LOG_NOTICE, "maximum number of processes active"); return 1; } 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) { if (wydawca_scanner (job)) job->state = STATE_QUEUED; else @@ -110,12 +111,20 @@ job_start (struct job *job) wakeup = 1; } 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) { logmsg (LOG_CRIT, "fork: %s", strerror (errno)); return -1; @@ -132,13 +141,14 @@ job_start (struct job *job) void 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; else queue = job->next; @@ -166,22 +176,23 @@ job_insert (struct job *job, struct job *elt) elt->next = job; if (p) p->prev = job; } -int +void schedule_job (const struct spool *spool, uid_t uid) { struct job *job; if (!spool) 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) { job = xzalloc (sizeof (*job)); job->spool = spool; @@ -227,28 +238,30 @@ print_status (struct job *job, int expect_term) } else prio = LOG_ERR; 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 job_queue_runner () { int status; @@ -49,14 +49,13 @@ open_listener () } else { /* 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); } /* FIXME: Setup umask */ } @@ -91,45 +90,45 @@ trim_crlf (char *s) { s[--len] = 0; if (len > 0 && s[len-1] == '\r') 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) logmsg (LOG_DEBUG, "recv: %s", buf); spool = wydawca_find_spool (buf); 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); return; } @@ -181,13 +180,13 @@ wydawca_listener () signal (SIGTERM, sig_term); signal (SIGQUIT, sig_term); signal (SIGINT, sig_term); while (!terminate) { int fd; - FILE *fp; + FILE *in, *out; int rc; fd_set rset; struct timeval to, *pto; union { struct sockaddr sa; struct sockaddr_in s_in; @@ -220,14 +219,26 @@ wydawca_listener () } len = sizeof (addr); 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 @@ -31,13 +31,13 @@ check_pidfile () { FILE *fp = fopen (pidfile, "r+"); 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) exit (EX_UNAVAILABLE); } else @@ -79,12 +79,12 @@ check_pidfile () logmsg (LOG_ERR, _("cannot open pidfile %s for writing: %s"), pidfile, strerror (errno)); 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 <http://www.gnu.org/licenses/>. */ + +#include "wydawca.h" +#include <mailutils/syslog.h> + +#ifdef WITH_LIBWRAP +# include <tcpd.h> + +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 @@ -563,13 +563,13 @@ expand_report (struct metadef *def, void *data) #define DECL_EXPAND_TIMER(what) \ static const char * \ __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) DECL_EXPAND_TIMER(user) DECL_EXPAND_TIMER(system) diff --git a/src/wydawca.h b/src/wydawca.h index f093504..863200f 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -434,12 +434,14 @@ int wydawca_set_uid (uid_t uid); 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 */ int url_to_vtab (mu_url_t url, struct virt_tab *vtab); int @@ -502,13 +504,13 @@ void report_init (void); void report_add (const char *fmt, ...); void report_finish (void); 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); /* profile.c */ void check_pidfile (void); @@ -526,6 +528,11 @@ void wydawca_listener (void); #define LOCK_FAILURE 4 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); |