aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-11-21 18:48:35 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-11-21 18:48:35 +0200
commitd20b648b02aa1f8caf9975a116c54e05d67d1c39 (patch)
treea060073bdc2da690dca5817220538e2410cd914e
parent118f9d898f8e0208aa01275cf37752b888c39d20 (diff)
downloadmailfromd-d20b648b02aa1f8caf9975a116c54e05d67d1c39.tar.gz
mailfromd-d20b648b02aa1f8caf9975a116c54e05d67d1c39.tar.bz2
Implement the callout server.
* mfd/savsrv.c: New file. * mfd/Makefile.am (mailfromd_SOURCES): Add savsrv.c. * mfd/callout.c (struct smtp_io_data): Add new fields: email, ehlo and mailfrom. (smtp_io_create): trim trailing ': ' from the id. (smtp_io_init, smtp_io_setup_callout): New functions. (smtp_io_free): Free new members. (smtp_io_email): New function. (callout_io): Change signature. (smtp_io_open): 2nd arg is const char *. (callout): Remove. (callout_host, callout_mx) (callout_strict, callout_standard): New functions. * mfd/engine.c (mfl_smtp_io_callback): Now extern. (check_on_host, check_mx_records): Remove. (method_strict, method_standard): Rewrite using new callout support. * mfd/mailfromd.h: Fix protos. (callout_host, callout_mx) (callout_strict, callout_standard): New functions. * mfd/main.c (cb_url) (callout_resolver, callout_resolver_section_param) (callout_resolver_cfg_init): Remove. (milter_config_stmt): Rename to server_config_stmt. Add new field `server'. (cb_milter_stmt_listen): Rename to cb_server_stmt_listen. (milter_section_param): Rename to server_section_param. (milter_section_parser): Rename to server_section_parser. The label of the statement determines the server type. (milter_cfg_init): Rename to server_cfg_init. (mf_cfg_param): Rename `milter' and `callout-resolver' statements. Add new statement `server'. (main): Call server_cfg_init. * mfd/bi_poll.m4 (_pollhost, _pollmx): Use callout_host and callout_mx, correspondingly. * mfd/cache.c (cache_get, cache_insert) (cache_get2, cache_insert2): String args are const. * mfd/dns.c (getmx): Likewise. * mfd/srvman.c: Add debugging statements.
-rw-r--r--mfd/Makefile.am1
-rw-r--r--mfd/bi_poll.m422
-rw-r--r--mfd/cache.c12
-rw-r--r--mfd/callout.c210
-rw-r--r--mfd/dns.c2
-rw-r--r--mfd/engine.c124
-rw-r--r--mfd/mailfromd.h31
-rw-r--r--mfd/main.c133
-rw-r--r--mfd/savsrv.c225
-rw-r--r--mfd/srvman.c32
10 files changed, 545 insertions, 247 deletions
diff --git a/mfd/Makefile.am b/mfd/Makefile.am
index d1288a9a..962c22a0 100644
--- a/mfd/Makefile.am
+++ b/mfd/Makefile.am
@@ -72,6 +72,7 @@ mailfromd_SOURCES = \
pragma.c\
prog.c\
prog.h\
+ savsrv.c\
srvman.c\
srvman.h\
spf.c\
diff --git a/mfd/bi_poll.m4 b/mfd/bi_poll.m4
index dc730200..efec3935 100644
--- a/mfd/bi_poll.m4
+++ b/mfd/bi_poll.m4
@@ -99,6 +99,8 @@ MF_DEFUN(_pollhost, NUMBER, STRING host, STRING email, STRING ehlo,
STRING mailfrom)
{
mf_status rc;
+ smtp_io_t io;
+ const char *id = mailfromd_msgid(env_get_context(env));
const struct locus *locus = env_get_locus(env);
trace("%s%s:%lu: POLLHOST %s FOR %s FROM %s AS %s",
@@ -107,8 +109,14 @@ MF_DEFUN(_pollhost, NUMBER, STRING host, STRING email, STRING ehlo,
email, host,
ehlo, mailfrom);
- rc = check_on_host(env, email, host, ehlo, mailfrom);
-
+ io = smtp_io_create(id ? id : "(none): ",
+ smtp_timeout_soft,
+ mfl_smtp_io_callback,
+ env);
+ smtp_io_setup_callout(io, email, ehlo, mailfrom);
+ rc = callout_host(io, host);
+ smtp_io_free(io);
+
MF_ASSERT(mf_resolved(rc), mf_status_to_exception(rc),
_("unhandled exception %s"), mf_exception_str(rc));
@@ -120,6 +128,8 @@ MF_DEFUN(_pollmx, NUMBER, STRING domain, STRING email, STRING ehlo,
STRING mailfrom)
{
mf_status rc;
+ smtp_io_t io;
+ const char *id = mailfromd_msgid(env_get_context(env));
const struct locus *locus = env_get_locus(env);
trace("%s%s:%lu: POLLMX %s FOR %s FROM %s AS %s",
@@ -127,7 +137,13 @@ MF_DEFUN(_pollmx, NUMBER, STRING domain, STRING email, STRING ehlo,
locus->file, locus->line,
domain, email, ehlo, mailfrom);
- rc = check_mx_records(env, email, domain, ehlo, mailfrom, NULL);
+ io = smtp_io_create(id ? id : "(none): ",
+ smtp_timeout_soft,
+ mfl_smtp_io_callback,
+ env);
+ smtp_io_setup_callout(io, email, ehlo, mailfrom);
+ rc = callout_mx(io, domain, NULL);
+ smtp_io_free(io);
MF_ASSERT(mf_resolved(rc), mf_status_to_exception(rc),
_("unhandled exception %s"), mf_exception_str(rc));
diff --git a/mfd/cache.c b/mfd/cache.c
index 99150a13..89318137 100644
--- a/mfd/cache.c
+++ b/mfd/cache.c
@@ -32,7 +32,7 @@ struct cache_result {
((s) == mf_success ? cache_format->expire_interval : negative_expire_interval)
mf_status
-cache_get(char *email)
+cache_get(const char *email)
{
mf_status rc;
DBM_FILE db;
@@ -57,7 +57,7 @@ cache_get(char *email)
memset (&key, 0, sizeof key);
memset (&contents, 0, sizeof contents);
- MU_DATUM_PTR (key) = email;
+ MU_DATUM_PTR (key) = (void*) email;
MU_DATUM_SIZE (key) = strlen (email) + 1;
if ((res = mu_dbm_fetch(&db, key, &contents)) == 0) {
char timebuf[80];
@@ -94,7 +94,7 @@ cache_get(char *email)
}
void
-cache_insert(char *email, mf_status rc)
+cache_insert(const char *email, mf_status rc)
{
DBM_FILE db;
DBM_DATUM key;
@@ -119,7 +119,7 @@ cache_insert(char *email, mf_status rc)
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
- MU_DATUM_PTR(key) = email;
+ MU_DATUM_PTR(key) = (void*) email;
MU_DATUM_SIZE(key) = strlen (email) + 1;
MU_DATUM_PTR(contents) = (void*)&res;
MU_DATUM_SIZE(contents) = sizeof(res);
@@ -150,7 +150,7 @@ cache_expire_item(const void *content)
}
mf_status
-cache_get2(char *email, char *client_addr)
+cache_get2(const char *email, const char *client_addr)
{
mf_status rc = mf_failure;
size_t size;
@@ -169,7 +169,7 @@ cache_get2(char *email, char *client_addr)
}
void
-cache_insert2(char *email, char *client_addr, mf_status rc)
+cache_insert2(const char *email, const char *client_addr, mf_status rc)
{
if (!cache_format->enabled)
return;
diff --git a/mfd/callout.c b/mfd/callout.c
index c6a75b5f..c028838e 100644
--- a/mfd/callout.c
+++ b/mfd/callout.c
@@ -38,11 +38,14 @@
#include "mailfromd.h"
-
#define SMTP_MAJOR(c) ((c)/100)
struct smtp_io_data {
char *id; /* I/O id */
+ char *email;
+ char *ehlo;
+ char *mailfrom;
+
time_t timeout[SMTP_NUM_TIMEOUT];
smtp_io_callback_t callback;
void *callback_closure;
@@ -63,7 +66,16 @@ smtp_io_create(const char *id, time_t timeout[], smtp_io_callback_t callback,
void *closure)
{
struct smtp_io_data *iop = xzalloc(sizeof(*iop));
- iop->id = xstrdup(id);
+
+ if (!id)
+ iop->id = xstrdup("null");
+ else {
+ size_t len;
+ iop->id = xstrdup(id);
+ len = strlen(iop->id);
+ if (len > 2 && strcmp(iop->id + len - 2, ": ") == 0)
+ iop->id[len - 2] = 0;
+ }
memcpy(&iop->timeout, timeout, sizeof(iop->timeout));
iop->callback = callback;
iop->callback_closure = closure;
@@ -74,6 +86,33 @@ smtp_io_create(const char *id, time_t timeout[], smtp_io_callback_t callback,
return iop;
}
+static void
+replstr(char **pdst, const char *str)
+{
+ if (*pdst)
+ free(*pdst);
+ *pdst = xstrdup(str);
+}
+
+void
+smtp_io_init(struct smtp_io_data *iop)
+{
+ iop->send_off = iop->recv_off = 0;
+ iop->start = iop->command = iop->reply = NULL;
+ iop->level = 0;
+}
+
+void
+smtp_io_setup_callout(struct smtp_io_data *iop,
+ const char *email,
+ const char *ehlo,
+ const char *mailfrom)
+{
+ replstr(&iop->email, email);
+ replstr(&iop->ehlo, ehlo);
+ replstr(&iop->mailfrom, mailfrom);
+}
+
void
smtp_io_free(struct smtp_io_data *iop)
{
@@ -84,6 +123,9 @@ smtp_io_free(struct smtp_io_data *iop)
}
obstack_free(&iop->stk, NULL);
free(iop->id);
+ free(iop->email);
+ free(iop->ehlo);
+ free(iop->mailfrom);
free(iop);
}
@@ -98,7 +140,7 @@ transcript(struct smtp_io_data *io, char *prefix, const char *msg)
--len;
}
if (len)
- logmsg(LOG_INFO, "%s%s %*.*s",
+ logmsg(LOG_INFO, "%s: %s %*.*s",
io->id,
prefix, len, len, msg);
}
@@ -343,6 +385,12 @@ smtp_last_received(struct smtp_io_data *iop)
return "nothing";
}
+const char *
+smtp_io_email(struct smtp_io_data *iop)
+{
+ return iop->email;
+}
+
/* Milter-specific functions */
@@ -359,38 +407,43 @@ reset(struct smtp_io_data *io)
}
static mf_status
-callout_io(struct smtp_io_data *io, char *email, char *ehlo,
- mu_address_t addr)
+callout_io(struct smtp_io_data *io, const char *hostname, mu_address_t addr)
{
size_t i;
size_t mailcount;
mf_status status;
+ if (io->callback)
+ io->callback(io->callback_closure, "INIT",
+ smtp_last_received(io));
+
mu_address_get_count(addr, &mailcount);
if (smtp_recv(io, smtp_timeout_initial))
return mf_temp_failure;
- io->callback(io->callback_closure, "INIT",
- smtp_last_received(io));
+ if (io->callback)
+ io->callback(io->callback_closure, "GRTNG",
+ smtp_last_received(io));
if (SMTP_MAJOR(io->code) != 2)
return SMTP_MAJOR(io->code) == 4 ?
mf_temp_failure : mf_not_found;
- smtp_send2(io, "HELO ", ehlo);
+ smtp_send2(io, "HELO ", io->ehlo);
if (smtp_recv(io, smtp_timeout_helo))
return mf_temp_failure;
if (SMTP_MAJOR(io->code) == 5) {
/* Let's try EHLO, then */
- smtp_send2(io, "EHLO ", ehlo);
+ smtp_send2(io, "EHLO ", io->ehlo);
if (smtp_recv(io, smtp_timeout_helo))
return mf_not_found;
}
-
- io->callback(io->callback_closure,
- "HELO", smtp_last_received(io));
+
+ if (io->callback)
+ io->callback(io->callback_closure,
+ "HELO", smtp_last_received(io));
if (SMTP_MAJOR(io->code) != 2)
return SMTP_MAJOR(io->code) == 4 ?
@@ -426,7 +479,7 @@ callout_io(struct smtp_io_data *io, char *email, char *ehlo,
if (status != mf_success)
return status;
- smtp_send3(io, "RCPT TO:<", email, ">");
+ smtp_send3(io, "RCPT TO:<", io->email, ">");
if (smtp_recv(io, smtp_timeout_rcpt))
return mf_temp_failure;
else if (SMTP_MAJOR(io->code) != 2)
@@ -437,18 +490,18 @@ callout_io(struct smtp_io_data *io, char *email, char *ehlo,
mf_status
-smtp_io_open(struct smtp_io_data *io, char *client_addr)
+smtp_io_open(struct smtp_io_data *io, const char *hostname)
{
int rc;
mu_stream_t stream;
struct timeout_ctl tctl;
- rc = mu_tcp_stream_create_with_source_ip (&stream, client_addr, 25,
+ rc = mu_tcp_stream_create_with_source_ip (&stream, hostname, 25,
source_address,
MU_STREAM_NONBLOCK);
if (rc) {
- mu_error(_("%scannot connect to `%s': %s"),
- io->id, client_addr,
+ mu_error(_("%s: cannot connect to `%s': %s"),
+ io->id, hostname,
mu_strerror(rc));
return mf_temp_failure;
}
@@ -464,7 +517,7 @@ smtp_io_open(struct smtp_io_data *io, char *client_addr)
continue;
}
}
- mu_error("%sstream_open: %s",
+ mu_error("%s: stream_open: %s",
io->id, mu_strerror(rc));
mu_stream_destroy(&stream, mu_stream_get_owner(stream));
return mf_temp_failure;
@@ -479,28 +532,28 @@ smtp_io_close(struct smtp_io_data *io)
{
if (io->stream) {
mu_stream_close(io->stream);
- mu_stream_destroy(&io->stream, mu_stream_get_owner(io->stream));
+ mu_stream_destroy(&io->stream,
+ mu_stream_get_owner(io->stream));
}
}
mf_status
-callout(struct smtp_io_data *io,
- char *client_addr,
- char *email, char *ehlo, char *mailfrom)
+callout_host(struct smtp_io_data *io, const char *hostname)
{
int rc;
mf_status status = mf_success;
mu_address_t addr;
+ const char *mailfrom;
- debug2(10, "email = %s, client_addr = %s", email, client_addr);
+ debug2(10, "email = %s, hostname = %s", io->email, hostname);
- status = smtp_io_open(io, client_addr);
+ smtp_io_init(io);
+ status = smtp_io_open(io, hostname);
if (status != mf_success)
return status;
/* FIXME-MU: compensate for mailutils deficiency */
- if (mailfrom[0] == 0)
- mailfrom = "<>";
+ mailfrom = (io->mailfrom[0] == 0) ? "<>" : io->mailfrom;
rc = mu_address_create(&addr, mailfrom);
if (rc) {
mu_error(_("cannot create address `%s': %s"),
@@ -508,17 +561,19 @@ callout(struct smtp_io_data *io,
return mf_temp_failure;
}
- status = callout_io(io, email, ehlo, addr);
+ status = callout_io(io, hostname, addr);
mu_address_destroy(&addr);
- io->callback(io->callback_closure,
- "SENT", smtp_last_sent(io));
- io->callback(io->callback_closure,
- "RECV", smtp_last_received(io));
+ if (io->callback) {
+ io->callback(io->callback_closure,
+ "SENT", smtp_last_sent(io));
+ io->callback(io->callback_closure,
+ "RECV", smtp_last_received(io));
+ }
debug4(1,
- "%spoll exited with status: %s; sent \"%s\", got \"%s\"",
+ "%s: poll exited with status: %s; sent \"%s\", got \"%s\"",
io->id,
mf_status_str(status),
smtp_last_sent(io),
@@ -533,7 +588,90 @@ callout(struct smtp_io_data *io,
}
mf_status
-listens_on (const char *client_addr, int port, time_t timeout)
+callout_mx(struct smtp_io_data *iop, const char *hostname, int *pcount)
+{
+ int i;
+ mxbuf_t mxbuf;
+ mf_status rc, mxstat = getmx(hostname, mxbuf);
+
+ if (pcount)
+ *pcount = 0;
+ switch (mxstat) {
+ case mf_temp_failure:
+ case mf_failure:
+ case mf_not_found:
+ rc = mxstat;
+ break;
+
+ case mf_success:
+ debug1(2,"Checking MX servers for %s", iop->email);
+ rc = mf_not_found;
+ for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
+ rc = callout_host(iop, mxbuf[i]);
+ if (mf_resolved(rc))
+ break;
+ }
+ if (pcount) {
+ for (; i < MAXMXCOUNT && mxbuf[i]; i++)
+ ;
+ *pcount = i;
+ }
+ dns_freemx(mxbuf);
+ break;
+
+ default:
+ abort();
+ }
+ return rc;
+}
+
+/* Method "strict". Verifies whether EMAIL is understood either by
+ host CLIENT_ADDR or one of MX servers of its domain */
+mf_status
+callout_strict(struct smtp_io_data *iop, const char *hostname)
+{
+ mf_status rc;
+
+ rc = callout_host(iop, hostname);
+ if (!mf_resolved(rc)) {
+ int mxcount;
+ mf_status mx_stat;
+ mx_stat = callout_mx(iop, hostname, &mxcount);
+ if (!(mx_stat == mf_not_found && mxcount == 0)
+ && (mf_resolved(mx_stat)
+ || mx_stat == mf_temp_failure))
+ rc = mx_stat;
+ }
+ return rc;
+}
+
+mf_status
+callout_standard(struct smtp_io_data *iop)
+{
+ int rc;
+
+ char *p = strchr(iop->email, '@');
+ if (p == NULL) {
+ mu_error(_("invalid address: %s"), iop->email);
+ rc = mf_not_found;
+ } else {
+ int mxcount;
+ p++;
+ rc = callout_mx(iop, p, &mxcount);
+ if (rc != mf_success && mxcount == 0) {
+ mf_status host_stat;
+ host_stat = callout_host(iop, p);
+ if (mf_resolved(host_stat)
+ || host_stat == mf_temp_failure)
+ rc = host_stat;
+ }
+ }
+ return rc;
+}
+
+
+mf_status
+listens_on (const char *hostname, int port, time_t timeout)
{
unsigned count = 0;
mu_stream_t stream;
@@ -543,8 +681,8 @@ listens_on (const char *client_addr, int port, time_t timeout)
if (port == 0)
port = 25;
- debug2(10, "client_addr = %s, port = %d", client_addr, port);
- rc = mu_tcp_stream_create_with_source_ip (&stream, client_addr, port,
+ debug2(10, "hostname = %s, port = %d", hostname, port);
+ rc = mu_tcp_stream_create_with_source_ip (&stream, hostname, port,
source_address,
MU_STREAM_NONBLOCK);
if (rc) {
@@ -567,7 +705,7 @@ listens_on (const char *client_addr, int port, time_t timeout)
}
mu_stream_destroy(&stream, mu_stream_get_owner(stream));
- debug3 (10, "mu_stream_open(%s): %s, %u", client_addr, mu_strerror(rc),
+ debug3 (10, "mu_stream_open(%s): %s, %u", hostname, mu_strerror(rc),
count);
return rc == 0 ? mf_success :
diff --git a/mfd/dns.c b/mfd/dns.c
index ed7065d0..1c33143b 100644
--- a/mfd/dns.c
+++ b/mfd/dns.c
@@ -37,7 +37,7 @@ dns_to_mf_status(dns_status stat)
}
mf_status
-getmx(char *host, mxbuf_t mxbuf)
+getmx(const char *host, mxbuf_t mxbuf)
{
mf_status rc = dns_cache_get(T_MX, host, mxbuf, MAXMXCOUNT);
if (!mf_resolved(rc)) {
diff --git a/mfd/engine.c b/mfd/engine.c
index 6c9b1cc6..e1f2de06 100644
--- a/mfd/engine.c
+++ b/mfd/engine.c
@@ -251,12 +251,17 @@ capture_eom(eval_environ_t env)
-static void
+void
mfl_smtp_io_callback(void *data, const char *key, const char *value)
{
eval_environ_t env = data;
- if (strcmp (key, "INIT") == 0)
+ if (strcmp (key, "INIT") == 0) {
+ set_last_poll_helo(env, "");
+ set_last_poll_greeting(env, "");
+ set_last_poll_sent(env, "");
+ set_last_poll_recv(env, "");
+ } else if (strcmp (key, "GRTNG") == 0)
set_last_poll_greeting(env, value);
else if (strcmp (key, "HELO") == 0)
set_last_poll_helo(env, "");
@@ -266,71 +271,6 @@ mfl_smtp_io_callback(void *data, const char *key, const char *value)
set_last_poll_recv(env, value);
}
-/* Verify whether EMAIL address is served by host CLIENT_ADDR. */
-mf_status
-check_on_host(eval_environ_t env, char *email, char *client_addr,
- char *ehlo, char *mailfrom)
-{
- mf_status status;
- smtp_io_t io;
- const char *id = mailfromd_msgid(env_get_context(env));
-
- io = smtp_io_create(id ? id : "(none)",
- smtp_timeout_soft,
- mfl_smtp_io_callback,
- env);
-
- set_last_poll_helo(env, "");
- set_last_poll_greeting(env, "");
- set_last_poll_sent(env, "");
- set_last_poll_recv(env, "");
-
- status = callout(io, client_addr, email, ehlo, mailfrom);
- smtp_io_free(io);
-
- return status;
-}
-
-mf_status
-check_mx_records(eval_environ_t env, char *email, char *client_addr,
- char *ehlo, char *mailfrom, int *pcount)
-{
- int i;
- mxbuf_t mxbuf;
- mf_status rc, mxstat = getmx(client_addr, mxbuf);
-
- if (pcount)
- *pcount = 0;
- switch (mxstat) {
- case mf_temp_failure:
- case mf_failure:
- case mf_not_found:
- rc = mxstat;
- break;
-
- case mf_success:
- debug1(2,"Checking MX servers for %s", email);
- rc = mf_not_found;
- for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
- rc = check_on_host(env, email, mxbuf[i],
- ehlo, mailfrom);
- if (mf_resolved(rc))
- break;
- }
- if (pcount) {
- for (; i < MAXMXCOUNT && mxbuf[i]; i++)
- ;
- *pcount = i;
- }
- dns_freemx(mxbuf);
- break;
-
- default:
- abort();
- }
- return rc;
-}
-
/* Method "strict". Verifies whether EMAIL is understood either by
host CLIENT_ADDR or one of MX servers of its domain */
mf_status
@@ -344,18 +284,19 @@ method_strict(eval_environ_t env, char *email, char *client_addr,
rc = cache_get2(email, client_addr);
if (!mf_resolved(rc)) {
+ smtp_io_t io;
+ const char *id = mailfromd_msgid(env_get_context(env));
+
set_cache_used(env, 0);
- rc = check_on_host(env, email, client_addr, ehlo, mailfrom);
- if (!mf_resolved(rc)) {
- int mxcount;
- mf_status mx_stat;
- mx_stat = check_mx_records(env, email, client_addr,
- ehlo, mailfrom, &mxcount);
- if (!(mx_stat == mf_not_found && mxcount == 0)
- && (mf_resolved(mx_stat)
- || mx_stat == mf_temp_failure))
- rc = mx_stat;
- }
+
+ io = smtp_io_create(id,
+ smtp_timeout_soft,
+ mfl_smtp_io_callback,
+ env);
+ smtp_io_setup_callout(io, email, ehlo, mailfrom);
+ rc = callout_strict(io, client_addr);
+ smtp_io_free(io);
+
if (mf_resolved(rc))
cache_insert2(email, client_addr, rc);
} else {
@@ -380,24 +321,17 @@ method_standard(eval_environ_t env, char *email, char *ehlo, char *mailfrom)
rc = cache_get(email);
if (!mf_resolved(rc)) {
- char *p = strchr(email, '@');
+ smtp_io_t io;
+ const char *id = mailfromd_msgid(env_get_context(env));
+
set_cache_used(env, 0);
- if (p == NULL) {
- mu_error(_("invalid address: %s"), email);
- rc = mf_not_found;
- } else {
- int mxcount;
- rc = check_mx_records(env, email, p+1, ehlo, mailfrom,
- &mxcount);
- if (rc != mf_success && mxcount == 0) {
- mf_status host_stat;
- host_stat = check_on_host(env, email, p+1,
- ehlo, mailfrom);
- if (mf_resolved(host_stat)
- || host_stat == mf_temp_failure)
- rc = host_stat;
- }
- }
+
+ io = smtp_io_create(id,
+ smtp_timeout_soft,
+ mfl_smtp_io_callback,
+ env);
+ rc = callout_standard(io);
+ smtp_io_free(io);
if (mf_resolved(rc))
cache_insert(email, rc);
} else {
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index 4ea27ff1..5df54636 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -151,7 +151,7 @@ mf_status resolve_ipstr_domain(const char *ipstr, const char *domain,
char **phbuf);
mf_status resolve_hostname(const char *host, char **pipbuf);
-mf_status getmx(char *ipstr, mxbuf_t mxbuf);
+mf_status getmx(const char *ipstr, mxbuf_t mxbuf);
mf_status getmxip(char *host, GACOPYZ_UINT32_T ipbuf[MAXMXCOUNT],
size_t *pcount);
@@ -955,6 +955,8 @@ void env_msgmod(eval_environ_t env, enum msgmod_opcode opcode,
void capture_on(void);
const char *env_get_macro(eval_environ_t env, const char *symbol);
+void mfl_smtp_io_callback(void *data, const char *key, const char *value);
+
/* Runtime functions */
const char *mailfromd_msgid(SMFICTX *ctx);
@@ -1037,10 +1039,10 @@ struct db_format *db_format_install(struct db_format *fmt);
struct db_format *db_format_lookup(const char *name);
void db_format_enumerate(dbfmt_enumerator_t fp, void *data);
-mf_status cache_get(char *email);
-void cache_insert(char *email, mf_status rc);
-mf_status cache_get2(char *email, char *client_addr);
-void cache_insert2(char *email, char *client_addr, mf_status rc);
+mf_status cache_get(const char *email);
+void cache_insert(const char *email, mf_status rc);
+mf_status cache_get2(const char *email, const char *client_addr);
+void cache_insert2(const char *email, const char *client_addr, mf_status rc);
mf_status dns_cache_get(int type, const char *keystr, char **rbuf,
size_t rcnt);
@@ -1132,9 +1134,22 @@ typedef struct smtp_io_data *smtp_io_t;
smtp_io_t smtp_io_create(const char *id, time_t timeout[],
smtp_io_callback_t callback,
void *closure);
+void smtp_io_setup_callout(struct smtp_io_data *iop,
+ const char *email,
+ const char *ehlo,
+ const char *mailfrom);
+
void smtp_io_free(struct smtp_io_data *iop);
-mf_status callout(smtp_io_t io,
- char *client_addr,
- char *email, char *ehlo, char *mailfrom);
+const char *smtp_io_email(struct smtp_io_data *iop);
+
+mf_status callout_host(struct smtp_io_data *, const char *);
+mf_status callout_mx(struct smtp_io_data *, const char *, int *);
+mf_status callout_strict(struct smtp_io_data *, const char *);
+mf_status callout_standard(struct smtp_io_data *);
+/* savsrv.c */
+int callout_session_server(const char *id, int fd,
+ struct sockaddr const *sa, socklen_t len,
+ void *server_data, void *srvman_data);
+
diff --git a/mfd/main.c b/mfd/main.c
index a1e89d6f..8ffff463 100644
--- a/mfd/main.c
+++ b/mfd/main.c
@@ -2092,80 +2092,19 @@ smtp_timeout_cfg_init()
}
-
-static int
-cb_url(mu_debug_t err, void *data, mu_config_value_t *arg)
-{
- mu_url_t url;
- int rc;
-
- if (mu_cfg_assert_value_type(arg, MU_CFG_STRING, err))
- return 0;
- rc = mu_url_create(&url, arg->v.string);
- if (rc) {
- mf_error_on_locus(err,
- _("cannot create URL from `%s': %s"),
- arg->v.string, mu_strerror(rc));
- return 0;
- }
- rc = mu_url_parse(url);
- if (rc) {
- mu_url_destroy(&url);
- mf_error_on_locus(err,
- _("%s: error parsing URL: %s"),
- arg->v.string, mu_strerror(rc));
- return 0;
- }
- *(mu_url_t*) data = url;
- return 0;
-}
-
-
-
-struct callout_resolver_server {
- mu_url_t url;
- mu_acl_t acl;
-};
-
-struct callout_resolver_server callout_resolver;
-
-struct mu_cfg_param callout_resolver_section_param[] = {
- { "listen", mu_cfg_callback,
- NULL, offsetof(struct callout_resolver_server, url), cb_url,
- N_("Listen on this URL."),
- N_("url") },
- { "acl", mu_cfg_section,
- NULL, offsetof(struct callout_resolver_server, acl) },
- { NULL }
-};
-
-void
-callout_resolver_cfg_init()
-{
- struct mu_cfg_section *section;
-
- if (mu_create_canned_section ("callout-resolver", &section) == 0) {
- section->parser = NULL;
- section->docstring = N_("Set-up callout resolver server.");
- section->label = NULL;
- mu_cfg_section_add_params(section,
- callout_resolver_section_param);
- }
-}
-
-
/* Milter configuration */
-struct milter_config_stmt {
+struct server_config_stmt {
const char *id;
mu_url_t url;
mu_acl_t acl;
size_t max_children;
+ mfd_server_func_t server;
};
-static struct milter_config_stmt milter_config_stmt;
+static struct server_config_stmt server_config_stmt;
static int
-cb_milter_stmt_listen(mu_debug_t err, void *data, mu_config_value_t *arg)
+cb_server_stmt_listen(mu_debug_t err, void *data, mu_config_value_t *arg)
{
if (mu_cfg_assert_value_type(arg, MU_CFG_STRING, err))
return 1;
@@ -2173,27 +2112,27 @@ cb_milter_stmt_listen(mu_debug_t err, void *data, mu_config_value_t *arg)
return 0;
}
-struct mu_cfg_param milter_section_param[] = {
+struct mu_cfg_param server_section_param[] = {
{ "id", mu_cfg_string,
- &milter_config_stmt.id, 0,
+ &server_config_stmt.id, 0,
NULL,
N_("Server ID.") },
{ "listen", mu_cfg_callback,
- &milter_config_stmt.url, 0,
- cb_milter_stmt_listen,
+ &server_config_stmt.url, 0,
+ cb_server_stmt_listen,
N_("Listen on this URL."),
N_("url") },
{ "max-instances", mu_cfg_size,
- &milter_config_stmt.max_children, 0,
+ &server_config_stmt.max_children, 0,
NULL,
N_("Maximum number of instances allowed for this server.") },
{ "acl", mu_cfg_section,
- &milter_config_stmt.acl },
+ &server_config_stmt.acl },
{ NULL }
};
static int
-milter_section_parser(enum mu_cfg_section_stage stage,
+server_section_parser(enum mu_cfg_section_stage stage,
const mu_cfg_node_t *node,
const char *section_label, void **section_data,
void *call_data,
@@ -2201,22 +2140,35 @@ milter_section_parser(enum mu_cfg_section_stage stage,
{
switch (stage) {
case mu_cfg_section_start:
- memset(&milter_config_stmt, 0, sizeof(milter_config_stmt));
+ memset(&server_config_stmt, 0, sizeof(server_config_stmt));
+ if (mu_cfg_assert_value_type (node->label, MU_CFG_STRING,
+ tree->debug))
+ return 1;
+ if (strcmp(node->label->v.string, "milter") == 0)
+ server_config_stmt.server = milter_session_server;
+ else if (strcmp(node->label->v.string, "callout") == 0)
+ server_config_stmt.server = callout_session_server;
+ else {
+ mu_cfg_format_error (tree->debug,
+ MU_DEBUG_ERROR,
+ _("unknown server type"));
+ return 1;
+ }
break;
case mu_cfg_section_end:
- if (!milter_config_stmt.id)
- milter_config_stmt.id = next_server_id();
- if (milter_config_stmt.url) {
+ if (!server_config_stmt.id)
+ server_config_stmt.id = next_server_id();
+ if (server_config_stmt.url && server_config_stmt.server) {
mfd_server_t srv =
- mfd_server_new(milter_config_stmt.id,
- milter_config_stmt.url,
- milter_session_server);
+ mfd_server_new(server_config_stmt.id,
+ server_config_stmt.url,
+ server_config_stmt.server);
if (srv) {
mfd_server_set_max_children(srv,
- milter_config_stmt.max_children);
+ server_config_stmt.max_children);
mfd_server_set_acl(srv,
- milter_config_stmt.acl);
+ server_config_stmt.acl);
mfd_srvman_attach_server(srv);
}
}
@@ -2226,15 +2178,15 @@ milter_section_parser(enum mu_cfg_section_stage stage,
}
void
-milter_cfg_init()
+server_cfg_init()
{
struct mu_cfg_section *section;
- if (mu_create_canned_section ("milter", &section) == 0) {
- section->parser = milter_section_parser;
- section->docstring = N_("Configure milter server.");
- section->label = NULL;
- mu_cfg_section_add_params(section, milter_section_param);
+ if (mu_create_canned_section ("server", &section) == 0) {
+ section->parser = server_section_parser;
+ section->docstring = N_("Configure milter or callout server.");
+ section->label = "milter | callout";
+ mu_cfg_section_add_params(section, server_section_param);
}
}
@@ -2317,7 +2269,7 @@ struct mu_cfg_param mf_cfg_param[] = {
{ "listen", mu_cfg_callback, NULL, 0, cb_milter_listen,
N_("Listen for milter requests on the given URL."),
N_("url") },
- { "milter", mu_cfg_section },
+ { "server", mu_cfg_section },
{ "acl", mu_cfg_section, &srvman_param.acl },
#ifdef USE_SYSLOG_ASYNC
{ "syslog-async", mu_cfg_bool, &use_syslog_async, 0, NULL,
@@ -2341,8 +2293,6 @@ struct mu_cfg_param mf_cfg_param[] = {
{ "database", mu_cfg_section, NULL },
- { "callout-resolver", mu_cfg_section, &callout_resolver },
-
{ NULL }
};
@@ -2668,8 +2618,7 @@ main(int argc, char **argv)
mu_acl_cfg_init();
database_cfg_init();
smtp_timeout_cfg_init();
- milter_cfg_init();
- callout_resolver_cfg_init();
+ server_cfg_init();
mu_argp_init(program_version, "<" PACKAGE_BUGREPORT ">");
mu_app_rcfile = SYSCONFDIR "/mailfromd.conf";
diff --git a/mfd/savsrv.c b/mfd/savsrv.c
new file mode 100644
index 00000000..4e90d364
--- /dev/null
+++ b/mfd/savsrv.c
@@ -0,0 +1,225 @@
+/* This file is part of Mailfromd.
+ Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#define MF_SOURCE_NAME MF_SOURCE_CALLOUT
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <mailutils/mailutils.h>
+#include <mailutils/daemon.h>
+
+#include "mailfromd.h"
+
+struct callout_command {
+ const char *command;
+ int argc;
+ int (*handler) (FILE *, int, char **);
+};
+
+struct vrfy_queue {
+ struct vrfy_queue *next;
+