diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-10-21 18:38:25 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-10-21 18:38:25 +0000 |
commit | 9701509fced80d18b30bde4e51bca7fb2e73b26e (patch) | |
tree | d32015055f10b55bd6f46bb22bb884283061653f | |
parent | 44e921546471416e57574f9c00a8014864b60276 (diff) | |
download | mailfromd-9701509fced80d18b30bde4e51bca7fb2e73b26e.tar.gz mailfromd-9701509fced80d18b30bde4e51bca7fb2e73b26e.tar.bz2 |
* src/dnsbase.c (cname_loop_body): Return TXT only if explicitly
required. Bug reported by Jan Rafaj.
git-svn-id: file:///svnroot/mailfromd/trunk@1518 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | src/bi_sa.m4 | 218 | ||||
-rw-r--r-- | src/dnsbase.c | 4 |
3 files changed, 182 insertions, 43 deletions
@@ -1,14 +1,17 @@ 2007-10-21 Sergey Poznyakoff <gray@gnu.org.ua> + * src/dnsbase.c (cname_loop_body): Return TXT only if explicitly + required. Bug reported by Jan Rafaj. + * src/engine.c: Fix timeout calculations (struct timeout_ctl): New data type (UPDATE_TTW,smtp_stream_wait,smtp_wait): Operate on struct timeout_ctl. All callers updated. (init_timeout_ctl): New function. 2007-10-12 Sergey Poznyakoff <gray@gnu.org.ua> * src/mtasim.c (_def_read): Return 0 if zero bytes were read (get_input_line): Fix counting of input bytes. (smtp): Fix checking for returns from process_data_reply. * gacopyz/server.c (srv_format_macros): Do not add trailing zero diff --git a/src/bi_sa.m4 b/src/bi_sa.m4 index 0ed7472b..8472bbe9 100644 --- a/src/bi_sa.m4 +++ b/src/bi_sa.m4 @@ -18,135 +18,264 @@ #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <string.h> #include <signal.h> MF_VAR(sa_score, NUMBER); MF_VAR(sa_threshold, NUMBER); MF_VAR(sa_keywords, STRING); MF_VAR(clamav_virus_name, STRING); + +struct mf_stream { + eval_environ_t env; + mu_stream_t str; + time_t start; + time_t timeout; +}; + +typedef struct mf_stream *mf_stream_t; + +/* FIXME: duplicated in engine.c */ +#define UPDATE_TTW(t,start) do { \ + time_t delta = time(NULL) - start; \ + if (t > delta) \ + t -= delta; \ + else \ + t = 0; \ +} while (0) + +extern int smtp_stream_wait(mu_stream_t stream, int flags, time_t *timeout); +static void spamd_destroy(mf_stream_t *pstream); + +mf_stream_t +mf_stream_new (eval_environ_t env, mu_stream_t stream, time_t start, + time_t timeout) +{ + mf_stream_t pmfs = xmalloc (sizeof pmfs[0]); + pmfs->env = env; + pmfs->str = stream; + pmfs->start = start; + pmfs->timeout = timeout; + return pmfs; +} + +int +mf_stream_sequential_read(mf_stream_t stream, char *buf, size_t size) +{ + int rc; + eval_environ_t env = stream->env; + + if (stream->timeout == 0) { + spamd_destroy(&stream); + MF_THROW(mf_temp_failure, + "sa_sequential_read: %s", + mu_strerror(ETIMEDOUT)); + } + + rc = smtp_stream_wait(stream->str, MU_STREAM_READY_RD, + &stream->timeout); + if (rc == 0) { + UPDATE_TTW(stream->timeout, stream->start); + rc = mu_stream_sequential_read(stream->str, buf, size, NULL); + } else { + spamd_destroy(&stream); + MF_THROW(mf_temp_failure, + "sa_sequential_read: %s", + mu_strerror(ETIMEDOUT)); + } + + return rc; +} + +int +mf_stream_sequential_readline(mf_stream_t stream, char *buf, size_t size, + size_t *nbytes) +{ + int rc; + eval_environ_t env = stream->env; + + if (stream->timeout == 0) { + spamd_destroy(&stream); + MF_THROW(mf_temp_failure, + "sa_sequential_readline: %s", + mu_strerror(ETIMEDOUT)); + } + rc = smtp_stream_wait(stream->str, MU_STREAM_READY_RD, + &stream->timeout); + if (rc == 0) { + UPDATE_TTW(stream->timeout, stream->start); + rc = mu_stream_sequential_readline(stream->str, buf, size, + nbytes); + } else { + spamd_destroy(&stream); + MF_THROW(mf_temp_failure, + "sa_sequential_readline: %s", + mu_strerror(ETIMEDOUT)); + } + return rc; +} + +int +mf_stream_sequential_write(mf_stream_t stream, char *buf, size_t size) +{ + int rc; + eval_environ_t env = stream->env; + + if (stream->timeout == 0) { + spamd_destroy(&stream); + MF_THROW(mf_temp_failure, + "sa_sequential_write: %s", + mu_strerror(ETIMEDOUT)); + } + + rc = smtp_stream_wait(stream->str, MU_STREAM_READY_WR, + &stream->timeout); + if (rc == 0) { + UPDATE_TTW(stream->timeout, stream->start); + rc = mu_stream_sequential_write(stream->str, buf, size); + } else { + spamd_destroy(&stream); + MF_THROW(mf_temp_failure, + "sa_sequential_write: %s", + mu_strerror(ETIMEDOUT)); + } + return rc; +} + + + static int -spamd_connect_tcp(eval_environ_t env, mu_stream_t *stream, - char *host, int port) +spamd_connect_tcp(eval_environ_t env, mf_stream_t *pmfs, + char *host, int port, time_t timeout) { - int rc = mu_tcp_stream_create(stream, host, port, 0); + mu_stream_t stream; + int rc = mu_tcp_stream_create(&stream, host, port, 0); MF_ASSERT(rc == 0, mf_failure, "mu_tcp_stream_create: %s", mu_strerror(rc)); - rc = mu_stream_open(*stream); + rc = mu_stream_open(stream); MF_ASSERT(rc == 0, mf_failure, "mu_stream_open: %s", mu_strerror(rc)); + *pmfs = mf_stream_new(env, stream, time(NULL), timeout); return rc; } static int -spamd_connect_socket(eval_environ_t env, mu_stream_t *stream, char *path) +spamd_connect_socket(eval_environ_t env, mf_stream_t *pmfs, char *path, + time_t timeout) { int fd, rc; FILE *fp; struct sockaddr_un addr; + mu_stream_t stream; fd = socket(PF_UNIX, SOCK_STREAM, 0); MF_ASSERT(fd >= 0, mf_failure, "socket: %s", mu_strerror(errno)); memset(&addr, 0, sizeof addr); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, path, sizeof addr.sun_path - 1); addr.sun_path[sizeof addr.sun_path - 1] = 0; if (connect(fd, (struct sockaddr *) &addr, sizeof(addr))) { close(fd); MF_THROW(mf_failure, "connect: %s", mu_strerror(errno)); } fp = fdopen(fd, "w+"); - rc = mu_stdio_stream_create(stream, fp, MU_STREAM_RDWR); + rc = mu_stdio_stream_create(&stream, fp, MU_STREAM_RDWR); if (rc) { fclose(fp); MF_THROW(mf_failure, "mu_stdio_stream_create: %s", mu_strerror(rc)); } - rc = mu_stream_open(*stream); + rc = mu_stream_open(stream); if (rc) { - mu_stream_destroy (stream, mu_stream_get_owner (*stream)); + mu_stream_destroy(&stream, mu_stream_get_owner(stream)); fclose(fp); MF_THROW(mf_failure, "mu_stream_open: %s", mu_strerror(rc)); } + + *pmfs = mf_stream_new(env, stream, time(NULL), timeout); + return rc; } static void -spamd_shutdown(mu_stream_t stream, int isfile, int flag) +spamd_shutdown(mf_stream_t stream, int isfile, int flag) { int fd; - mu_transport_t trans; - mu_stream_flush(stream); - mu_stream_get_transport(stream, &trans); + + mu_stream_flush(stream->str); + mu_stream_get_transport(stream->str, &trans); if (isfile) fd = fileno((FILE*)trans); else fd = (int) trans; shutdown(fd, flag); } static void -spamd_destroy(mu_stream_t *stream) +spamd_destroy(mf_stream_t *pstream) { - mu_stream_close(*stream); - mu_stream_destroy(stream, mu_stream_get_owner(*stream)); + mf_stream_t stream = *pstream; + mu_stream_close(stream->str); + mu_stream_destroy(&stream->str, mu_stream_get_owner(stream->str)); + free(stream); + *pstream = NULL; } static void -spamd_send_command(mu_stream_t stream, const char *fmt, ...) +spamd_send_command(mf_stream_t stream, const char *fmt, ...) { char buf[512]; size_t n; va_list ap; va_start (ap, fmt); n = vsnprintf (buf, sizeof buf, fmt, ap); va_end (ap); - mu_stream_sequential_write(stream, buf, n); - mu_stream_sequential_write(stream, "\r\n", 2); + mf_stream_sequential_write(stream, buf, n); + mf_stream_sequential_write(stream, "\r\n", 2); } static void -spamd_send_stream(mu_stream_t stream, mu_stream_t instr) +spamd_send_stream(mf_stream_t stream, mu_stream_t instr) { size_t size; char buf[512]; mu_stream_seek(instr, 0, SEEK_SET); while (mu_stream_sequential_readline(instr, buf, sizeof(buf), &size) == 0 && size > 0) { debug3(80,"<< %*.*s", size, size, buf); - mu_stream_sequential_write (stream, buf, size); + mf_stream_sequential_write(stream, buf, size); } } static int -spamd_read_line(mu_stream_t stream, char *buffer, size_t size, size_t *pn) +spamd_read_line(mf_stream_t stream, char *buffer, size_t size, size_t *pn) { size_t n = 0; - int rc = mu_stream_sequential_readline(stream, buffer, size, &n); + int rc = mf_stream_sequential_readline(stream, buffer, size, &n); if (rc == 0) { if (pn) *pn = n; while (n > 0 && (buffer[n-1] == '\r' || buffer[n-1] == '\n')) n--; buffer[n] = 0; debug1(80,">> %s", buffer); } return rc; } #define char_to_num(c) (c-'0') @@ -178,29 +307,29 @@ decode_float(long *vn, char *str, int digits) frac++; } else for (; i < digits; i++) frac *= 10; } *vn = v + frac; if (negative) *vn = - *vn; } static int -decode_boolean (char *str) +decode_boolean(char *str) { - if (strcasecmp (str, "true") == 0) + if (strcasecmp(str, "true") == 0) return 1; - else if (strcasecmp (str, "false") == 0) + else if (strcasecmp(str, "false") == 0) return 0; /*else?*/ return 0; } typedef RETSIGTYPE (*signal_handler_fn)(int); static signal_handler_fn set_signal_handler (int sig, signal_handler_fn h) { #ifdef HAVE_SIGACTION struct sigaction act, oldact; @@ -213,30 +342,31 @@ set_signal_handler (int sig, signal_handler_fn h) return signal (sig, h); #endif } static int got_sigpipe; static RETSIGTYPE sigpipe_handler (int sig) { got_sigpipe = 1; } -mu_stream_t -open_connection(eval_environ_t env, char *urlstr, int *isfile, char **phost) +mf_stream_t +open_connection(eval_environ_t env, char *urlstr, int *isfile, char **phost, + long timeout) { char *path = NULL; short port = 0; - mu_stream_t str = NULL; + mf_stream_t str = NULL; int rc; if (urlstr[0] == '/') { path = strdup(urlstr); if (!path) runtime_error(env, _("Not enough memory")); } else { char buffer[10]; mu_url_t url = NULL; rc = mu_url_create(&url, urlstr); if (rc) @@ -301,62 +431,63 @@ open_connection(eval_environ_t env, char *urlstr, int *isfile, char **phost) mu_url_destroy(&url); runtime_error(env, _("Not enough memory")); } mu_url_get_host(url, path, size + 1, NULL); } else MF_THROW(mf_url, _("Invalid URL: %s"), buffer); mu_url_destroy(&url); } if (port == 0) { - rc = spamd_connect_socket(env, &str, path); + rc = spamd_connect_socket(env, &str, path, timeout); *isfile = 1; } else { - rc = spamd_connect_tcp(env, &str, path, port); + rc = spamd_connect_tcp(env, &str, path, port, timeout); *isfile = 0; } if (rc == 0 && phost) { if (port) { *phost = path; path = NULL; } else *phost = NULL; } free(path); return str; } MF_STATE(eom) MF_CAPTURE -MF_DEFUN(sa, NUMBER, STRING urlstr, NUMBER prec) +MF_DEFUN(sa, NUMBER, STRING urlstr, NUMBER prec, OPTIONAL, NUMBER timeout) { mu_off_t msize; size_t size; mu_stream_t mstr = env_get_stream(env); - mu_stream_t ostr; + mf_stream_t ostr; signal_handler_fn handler; char buffer[512]; char version_str[19]; char spam_str[6], score_str[21], threshold_str[21]; long version; int result; long score, threshold; int isfile; - ostr = open_connection(env, urlstr, &isfile, NULL); + ostr = open_connection(env, urlstr, &isfile, NULL, + MF_OPTVAL(timeout, 7200)); mu_stream_size(mstr, &msize); spamd_send_command(ostr, "SYMBOLS SPAMC/1.2"); spamd_send_command(ostr, "Content-length: %lu", (unsigned long) msize); /*FIXME: spamd_send_command(ostr, "User: %s", ??) */ got_sigpipe = 0; handler = set_signal_handler(SIGPIPE, sigpipe_handler); spamd_send_command(ostr, ""); spamd_send_stream(ostr, mstr); spamd_shutdown(ostr, isfile, SHUT_WR); set_signal_handler(SIGPIPE, handler); @@ -405,71 +536,76 @@ MF_DEFUN(sa, NUMBER, STRING urlstr, NUMBER prec) while (spamd_read_line(ostr, buffer, sizeof buffer, &size) == 0 && size > 0) /* Drain input */; spamd_destroy(&ostr); MF_RETURN(result); } END MF_STATE(eom) MF_CAPTURE -MF_DEFUN(clamav, NUMBER, STRING urlstr) +MF_DEFUN(clamav, NUMBER, STRING urlstr, OPTIONAL, NUMBER timeout) { mu_stream_t mstr = env_get_stream(env); - mu_stream_t cstr, dstr; + mf_stream_t cstr, dstr; + mu_stream_t str; char buffer[512]; char *host; unsigned short port; int rc; signal_handler_fn handler; char *p; int isfile; - - cstr = open_connection(env, urlstr, &isfile, &host); + + cstr = open_connection(env, urlstr, &isfile, &host, + MF_OPTVAL(timeout, 7200)); spamd_send_command(cstr, "STREAM"); spamd_read_line(cstr, buffer, sizeof buffer, NULL); if (sscanf(buffer, "PORT %hu\n", &port) != 1) { spamd_destroy(&cstr); MF_THROW(mf_failure, _("Bad response from clamav: expected `PORT' but found `%s'"), buffer); } if (!host) host = strdup("127.0.0.1"); /* FIXME */ - - rc = mu_tcp_stream_create(&dstr, host, port, 0); + + rc = mu_tcp_stream_create(&str, host, port, 0); free(host); if (rc) { spamd_destroy(&cstr); MF_THROW(mf_failure, "mu_tcp_stream_create: %s", mu_strerror(rc)); } - rc = mu_stream_open(dstr); + rc = mu_stream_open(str); if (rc) { spamd_destroy(&cstr); - mu_stream_destroy(&dstr, mu_stream_get_owner(dstr)); + mu_stream_destroy(&str, mu_stream_get_owner(str)); MF_THROW(mf_failure, "mu_stream_open: %s", mu_strerror(rc)); } handler = set_signal_handler(SIGPIPE, sigpipe_handler); + dstr = mf_stream_new (env, str, cstr->start, cstr->timeout); spamd_send_stream(dstr, mstr); spamd_shutdown(dstr, 0, SHUT_WR); + spamd_destroy(&dstr); + set_signal_handler(SIGPIPE, handler); rc = spamd_read_line(cstr, buffer, sizeof buffer, NULL); spamd_destroy(&cstr); MF_ASSERT(rc == 0, mf_failure, _("Error reading clamav response: %s"), mu_strerror(rc)); p = strrchr(buffer, ' '); MF_ASSERT(p, mf_failure, _("Unknown clamav response: %s"), buffer); ++p; if (strncmp(p, "OK", 2) == 0) diff --git a/src/dnsbase.c b/src/dnsbase.c index cf4b95a4..cbb658d0 100644 --- a/src/dnsbase.c +++ b/src/dnsbase.c @@ -238,25 +238,25 @@ dns_freemx(mxbuf_t mxbuf) struct loop_data { int qtype; /* Type of the query */ char *name; /* Key to look up */ size_t name_size; /* Length of the key */ char *domain; /* Domain name */ size_t domain_size; /* Length of the domain name */ char *answer; /* Answer buffer */ size_t answer_size; /* Size of answer buffer */ /* Return data: */ char *hbuf; /* Return buffer */ size_t hbsize; /* Size of return buffer */ - size_t hbcount; /* ?? */ + size_t hbcount; /* Number of items returned */ time_t ttl; /* TTL value */ dns_status status; /* Status */ int atype; /* On input: desired answer type or T_ANY On output: Answer type */ /* Internal data */ size_t loopcnt; /* Number of CNAME loops allowed */ }; #define NSIZE MAX(MAXPACKET, MAXDNAME*2+2) #define SET_STATUS(lp,s) if ((lp)->status != dns_success) (lp)->status = s @@ -409,25 +409,25 @@ cname_loop_body(struct loop_data *lp) } l = strlen(nbuf); if (lp->hbcount + l >= lp->hbsize) break; memcpy(lp->hbuf + lp->hbcount, nbuf, l); lp->hbcount += l; lp->hbuf[lp->hbcount++] = 0; lp->atype = T_PTR; SET_STATUS(lp, dns_success); break; case T_TXT: - if (lp->atype != T_ANY && lp->atype != type) + if (lp->atype != type) continue; l = cp[0]; if (lp->hbcount + l >= lp->hbsize) break; memcpy(lp->hbuf + lp->hbcount, cp + 1, l); lp->hbcount += l; lp->hbuf[lp->hbcount++] = 0; lp->atype = T_TXT; SET_STATUS(lp, dns_success); break; case T_CNAME: |