summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreric <eric@openbsd.org>2013-05-24 17:03:14 +0000
committereric <eric@openbsd.org>2013-05-24 17:03:14 +0000
commit299c4efe12e77bae73d606814f8d26caf2899d5e (patch)
tree5f235afe5f57e2b38493b87b42a79203484124bc
parentFix dow register value in resettodr() - kernel computes it zero-based, but (diff)
downloadwireguard-openbsd-299c4efe12e77bae73d606814f8d26caf2899d5e.tar.xz
wireguard-openbsd-299c4efe12e77bae73d606814f8d26caf2899d5e.zip
sync with OpenSMTPD 5.3.2
ok gilles@
-rw-r--r--usr.sbin/smtpd/Makefile2
-rw-r--r--usr.sbin/smtpd/aldap.c8
-rw-r--r--usr.sbin/smtpd/aliases.c29
-rw-r--r--usr.sbin/smtpd/bounce.c12
-rw-r--r--usr.sbin/smtpd/compress_backend.c65
-rw-r--r--usr.sbin/smtpd/compress_gzip.c158
-rw-r--r--usr.sbin/smtpd/config.c7
-rw-r--r--usr.sbin/smtpd/control.c19
-rw-r--r--usr.sbin/smtpd/delivery.c6
-rw-r--r--usr.sbin/smtpd/delivery_filename.c3
-rw-r--r--usr.sbin/smtpd/delivery_lmtp.c237
-rw-r--r--usr.sbin/smtpd/delivery_maildir.c5
-rw-r--r--usr.sbin/smtpd/delivery_mbox.c6
-rw-r--r--usr.sbin/smtpd/delivery_mda.c3
-rw-r--r--usr.sbin/smtpd/dict.c70
-rw-r--r--usr.sbin/smtpd/dns.c22
-rw-r--r--usr.sbin/smtpd/enqueue.c16
-rw-r--r--usr.sbin/smtpd/envelope.c8
-rw-r--r--usr.sbin/smtpd/expand.c22
-rw-r--r--usr.sbin/smtpd/filter_api.c57
-rw-r--r--usr.sbin/smtpd/forward.c14
-rw-r--r--usr.sbin/smtpd/iobuf.c5
-rw-r--r--usr.sbin/smtpd/ioev.c46
-rw-r--r--usr.sbin/smtpd/lka.c117
-rw-r--r--usr.sbin/smtpd/lka_session.c97
-rw-r--r--usr.sbin/smtpd/log.c19
-rw-r--r--usr.sbin/smtpd/makemap.c57
-rw-r--r--usr.sbin/smtpd/makemap/Makefile9
-rw-r--r--usr.sbin/smtpd/mda.c35
-rw-r--r--usr.sbin/smtpd/mfa.c3
-rw-r--r--usr.sbin/smtpd/mfa_session.c28
-rw-r--r--usr.sbin/smtpd/mproc.c154
-rw-r--r--usr.sbin/smtpd/mta.c62
-rw-r--r--usr.sbin/smtpd/mta_session.c72
-rw-r--r--usr.sbin/smtpd/parse.y151
-rw-r--r--usr.sbin/smtpd/parser.c7
-rw-r--r--usr.sbin/smtpd/parser.h8
-rw-r--r--usr.sbin/smtpd/queue.c142
-rw-r--r--usr.sbin/smtpd/queue_backend.c139
-rw-r--r--usr.sbin/smtpd/queue_fsqueue.c62
-rw-r--r--usr.sbin/smtpd/queue_null.c3
-rw-r--r--usr.sbin/smtpd/queue_ram.c5
-rw-r--r--usr.sbin/smtpd/ruleset.c3
-rw-r--r--usr.sbin/smtpd/scheduler.c65
-rw-r--r--usr.sbin/smtpd/scheduler_backend.c3
-rw-r--r--usr.sbin/smtpd/scheduler_null.c40
-rw-r--r--usr.sbin/smtpd/scheduler_ramqueue.c231
-rw-r--r--usr.sbin/smtpd/smtp.c6
-rw-r--r--usr.sbin/smtpd/smtp_session.c116
-rw-r--r--usr.sbin/smtpd/smtpctl.86
-rw-r--r--usr.sbin/smtpd/smtpctl.c119
-rw-r--r--usr.sbin/smtpd/smtpctl/Makefile2
-rw-r--r--usr.sbin/smtpd/smtpd-api.h34
-rw-r--r--usr.sbin/smtpd/smtpd-defines.h29
-rw-r--r--usr.sbin/smtpd/smtpd.84
-rw-r--r--usr.sbin/smtpd/smtpd.c193
-rw-r--r--usr.sbin/smtpd/smtpd.conf.518
-rw-r--r--usr.sbin/smtpd/smtpd.h232
-rw-r--r--usr.sbin/smtpd/smtpd/Makefile4
-rw-r--r--usr.sbin/smtpd/ssl.c7
-rw-r--r--usr.sbin/smtpd/ssl_smtpd.c3
-rw-r--r--usr.sbin/smtpd/stat_backend.c16
-rw-r--r--usr.sbin/smtpd/stat_ramstat.c3
-rw-r--r--usr.sbin/smtpd/table.c571
-rw-r--r--usr.sbin/smtpd/table_db.c190
-rw-r--r--usr.sbin/smtpd/table_getpwnam.c46
-rw-r--r--usr.sbin/smtpd/table_ldap.c200
-rw-r--r--usr.sbin/smtpd/table_sqlite.c150
-rw-r--r--usr.sbin/smtpd/table_static.c340
-rw-r--r--usr.sbin/smtpd/to.c48
-rw-r--r--usr.sbin/smtpd/tree.c70
-rw-r--r--usr.sbin/smtpd/util.c39
-rw-r--r--usr.sbin/smtpd/waitq.c4
73 files changed, 2760 insertions, 2022 deletions
diff --git a/usr.sbin/smtpd/Makefile b/usr.sbin/smtpd/Makefile
index 98cb2c8c839..06920b9248e 100644
--- a/usr.sbin/smtpd/Makefile
+++ b/usr.sbin/smtpd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.9 2009/03/18 01:56:52 jacekm Exp $
+# $OpenBSD: Makefile,v 1.10 2013/05/24 17:03:14 eric Exp $
.include <bsd.own.mk>
diff --git a/usr.sbin/smtpd/aldap.c b/usr.sbin/smtpd/aldap.c
index bf470853b9b..796aebd26df 100644
--- a/usr.sbin/smtpd/aldap.c
+++ b/usr.sbin/smtpd/aldap.c
@@ -1,5 +1,5 @@
-/* $Id: aldap.c,v 1.4 2013/01/31 18:34:43 eric Exp $ */
-/* $OpenBSD: aldap.c,v 1.4 2013/01/31 18:34:43 eric Exp $ */
+/* $Id: aldap.c,v 1.5 2013/05/24 17:03:14 eric Exp $ */
+/* $OpenBSD: aldap.c,v 1.5 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
@@ -29,7 +29,7 @@
#if 0
#define DEBUG
#endif
-#define VERSION 3
+#define ALDAP_VERSION 3
static struct ber_element *ldap_parse_search_filter(struct ber_element *,
char *);
@@ -92,7 +92,7 @@ aldap_bind(struct aldap *ldap, char *binddn, char *bindcred)
goto fail;
elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP,
- (unsigned long)LDAP_REQ_BIND, VERSION, binddn, bindcred,
+ (unsigned long)LDAP_REQ_BIND, ALDAP_VERSION, binddn, bindcred,
BER_CLASS_CONTEXT, (unsigned long)LDAP_AUTH_SIMPLE);
if (elm == NULL)
goto fail;
diff --git a/usr.sbin/smtpd/aliases.c b/usr.sbin/smtpd/aliases.c
index 8056487ed45..899540289a3 100644
--- a/usr.sbin/smtpd/aliases.c
+++ b/usr.sbin/smtpd/aliases.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aliases.c,v 1.63 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: aliases.c,v 1.64 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -40,10 +39,10 @@ int
aliases_get(struct expand *expand, const char *username)
{
struct expandnode *xn;
- char buf[MAX_LOCALPART_SIZE];
+ char buf[SMTPD_MAXLOCALPARTSIZE];
size_t nbaliases;
int ret;
- struct expand *xp = NULL;
+ union lookup lk;
struct table *mapping = NULL;
struct table *userbase = NULL;
@@ -51,13 +50,13 @@ aliases_get(struct expand *expand, const char *username)
userbase = expand->rule->r_userbase;
xlowercase(buf, username, sizeof(buf));
- ret = table_lookup(mapping, buf, K_ALIAS, (void **)&xp);
+ ret = table_lookup(mapping, buf, K_ALIAS, &lk);
if (ret <= 0)
return ret;
/* foreach node in table_alias expandtree, we merge */
nbaliases = 0;
- RB_FOREACH(xn, expandtree, &xp->tree) {
+ RB_FOREACH(xn, expandtree, &lk.expand->tree) {
if (xn->type == EXPAND_INCLUDE)
nbaliases += aliases_expand_include(expand,
xn->u.buffer);
@@ -69,7 +68,7 @@ aliases_get(struct expand *expand, const char *username)
}
}
- expand_free(xp);
+ expand_free(lk.expand);
log_debug("debug: aliases_get: returned %zd aliases", nbaliases);
return nbaliases;
@@ -123,7 +122,7 @@ int
aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr)
{
struct expandnode *xn;
- struct expand *xp;
+ union lookup lk;
char buf[SMTPD_MAXLINESIZE];
char *pbuf;
int nbaliases;
@@ -140,7 +139,7 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr)
xlowercase(buf, buf, sizeof(buf));
/* First, we lookup for full entry: user@domain */
- ret = table_lookup(mapping, buf, K_ALIAS, (void **)&xp);
+ ret = table_lookup(mapping, buf, K_ALIAS, &lk);
if (ret < 0)
return (-1);
if (ret)
@@ -149,7 +148,7 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr)
/* Failed ? We lookup for username only */
pbuf = strchr(buf, '@');
*pbuf = '\0';
- ret = table_lookup(mapping, buf, K_ALIAS, (void **)&xp);
+ ret = table_lookup(mapping, buf, K_ALIAS, &lk);
if (ret < 0)
return (-1);
if (ret)
@@ -157,21 +156,21 @@ aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr)
*pbuf = '@';
/* Failed ? We lookup for catch all for virtual domain */
- ret = table_lookup(mapping, pbuf, K_ALIAS, (void **)&xp);
+ ret = table_lookup(mapping, pbuf, K_ALIAS, &lk);
if (ret < 0)
return (-1);
if (ret)
goto expand;
/* Failed ? We lookup for a *global* catch all */
- ret = table_lookup(mapping, "@", K_ALIAS, (void **)&xp);
+ ret = table_lookup(mapping, "@", K_ALIAS, &lk);
if (ret <= 0)
return (ret);
expand:
/* foreach node in table_virtual expand, we merge */
nbaliases = 0;
- RB_FOREACH(xn, expandtree, &xp->tree) {
+ RB_FOREACH(xn, expandtree, &lk.expand->tree) {
if (xn->type == EXPAND_INCLUDE)
nbaliases += aliases_expand_include(expand,
xn->u.buffer);
@@ -183,7 +182,7 @@ expand:
}
}
- expand_free(xp);
+ expand_free(lk.expand);
log_debug("debug: aliases_virtual_get: '%s' resolved to %d nodes",
buf, nbaliases);
@@ -197,7 +196,7 @@ aliases_expand_include(struct expand *expand, const char *filename)
FILE *fp;
char *line;
size_t len, lineno = 0;
- char delim[3] = { '\\', '\0', '#' };
+ char delim[3] = { '\\', '#', '\0' };
fp = fopen(filename, "r");
if (fp == NULL) {
diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c
index d09cd7604fd..0d02897feef 100644
--- a/usr.sbin/smtpd/bounce.c
+++ b/usr.sbin/smtpd/bounce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bounce.c,v 1.55 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: bounce.c,v 1.56 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@poolp.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <err.h>
@@ -128,7 +127,7 @@ bounce_add(uint64_t evpid)
bounce_init();
if (queue_envelope_load(evpid, &evp) == 0) {
- m_create(p_scheduler, IMSG_DELIVERY_PERMFAIL, 0, 0, -1, 9);
+ m_create(p_scheduler, IMSG_DELIVERY_PERMFAIL, 0, 0, -1);
m_add_evpid(p_scheduler, evpid);
m_close(p_scheduler);
return;
@@ -440,7 +439,7 @@ bounce_next(struct bounce_session *s)
n = iobuf_queued(&s->iobuf);
- while (iobuf_len(&s->iobuf) < BOUNCE_HIWAT) {
+ while (iobuf_queued(&s->iobuf) < BOUNCE_HIWAT) {
line = fgetln(s->msgfp, &len);
if (line == NULL)
break;
@@ -505,12 +504,11 @@ bounce_delivery(struct bounce_message *msg, int delivery, const char *status)
evp.lasttry = msg->timeout;
envelope_set_errormsg(&evp, "%s", status);
queue_envelope_update(&evp);
- m_create(p_scheduler, delivery, 0, 0, -1, MSZ_EVP);
+ m_create(p_scheduler, delivery, 0, 0, -1);
m_add_envelope(p_scheduler, &evp);
m_close(p_scheduler);
} else {
- m_create(p_scheduler, delivery, 0, 0, -1,
- sizeof(be->id) + 1);
+ m_create(p_scheduler, delivery, 0, 0, -1);
m_add_evpid(p_scheduler, be->id);
m_close(p_scheduler);
queue_envelope_delete(be->id);
diff --git a/usr.sbin/smtpd/compress_backend.c b/usr.sbin/smtpd/compress_backend.c
index b7a957671c1..08ac9665a32 100644
--- a/usr.sbin/smtpd/compress_backend.c
+++ b/usr.sbin/smtpd/compress_backend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compress_backend.c,v 1.7 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: compress_backend.c,v 1.8 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Charles Longeau <chl@openbsd.org>
@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -32,71 +31,39 @@
#include "smtpd.h"
-extern struct compress_backend compress_gzip;
+#define BUFFER_SIZE 16364
-static struct compress_backend *backend = NULL;
+extern struct compress_backend compress_gzip;
-int
-compress_backend_init(const char *name)
+struct compress_backend *
+compress_backend_lookup(const char *name)
{
if (!strcmp(name, "gzip"))
- backend = &compress_gzip;
-
- if (backend)
- return (1);
- return (0);
-}
-
-void *
-compress_new(void)
-{
- return (backend->compress_new());
-}
-
-size_t
-compress_chunk(void *hdl, void *ib, size_t ibsz, void *ob, size_t obsz)
-{
- return (backend->compress_chunk(hdl, ib, ibsz, ob, obsz));
-}
+ return &compress_gzip;
-size_t
-compress_finalize(void *hdl, void *ob, size_t obsz)
-{
- return (backend->compress_finalize(hdl, ob, obsz));
-}
-
-void *
-uncompress_new(void)
-{
- return (backend->uncompress_new());
-}
-
-size_t
-uncompress_chunk(void *hdl, void *ib, size_t ibsz, void *ob, size_t obsz)
-{
- return (backend->uncompress_chunk(hdl, ib, ibsz, ob, obsz));
+ return NULL;
}
size_t
-uncompress_finalize(void *hdl, void *ob, size_t obsz)
+compress_chunk(void *ib, size_t ibsz, void *ob, size_t obsz)
{
- return (backend->uncompress_finalize(hdl, ob, obsz));
+ return (env->sc_comp->compress_chunk(ib, ibsz, ob, obsz));
}
size_t
-compress_buffer(char *ib, size_t iblen, char *ob, size_t oblen)
+uncompress_chunk(void *ib, size_t ibsz, void *ob, size_t obsz)
{
- return (compress_chunk(NULL, ib, iblen, ob, oblen));
+ return (env->sc_comp->uncompress_chunk(ib, ibsz, ob, obsz));
}
-size_t
-uncompress_buffer(char *ib, size_t iblen, char *ob, size_t oblen)
+int
+compress_file(FILE *ifile, FILE *ofile)
{
- return (uncompress_chunk(NULL, ib, iblen, ob, oblen));
+ return (env->sc_comp->compress_file(ifile, ofile));
}
int
uncompress_file(FILE *ifile, FILE *ofile)
{
- return (0);
-};
+ return (env->sc_comp->uncompress_file(ifile, ofile));
+}
diff --git a/usr.sbin/smtpd/compress_gzip.c b/usr.sbin/smtpd/compress_gzip.c
index 32a31770fc3..e601137f1f2 100644
--- a/usr.sbin/smtpd/compress_gzip.c
+++ b/usr.sbin/smtpd/compress_gzip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compress_gzip.c,v 1.6 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: compress_gzip.c,v 1.7 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -39,55 +38,146 @@
#include "smtpd.h"
#include "log.h"
-static void* compress_gzip_new(void);
-static size_t compress_gzip_chunk(void *, void *, size_t, void *, size_t);
-static size_t compress_gzip_finalize(void *, void *, size_t);
-static void* uncompress_gzip_new(void);
-static size_t uncompress_gzip_chunk(void *, void *, size_t, void *, size_t);
-static size_t uncompress_gzip_finalize(void *, void *, size_t);
+
+#define GZIP_BUFFER_SIZE 16384
+
+
+static size_t compress_gzip_chunk(void *, size_t, void *, size_t);
+static size_t uncompress_gzip_chunk(void *, size_t, void *, size_t);
+static int compress_gzip_file(FILE *, FILE *);
+static int uncompress_gzip_file(FILE *, FILE *);
+
struct compress_backend compress_gzip = {
- compress_gzip_new,
compress_gzip_chunk,
- compress_gzip_finalize,
-
- uncompress_gzip_new,
uncompress_gzip_chunk,
- uncompress_gzip_finalize,
-};
-static void *
-compress_gzip_new(void)
-{
- return (NULL);
-}
+ compress_gzip_file,
+ uncompress_gzip_file,
+};
static size_t
-compress_gzip_chunk(void *hdl, void *ib, size_t ibsz, void *ob, size_t obsz)
+compress_gzip_chunk(void *ib, size_t ibsz, void *ob, size_t obsz)
{
- return (-1);
+ z_stream *strm;
+ size_t ret = 0;
+
+ if ((strm = calloc(1, sizeof *strm)) == NULL)
+ return 0;
+
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ if (deflateInit2(strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
+ (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK)
+ goto end;
+
+ strm->avail_in = ibsz;
+ strm->next_in = (unsigned char *)ib;
+ strm->avail_out = obsz;
+ strm->next_out = (unsigned char *)ob;
+ if (deflate(strm, Z_FINISH) != Z_STREAM_END)
+ goto end;
+
+ ret = strm->total_out;
+
+end:
+ deflateEnd(strm);
+ free(strm);
+ return ret;
}
+
static size_t
-compress_gzip_finalize(void *hdl, void *ob, size_t obsz)
+uncompress_gzip_chunk(void *ib, size_t ibsz, void *ob, size_t obsz)
{
- return (-1);
-}
+ z_stream *strm;
+ size_t ret = 0;
-static void *
-uncompress_gzip_new(void)
-{
- return (NULL);
+ if ((strm = calloc(1, sizeof *strm)) == NULL)
+ return 0;
+
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ strm->avail_in = 0;
+ strm->next_in = Z_NULL;
+
+ if (inflateInit2(strm, (15+16)) != Z_OK)
+ goto end;
+
+ strm->avail_in = ibsz;
+ strm->next_in = (unsigned char *)ib;
+ strm->avail_out = obsz;
+ strm->next_out = (unsigned char *)ob;
+
+ if (inflate(strm, Z_FINISH) != Z_STREAM_END)
+ goto end;
+
+ ret = strm->total_out;
+
+end:
+ deflateEnd(strm);
+ free(strm);
+ return ret;
}
-static size_t
-uncompress_gzip_chunk(void *hdl, void *ib, size_t ibsz, void *ob, size_t obsz)
+
+static int
+compress_gzip_file(FILE *in, FILE *out)
{
- return (-1);
+ gzFile gzf;
+ char ibuf[GZIP_BUFFER_SIZE];
+ int r, w;
+ int ret = 0;
+
+ if (in == NULL || out == NULL)
+ return (0);
+
+ gzf = gzdopen(fileno(out), "wb");
+ if (gzf == NULL)
+ return (0);
+
+ while ((r = fread(ibuf, 1, GZIP_BUFFER_SIZE, in)) != 0) {
+ if ((w = gzwrite(gzf, ibuf, r)) != r)
+ goto end;
+ }
+ if (! feof(in))
+ goto end;
+
+ ret = 1;
+
+end:
+ gzclose(gzf);
+ return (ret);
}
-static size_t
-uncompress_gzip_finalize(void *hdl, void *ob, size_t obsz)
+
+static int
+uncompress_gzip_file(FILE *in, FILE *out)
{
- return (-1);
+ gzFile gzf;
+ char obuf[GZIP_BUFFER_SIZE];
+ int r, w;
+ int ret = 0;
+
+ if (in == NULL || out == NULL)
+ return (0);
+
+ gzf = gzdopen(fileno(in), "r");
+ if (gzf == NULL)
+ return (0);
+
+ while ((r = gzread(gzf, obuf, sizeof(obuf))) > 0) {
+ if ((w = fwrite(obuf, r, 1, out)) != 1)
+ goto end;
+ }
+ if (! gzeof(gzf))
+ goto end;
+
+ ret = 1;
+
+end:
+ gzclose(gzf);
+ return (ret);
}
diff --git a/usr.sbin/smtpd/config.c b/usr.sbin/smtpd/config.c
index e553c5bef96..c647a479b69 100644
--- a/usr.sbin/smtpd/config.c
+++ b/usr.sbin/smtpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.19 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: config.c,v 1.20 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <event.h>
@@ -54,12 +53,10 @@ purge_config(uint8_t what)
env->sc_listeners = NULL;
}
if (what & PURGE_TABLES) {
- while (tree_root(env->sc_tables_tree, NULL, (void **)&t))
+ while (dict_root(env->sc_tables_dict, NULL, (void **)&t))
table_destroy(t);
free(env->sc_tables_dict);
- free(env->sc_tables_tree);
env->sc_tables_dict = NULL;
- env->sc_tables_tree = NULL;
}
if (what & PURGE_RULES) {
while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) {
diff --git a/usr.sbin/smtpd/control.c b/usr.sbin/smtpd/control.c
index e3267d6d6fd..8312bad41ca 100644
--- a/usr.sbin/smtpd/control.c
+++ b/usr.sbin/smtpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.84 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: control.c,v 1.85 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -320,6 +319,7 @@ control_accept(int listenfd, short event, void *arg)
if (getpeereid(connfd, &c->euid, &c->egid) == -1)
fatal("getpeereid");
c->id = ++connid;
+ c->mproc.proc = PROC_CLIENT;
c->mproc.handler = control_dispatch_ext;
c->mproc.data = c;
mproc_init(&c->mproc, connfd);
@@ -413,6 +413,11 @@ control_dispatch_ext(struct mproc *p, struct imsg *imsg)
return;
}
+ if (imsg->hdr.peerid != IMSG_VERSION) {
+ m_compose(p, IMSG_CTL_FAIL, IMSG_VERSION, 0, -1, NULL, 0);
+ return;
+ }
+
switch (imsg->hdr.type) {
case IMSG_SMTP_ENQUEUE_FD:
if (env->sc_flags & (SMTPD_SMTP_PAUSED |
@@ -477,7 +482,7 @@ control_dispatch_ext(struct mproc *p, struct imsg *imsg)
verbose = v;
log_verbose(verbose);
- m_create(p_parent, IMSG_CTL_VERBOSE, 0, 0, -1, 9);
+ m_create(p_parent, IMSG_CTL_VERBOSE, 0, 0, -1);
m_add_int(p_parent, verbose);
m_close(p_parent);
@@ -495,7 +500,7 @@ control_dispatch_ext(struct mproc *p, struct imsg *imsg)
verbose |= v;
log_verbose(verbose);
- m_create(p_parent, IMSG_CTL_TRACE, 0, 0, -1, 9);
+ m_create(p_parent, IMSG_CTL_TRACE, 0, 0, -1);
m_add_int(p_parent, v);
m_close(p_parent);
@@ -513,7 +518,7 @@ control_dispatch_ext(struct mproc *p, struct imsg *imsg)
verbose &= ~v;
log_verbose(verbose);
- m_create(p_parent, IMSG_CTL_UNTRACE, 0, 0, -1, 9);
+ m_create(p_parent, IMSG_CTL_UNTRACE, 0, 0, -1);
m_add_int(p_parent, v);
m_close(p_parent);
@@ -530,7 +535,7 @@ control_dispatch_ext(struct mproc *p, struct imsg *imsg)
memcpy(&v, imsg->data, sizeof(v));
profiling |= v;
- m_create(p_parent, IMSG_CTL_PROFILE, 0, 0, -1, 9);
+ m_create(p_parent, IMSG_CTL_PROFILE, 0, 0, -1);
m_add_int(p_parent, v);
m_close(p_parent);
@@ -547,7 +552,7 @@ control_dispatch_ext(struct mproc *p, struct imsg *imsg)
memcpy(&v, imsg->data, sizeof(v));
profiling &= ~v;
- m_create(p_parent, IMSG_CTL_UNPROFILE, 0, 0, -1, 9);
+ m_create(p_parent, IMSG_CTL_UNPROFILE, 0, 0, -1);
m_add_int(p_parent, v);
m_close(p_parent);
diff --git a/usr.sbin/smtpd/delivery.c b/usr.sbin/smtpd/delivery.c
index c2d63484216..7e0519b953f 100644
--- a/usr.sbin/smtpd/delivery.c
+++ b/usr.sbin/smtpd/delivery.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: delivery.c,v 1.3 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: delivery.c,v 1.4 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -38,6 +37,7 @@ extern struct delivery_backend delivery_backend_mbox;
extern struct delivery_backend delivery_backend_mda;
extern struct delivery_backend delivery_backend_maildir;
extern struct delivery_backend delivery_backend_filename;
+extern struct delivery_backend delivery_backend_lmtp;
struct delivery_backend *
delivery_backend_lookup(enum action_type type)
@@ -51,6 +51,8 @@ delivery_backend_lookup(enum action_type type)
return &delivery_backend_maildir;
case A_FILENAME:
return &delivery_backend_filename;
+ case A_LMTP:
+ return &delivery_backend_lmtp;
default:
fatal("unsupported delivery_backend type");
}
diff --git a/usr.sbin/smtpd/delivery_filename.c b/usr.sbin/smtpd/delivery_filename.c
index 097d68153ae..1ce62432834 100644
--- a/usr.sbin/smtpd/delivery_filename.c
+++ b/usr.sbin/smtpd/delivery_filename.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: delivery_filename.c,v 1.8 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: delivery_filename.c,v 1.9 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
diff --git a/usr.sbin/smtpd/delivery_lmtp.c b/usr.sbin/smtpd/delivery_lmtp.c
new file mode 100644
index 00000000000..53f8552ce28
--- /dev/null
+++ b/usr.sbin/smtpd/delivery_lmtp.c
@@ -0,0 +1,237 @@
+/* $OpenBSD: delivery_lmtp.c,v 1.1 2013/05/24 17:03:14 eric Exp $ */
+
+/*
+ * Copyright (c) 2013 Ashish SHUKLA <ashish.is@lostca.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <event.h>
+#include <fcntl.h>
+#include <imsg.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+#include "log.h"
+
+
+/* mda backend */
+static void delivery_lmtp_open(struct deliver *);
+
+static int inet_socket(char *);
+static int unix_socket(char *);
+static char* lmtp_getline(FILE *);
+
+struct delivery_backend delivery_backend_lmtp = {
+ 0, delivery_lmtp_open
+};
+
+enum lmtp_state {
+ LMTP_BANNER,
+ LMTP_LHLO,
+ LMTP_MAIL_FROM,
+ LMTP_RCPT_TO,
+ LMTP_DATA,
+ LMTP_QUIT,
+ LMTP_BYE
+};
+
+static int
+inet_socket (char *address)
+{
+ int s, n;
+ char *hostname, *servname;
+ struct addrinfo hints;
+ struct addrinfo *result0, *result;
+
+ servname = strchr(address, ':');
+ *servname++ = '\0';
+ hostname = address;
+ s = -1;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ n = getaddrinfo(hostname, servname, &hints, &result0);
+ if (n)
+ errx(1, "%s", gai_strerror(n));
+
+ for (result = result0; s < 0 && result; result = result->ai_next) {
+ if ((s = socket(result->ai_family, result->ai_socktype,
+ result->ai_protocol)) == -1) {
+ warn("socket");
+ continue;
+ }
+ if (connect(s, result->ai_addr, result->ai_addrlen) == -1) {
+ warn("connect");
+ close(s);
+ s = -1;
+ continue;
+ }
+ break;
+ }
+
+ freeaddrinfo(result0);
+
+ return s;
+}
+
+static int
+unix_socket(char *path) {
+ struct sockaddr_un addr;
+ int s;
+
+ bzero(&addr, sizeof(addr));
+
+ if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) {
+ warn("socket");
+ return -1;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
+
+ if (connect(s, (struct sockaddr*) &addr, sizeof(addr)) == -1) {
+ warn("connect");
+ close(s);
+ return -1;
+ }
+
+ return s;
+}
+
+static void
+delivery_lmtp_open(struct deliver *deliver)
+{
+ char *buffer;
+ char *lbuf;
+ char lhloname[255];
+ int s;
+ FILE *fp;
+ enum lmtp_state state = LMTP_BANNER;
+ size_t len;
+
+ fp = NULL;
+
+ if (deliver->to[0] == '/')
+ s = unix_socket(deliver->to);
+ else
+ s = inet_socket(deliver->to);
+
+ if (s == -1 || (fp = fdopen(s, "r+")) == NULL)
+ err(1, "couldn't establish connection");
+
+ while (!feof(fp) && !ferror(fp) && state != LMTP_BYE) {
+ buffer = lmtp_getline(fp);
+ if (buffer == NULL)
+ err(1, "No input received");
+
+ switch (state) {
+ case LMTP_BANNER:
+ if (strncmp("220 ", buffer, 4) != 0)
+ errx(1, "Invalid LMTP greeting: %s\n", buffer);
+ gethostname(lhloname, sizeof lhloname );
+ fprintf(fp, "LHLO %s\r\n", lhloname);
+ state = LMTP_LHLO;
+ break;
+
+ case LMTP_LHLO:
+ if (buffer[0] != '2')
+ errx(1, "LHLO rejected: %s\n", buffer);
+ if (strlen(buffer) < 4)
+ errx(1, "Invalid LMTP LHLO answer: %s\n", buffer);
+ if (buffer[3] == '-')
+ continue; /* multi-line */
+ fprintf(fp, "MAIL FROM:<%s>\r\n", deliver->from);
+ state = LMTP_MAIL_FROM;
+ break;
+
+ case LMTP_MAIL_FROM:
+ if (buffer[0] != '2')
+ errx(1, "MAIL FROM rejected: %s\n", buffer);
+ fprintf(fp, "RCPT TO:<%s>\r\n", deliver->user);
+ state = LMTP_RCPT_TO;
+ break;
+
+ case LMTP_RCPT_TO:
+ if (buffer[0] != '2')
+ errx(1, "RCPT TO rejected: %s\n", buffer);
+ fprintf(fp, "DATA\r\n");
+ state = LMTP_DATA;
+ break;
+
+ case LMTP_DATA:
+ if (buffer[0] != '3')
+ errx(1, "DATA rejected: %s\n", buffer);
+ lbuf = NULL;
+ while ((buffer = fgetln(stdin, &len))) {
+ if (buffer[len- 1] == '\n')
+ buffer[len - 1] = '\0';
+ else {
+ if ((lbuf = malloc(len + 1)) == NULL)
+ err(1, NULL);
+ memcpy(lbuf, buffer, len);
+ lbuf[len] = '\0';
+ buffer = lbuf;
+ }
+ fprintf(fp, "%s%s\r\n",
+ *buffer == '.' ? "." : "", buffer);
+ }
+ free(lbuf);
+ fprintf(fp, ".\r\n");
+ state = LMTP_QUIT;
+ break;
+
+ case LMTP_QUIT:
+ if (buffer[0] != '2')
+ errx(1, "Delivery error: %s\n", buffer);
+ fprintf(fp, "QUIT\r\n");
+ state = LMTP_BYE;
+ break;
+
+ case LMTP_BYE:
+ break;
+ }
+ }
+
+ _exit(0);
+}
+
+static char*
+lmtp_getline(FILE *fp)
+{
+ char *buffer;
+ size_t len;
+
+ if ((buffer = fgetln(fp, &len)) != NULL) {
+ if (len >= 2 && buffer[len-2] == '\r')
+ buffer[len-2] = '\0';
+ buffer[len-1] = '\0';
+ }
+
+ return buffer;
+}
diff --git a/usr.sbin/smtpd/delivery_maildir.c b/usr.sbin/smtpd/delivery_maildir.c
index 663bb1cb755..4f854e18526 100644
--- a/usr.sbin/smtpd/delivery_maildir.c
+++ b/usr.sbin/smtpd/delivery_maildir.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: delivery_maildir.c,v 1.11 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: delivery_maildir.c,v 1.12 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -52,7 +51,7 @@ struct delivery_backend delivery_backend_maildir = {
static void
delivery_maildir_open(struct deliver *deliver)
{
- char tmp[PATH_MAX], new[PATH_MAX];
+ char tmp[SMTPD_MAXPATHLEN], new[SMTPD_MAXPATHLEN];
int ch, fd;
FILE *fp;
char *msg;
diff --git a/usr.sbin/smtpd/delivery_mbox.c b/usr.sbin/smtpd/delivery_mbox.c
index 34b9eb37ee8..13bb2178d86 100644
--- a/usr.sbin/smtpd/delivery_mbox.c
+++ b/usr.sbin/smtpd/delivery_mbox.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: delivery_mbox.c,v 1.8 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: delivery_mbox.c,v 1.9 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -56,6 +55,9 @@ delivery_mbox_open(struct deliver *deliver)
environ_new[0] = "PATH=" _PATH_DEFPATH;
environ_new[1] = (char *)NULL;
environ = environ_new;
+
+ if (deliver->from[0] == '\0')
+ strlcpy(deliver->from, "MAILER-DAEMON", sizeof deliver->from);
execle(PATH_MAILLOCAL, PATH_MAILLOCAL, "-f", deliver->from,
deliver->to, (char *)NULL, environ_new);
perror("execle");
diff --git a/usr.sbin/smtpd/delivery_mda.c b/usr.sbin/smtpd/delivery_mda.c
index a087f5617a4..f374e702a88 100644
--- a/usr.sbin/smtpd/delivery_mda.c
+++ b/usr.sbin/smtpd/delivery_mda.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: delivery_mda.c,v 1.7 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: delivery_mda.c,v 1.8 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
diff --git a/usr.sbin/smtpd/dict.c b/usr.sbin/smtpd/dict.c
index b513413e7f7..07fdc771e7c 100644
--- a/usr.sbin/smtpd/dict.c
+++ b/usr.sbin/smtpd/dict.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dict.c,v 1.1 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: dict.c,v 1.2 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -41,7 +41,7 @@ struct dictentry {
static int dictentry_cmp(struct dictentry *, struct dictentry *);
-SPLAY_PROTOTYPE(dict, dictentry, entry, dictentry_cmp);
+SPLAY_PROTOTYPE(_dict, dictentry, entry, dictentry_cmp);
int
dict_check(struct dict *d, const char *k)
@@ -51,7 +51,7 @@ dict_check(struct dict *d, const char *k)
if (strlcpy(key.key, k, sizeof key.key) >= sizeof key.key)
errx(1, "dict_check(%p, %s): key too large", d, k);
- return (SPLAY_FIND(dict, d, &key) != NULL);
+ return (SPLAY_FIND(_dict, &d->dict, &key) != NULL);
}
void *
@@ -62,11 +62,13 @@ dict_set(struct dict *d, const char *k, void *data)
if (strlcpy(key.key, k, sizeof key.key) >= sizeof key.key)
errx(1, "dict_set(%p, %s): key too large", d, k);
- if ((entry = SPLAY_FIND(dict, d, &key)) == NULL) {
- entry = xmalloc(sizeof *entry, "dict_set");
+ if ((entry = SPLAY_FIND(_dict, &d->dict, &key)) == NULL) {
+ if ((entry = malloc(sizeof *entry)) == NULL)
+ err(1, "dict_set: malloc");
(void)strlcpy(entry->key, k, sizeof entry->key);
- SPLAY_INSERT(dict, d, entry);
+ SPLAY_INSERT(_dict, &d->dict, entry);
old = NULL;
+ d->count += 1;
} else
old = entry->data;
@@ -80,12 +82,14 @@ dict_xset(struct dict *d, const char * k, void *data)
{
struct dictentry *entry;
- entry = xmalloc(sizeof *entry, "dict_xset");
+ if ((entry = malloc(sizeof *entry)) == NULL)
+ err(1, "dict_xset: malloc");
if (strlcpy(entry->key, k, sizeof entry->key) >= sizeof entry->key)
errx(1, "dict_xset(%p, %s): key too large", d, k);
entry->data = data;
- if (SPLAY_INSERT(dict, d, entry))
+ if (SPLAY_INSERT(_dict, &d->dict, entry))
errx(1, "dict_xset(%p, %s)", d, k);
+ d->count += 1;
}
void *
@@ -95,7 +99,7 @@ dict_get(struct dict *d, const char *k)
if (strlcpy(key.key, k, sizeof key.key) >= sizeof key.key)
errx(1, "dict_get(%p, %s): key too large", d, k);
- if ((entry = SPLAY_FIND(dict, d, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_dict, &d->dict, &key)) == NULL)
return (NULL);
return (entry->data);
@@ -108,7 +112,7 @@ dict_xget(struct dict *d, const char *k)
if (strlcpy(key.key, k, sizeof key.key) >= sizeof key.key)
errx(1, "dict_xget(%p, %s): key too large", d, k);
- if ((entry = SPLAY_FIND(dict, d, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_dict, &d->dict, &key)) == NULL)
errx(1, "dict_xget(%p, %s)", d, k);
return (entry->data);
@@ -122,12 +126,13 @@ dict_pop(struct dict *d, const char *k)
if (strlcpy(key.key, k, sizeof key.key) >= sizeof key.key)
errx(1, "dict_pop(%p, %s): key too large", d, k);
- if ((entry = SPLAY_FIND(dict, d, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_dict, &d->dict, &key)) == NULL)
return (NULL);
data = entry->data;
- SPLAY_REMOVE(dict, d, entry);
+ SPLAY_REMOVE(_dict, &d->dict, entry);
free(entry);
+ d->count -= 1;
return (data);
}
@@ -140,12 +145,13 @@ dict_xpop(struct dict *d, const char *k)
if (strlcpy(key.key, k, sizeof key.key) >= sizeof key.key)
errx(1, "dict_xpop(%p, %s): key too large", d, k);
- if ((entry = SPLAY_FIND(dict, d, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_dict, &d->dict, &key)) == NULL)
errx(1, "dict_xpop(%p, %s)", d, k);
data = entry->data;
- SPLAY_REMOVE(dict, d, entry);
+ SPLAY_REMOVE(_dict, &d->dict, entry);
free(entry);
+ d->count -= 1;
return (data);
}
@@ -155,15 +161,17 @@ dict_poproot(struct dict *d, const char **k, void **data)
{
struct dictentry *entry;
- entry = SPLAY_ROOT(d);
+ entry = SPLAY_ROOT(&d->dict);
if (entry == NULL)
return (0);
if (k)
*k = entry->key;
if (data)
*data = entry->data;
- SPLAY_REMOVE(dict, d, entry);
+ SPLAY_REMOVE(_dict, &d->dict, entry);
free(entry);
+ d->count -= 1;
+
return (1);
}
@@ -172,7 +180,7 @@ dict_root(struct dict *d, const char **k, void **data)
{
struct dictentry *entry;
- entry = SPLAY_ROOT(d);
+ entry = SPLAY_ROOT(&d->dict);
if (entry == NULL)
return (0);
if (k)
@@ -188,9 +196,9 @@ dict_iter(struct dict *d, void **hdl, const char **k, void **data)
struct dictentry *curr = *hdl;
if (curr == NULL)
- curr = SPLAY_MIN(dict, d);
+ curr = SPLAY_MIN(_dict, &d->dict);
else
- curr = SPLAY_NEXT(dict, d, curr);
+ curr = SPLAY_NEXT(_dict, &d->dict, curr);
if (curr) {
*hdl = curr;
@@ -212,21 +220,21 @@ dict_iterfrom(struct dict *d, void **hdl, const char *kfrom, const char **k,
if (curr == NULL) {
if (kfrom == NULL)
- curr = SPLAY_MIN(dict, d);
+ curr = SPLAY_MIN(_dict, &d->dict);
else {
if (strlcpy(key.key, kfrom, sizeof key.key)
>= sizeof key.key)
errx(1, "dict_iterfrom(%p, %s): key too large",
d, kfrom);
- curr = SPLAY_FIND(dict, d, &key);
+ curr = SPLAY_FIND(_dict, &d->dict, &key);
if (curr == NULL) {
- SPLAY_INSERT(dict, d, &key);
- curr = SPLAY_NEXT(dict, d, &key);
- SPLAY_REMOVE(dict, d, &key);
+ SPLAY_INSERT(_dict, &d->dict, &key);
+ curr = SPLAY_NEXT(_dict, &d->dict, &key);
+ SPLAY_REMOVE(_dict, &d->dict, &key);
}
}
} else
- curr = SPLAY_NEXT(dict, d, curr);
+ curr = SPLAY_NEXT(_dict, &d->dict, curr);
if (curr) {
*hdl = curr;
@@ -245,12 +253,14 @@ dict_merge(struct dict *dst, struct dict *src)
{
struct dictentry *entry;
- while (!SPLAY_EMPTY(src)) {
- entry = SPLAY_ROOT(src);
- SPLAY_REMOVE(dict, src, entry);
- if (SPLAY_INSERT(dict, dst, entry))
+ while (!SPLAY_EMPTY(&src->dict)) {
+ entry = SPLAY_ROOT(&src->dict);
+ SPLAY_REMOVE(_dict, &src->dict, entry);
+ if (SPLAY_INSERT(_dict, &dst->dict, entry))
errx(1, "dict_merge: duplicate");
}
+ dst->count += src->count;
+ src->count = 0;
}
static int
@@ -259,4 +269,4 @@ dictentry_cmp(struct dictentry *a, struct dictentry *b)
return strcmp(a->key, b->key);
}
-SPLAY_GENERATE(dict, dictentry, entry, dictentry_cmp);
+SPLAY_GENERATE(_dict, dictentry, entry, dictentry_cmp);
diff --git a/usr.sbin/smtpd/dns.c b/usr.sbin/smtpd/dns.c
index 33e0eb5fc40..506f82f027b 100644
--- a/usr.sbin/smtpd/dns.c
+++ b/usr.sbin/smtpd/dns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.65 2013/04/30 12:07:21 eric Exp $ */
+/* $OpenBSD: dns.c,v 1.66 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -48,7 +48,7 @@ struct dns_session {
struct mproc *p;
uint64_t reqid;
int type;
- char name[MAXHOSTNAMELEN];
+ char name[SMTPD_MAXHOSTNAMELEN];
size_t mxfound;
int error;
int refcount;
@@ -69,7 +69,7 @@ static void dns_dispatch_mx_preference(int, struct async_res *, void *);
void
dns_query_host(uint64_t id, const char *host)
{
- m_create(p_lka, IMSG_DNS_HOST, 0, 0, -1, 128);
+ m_create(p_lka, IMSG_DNS_HOST, 0, 0, -1);
m_add_id(p_lka, id);
m_add_string(p_lka, host);
m_close(p_lka);
@@ -78,7 +78,7 @@ dns_query_host(uint64_t id, const char *host)
void
dns_query_ptr(uint64_t id, const struct sockaddr *sa)
{
- m_create(p_lka, IMSG_DNS_PTR, 0, 0, -1, 128);
+ m_create(p_lka, IMSG_DNS_PTR, 0, 0, -1);
m_add_id(p_lka, id);
m_add_sockaddr(p_lka, sa);
m_close(p_lka);
@@ -87,7 +87,7 @@ dns_query_ptr(uint64_t id, const struct sockaddr *sa)
void
dns_query_mx(uint64_t id, const char *domain)
{
- m_create(p_lka, IMSG_DNS_MX, 0, 0, -1, 128);
+ m_create(p_lka, IMSG_DNS_MX, 0, 0, -1);
m_add_id(p_lka, id);
m_add_string(p_lka, domain);
m_close(p_lka);
@@ -96,7 +96,7 @@ dns_query_mx(uint64_t id, const char *domain)
void
dns_query_mx_preference(uint64_t id, const char *domain, const char *mx)
{
- m_create(p_lka, IMSG_DNS_MX_PREFERENCE, 0, 0, -1, 128);
+ m_create(p_lka, IMSG_DNS_MX_PREFERENCE, 0, 0, -1);
m_add_id(p_lka, id);
m_add_string(p_lka, domain);
m_add_string(p_lka, mx);
@@ -171,7 +171,7 @@ dns_dispatch_host(int ev, struct async_res *ar, void *arg)
for (ai = ar->ar_addrinfo; ai; ai = ai->ai_next) {
s->mxfound++;
- m_create(s->p, IMSG_DNS_HOST, 0, 0, -1, 128);
+ m_create(s->p, IMSG_DNS_HOST, 0, 0, -1);
m_add_id(s->p, s->reqid);
m_add_sockaddr(s->p, ai->ai_addr);
m_add_int(s->p, lookup->preference);
@@ -187,7 +187,7 @@ dns_dispatch_host(int ev, struct async_res *ar, void *arg)
if (--s->refcount)
return;
- m_create(s->p, IMSG_DNS_HOST_END, 0, 0, -1, 24);
+ m_create(s->p, IMSG_DNS_HOST_END, 0, 0, -1);
m_add_id(s->p, s->reqid);
m_add_int(s->p, s->mxfound ? DNS_OK : DNS_ENOTFOUND);
m_close(s->p);
@@ -200,7 +200,7 @@ dns_dispatch_ptr(int ev, struct async_res *ar, void *arg)
struct dns_session *s = arg;
/* The error code could be more precise, but we don't currently care */
- m_create(s->p, IMSG_DNS_PTR, 0, 0, -1, 512);
+ m_create(s->p, IMSG_DNS_PTR, 0, 0, -1);
m_add_id(s->p, s->reqid);
m_add_int(s->p, ar->ar_gai_errno ? DNS_ENOTFOUND : DNS_OK);
if (ar->ar_gai_errno == 0)
@@ -222,7 +222,7 @@ dns_dispatch_mx(int ev, struct async_res *ar, void *arg)
if (ar->ar_h_errno && ar->ar_h_errno != NO_DATA) {
- m_create(s->p, IMSG_DNS_HOST_END, 0, 0, -1, 24);
+ m_create(s->p, IMSG_DNS_HOST_END, 0, 0, -1);
m_add_id(s->p, s->reqid);
if (ar->ar_rcode == NXDOMAIN)
m_add_int(s->p, DNS_ENONAME);
@@ -297,7 +297,7 @@ dns_dispatch_mx_preference(int ev, struct async_res *ar, void *arg)
free(ar->ar_data);
- m_create(s->p, IMSG_DNS_MX_PREFERENCE, 0, 0, -1, 36);
+ m_create(s->p, IMSG_DNS_MX_PREFERENCE, 0, 0, -1);
m_add_id(s->p, s->reqid);
m_add_int(s->p, error);
if (error == DNS_OK)
diff --git a/usr.sbin/smtpd/enqueue.c b/usr.sbin/smtpd/enqueue.c
index 0413d27927d..e51f4a220fa 100644
--- a/usr.sbin/smtpd/enqueue.c
+++ b/usr.sbin/smtpd/enqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: enqueue.c,v 1.67 2013/01/31 18:34:43 eric Exp $ */
+/* $OpenBSD: enqueue.c,v 1.68 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2005 Henning Brauer <henning@bulabula.org>
@@ -18,11 +18,10 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/tree.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
@@ -96,7 +95,7 @@ struct {
#define WSP(c) (c == ' ' || c == '\t')
int verbose = 0;
-char host[MAXHOSTNAMELEN];
+char host[SMTPD_MAXHOSTNAMELEN];
char *user = NULL;
time_t timestamp;
@@ -694,7 +693,7 @@ open_connection(void)
int fd;
int n;
- imsg_compose(ibuf, IMSG_SMTP_ENQUEUE_FD, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_SMTP_ENQUEUE_FD, IMSG_VERSION, 0, -1, NULL, 0);
while (ibuf->w.queued)
if (msgbuf_write(&ibuf->w) < 0)
@@ -732,7 +731,7 @@ open_connection(void)
int
enqueue_offline(int argc, char *argv[])
{
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
FILE *fp;
int i, fd, ch;
mode_t omode;
@@ -753,6 +752,11 @@ enqueue_offline(int argc, char *argv[])
}
umask(omode);
+ if (fchmod(fd, 0600) == -1) {
+ unlink(path);
+ exit(1);
+ }
+
for (i = 1; i < argc; i++) {
if (strchr(argv[i], '|') != NULL) {
warnx("%s contains illegal character", argv[i]);
diff --git a/usr.sbin/smtpd/envelope.c b/usr.sbin/smtpd/envelope.c
index da8cdbfd3ac..03a966befed 100644
--- a/usr.sbin/smtpd/envelope.c
+++ b/usr.sbin/smtpd/envelope.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: envelope.c,v 1.19 2013/01/31 18:34:43 eric Exp $ */
+/* $OpenBSD: envelope.c,v 1.20 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -592,6 +591,8 @@ ascii_load_mda_method(enum action_type *dest, char *buf)
*dest = A_FILENAME;
else if (strcasecmp(buf, "mda") == 0)
*dest = A_MDA;
+ else if (strcasecmp(buf, "lmtp") == 0)
+ *dest = A_LMTP;
else
return 0;
return 1;
@@ -697,6 +698,9 @@ ascii_dump_mda_method(enum action_type type, char *dest, size_t len)
char *p = NULL;
switch (type) {
+ case A_LMTP:
+ p = "lmtp";
+ break;
case A_MAILDIR:
p = "maildir";
break;
diff --git a/usr.sbin/smtpd/expand.c b/usr.sbin/smtpd/expand.c
index 4e96cdf08fe..811ce093625 100644
--- a/usr.sbin/smtpd/expand.c
+++ b/usr.sbin/smtpd/expand.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: expand.c,v 1.22 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: expand.c,v 1.23 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@poolp.org>
@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -41,6 +40,22 @@ expand_lookup(struct expand *expand, struct expandnode *key)
return RB_FIND(expandtree, &expand->tree, key);
}
+int
+expand_to_text(struct expand *expand, char *buf, size_t sz)
+{
+ struct expandnode *xn;
+
+ buf[0] = '\0';
+
+ RB_FOREACH(xn, expandtree, &expand->tree) {
+ if (buf[0])
+ strlcat(buf, ", ", sz);
+ strlcat(buf, expandnode_to_text(xn), sz);
+ }
+
+ return 1;
+}
+
void
expand_insert(struct expand *expand, struct expandnode *node)
{
@@ -223,6 +238,9 @@ expandnode_info(struct expandnode *e)
case EXPAND_ADDRESS:
type = "address";
break;
+ case EXPAND_ERROR:
+ type = "error";
+ break;
case EXPAND_INVALID:
default:
return NULL;
diff --git a/usr.sbin/smtpd/filter_api.c b/usr.sbin/smtpd/filter_api.c
index ba7696f3d9d..1c97d6a5a96 100644
--- a/usr.sbin/smtpd/filter_api.c
+++ b/usr.sbin/smtpd/filter_api.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: filter_api.c,v 1.6 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: filter_api.c,v 1.7 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -39,6 +39,8 @@ struct query {
};
static int register_done;
+static const char *filter_name;
+
static struct filter_internals {
struct mproc p;
@@ -72,12 +74,6 @@ static void filter_dispatch_helo(uint64_t, uint64_t, const char *);
static void filter_dispatch_mail(uint64_t, uint64_t, struct mailaddr *);
static void filter_dispatch_rcpt(uint64_t, uint64_t, struct mailaddr *);
-const char *
-proc_to_str(int proc)
-{
- return "PEER";
-}
-
void
filter_api_on_notify(void(*cb)(uint64_t, enum filter_status))
{
@@ -171,6 +167,10 @@ filter_api_loop(void)
register_done = 1;
+ mproc_enable(&fi.p);
+
+ usleep(1000000);
+
if (event_dispatch() < 0)
errx(1, "event_dispatch");
}
@@ -211,7 +211,7 @@ filter_api_reject_code(uint64_t id, enum filter_status status, uint32_t code,
void
filter_api_data(uint64_t id, const char *line)
{
- m_create(&fi.p, IMSG_FILTER_DATA, 0, 0, -1, 1024);
+ m_create(&fi.p, IMSG_FILTER_DATA, 0, 0, -1);
m_add_id(&fi.p, id);
m_add_string(&fi.p, line);
m_close(&fi.p);
@@ -225,7 +225,7 @@ filter_response(uint64_t qid, int status, int code, const char *line, int notify
q = tree_xpop(&queries, qid);
free(q);
- m_create(&fi.p, IMSG_FILTER_RESPONSE, 0, 0, -1, 64);
+ m_create(&fi.p, IMSG_FILTER_RESPONSE, 0, 0, -1);
m_add_id(&fi.p, qid);
m_add_int(&fi.p, status);
m_add_int(&fi.p, code);
@@ -238,6 +238,7 @@ filter_response(uint64_t qid, int status, int code, const char *line, int notify
static void
filter_api_init(void)
{
+ extern const char *__progname;
static int init = 0;
if (init)
@@ -245,9 +246,17 @@ filter_api_init(void)
init = 1;
- bzero(&fi, sizeof(fi));
+ smtpd_process = PROC_FILTER;
+ filter_name = __progname;
+
tree_init(&queries);
event_init();
+
+ bzero(&fi, sizeof(fi));
+ fi.p.proc = PROC_MFA;
+ fi.p.name = "filter";
+ fi.p.handler = filter_dispatch;
+
mproc_init(&fi.p, 0);
}
@@ -262,6 +271,8 @@ filter_dispatch(struct mproc *p, struct imsg *imsg)
uint64_t id, qid;
int status, event, hook;
+ log_debug("debug: %s: imsg %i", filter_name, imsg->hdr.type);
+
switch (imsg->hdr.type) {
case IMSG_FILTER_REGISTER:
m_msg(&m, imsg);
@@ -269,7 +280,7 @@ filter_dispatch(struct mproc *p, struct imsg *imsg)
m_end(&m);
if (v != FILTER_API_VERSION)
errx(1, "API version mismatch");
- m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1, 18);
+ m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1);
m_add_int(p, fi.hooks);
m_add_int(p, fi.flags);
m_close(p);
@@ -396,3 +407,27 @@ filter_dispatch_eom(uint64_t id, uint64_t qid)
{
fi.cb.eom(id, qid);
}
+
+/*
+ * These functions are called from mproc.c
+ */
+
+enum smtp_proc_type smtpd_process;
+
+const char *
+proc_name(enum smtp_proc_type proc)
+{
+ if (proc == PROC_FILTER)
+ return filter_name;
+ return "filter";
+}
+
+const char *
+imsg_to_str(int imsg)
+{
+ static char buf[32];
+
+ snprintf(buf, sizeof(buf), "%i", imsg);
+
+ return (buf);
+}
diff --git a/usr.sbin/smtpd/forward.c b/usr.sbin/smtpd/forward.c
index b1a498597e8..151e8a3d977 100644
--- a/usr.sbin/smtpd/forward.c
+++ b/usr.sbin/smtpd/forward.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: forward.c,v 1.34 2013/01/31 18:34:43 eric Exp $ */
+/* $OpenBSD: forward.c,v 1.35 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -45,18 +44,22 @@ forwards_get(int fd, struct expand *expand)
char *line = NULL;
size_t len;
size_t lineno;
+ size_t save;
int ret;
struct stat sb;
- ret = 0;
+ ret = -1;
if (fstat(fd, &sb) == -1)
goto end;
- /* empty or over MAX_FORWARD_SIZE, temporarily fail */
+ /* if it's empty just pretend that no expansion took place */
if (sb.st_size == 0) {
log_info("info: forward file is empty");
+ ret = 0;
goto end;
}
+
+ /* over MAX_FORWARD_SIZE, temporarily fail */
if (sb.st_size >= MAX_FORWARD_SIZE) {
log_info("info: forward file exceeds max size");
goto end;
@@ -68,6 +71,7 @@ forwards_get(int fd, struct expand *expand)
}
lineno = 0;
+ save = expand->nb_nodes;
while ((line = fparseln(fp, &len, &lineno, NULL, 0)) != NULL) {
if (! expand_line(expand, line, 0)) {
log_info("info: parse error in forward file");
@@ -80,7 +84,7 @@ forwards_get(int fd, struct expand *expand)
free(line);
}
- ret = 1;
+ ret = expand->nb_nodes > save ? 1 : 0;
end:
if (line)
diff --git a/usr.sbin/smtpd/iobuf.c b/usr.sbin/smtpd/iobuf.c
index 0523302943e..8d3e6a54c00 100644
--- a/usr.sbin/smtpd/iobuf.c
+++ b/usr.sbin/smtpd/iobuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iobuf.c,v 1.4 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: iobuf.c,v 1.5 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -15,11 +15,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/usr.sbin/smtpd/ioev.c b/usr.sbin/smtpd/ioev.c
index 8d9094a5b98..fdc9fa400ff 100644
--- a/usr.sbin/smtpd/ioev.c
+++ b/usr.sbin/smtpd/ioev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioev.c,v 1.11 2013/02/05 11:45:18 gilles Exp $ */
+/* $OpenBSD: ioev.c,v 1.12 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -15,7 +15,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
@@ -118,6 +118,7 @@ io_strevent(int evt)
switch (evt) {
CASE(IO_CONNECTED);
CASE(IO_TLSREADY);
+ CASE(IO_TLSVERIFIED);
CASE(IO_DATAIN);
CASE(IO_LOWAT);
CASE(IO_DISCONNECTED);
@@ -622,6 +623,8 @@ void
io_dispatch_connect(int fd, short ev, void *humppa)
{
struct io *io = humppa;
+ int r, e;
+ socklen_t sl;
io_frame_enter("io_dispatch_connect", io, ev);
@@ -630,8 +633,22 @@ io_dispatch_connect(int fd, short ev, void *humppa)
io->sock = -1;
io_callback(io, IO_TIMEOUT);
} else {
- io->state = IO_STATE_UP;
- io_callback(io, IO_CONNECTED);
+ sl = sizeof(e);
+ r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &e, &sl);
+ if (r == -1) {
+ warn("io_dispatch_connect: getsockopt");
+ e = errno;
+ }
+ if (e) {
+ close(fd);
+ io->sock = -1;
+ io->error = strerror(e);
+ io_callback(io, e == ETIMEDOUT ? IO_TIMEOUT : IO_ERROR);
+ }
+ else {
+ io->state = IO_STATE_UP;
+ io_callback(io, IO_CONNECTED);
+ }
}
io_frame_leave(io);
@@ -675,11 +692,11 @@ io_start_tls(struct io *io, void *ssl)
if (mode == IO_WRITE) {
io->state = IO_STATE_CONNECT_SSL;
SSL_set_connect_state(io->ssl);
- io_reset(io, EV_READ | EV_WRITE, io_dispatch_connect_ssl);
+ io_reset(io, EV_WRITE, io_dispatch_connect_ssl);
} else {
io->state = IO_STATE_ACCEPT_SSL;
SSL_set_accept_state(io->ssl);
- io_reset(io, EV_READ | EV_WRITE, io_dispatch_accept_ssl);
+ io_reset(io, EV_READ, io_dispatch_accept_ssl);
}
return (0);
@@ -853,29 +870,36 @@ io_dispatch_write_ssl(int fd, short event, void *humppa)
void
io_reload_ssl(struct io *io)
{
+ short ev = 0;
void (*dispatch)(int, short, void*) = NULL;
switch (io->state) {
case IO_STATE_CONNECT_SSL:
+ ev = EV_WRITE;
dispatch = io_dispatch_connect_ssl;
break;
case IO_STATE_ACCEPT_SSL:
+ ev = EV_READ;
dispatch = io_dispatch_accept_ssl;
break;
case IO_STATE_UP:
- if ((io->flags & IO_RW) == IO_READ)
+ ev = 0;
+ if (IO_READING(io) && !(io->flags & IO_PAUSE_IN)) {
+ ev = EV_READ;
dispatch = io_dispatch_read_ssl;
- else {
- if (io_queued(io) == 0)
- return; /* nothing to write */
+ }
+ else if (IO_WRITING(io) && !(io->flags & IO_PAUSE_OUT) && io_queued(io)) {
+ ev = EV_WRITE;
dispatch = io_dispatch_write_ssl;
}
+ if (! ev)
+ return; /* paused */
break;
default:
errx(1, "io_reload_ssl(): bad state");
}
- io_reset(io, EV_READ | EV_WRITE, dispatch);
+ io_reset(io, ev, dispatch);
}
#endif /* IO_SSL */
diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c
index eea6d30edd9..62494e3c0a7 100644
--- a/usr.sbin/smtpd/lka.c
+++ b/usr.sbin/smtpd/lka.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka.c,v 1.151 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: lka.c,v 1.152 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/uio.h>
@@ -65,12 +64,10 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
void *tmp;
int ret;
const char *key, *val;
- char *src;
struct ssl *ssl;
struct iovec iov[3];
static struct dict *ssl_dict;
static struct dict *tables_dict;
- static struct tree *tables_tree;
static struct table *table_last;
static struct ca_vrfy_req_msg *req_ca_vrfy_smtp = NULL;
static struct ca_vrfy_req_msg *req_ca_vrfy_mta = NULL;
@@ -79,15 +76,15 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
struct ca_cert_req_msg *req_ca_cert;
struct ca_cert_resp_msg resp_ca_cert;
struct sockaddr_storage ss;
- struct addrinfo hints, *ai;
struct userinfo userinfo;
struct addrname addrname;
struct envelope evp;
struct msg m;
+ union lookup lk;
char buf[SMTPD_MAXLINESIZE];
const char *tablename, *username, *password, *label;
uint64_t reqid;
- size_t i, len;
+ size_t i;
int v;
if (imsg->hdr.type == IMSG_DNS_HOST ||
@@ -159,7 +156,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
resp_ca_vrfy.reqid = req_ca_vrfy_smtp->reqid;
- if (! lka_X509_verify(req_ca_vrfy_smtp, "/etc/ssl/cert.pem", NULL))
+ if (! lka_X509_verify(req_ca_vrfy_smtp, CA_FILE, NULL))
resp_ca_vrfy.status = CA_FAIL;
else
resp_ca_vrfy.status = CA_OK;
@@ -185,7 +182,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
if (!tablename[0]) {
m_create(p_parent, IMSG_LKA_AUTHENTICATE,
- 0, 0, -1, 128);
+ 0, 0, -1);
m_add_id(p_parent, reqid);
m_add_string(p_parent, username);
m_add_string(p_parent, password);
@@ -195,7 +192,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
ret = lka_authenticate(tablename, username, password);
- m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1, 128);
+ m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1);
m_add_id(p, reqid);
m_add_int(p, ret);
m_close(p);
@@ -213,10 +210,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
ret = lka_userinfo(tablename, username, &userinfo);
- len = 32 + strlen(tablename) + strlen(username);
- if (ret == LKA_OK)
- len += sizeof(userinfo);
- m_create(p, IMSG_LKA_USERINFO, 0, 0, -1, len);
+ m_create(p, IMSG_LKA_USERINFO, 0, 0, -1);
m_add_string(p, tablename);
m_add_string(p, username);
m_add_int(p, ret);
@@ -282,7 +276,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
resp_ca_vrfy.reqid = req_ca_vrfy_mta->reqid;
- if (! lka_X509_verify(req_ca_vrfy_mta, "/etc/ssl/cert.pem", NULL))
+ if (! lka_X509_verify(req_ca_vrfy_mta, CA_FILE, NULL))
resp_ca_vrfy.status = CA_FAIL;
else
resp_ca_vrfy.status = CA_OK;
@@ -307,7 +301,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
lka_credentials(tablename, label, buf, sizeof(buf));
- m_create(p, IMSG_LKA_SECRET, 0, 0, -1, 128);
+ m_create(p, IMSG_LKA_SECRET, 0, 0, -1);
m_add_id(p, reqid);
m_add_string(p, buf);
m_close(p);
@@ -318,34 +312,26 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
m_get_id(&m, &reqid);
m_get_string(&m, &tablename);
- table = table_findbyname(tablename);
+ table = table_find(tablename, NULL);
- m_create(p, IMSG_LKA_SOURCE, 0, 0, -1, 64);
+ m_create(p, IMSG_LKA_SOURCE, 0, 0, -1);
m_add_id(p, reqid);
if (table == NULL) {
log_warn("warn: source address table %s missing",
tablename);
m_add_int(p, LKA_TEMPFAIL);
- }
+ }
else {
- ret = table_fetch(table, K_SOURCE, &src);
+ ret = table_fetch(table, K_SOURCE, &lk);
if (ret == -1)
m_add_int(p, LKA_TEMPFAIL);
else if (ret == 0)
m_add_int(p, LKA_PERMFAIL);
else {
- /* XXX find a nicer way? */
- bzero(&hints, sizeof hints);
- hints.ai_flags = AI_NUMERICHOST;
- if (getaddrinfo(src, NULL, &hints, &ai) != 0)
- m_add_int(p, LKA_TEMPFAIL);
- else {
- m_add_int(p, LKA_OK);
- m_add_sockaddr(p, ai->ai_addr);
- freeaddrinfo(ai);
- }
- free(src);
+ m_add_int(p, LKA_OK);
+ m_add_sockaddr(p,
+ (struct sockaddr *)&lk.source.addr);
}
}
m_close(p);
@@ -361,7 +347,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
ret = lka_addrname(tablename, (struct sockaddr*)&ss,
&addrname);
- m_create(p, IMSG_LKA_HELO, 0, 0, -1, 1024);
+ m_create(p, IMSG_LKA_HELO, 0, 0, -1);
m_add_id(p, reqid);
m_add_int(p, ret);
if (ret == LKA_OK)
@@ -379,15 +365,12 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
sizeof *env->sc_rules, "lka:sc_rules_reload");
tables_dict = xcalloc(1,
sizeof *tables_dict, "lka:tables_dict");
- tables_tree = xcalloc(1,
- sizeof *tables_tree, "lka:tables_tree");
ssl_dict = calloc(1, sizeof *ssl_dict);
if (ssl_dict == NULL)
fatal(NULL);
dict_init(ssl_dict);
dict_init(tables_dict);
- tree_init(tables_tree);
TAILQ_INIT(env->sc_rules_reload);
return;
@@ -425,14 +408,13 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
"lka:table");
dict_init(&table->t_dict);
dict_set(tables_dict, table->t_name, table);
- tree_set(tables_tree, table->t_id, table);
return;
case IMSG_CONF_RULE_SOURCE:
rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
tmp = env->sc_tables_dict;
env->sc_tables_dict = tables_dict;
- rule->r_sources = table_findbyname(imsg->data);
+ rule->r_sources = table_find(imsg->data, NULL);
if (rule->r_sources == NULL)
fatalx("lka: tables inconsistency");
env->sc_tables_dict = tmp;
@@ -442,7 +424,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
tmp = env->sc_tables_dict;
env->sc_tables_dict = tables_dict;
- rule->r_senders = table_findbyname(imsg->data);
+ rule->r_senders = table_find(imsg->data, NULL);
if (rule->r_senders == NULL)
fatalx("lka: tables inconsistency");
env->sc_tables_dict = tmp;
@@ -452,7 +434,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
tmp = env->sc_tables_dict;
env->sc_tables_dict = tables_dict;
- rule->r_destination = table_findbyname(imsg->data);
+ rule->r_destination = table_find(imsg->data, NULL);
if (rule->r_destination == NULL)
fatalx("lka: tables inconsistency");
env->sc_tables_dict = tmp;
@@ -462,7 +444,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
tmp = env->sc_tables_dict;
env->sc_tables_dict = tables_dict;
- rule->r_mapping = table_findbyname(imsg->data);
+ rule->r_mapping = table_find(imsg->data, NULL);
if (rule->r_mapping == NULL)
fatalx("lka: tables inconsistency");
env->sc_tables_dict = tmp;
@@ -472,7 +454,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
tmp = env->sc_tables_dict;
env->sc_tables_dict = tables_dict;
- rule->r_userbase = table_findbyname(imsg->data);
+ rule->r_userbase = table_find(imsg->data, NULL);
if (rule->r_userbase == NULL)
fatalx("lka: tables inconsistency");
env->sc_tables_dict = tmp;
@@ -497,20 +479,20 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
if (env->sc_rules)
purge_config(PURGE_RULES);
- if (env->sc_tables_tree) {
+ if (env->sc_tables_dict) {
table_close_all();
purge_config(PURGE_TABLES);
}
env->sc_rules = env->sc_rules_reload;
env->sc_ssl_dict = ssl_dict;
env->sc_tables_dict = tables_dict;
- env->sc_tables_tree = tables_tree;
+ if (verbose & TRACE_TABLES)
+ table_dump_all();
table_open_all();
ssl_dict = NULL;
table_last = NULL;
tables_dict = NULL;
- tables_tree = NULL;
/* Start fulfilling requests */
mproc_enable(p_mda);
@@ -545,7 +527,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
if (p->proc == PROC_CONTROL) {
switch (imsg->hdr.type) {
case IMSG_LKA_UPDATE_TABLE:
- table = table_findbyname(imsg->data);
+ table = table_find(imsg->data, NULL);
if (table == NULL) {
log_warnx("warn: Lookup table not found: "
"\"%s\"", (char *)imsg->data);
@@ -659,18 +641,17 @@ static int
lka_authenticate(const char *tablename, const char *user, const char *password)
{
struct table *table;
- struct credentials *creds;
- int r;
+ union lookup lk;
- log_trace(TRACE_LOOKUP, "lookup: authenticating for %s:%s", tablename, user);
- table = table_findbyname(tablename);
+ log_debug("debug: lka: authenticating for %s:%s", tablename, user);
+ table = table_find(tablename, NULL);
if (table == NULL) {
log_warnx("warn: could not find table %s needed for authentication",
tablename);
return (LKA_TEMPFAIL);
}
- switch (table_lookup(table, user, K_CREDENTIALS, (void **)&creds)) {
+ switch (table_lookup(table, user, K_CREDENTIALS, &lk)) {
case -1:
log_warnx("warn: user credentials lookup fail for %s:%s",
tablename, user);
@@ -678,9 +659,7 @@ lka_authenticate(const char *tablename, const char *user, const char *password)
case 0:
return (LKA_PERMFAIL);
default:
- r = !strcmp(creds->password, crypt(password, creds->password));
- free(creds);
- if (r)
+ if (!strcmp(lk.creds.password, crypt(password, lk.creds.password)))
return (LKA_OK);
return (LKA_PERMFAIL);
}
@@ -690,11 +669,11 @@ static int
lka_credentials(const char *tablename, const char *label, char *dst, size_t sz)
{
struct table *table;
- struct credentials *creds;
+ union lookup lk;
char *buf;
int buflen, r;
- table = table_findbyname(tablename);
+ table = table_find(tablename, NULL);
if (table == NULL) {
log_warnx("warn: credentials table %s missing", tablename);
return (LKA_TEMPFAIL);
@@ -702,7 +681,7 @@ lka_credentials(const char *tablename, const char *label, char *dst, size_t sz)
dst[0] = '\0';
- switch(table_lookup(table, label, K_CREDENTIALS, (void **)&creds)) {
+ switch(table_lookup(table, label, K_CREDENTIALS, &lk)) {
case -1:
log_warnx("warn: credentials lookup fail for %s:%s",
tablename, label);
@@ -713,12 +692,10 @@ lka_credentials(const char *tablename, const char *label, char *dst, size_t sz)
return (LKA_PERMFAIL);
default:
if ((buflen = asprintf(&buf, "%c%s%c%s", '\0',
- creds->username, '\0', creds->password)) == -1) {
- free(creds);
+ lk.creds.username, '\0', lk.creds.password)) == -1) {
log_warn("warn");
return (LKA_TEMPFAIL);
}
- free(creds);
r = __b64_ntop((unsigned char *)buf, buflen, dst, sz);
free(buf);
@@ -735,17 +712,17 @@ lka_credentials(const char *tablename, const char *label, char *dst, size_t sz)
static int
lka_userinfo(const char *tablename, const char *username, struct userinfo *res)
{
- struct userinfo *info;
struct table *table;
+ union lookup lk;
- log_trace(TRACE_LOOKUP, "lookup: userinfo %s:%s", tablename, username);
- table = table_findbyname(tablename);
+ log_debug("debug: lka: userinfo %s:%s", tablename, username);
+ table = table_find(tablename, NULL);
if (table == NULL) {
log_warnx("warn: cannot find user table %s", tablename);
return (LKA_TEMPFAIL);
}
- switch (table_lookup(table, username, K_USERINFO, (void **)&info)) {
+ switch (table_lookup(table, username, K_USERINFO, &lk)) {
case -1:
log_warnx("warn: failure during userinfo lookup %s:%s",
tablename, username);
@@ -753,8 +730,7 @@ lka_userinfo(const char *tablename, const char *username, struct userinfo *res)
case 0:
return (LKA_PERMFAIL);
default:
- *res = *info;
- free(info);
+ *res = lk.userinfo;
return (LKA_OK);
}
}
@@ -763,20 +739,20 @@ static int
lka_addrname(const char *tablename, const struct sockaddr *sa,
struct addrname *res)
{
- struct addrname *addrname;
struct table *table;
+ union lookup lk;
const char *source;
source = sa_to_text(sa);
- log_trace(TRACE_LOOKUP, "lookup: helo %s:%s", tablename, source);
- table = table_findbyname(tablename);
+ log_debug("debug: lka: helo %s:%s", tablename, source);
+ table = table_find(tablename, NULL);
if (table == NULL) {
log_warnx("warn: cannot find helo table %s", tablename);
return (LKA_TEMPFAIL);
}
- switch (table_lookup(table, source, K_ADDRNAME, (void **)&addrname)) {
+ switch (table_lookup(table, source, K_ADDRNAME, &lk)) {
case -1:
log_warnx("warn: failure during helo lookup %s:%s",
tablename, source);
@@ -784,8 +760,7 @@ lka_addrname(const char *tablename, const struct sockaddr *sa,
case 0:
return (LKA_PERMFAIL);
default:
- *res = *addrname;
- free(addrname);
+ *res = lk.addrname;
return (LKA_OK);
}
}
@@ -829,7 +804,7 @@ lka_X509_verify(struct ca_vrfy_req_msg *vrfy,
}
}
if (! ca_X509_verify(x509, x509_chain, CAfile, NULL, &errstr))
- log_trace(TRACE_LOOKUP, "lookup: X509 verify: %s", errstr);
+ log_debug("debug: lka: X509 verify: %s", errstr);
else
ret = 1;
diff --git a/usr.sbin/smtpd/lka_session.c b/usr.sbin/smtpd/lka_session.c
index cfb1fc592cf..3d79254fc7c 100644
--- a/usr.sbin/smtpd/lka_session.c
+++ b/usr.sbin/smtpd/lka_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka_session.c,v 1.55 2013/02/14 12:30:49 gilles Exp $ */
+/* $OpenBSD: lka_session.c,v 1.56 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
@@ -53,6 +52,7 @@ struct lka_session {
int flags;
int error;
+ const char *errormsg;
struct envelope envelope;
struct xnodes nodes;
/* waiting for fwdrq */
@@ -70,7 +70,8 @@ static size_t lka_expand_format(char *, size_t, const struct envelope *,
static void mailaddr_to_username(const struct mailaddr *, char *, size_t);
static const char * mailaddr_tag(const struct mailaddr *);
-static struct tree sessions = SPLAY_INITIALIZER(&sessions);
+static int init;
+static struct tree sessions;
#define MAXTOKENLEN 128
@@ -80,6 +81,11 @@ lka_session(uint64_t id, struct envelope *envelope)
struct lka_session *lks;
struct expandnode xn;
+ if (init == 0) {
+ init = 1;
+ tree_init(&sessions);
+ }
+
lks = xcalloc(1, sizeof(*lks), "lka_session");
lks->id = id;
RB_INIT(&lks->expand.tree);
@@ -104,6 +110,7 @@ lka_session_forward_reply(struct forward_req *fwreq, int fd)
struct lka_session *lks;
struct rule *rule;
struct expandnode *xn;
+ int ret;
lks = tree_xget(&sessions, fwreq->id);
xn = lks->node;
@@ -132,11 +139,17 @@ lka_session_forward_reply(struct forward_req *fwreq, int fd)
xn->mapping = rule->r_mapping;
xn->userbase = rule->r_userbase;
/* forwards_get() will close the descriptor no matter what */
- if (! forwards_get(fd, &lks->expand)) {
+ ret = forwards_get(fd, &lks->expand);
+ if (ret == -1) {
log_trace(TRACE_EXPAND, "expand: temporary "
"forward error for user %s", fwreq->user);
lks->error = LKA_TEMPFAIL;
}
+ else if (ret == 0) {
+ log_trace(TRACE_EXPAND, "expand: empty .forward "
+ "for user %s, just deliver", fwreq->user);
+ lka_submit(lks, rule, xn);
+ }
}
break;
default:
@@ -174,9 +187,19 @@ lka_resume(struct lka_session *lks)
}
error:
if (lks->error) {
- m_create(p_smtp, IMSG_LKA_EXPAND_RCPT, 0, 0, -1, 24);
+ m_create(p_smtp, IMSG_LKA_EXPAND_RCPT, 0, 0, -1);
m_add_id(p_smtp, lks->id);
m_add_int(p_smtp, lks->error);
+
+ if (lks->errormsg)
+ m_add_string(p_smtp, lks->errormsg);
+ else {
+ if (lks->error == LKA_PERMFAIL)
+ m_add_string(p_smtp, "550 Invalid recipient");
+ else if (lks->error == LKA_TEMPFAIL)
+ m_add_string(p_smtp, "451 Temporary failure");
+ }
+
m_close(p_smtp);
while ((ep = TAILQ_FIRST(&lks->deliverylist)) != NULL) {
TAILQ_REMOVE(&lks->deliverylist, ep, entry);
@@ -187,15 +210,14 @@ lka_resume(struct lka_session *lks)
/* Process the delivery list and submit envelopes to queue */
while ((ep = TAILQ_FIRST(&lks->deliverylist)) != NULL) {
TAILQ_REMOVE(&lks->deliverylist, ep, entry);
- m_create(p_queue, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
- MSZ_EVP);
+ m_create(p_queue, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1);
m_add_id(p_queue, lks->id);
m_add_envelope(p_queue, ep);
m_close(p_queue);
free(ep);
}
- m_create(p_queue, IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1, 9);
+ m_create(p_queue, IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1);
m_add_id(p_queue, lks->id);
m_close(p_queue);
}
@@ -211,8 +233,9 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
struct forward_req fwreq;
struct envelope ep;
struct expandnode node;
+ struct mailaddr maddr;
int r;
- struct userinfo *tu = NULL;
+ union lookup lk;
if (xn->depth >= EXPAND_DEPTH) {
log_trace(TRACE_EXPAND, "expand: lka_expand: node too deep.");
@@ -255,7 +278,15 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
lks->expand.rule = rule;
lks->expand.parent = xn;
lks->expand.alias = 1;
- r = aliases_virtual_get(&lks->expand, &xn->u.mailaddr);
+
+ /* temporary replace the mailaddr with a copy where
+ * we eventually strip the '+'-part before lookup.
+ */
+ maddr = xn->u.mailaddr;
+ mailaddr_to_username(&xn->u.mailaddr, maddr.user,
+ sizeof maddr.user);
+
+ r = aliases_virtual_get(&lks->expand, &maddr);
if (r == -1) {
lks->error = LKA_TEMPFAIL;
log_trace(TRACE_EXPAND, "expand: lka_expand: "
@@ -317,7 +348,7 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
break;
}
- r = table_lookup(rule->r_userbase, xn->u.user, K_USERINFO, (void **)&tu);
+ r = table_lookup(rule->r_userbase, xn->u.user, K_USERINFO, &lk);
if (r == -1) {
log_trace(TRACE_EXPAND, "expand: lka_expand: "
"backend error while searching user");
@@ -335,14 +366,13 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
lks->rule = rule;
lks->node = xn;
fwreq.id = lks->id;
- (void)strlcpy(fwreq.user, tu->username, sizeof(fwreq.user));
- (void)strlcpy(fwreq.directory, tu->directory, sizeof(fwreq.directory));
- fwreq.uid = tu->uid;
- fwreq.gid = tu->gid;
+ (void)strlcpy(fwreq.user, lk.userinfo.username, sizeof(fwreq.user));
+ (void)strlcpy(fwreq.directory, lk.userinfo.directory, sizeof(fwreq.directory));
+ fwreq.uid = lk.userinfo.uid;
+ fwreq.gid = lk.userinfo.gid;
m_compose(p_parent, IMSG_PARENT_FORWARD_OPEN, 0, 0, -1,
&fwreq, sizeof(fwreq));
lks->flags |= F_WAITING;
- free(tu);
break;
case EXPAND_FILENAME:
@@ -351,6 +381,16 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
lka_submit(lks, rule, xn);
break;
+ case EXPAND_ERROR:
+ log_trace(TRACE_EXPAND, "expand: lka_expand: error: %s "
+ "[depth=%d]", xn->u.buffer, xn->depth);
+ if (xn->u.buffer[0] == '4')
+ lks->error = LKA_TEMPFAIL;
+ else if (xn->u.buffer[0] == '5')
+ lks->error = LKA_PERMFAIL;
+ lks->errormsg = xn->u.buffer;
+ break;
+
case EXPAND_FILTER:
log_trace(TRACE_EXPAND, "expand: lka_expand: filter: %s "
"[depth=%d]", xn->u.buffer, xn->depth);
@@ -375,7 +415,7 @@ lka_find_ancestor(struct expandnode *xn, enum expand_type type)
static void
lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
{
- struct userinfo *tu;
+ union lookup lk;
struct envelope *ep;
struct expandnode *xn2;
const char *tag;
@@ -392,10 +432,12 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
ep->type = D_MTA;
ep->dest = xn->u.mailaddr;
ep->agent.mta.relay = rule->r_value.relayhost;
- if (rule->r_as && rule->r_as->user[0])
+
+ /* only rewrite if not a bounce */
+ if (ep->sender.user[0] && rule->r_as && rule->r_as->user[0])
strlcpy(ep->sender.user, rule->r_as->user,
sizeof ep->sender.user);
- if (rule->r_as && rule->r_as->domain[0])
+ if (ep->sender.user[0] && rule->r_as && rule->r_as->domain[0])
strlcpy(ep->sender.domain, rule->r_as->domain,
sizeof ep->sender.domain);
break;
@@ -403,6 +445,7 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
case A_MAILDIR:
case A_FILENAME:
case A_MDA:
+ case A_LMTP:
ep->type = D_MDA;
ep->dest = lka_find_ancestor(xn, EXPAND_ADDRESS)->u.mailaddr;
@@ -418,8 +461,8 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
sizeof(ep->agent.mda.username));
}
- r = table_lookup(rule->r_userbase, ep->agent.mda.username, K_USERINFO,
- (void **)&tu);
+ r = table_lookup(rule->r_userbase, ep->agent.mda.username,
+ K_USERINFO, &lk);
if (r <= 0) {
lks->error = (r == -1) ? LKA_TEMPFAIL : LKA_PERMFAIL;
free(ep);
@@ -427,7 +470,7 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
}
strlcpy(ep->agent.mda.usertable, rule->r_userbase->t_name,
sizeof ep->agent.mda.usertable);
- strlcpy(ep->agent.mda.username, tu->username,
+ strlcpy(ep->agent.mda.username, lk.userinfo.username,
sizeof ep->agent.mda.username);
if (xn->type == EXPAND_FILENAME) {
@@ -456,8 +499,7 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
fatalx("lka_deliver: bad node type");
r = lka_expand_format(ep->agent.mda.buffer,
- sizeof(ep->agent.mda.buffer), ep, tu);
- free(tu);
+ sizeof(ep->agent.mda.buffer), ep, &lk.userinfo);
if (!r) {
lks->error = LKA_TEMPFAIL;
log_warnx("warn: format string error while"
@@ -485,6 +527,7 @@ lka_expand_token(char *dest, size_t len, const char *token,
ssize_t i;
ssize_t begoff, endoff;
const char *errstr = NULL;
+ int replace = 1;
begoff = 0;
endoff = EXPAND_BUFFER;
@@ -545,8 +588,10 @@ lka_expand_token(char *dest, size_t len, const char *token,
string = ep->sender.domain;
else if (! strcasecmp("user.username", rtoken))
string = ui->username;
- else if (! strcasecmp("user.directory", rtoken))
+ else if (! strcasecmp("user.directory", rtoken)) {
string = ui->directory;
+ replace = 0;
+ }
else if (! strcasecmp("dest.user", rtoken))
string = ep->dest.user;
else if (! strcasecmp("dest.domain", rtoken))
@@ -592,7 +637,7 @@ lka_expand_token(char *dest, size_t len, const char *token,
string += begoff;
for (; i; i--) {
- *dest = (*string == '/') ? ':' : *string;
+ *dest = (replace && *string == '/') ? ':' : *string;
dest++;
string++;
}
diff --git a/usr.sbin/smtpd/log.c b/usr.sbin/smtpd/log.c
index 637bf8e48d7..b553f2a5160 100644
--- a/usr.sbin/smtpd/log.c
+++ b/usr.sbin/smtpd/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.14 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: log.c,v 1.15 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <errno.h>
@@ -33,7 +32,9 @@
#include "log.h"
-static int debug;
+#define TRACE_DEBUG 0x1
+
+static int foreground;
static int verbose;
void vlog(int, const char *, va_list);
@@ -42,14 +43,12 @@ void logit(int, const char *, ...)
void
-log_init(int n_debug)
+log_init(int n_foreground)
{
extern char *__progname;
- debug = n_debug;
- verbose = n_debug;
-
- if (!debug)
+ foreground = n_foreground;
+ if (! foreground)
openlog(__progname, LOG_PID | LOG_NDELAY, LOG_MAIL);
tzset();
@@ -76,7 +75,7 @@ vlog(int pri, const char *fmt, va_list ap)
{
char *nfmt;
- if (debug) {
+ if (foreground) {
/* best effort in out of mem situations */
if (asprintf(&nfmt, "%s\n", fmt) == -1) {
vfprintf(stderr, fmt, ap);
@@ -140,7 +139,7 @@ log_debug(const char *emsg, ...)
{
va_list ap;
- if (verbose) {
+ if (verbose & TRACE_DEBUG) {
va_start(ap, emsg);
vlog(LOG_DEBUG, emsg, ap);
va_end(ap);
diff --git a/usr.sbin/smtpd/makemap.c b/usr.sbin/smtpd/makemap.c
index bdae0d4d858..1df0e3b04d0 100644
--- a/usr.sbin/smtpd/makemap.c
+++ b/usr.sbin/smtpd/makemap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: makemap.c,v 1.44 2013/03/29 12:56:19 tobias Exp $ */
+/* $OpenBSD: makemap.c,v 1.45 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -21,7 +21,6 @@
#include <sys/stat.h>
#include <sys/tree.h>
#include <sys/queue.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <db.h>
@@ -34,8 +33,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <util.h>
#include <unistd.h>
+#include <util.h>
#include "smtpd.h"
#include "log.h"
@@ -45,7 +44,7 @@
extern char *__progname;
__dead void usage(void);
-static int parse_map(FILE *, char *);
+static int parse_map(char *);
static int parse_entry(char *, size_t, size_t);
static int parse_mapentry(char *, size_t, size_t);
static int parse_setentry(char *, size_t, size_t);
@@ -85,13 +84,13 @@ int
main(int argc, char *argv[])
{
struct stat sb;
- char dbname[MAXPATHLEN];
- FILE *fp;
+ char dbname[SMTPD_MAXPATHLEN];
char *opts;
char *conf;
int ch;
DBTYPE dbtype = DB_HASH;
char *p;
+ mode_t omode;
log_init(1);
@@ -173,40 +172,32 @@ main(int argc, char *argv[])
if (oflag == NULL && asprintf(&oflag, "%s.db", source) == -1)
err(1, "asprintf");
+ if (strcmp(source, "-") != 0)
+ if (stat(source, &sb) == -1)
+ err(1, "stat: %s", source);
+
if (! bsnprintf(dbname, sizeof(dbname), "%s.XXXXXXXXXXX", oflag))
errx(1, "path too long");
+ omode = umask(7077);
+ if (mkstemp(dbname) == -1)
+ err(1, "mkstemp");
+ umask(omode);
- if (mktemp(dbname) == NULL)
- err(1, "mktemp");
-
- db = dbopen(dbname, O_EXCL|O_CREAT|O_EXLOCK|O_RDWR|O_SYNC, 0644,
- dbtype, NULL);
+ db = dbopen(dbname, O_EXLOCK|O_RDWR|O_SYNC, 0644, dbtype, NULL);
if (db == NULL) {
warn("dbopen: %s", dbname);
goto bad;
}
if (strcmp(source, "-") != 0)
- fp = fopen(source, "r");
- else
- fp = fdopen(STDIN_FILENO, "r");
- if (fp == NULL) {
- warn("%s", source);
- goto bad;
- }
-
- if (strcmp(source, "-") != 0) {
- if (fstat(fileno(fp), &sb) == -1)
- err(1, "stat: %s", source);
- if (fchown(db->fd(db), sb.st_uid, sb.st_gid) == -1 ||
- fchmod(db->fd(db), sb.st_mode) == -1) {
+ if (fchmod(db->fd(db), sb.st_mode) == -1 ||
+ fchown(db->fd(db), sb.st_uid, sb.st_gid) == -1) {
warn("couldn't carry ownership and perms to %s",
dbname);
goto bad;
}
- }
- if (! parse_map(fp, source))
+ if (! parse_map(source))
goto bad;
if (db->close(db) == -1) {
@@ -231,13 +222,23 @@ bad:
}
int
-parse_map(FILE *fp, char *filename)
+parse_map(char *filename)
{
+ FILE *fp;
char *line;
size_t len;
size_t lineno = 0;
char delim[] = { '\\', 0, 0 };
+ if (strcmp(filename, "-") == 0)
+ fp = fdopen(0, "r");
+ else
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ warn("%s", filename);
+ return 0;
+ }
+
if (!isatty(fileno(fp)) && flock(fileno(fp), LOCK_SH|LOCK_NB) == -1) {
if (errno == EWOULDBLOCK)
warnx("%s is locked", filename);
@@ -424,7 +425,7 @@ conf_aliases(char *cfgpath)
if (parse_config(env, cfgpath, 0))
exit(1);
- table = table_findbyname("aliases");
+ table = table_find("aliases", NULL);
if (table == NULL)
return (PATH_ALIASES);
diff --git a/usr.sbin/smtpd/makemap/Makefile b/usr.sbin/smtpd/makemap/Makefile
index 04c4290e909..1ff588b799b 100644
--- a/usr.sbin/smtpd/makemap/Makefile
+++ b/usr.sbin/smtpd/makemap/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.18 2013/01/31 14:17:48 eric Exp $
+# $OpenBSD: Makefile,v 1.19 2013/05/24 17:03:14 eric Exp $
.PATH: ${.CURDIR}/..
@@ -25,10 +25,11 @@ SRCS+= table_static.c
SRCS+= table_db.c
SRCS+= table_getpwnam.c
SRCS+= table_ldap.c
+SRCS+= table_sqlite.c
+
SRCS+= ber.c
SRCS+= aldap.c
-SRCS+= table_sqlite.c
-DPADD+= ${LIBUTIL} ${LIBCRYPTO} ${LIBSQLITE3}
-LDADD+= -lutil -lcrypto -lsqlite3
+DPADD+= ${LIBUTIL} ${LIBCRYPTO} ${LIBSQLITE3} ${LIBZ}
+LDADD+= -lutil -lcrypto -lsqlite3 -lz
.include <bsd.prog.mk>
diff --git a/usr.sbin/smtpd/mda.c b/usr.sbin/smtpd/mda.c
index 4b98b3937a4..f5a8fefbde9 100644
--- a/usr.sbin/smtpd/mda.c
+++ b/usr.sbin/smtpd/mda.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mda.c,v 1.90 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: mda.c,v 1.91 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -22,7 +22,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -68,8 +67,8 @@ struct mda_envelope {
struct mda_user {
TAILQ_ENTRY(mda_user) entry;
TAILQ_ENTRY(mda_user) entry_runnable;
- char name[MAXLOGNAME];
- char usertable[MAXPATHLEN];
+ char name[SMTPD_MAXLOGNAME];
+ char usertable[SMTPD_MAXPATHLEN];
size_t evpcount;
TAILQ_HEAD(, mda_envelope) envelopes;
int flags;
@@ -218,8 +217,7 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
strlcpy(u->name, username, sizeof u->name);
strlcpy(u->usertable, usertable, sizeof u->usertable);
u->flags |= FLAG_USER_WAITINFO;
- m_create(p_lka, IMSG_LKA_USERINFO, 0, 0, -1,
- 32 + strlen(usertable) + strlen(username));
+ m_create(p_lka, IMSG_LKA_USERINFO, 0, 0, -1);
m_add_string(p_lka, usertable);
m_add_string(p_lka, username);
m_close(p_lka);
@@ -358,6 +356,17 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
sizeof deliver.to);
break;
+ case A_LMTP:
+ deliver.mode = A_LMTP;
+ deliver.userinfo = *userinfo;
+ strlcpy(deliver.user, userinfo->username,
+ sizeof(deliver.user));
+ strlcpy(deliver.to, e->buffer,
+ sizeof(deliver.to));
+ strlcpy(deliver.from, e->sender,
+ sizeof(deliver.from));
+ break;
+
default:
errx(1, "mda: unknown delivery method: %d",
e->method);
@@ -367,8 +376,7 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
"for session %016"PRIx64 " evpid %016"PRIx64,
s->id, s->evp->id);
- m_create(p_parent, IMSG_PARENT_FORK_MDA, 0, 0, -1,
- 32 + sizeof(deliver));
+ m_create(p_parent, IMSG_PARENT_FORK_MDA, 0, 0, -1);
m_add_id(p_parent, reqid);
m_add_data(p_parent, &deliver, sizeof(deliver));
m_close(p_parent);
@@ -557,6 +565,7 @@ mda_io(struct io *io, int evt)
case IO_LOWAT:
/* done */
+ done:
if (s->datafp == NULL) {
log_debug("debug: mda: all data sent for session"
" %016"PRIx64 " evpid %016"PRIx64,
@@ -570,7 +579,7 @@ mda_io(struct io *io, int evt)
break;
if (iobuf_queue(&s->iobuf, ln, len) == -1) {
m_create(p_parent, IMSG_PARENT_KILL_MDA,
- 0, 0, -1, 128);
+ 0, 0, -1);
m_add_id(p_parent, s->id);
m_add_string(p_parent, "Out of memory");
m_close(p_parent);
@@ -587,7 +596,7 @@ mda_io(struct io *io, int evt)
if (ferror(s->datafp)) {
log_debug("debug: mda: ferror on session %016"PRIx64,
s->id);
- m_create(p_parent, IMSG_PARENT_KILL_MDA, 0, 0, -1, 128);
+ m_create(p_parent, IMSG_PARENT_KILL_MDA, 0, 0, -1);
m_add_id(p_parent, s->id);
m_add_string(p_parent, "Error reading body");
m_close(p_parent);
@@ -601,6 +610,8 @@ mda_io(struct io *io, int evt)
s->id, s->evp->id);
fclose(s->datafp);
s->datafp = NULL;
+ if (iobuf_queued(&s->iobuf) == 0)
+ goto done;
}
return;
@@ -793,7 +804,7 @@ mda_drain(void)
" for user \"%s\" evpid %016" PRIx64, s->id, u->name,
s->evp->id);
- m_create(p_queue, IMSG_QUEUE_MESSAGE_FD, 0, 0, -1, 18);
+ m_create(p_queue, IMSG_QUEUE_MESSAGE_FD, 0, 0, -1);
m_add_id(p_queue, s->id);
m_add_msgid(p_queue, evpid_to_msgid(s->evp->id));
m_close(p_queue);
@@ -867,6 +878,8 @@ mda_log(const struct mda_envelope *evp, const char *prefix, const char *status)
method = "file";
else if (evp->method == A_MDA)
method = "mda";
+ else if (evp->method == A_LMTP)
+ method = "lmtp";
else
method = "???";
diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c
index ad484c51d7f..c27b485937e 100644
--- a/usr.sbin/smtpd/mfa.c
+++ b/usr.sbin/smtpd/mfa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa.c,v 1.75 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: mfa.c,v 1.76 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -21,7 +21,6 @@
#include <sys/wait.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <err.h>
diff --git a/usr.sbin/smtpd/mfa_session.c b/usr.sbin/smtpd/mfa_session.c
index ba14eb7e94a..6d808a254d2 100644
--- a/usr.sbin/smtpd/mfa_session.c
+++ b/usr.sbin/smtpd/mfa_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa_session.c,v 1.16 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: mfa_session.c,v 1.17 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
@@ -88,7 +87,7 @@ struct mfa_query {
struct {
struct sockaddr_storage local;
struct sockaddr_storage remote;
- char hostname[MAXHOSTNAMELEN];
+ char hostname[SMTPD_MAXHOSTNAMELEN];
} connect;
char line[SMTPD_MAXLINESIZE];
struct mailaddr maddr;
@@ -142,12 +141,12 @@ mfa_filter_init(void)
f = xcalloc(1, sizeof *f, "mfa_filter_init");
p = &f->mproc;
p->handler = mfa_filter_imsg;
- p->proc = -1;
+ p->proc = PROC_FILTER;
p->name = xstrdup(filter->name, "mfa_filter_init");
p->data = f;
if (mproc_fork(p, filter->path, filter->name) < 0)
fatalx("mfa_filter_init");
- m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1, 5);
+ m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1);
m_add_u32(p, FILTER_API_VERSION);
m_close(p);
mproc_enable(p);
@@ -261,7 +260,7 @@ mfa_run_data(struct mfa_filter *f, uint64_t id, const char *line)
while (f) {
if (f->hooks & HOOK_DATALINE) {
p = &f->mproc;
- m_create(p, IMSG_FILTER_DATA, 0, 0, -1, len);
+ m_create(p, IMSG_FILTER_DATA, 0, 0, -1);
m_add_id(p, id);
m_add_string(p, line);
m_close(p);
@@ -285,7 +284,7 @@ mfa_run_data(struct mfa_filter *f, uint64_t id, const char *line)
log_trace(TRACE_MFA,
"mfa: sending final data to smtp for %016"PRIx64" on filter %p: %s", id, f, line);
- m_create(p_smtp, IMSG_MFA_SMTP_DATA, 0, 0, -1, len);
+ m_create(p_smtp, IMSG_MFA_SMTP_DATA, 0, 0, -1);
m_add_id(p_smtp, id);
m_add_string(p_smtp, line);
m_close(p_smtp);
@@ -375,7 +374,7 @@ mfa_drain_query(struct mfa_query *q)
/* Done, notify all listeners and return smtp response */
while (tree_poproot(&q->notify, NULL, (void**)&f)) {
- m_create(&f->mproc, IMSG_FILTER_NOTIFY, 0, 0, -1, 16);
+ m_create(&f->mproc, IMSG_FILTER_NOTIFY, 0, 0, -1);
m_add_id(&f->mproc, q->qid);
m_add_int(&f->mproc, q->smtp.status);
m_close(&f->mproc);
@@ -384,7 +383,7 @@ mfa_drain_query(struct mfa_query *q)
len = 48;
if (q->smtp.response)
len += strlen(q->smtp.response);
- m_create(p_smtp, IMSG_MFA_SMTP_RESPONSE, 0, 0, -1, len);
+ m_create(p_smtp, IMSG_MFA_SMTP_RESPONSE, 0, 0, -1);
m_add_id(p_smtp, q->session->id);
m_add_int(p_smtp, q->smtp.status);
m_add_u32(p_smtp, q->smtp.code);
@@ -419,7 +418,7 @@ mfa_run_query(struct mfa_filter *f, struct mfa_query *q)
mfa_filter_to_text(f), mfa_query_to_text(q));
if (q->type == QT_QUERY) {
- m_create(&f->mproc, IMSG_FILTER_QUERY, 0, 0, -1, 1024);
+ m_create(&f->mproc, IMSG_FILTER_QUERY, 0, 0, -1);
m_add_id(&f->mproc, q->session->id);
m_add_id(&f->mproc, q->qid);
m_add_int(&f->mproc, q->hook);
@@ -449,7 +448,7 @@ mfa_run_query(struct mfa_filter *f, struct mfa_query *q)
q->state = QUERY_RUNNING;
}
else {
- m_create(&f->mproc, IMSG_FILTER_EVENT, 0, 0, -1, 16);
+ m_create(&f->mproc, IMSG_FILTER_EVENT, 0, 0, -1);
m_add_id(&f->mproc, q->session->id);
m_add_int(&f->mproc, q->hook);
m_close(&f->mproc);
@@ -467,6 +466,13 @@ mfa_filter_imsg(struct mproc *p, struct imsg *imsg)
int status, code, notify;
f = p->data;
+
+ if (imsg == NULL) {
+ log_warnx("warn: filter \"%s\" closed unexpectedly",
+ p->name);
+ fatalx("exiting");
+ }
+
log_trace(TRACE_MFA, "mfa: imsg %s from filter %s",
filterimsg_to_str(imsg->hdr.type),
mfa_filter_to_text(f));
diff --git a/usr.sbin/smtpd/mproc.c b/usr.sbin/smtpd/mproc.c
index 0ca56245c80..ba86405520e 100644
--- a/usr.sbin/smtpd/mproc.c
+++ b/usr.sbin/smtpd/mproc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mproc.c,v 1.2 2013/01/31 18:34:43 eric Exp $ */
+/* $OpenBSD: mproc.c,v 1.3 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@faurot.net>
@@ -43,9 +43,6 @@ static void mproc_dispatch(int, short, void *);
static ssize_t msgbuf_write2(struct msgbuf *);
-static uint32_t reqtype;
-static size_t reqlen;
-
int
mproc_fork(struct mproc *p, const char *path, const char *arg)
{
@@ -100,7 +97,8 @@ void
mproc_enable(struct mproc *p)
{
if (p->enable == 0) {
- log_debug("debug: enabling %s -> %s", proc_name(smtpd_process),
+ log_trace(TRACE_MPROC, "mproc: %s -> %s: enabled",
+ proc_name(smtpd_process),
proc_name(p->proc));
p->enable = 1;
}
@@ -111,7 +109,8 @@ void
mproc_disable(struct mproc *p)
{
if (p->enable == 1) {
- log_debug("debug: disabling %s -> %s", proc_name(smtpd_process),
+ log_trace(TRACE_MPROC, "mproc: %s -> %s: disabled",
+ proc_name(smtpd_process),
proc_name(p->proc));
p->enable = 0;
}
@@ -152,10 +151,17 @@ mproc_dispatch(int fd, short event, void *arg)
if (event & EV_READ) {
- if ((n = imsg_read(&p->imsgbuf)) == -1)
- fatal("imsg_read");
+ if ((n = imsg_read(&p->imsgbuf)) == -1) {
+ log_warn("warn: %s -> %s: imsg_read",
+ proc_name(smtpd_process), p->name);
+ fatal("exiting");
+ }
if (n == 0) {
/* this pipe is dead, so remove the event handler */
+ if (smtpd_process != PROC_CONTROL ||
+ p->proc != PROC_CLIENT)
+ log_warnx("warn: %s -> %s: pipe closed",
+ proc_name(smtpd_process), p->name);
p->handler(p, NULL);
return;
}
@@ -268,6 +274,12 @@ m_forward(struct mproc *p, struct imsg *imsg)
imsg->hdr.pid, imsg->fd, imsg->data,
imsg->hdr.len - sizeof(imsg->hdr));
+ log_trace(TRACE_MPROC, "mproc: %s -> %s : %zu %s (forward)",
+ proc_name(smtpd_process),
+ proc_name(p->proc),
+ imsg->hdr.len - sizeof(imsg->hdr),
+ imsg_to_str(imsg->hdr.type));
+
p->msg_out += 1;
p->bytes_queued += imsg->hdr.len;
if (p->bytes_queued > p->bytes_queued_max)
@@ -282,6 +294,12 @@ m_compose(struct mproc *p, uint32_t type, uint32_t peerid, pid_t pid, int fd,
{
imsg_compose(&p->imsgbuf, type, peerid, pid, fd, data, len);
+ log_trace(TRACE_MPROC, "mproc: %s -> %s : %zu %s",
+ proc_name(smtpd_process),
+ proc_name(p->proc),
+ len,
+ imsg_to_str(type));
+
p->msg_out += 1;
p->bytes_queued += len + IMSG_HEADER_SIZE;
if (p->bytes_queued > p->bytes_queued_max)
@@ -294,73 +312,99 @@ void
m_composev(struct mproc *p, uint32_t type, uint32_t peerid, pid_t pid,
int fd, const struct iovec *iov, int n)
{
+ size_t len;
int i;
imsg_composev(&p->imsgbuf, type, peerid, pid, fd, iov, n);
- p->msg_out += 1;
- p->bytes_queued += IMSG_HEADER_SIZE;
+ len = 0;
for (i = 0; i < n; i++)
- p->bytes_queued += iov[i].iov_len;
+ len += iov[i].iov_len;
+
+ p->msg_out += 1;
+ p->bytes_queued += IMSG_HEADER_SIZE + len;
if (p->bytes_queued > p->bytes_queued_max)
p->bytes_queued_max = p->bytes_queued;
+ log_trace(TRACE_MPROC, "mproc: %s -> %s : %zu %s",
+ proc_name(smtpd_process),
+ proc_name(p->proc),
+ len,
+ imsg_to_str(type));
+
mproc_event_add(p);
}
void
-m_create(struct mproc *p, uint32_t type, uint32_t peerid, pid_t pid, int fd,
- size_t len)
+m_create(struct mproc *p, uint32_t type, uint32_t peerid, pid_t pid, int fd)
{
- if (p->ibuf)
- fatal("ibuf already rhere");
-
- reqtype = type;
- reqlen = len;
-
- p->ibuf = imsg_create(&p->imsgbuf, type, peerid, pid, len);
- if (p->ibuf == NULL)
- fatal("imsg_create");
+ if (p->m_buf == NULL) {
+ p->m_alloc = 128;
+ log_trace(TRACE_MPROC, "mproc: %s -> %s: allocating %zu",
+ proc_name(smtpd_process),
+ proc_name(p->proc),
+ p->m_alloc);
+ p->m_buf = malloc(p->m_alloc);
+ if (p->m_buf == NULL)
+ fatal("warn: m_create: malloc");
+ }
- /* Is this a problem with imsg? */
- p->ibuf->fd = fd;
+ p->m_pos = 0;
+ p->m_type = type;
+ p->m_peerid = peerid;
+ p->m_pid = pid;
+ p->m_fd = fd;
}
void
m_add(struct mproc *p, const void *data, size_t len)
{
- if (p->ibuferror)
- return;
+ size_t alloc;
+ void *tmp;
- if (ibuf_add(p->ibuf, data, len) == -1)
- p->ibuferror = 1;
+ if (p->m_pos + len + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
+ log_warnx("warn: message to large");
+ fatal(NULL);
+ }
+
+ alloc = p->m_alloc;
+ while (p->m_pos + len > alloc)
+ alloc *= 2;
+ if (alloc != p->m_alloc) {
+ log_trace(TRACE_MPROC, "mproc: %s -> %s: realloc %zu -> %zu",
+ proc_name(smtpd_process),
+ proc_name(p->proc),
+ p->m_alloc,
+ alloc);
+
+ tmp = realloc(p->m_buf, alloc);
+ if (tmp == NULL)
+ fatal("realloc");
+ p->m_alloc = alloc;
+ p->m_buf = tmp;
+ }
+
+ memmove(p->m_buf + p->m_pos, data, len);
+ p->m_pos += len;
}
void
m_close(struct mproc *p)
{
- imsg_close(&p->imsgbuf, p->ibuf);
+ if (imsg_compose(&p->imsgbuf, p->m_type, p->m_peerid, p->m_pid, p->m_fd,
+ p->m_buf, p->m_pos) == -1)
+ fatal("imsg_compose");
- if (verbose & TRACE_IMSGSIZE &&
- reqlen != p->ibuf->wpos - IMSG_HEADER_SIZE)
- log_debug("msg-len: too %s %zu -> %zu : %s -> %s : %s",
- (reqlen < p->ibuf->wpos - IMSG_HEADER_SIZE) ? "small" : "large",
- reqlen, p->ibuf->wpos - IMSG_HEADER_SIZE,
- proc_name(smtpd_process),
- proc_name(p->proc),
- imsg_to_str(reqtype));
- else if (verbose & TRACE_IMSGSIZE)
- log_debug("msg-len: ok %zu : %s -> %s : %s",
- p->ibuf->wpos - IMSG_HEADER_SIZE,
+ log_trace(TRACE_MPROC, "mproc: %s -> %s : %zu %s",
proc_name(smtpd_process),
proc_name(p->proc),
- imsg_to_str(reqtype));
+ p->m_pos,
+ imsg_to_str(p->m_type));
p->msg_out += 1;
- p->bytes_queued += p->ibuf->wpos;
+ p->bytes_queued += p->m_pos + IMSG_HEADER_SIZE;
if (p->bytes_queued > p->bytes_queued_max)
p->bytes_queued_max = p->bytes_queued;
- p->ibuf = NULL;
mproc_event_add(p);
}
@@ -438,24 +482,16 @@ m_get_typed_sized(struct msg *m, uint8_t type, const void **dst, size_t *sz)
static void
m_add_typed(struct mproc *p, uint8_t type, const void *data, size_t len)
{
- if (p->ibuferror)
- return;
-
- if (ibuf_add(p->ibuf, &type, 1) == -1 ||
- ibuf_add(p->ibuf, data, len) == -1)
- p->ibuferror = 1;
+ m_add(p, &type, 1);
+ m_add(p, data, len);
}
static void
m_add_typed_sized(struct mproc *p, uint8_t type, const void *data, size_t len)
{
- if (p->ibuferror)
- return;
-
- if (ibuf_add(p->ibuf, &type, 1) == -1 ||
- ibuf_add(p->ibuf, &len, sizeof(len)) == -1 ||
- ibuf_add(p->ibuf, data, len) == -1)
- p->ibuferror = 1;
+ m_add(p, &type, 1);
+ m_add(p, &len, sizeof(len));
+ m_add(p, data, len);
}
enum {
@@ -532,6 +568,7 @@ m_add_mailaddr(struct mproc *m, const struct mailaddr *maddr)
m_add_typed(m, M_MAILADDR, maddr, sizeof(*maddr));
}
+#ifndef BUILD_FILTER
void
m_add_envelope(struct mproc *m, const struct envelope *evp)
{
@@ -545,6 +582,7 @@ m_add_envelope(struct mproc *m, const struct envelope *evp)
m_add_typed_sized(m, M_ENVELOPE, buf, strlen(buf) + 1);
#endif
}
+#endif
void
m_get_int(struct msg *m, int *i)
@@ -622,6 +660,7 @@ m_get_mailaddr(struct msg *m, struct mailaddr *maddr)
m_get_typed(m, M_MAILADDR, maddr, sizeof(*maddr));
}
+#ifndef BUILD_FILTER
void
m_get_envelope(struct msg *m, struct envelope *evp)
{
@@ -636,7 +675,8 @@ m_get_envelope(struct msg *m, struct envelope *evp)
m_get_typed_sized(m, M_ENVELOPE, &d, &s);
if (!envelope_load_buffer(evp, d, s - 1))
- fatalx("failed to load envelope");
+ fatalx("failed to retreive envelope");
evp->id = evpid;
#endif
}
+#endif
diff --git a/usr.sbin/smtpd/mta.c b/usr.sbin/smtpd/mta.c
index 89e54d40efb..df79762fef5 100644
--- a/usr.sbin/smtpd/mta.c
+++ b/usr.sbin/smtpd/mta.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mta.c,v 1.156 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: mta.c,v 1.157 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -22,7 +22,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -72,7 +71,7 @@ static void mta_relay_timeout(int, short, void *);
static void mta_flush(struct mta_relay *, int, const char *);
static struct mta_route *mta_find_route(struct mta_connector *);
static void mta_log(const struct mta_envelope *, const char *, const char *,
- const char *);
+ const char *, const char *);
SPLAY_HEAD(mta_relay_tree, mta_relay);
static struct mta_relay *mta_relay(struct envelope *);
@@ -577,23 +576,23 @@ mta_route_next_task(struct mta_relay *relay, struct mta_route *route)
}
void
-mta_delivery(struct mta_envelope *e, const char *relay, int delivery,
- const char *status)
+mta_delivery(struct mta_envelope *e, const char *source, const char *relay,
+ int delivery, const char *status)
{
if (delivery == IMSG_DELIVERY_OK) {
- mta_log(e, "Ok", relay, status);
+ mta_log(e, "Ok", source, relay, status);
queue_ok(e->id);
}
else if (delivery == IMSG_DELIVERY_TEMPFAIL) {
- mta_log(e, "TempFail", relay, status);
+ mta_log(e, "TempFail", source, relay, status);
queue_tempfail(e->id, status);
}
else if (delivery == IMSG_DELIVERY_PERMFAIL) {
- mta_log(e, "PermFail", relay, status);
+ mta_log(e, "PermFail", source, relay, status);
queue_permfail(e->id, status);
}
else if (delivery == IMSG_DELIVERY_LOOP) {
- mta_log(e, "PermFail", relay, "Loop detected");
+ mta_log(e, "PermFail", source, relay, "Loop detected");
queue_loop(e->id);
}
else
@@ -634,7 +633,7 @@ mta_query_secret(struct mta_relay *relay)
tree_xset(&wait_secret, relay->id, relay);
relay->status |= RELAY_WAIT_SECRET;
- m_create(p_lka, IMSG_LKA_SECRET, 0, 0, -1, 128);
+ m_create(p_lka, IMSG_LKA_SECRET, 0, 0, -1);
m_add_id(p_lka, relay->id);
m_add_string(p_lka, relay->authtable);
m_add_string(p_lka, relay->authlabel);
@@ -663,7 +662,7 @@ mta_query_source(struct mta_relay *relay)
{
log_debug("debug: mta_query_source(%s)", mta_relay_to_text(relay));
- m_create(p_lka, IMSG_LKA_SOURCE, 0, 0, -1, 64);
+ m_create(p_lka, IMSG_LKA_SOURCE, 0, 0, -1);
m_add_id(p_lka, relay->id);
m_add_string(p_lka, relay->sourcetable);
m_close(p_lka);
@@ -980,17 +979,12 @@ mta_flush(struct mta_relay *relay, int fail, const char *error)
{
struct mta_envelope *e;
struct mta_task *task;
- const char *pfx;
size_t n;
log_debug("debug: mta_flush(%s, %i, \"%s\")",
mta_relay_to_text(relay), fail, error);
- if (fail == IMSG_DELIVERY_TEMPFAIL)
- pfx = "TempFail";
- else if (fail == IMSG_DELIVERY_PERMFAIL)
- pfx = "PermFail";
- else
+ if (fail != IMSG_DELIVERY_TEMPFAIL && fail != IMSG_DELIVERY_PERMFAIL)
errx(1, "unexpected delivery status %i", fail);
n = 0;
@@ -998,7 +992,7 @@ mta_flush(struct mta_relay *relay, int fail, const char *error)
TAILQ_REMOVE(&relay->tasks, task, entry);
while ((e = TAILQ_FIRST(&task->envelopes))) {
TAILQ_REMOVE(&task->envelopes, e, entry);
- mta_delivery(e, relay->domain->name, fail, error);
+ mta_delivery(e, NULL, relay->domain->name, fail, error);
free(e->dest);
free(e->rcpt);
free(e);
@@ -1116,11 +1110,6 @@ mta_find_route(struct mta_connector *c)
mta_connector_to_text(c));
c->flags |= CONNECTOR_MX_ERROR;
}
- else if (family_mismatch) {
- log_info("smtp-out: Address family mismatch on connector %s",
- mta_connector_to_text(c));
- c->flags |= CONNECTOR_FAMILY_ERROR;
- }
else if (limit_route) {
log_debug("debug: mta: hit route limit on connector %s",
mta_connector_to_text(c));
@@ -1131,26 +1120,45 @@ mta_find_route(struct mta_connector *c)
mta_connector_to_text(c));
c->flags |= CONNECTOR_LIMIT_HOST;
}
+ else if (family_mismatch) {
+ log_info("smtp-out: Address family mismatch on connector %s",
+ mta_connector_to_text(c));
+ c->flags |= CONNECTOR_FAMILY_ERROR;
+ }
return (NULL);
}
static void
-mta_log(const struct mta_envelope *evp, const char *prefix, const char *relay,
- const char *status)
+mta_log(const struct mta_envelope *evp, const char *prefix, const char *source,
+ const char *relay, const char *status)
{
+ char session[SMTPD_MAXLINESIZE];
char rcpt[SMTPD_MAXLINESIZE];
+ char src[SMTPD_MAXLINESIZE];
+
+ session[0] = '\0';
+ if (evp->session)
+ snprintf(session, sizeof session, "session=%016"PRIx64", ",
+ evp->session);
rcpt[0] = '\0';
if (evp->rcpt)
snprintf(rcpt, sizeof rcpt, "rcpt=<%s>, ", evp->rcpt);
- log_info("relay: %s for %016" PRIx64 ": from=<%s>, to=<%s>, "
- "%srelay=%s, delay=%s, stat=%s",
+ src[0] = '\0';
+ if (source)
+ snprintf(src, sizeof src, "source=%s, ", source);
+
+
+ log_info("relay: %s for %016" PRIx64 ": %sfrom=<%s>, to=<%s>, "
+ "%s%srelay=%s, delay=%s, stat=%s",
prefix,
evp->id,
+ session,
evp->task->sender,
evp->dest,
+ src,
rcpt,
relay,
duration_to_text(time(NULL) - evp->creation),
diff --git a/usr.sbin/smtpd/mta_session.c b/usr.sbin/smtpd/mta_session.c
index a0e9d5061c2..0615d691f24 100644
--- a/usr.sbin/smtpd/mta_session.c
+++ b/usr.sbin/smtpd/mta_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mta_session.c,v 1.35 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: mta_session.c,v 1.36 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -22,7 +22,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
@@ -235,12 +234,20 @@ mta_session_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_id(&m, &reqid);
m_end(&m);
- if (imsg->fd == -1)
- fatalx("mta: cannot obtain msgfd");
s = mta_tree_pop(&wait_fd, reqid);
if (s == NULL) {
- close(imsg->fd);
+ if (imsg->fd != -1)
+ close(imsg->fd);
+ return;
+ }
+
+ if (imsg->fd == -1) {
+ log_debug("debug: mta: failed to obtain msg fd");
+ mta_flush_task(s, IMSG_DELIVERY_TEMPFAIL,
+ "Could not get message fd", 0);
+ mta_enter_state(s, MTA_READY);
+ io_reload(&s->io);
return;
}
@@ -425,7 +432,7 @@ mta_connect(struct mta_session *s)
if (s->helo == NULL) {
if (s->relay->helotable && s->route->src->sa) {
- m_create(p_lka, IMSG_LKA_HELO, 0, 0, -1, 64);
+ m_create(p_lka, IMSG_LKA_HELO, 0, 0, -1);
m_add_id(p_lka, s->id);
m_add_string(p_lka, s->relay->helotable);
m_add_sockaddr(p_lka, s->route->src->sa);
@@ -608,7 +615,7 @@ mta_enter_state(struct mta_session *s, int newstate)
stat_increment("mta.task.running", 1);
- m_create(p_queue, IMSG_QUEUE_MESSAGE_FD, 0, 0, -1, 18);
+ m_create(p_queue, IMSG_QUEUE_MESSAGE_FD, 0, 0, -1);
m_add_id(p_queue, s->id);
m_add_msgid(p_queue, s->task->msgid);
m_close(p_queue);
@@ -644,6 +651,10 @@ mta_enter_state(struct mta_session *s, int newstate)
s->flags |= MTA_FREE;
break;
}
+ if (q == 0) {
+ mta_enter_state(s, MTA_BODY);
+ break;
+ }
log_trace(TRACE_MTA, "mta: %p: >>> [...%zi bytes...]", s, q);
break;
@@ -684,6 +695,8 @@ mta_response(struct mta_session *s, char *line)
struct mta_envelope *e;
char buf[SMTPD_MAXLINESIZE];
int delivery;
+ struct sockaddr sa;
+ socklen_t sa_len;
switch (s->state) {
@@ -779,7 +792,21 @@ mta_response(struct mta_session *s, char *line)
TAILQ_REMOVE(&s->task->envelopes, e, entry);
snprintf(buf, sizeof(buf), "%s",
mta_host_to_text(s->route->dst));
- mta_delivery(e, buf, delivery, line);
+
+ /* we're about to log, associate session to envelope */
+ e->session = s->id;
+
+ /* XXX */
+ /*
+ * getsockname() can only fail with ENOBUFS here
+ * best effort, don't log source ...
+ */
+ sa_len = sizeof sa;
+ if (getsockname(s->io.sock, &sa, &sa_len) < 0)
+ mta_delivery(e, NULL, buf, delivery, line);
+ else
+ mta_delivery(e, sa_to_text(&sa),
+ buf, delivery, line);
free(e->dest);
free(e->rcpt);
free(e);
@@ -848,7 +875,6 @@ mta_io(struct io *io, int evt)
size_t len;
const char *error;
int cont;
- const char *schema;
log_trace(TRACE_IO, "mta: %p: %s %s", s, io_strevent(evt),
io_strio(io));
@@ -856,15 +882,6 @@ mta_io(struct io *io, int evt)
switch (evt) {
case IO_CONNECTED:
- if (s->use_smtp_tls)
- schema = "smtp+tls://";
- else if (s->use_starttls)
- schema = "tls://";
- else if (s->use_smtps)
- schema = "smtps://";
- else
- schema = "smtp://";
-
log_info("smtp-out: Connected on session %016"PRIx64, s->id);
if (s->use_smtps) {
@@ -1067,6 +1084,8 @@ mta_flush_task(struct mta_session *s, int delivery, const char *error, size_t co
struct mta_envelope *e;
char relay[SMTPD_MAXLINESIZE];
size_t n;
+ struct sockaddr sa;
+ socklen_t sa_len;
snprintf(relay, sizeof relay, "%s", mta_host_to_text(s->route->dst));
@@ -1079,7 +1098,22 @@ mta_flush_task(struct mta_session *s, int delivery, const char *error, size_t co
}
TAILQ_REMOVE(&s->task->envelopes, e, entry);
- mta_delivery(e, relay, delivery, error);
+
+ /* we're about to log, associate session to envelope */
+ e->session = s->id;
+
+ /* XXX */
+ /*
+ * getsockname() can only fail with ENOBUFS here
+ * best effort, don't log source ...
+ */
+ sa_len = sizeof sa;
+ if (getsockname(s->io.sock, &sa, &sa_len) < 0)
+ mta_delivery(e, NULL, relay, delivery, error);
+ else
+ mta_delivery(e, sa_to_text(&sa),
+ relay, delivery, error);
+
free(e->dest);
free(e->rcpt);
free(e);
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index b6d3e96f19e..bf51f6bb9e8 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.116 2013/03/06 21:42:40 sthen Exp $ */
+/* $OpenBSD: parse.y,v 1.117 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -25,7 +25,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
@@ -108,7 +107,7 @@ int is_if_in_group(const char *, const char *);
typedef struct {
union {
int64_t number;
- objid_t object;
+ struct table *table;
char *string;
struct host *host;
struct mailaddr *maddr;
@@ -120,15 +119,15 @@ typedef struct {
%token AS QUEUE COMPRESSION MAXMESSAGESIZE LISTEN ON ANY PORT EXPIRE
%token TABLE SSL SMTPS CERTIFICATE DOMAIN BOUNCEWARN
-%token RELAY BACKUP VIA DELIVER TO MAILDIR MBOX HOSTNAME HELO
+%token RELAY BACKUP VIA DELIVER TO LMTP MAILDIR MBOX HOSTNAME HELO
%token ACCEPT REJECT INCLUDE ERROR MDA FROM FOR SOURCE
%token ARROW AUTH TLS LOCAL VIRTUAL TAG TAGGED ALIAS FILTER KEY
%token AUTH_OPTIONAL TLS_REQUIRE USERBASE SENDER
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.table> table
-%type <v.number> port from auth ssl size expire sender
-%type <v.object> tables tablenew tableref destination alias virtual usermapping userbase credentials
+%type <v.number> port auth ssl size expire
+%type <v.table> tables tablenew tableref destination alias virtual usermapping userbase credentials from sender
%type <v.maddr> relay_as
%type <v.string> certificate tag tagged relay_source listen_helo relay_helo relay_backup
%%
@@ -247,11 +246,11 @@ auth : AUTH {
$$ = F_AUTH;
}
| AUTH tables {
- strlcpy(l.authtable, table_find($2)->t_name, sizeof l.authtable);
+ strlcpy(l.authtable, ($2)->t_name, sizeof l.authtable);
$$ = F_AUTH|F_AUTH_REQUIRE;
}
| AUTH_OPTIONAL tables {
- strlcpy(l.authtable, table_find($2)->t_name, sizeof l.authtable);
+ strlcpy(l.authtable, ($2)->t_name, sizeof l.authtable);
$$ = F_AUTH;
}
| /* empty */ { $$ = 0; }
@@ -317,7 +316,7 @@ bouncedelays : bouncedelays ',' bouncedelay
;
credentials : AUTH tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_HASH, K_CREDENTIALS)) {
yyerror("invalid use of table \"%s\" as AUTH parameter",
@@ -325,7 +324,7 @@ credentials : AUTH tables {
YYERROR;
}
- $$ = t->t_id;
+ $$ = t;
}
| /* empty */ { $$ = 0; }
;
@@ -336,6 +335,9 @@ listen_helo : HOSTNAME STRING { $$ = $2; }
main : BOUNCEWARN {
bzero(conf->sc_bounce_warn, sizeof conf->sc_bounce_warn);
} bouncedelays
+ | QUEUE COMPRESSION {
+ conf->sc_queue_flags |= QUEUE_COMPRESSION;
+ }
| EXPIRE STRING {
conf->sc_qexpire = delaytonum($2);
if (conf->sc_qexpire == -1) {
@@ -487,8 +489,8 @@ table : TABLE STRING STRING {
free($3);
YYERROR;
}
- table = table_create(backend, $2, config);
- if (! table->t_backend->config(table, config)) {
+ table = table_create(backend, $2, NULL, config);
+ if (!table_config(table)) {
yyerror("invalid backend configuration for table %s",
table->t_name);
free($2);
@@ -499,7 +501,7 @@ table : TABLE STRING STRING {
free($3);
}
| TABLE STRING {
- table = table_create("static", $2, NULL);
+ table = table_create("static", $2, NULL, NULL);
free($2);
} '{' tableval_list '}' {
table = NULL;
@@ -538,30 +540,29 @@ tableval_list : string_list { }
tablenew : STRING {
struct table *t;
- t = table_create("static", NULL, NULL);
+ t = table_create("static", NULL, NULL, NULL);
t->t_type = T_LIST;
table_add(t, $1, NULL);
free($1);
- $$ = t->t_id;
- table = table_create("static", NULL, NULL);
+ $$ = t;
}
| '{' {
- table = table_create("static", NULL, NULL);
+ table = table_create("static", NULL, NULL, NULL);
} tableval_list '}' {
- $$ = table->t_id;
+ $$ = table;
}
;
tableref : '<' STRING '>' {
struct table *t;
- if ((t = table_findbyname($2)) == NULL) {
+ if ((t = table_find($2, NULL)) == NULL) {
yyerror("no such table: %s", $2);
free($2);
YYERROR;
}
free($2);
- $$ = t->t_id;
+ $$ = t;
}
;
@@ -570,7 +571,7 @@ tables : tablenew { $$ = $1; }
;
alias : ALIAS tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) {
yyerror("invalid use of table \"%s\" as ALIAS parameter",
@@ -578,12 +579,12 @@ alias : ALIAS tables {
YYERROR;
}
- $$ = t->t_id;
+ $$ = t;
}
;
virtual : VIRTUAL tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_service(t, K_ALIAS)) {
yyerror("invalid use of table \"%s\" as VIRTUAL parameter",
@@ -591,7 +592,7 @@ virtual : VIRTUAL tables {
YYERROR;
}
- $$ = t->t_id;
+ $$ = t;
}
;
@@ -610,7 +611,7 @@ usermapping : alias {
;
userbase : USERBASE tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_HASH, K_USERINFO)) {
yyerror("invalid use of table \"%s\" as USERBASE parameter",
@@ -618,16 +619,16 @@ userbase : USERBASE tables {
YYERROR;
}
- $$ = t->t_id;
+ $$ = t;
}
- | /**/ { $$ = table_findbyname("<getpwnam>")->t_id; }
+ | /**/ { $$ = table_find("<getpwnam>", NULL); }
;
destination : DOMAIN tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) {
yyerror("invalid use of table \"%s\" as DOMAIN parameter",
@@ -635,14 +636,14 @@ destination : DOMAIN tables {
YYERROR;
}
- $$ = t->t_id;
+ $$ = t;
}
- | LOCAL { $$ = table_findbyname("<localnames>")->t_id; }
+ | LOCAL { $$ = table_find("<localnames>", NULL); }
| ANY { $$ = 0; }
;
relay_source : SOURCE tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_LIST, K_SOURCE)) {
yyerror("invalid use of table \"%s\" as "
"SOURCE parameter", t->t_name);
@@ -654,7 +655,7 @@ relay_source : SOURCE tables {
;
relay_helo : HELO tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) {
yyerror("invalid use of table \"%s\" as "
"HELO parameter", t->t_name);
@@ -698,7 +699,7 @@ relay_as : AS STRING {
;
action : userbase DELIVER TO MAILDIR {
- rule->r_userbase = table_find($1);
+ rule->r_userbase = $1;
rule->r_action = A_MAILDIR;
if (strlcpy(rule->r_value.buffer, "~/Maildir",
sizeof(rule->r_value.buffer)) >=
@@ -706,7 +707,7 @@ action : userbase DELIVER TO MAILDIR {
fatal("pathname too long");
}
| userbase DELIVER TO MAILDIR STRING {
- rule->r_userbase = table_find($1);
+ rule->r_userbase = $1;
rule->r_action = A_MAILDIR;
if (strlcpy(rule->r_value.buffer, $5,
sizeof(rule->r_value.buffer)) >=
@@ -714,8 +715,20 @@ action : userbase DELIVER TO MAILDIR {
fatal("pathname too long");
free($5);
}
+ | userbase DELIVER TO LMTP STRING {
+ rule->r_userbase = $1;
+ rule->r_action = A_LMTP;
+ if (strchr($5, ':') || $5[0] == '/') {
+ if (strlcpy(rule->r_value.buffer, $5,
+ sizeof(rule->r_value.buffer))
+ >= sizeof(rule->r_value.buffer))
+ fatal("lmtp destination too long");
+ } else
+ fatal("invalid lmtp destination");
+ free($5);
+ }
| userbase DELIVER TO MBOX {
- rule->r_userbase = table_find($1);
+ rule->r_userbase = $1;
rule->r_action = A_MBOX;
if (strlcpy(rule->r_value.buffer, _PATH_MAILDIR "/%u",
sizeof(rule->r_value.buffer))
@@ -723,7 +736,7 @@ action : userbase DELIVER TO MAILDIR {
fatal("pathname too long");
}
| userbase DELIVER TO MDA STRING {
- rule->r_userbase = table_find($1);
+ rule->r_userbase = $1;
rule->r_action = A_MDA;
if (strlcpy(rule->r_value.buffer, $5,
sizeof(rule->r_value.buffer))
@@ -734,10 +747,6 @@ action : userbase DELIVER TO MAILDIR {
| RELAY relay_as relay_source relay_helo {
rule->r_action = A_RELAY;
rule->r_as = $2;
- if ($4 != NULL && $3 == NULL) {
- yyerror("HELO can only be used with SOURCE");
- YYERROR;
- }
if ($3)
strlcpy(rule->r_value.relayhost.sourcetable, $3,
sizeof rule->r_value.relayhost.sourcetable);
@@ -754,14 +763,11 @@ action : userbase DELIVER TO MAILDIR {
strlcpy(rule->r_value.relayhost.hostname, $2,
sizeof (rule->r_value.relayhost.hostname));
else
- strlcpy(rule->r_value.relayhost.hostname, env->sc_hostname,
+ strlcpy(rule->r_value.relayhost.hostname,
+ env->sc_hostname,
sizeof (rule->r_value.relayhost.hostname));
free($2);
- if ($5 != NULL && $4 == NULL) {
- yyerror("HELO can only be used with SOURCE");
- YYERROR;
- }
if ($4)
strlcpy(rule->r_value.relayhost.sourcetable, $4,
sizeof rule->r_value.relayhost.sourcetable);
@@ -792,7 +798,7 @@ action : userbase DELIVER TO MAILDIR {
free($6);
YYERROR;
}
- t = table_find($5);
+ t = $5;
strlcpy(rule->r_value.relayhost.authtable, t->t_name,
sizeof(rule->r_value.relayhost.authtable));
}
@@ -804,10 +810,7 @@ action : userbase DELIVER TO MAILDIR {
fatal("certificate path too long");
}
free($4);
- if ($8 != NULL && $7 == NULL) {
- yyerror("HELO can only be used with SOURCE");
- YYERROR;
- }
+
if ($7)
strlcpy(rule->r_value.relayhost.sourcetable, $7,
sizeof rule->r_value.relayhost.sourcetable);
@@ -818,7 +821,7 @@ action : userbase DELIVER TO MAILDIR {
;
from : FROM tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_LIST, K_NETADDR)) {
yyerror("invalid use of table \"%s\" as FROM parameter",
@@ -826,21 +829,21 @@ from : FROM tables {
YYERROR;
}
- $$ = t->t_id;
+ $$ = t;
}
| FROM ANY {
- $$ = table_findbyname("<anyhost>")->t_id;
+ $$ = table_find("<anyhost>", NULL);
}
| FROM LOCAL {
- $$ = table_findbyname("<localhost>")->t_id;
+ $$ = table_find("<localhost>", NULL);
}
| /* empty */ {
- $$ = table_findbyname("<localhost>")->t_id;
+ $$ = table_find("<localhost>", NULL);
}
;
sender : SENDER tables {
- struct table *t = table_find($2);
+ struct table *t = $2;
if (! table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) {
yyerror("invalid use of table \"%s\" as SENDER parameter",
@@ -848,9 +851,9 @@ sender : SENDER tables {
YYERROR;
}
- $$ = t->t_id;
+ $$ = t;
}
- | /* empty */ { $$ = 0; }
+ | /* empty */ { $$ = NULL; }
;
rule : ACCEPT {
@@ -858,10 +861,10 @@ rule : ACCEPT {
} tagged from sender FOR destination usermapping action expire {
rule->r_decision = R_ACCEPT;
- rule->r_sources = table_find($4);
- rule->r_senders = table_find($5);
- rule->r_destination = table_find($7);
- rule->r_mapping = table_find($8);
+ rule->r_sources = $4;
+ rule->r_senders = $5;
+ rule->r_destination = $7;
+ rule->r_mapping = $8;
if ($3) {
if (strlcpy(rule->r_tag, $3, sizeof rule->r_tag)
>= sizeof rule->r_tag) {
@@ -901,10 +904,10 @@ rule : ACCEPT {
rule = xcalloc(1, sizeof(*rule), "parse rule: REJECT");
} tagged from sender FOR destination usermapping {
rule->r_decision = R_REJECT;
- rule->r_sources = table_find($4);
- rule->r_sources = table_find($5);
- rule->r_destination = table_find($7);
- rule->r_mapping = table_find($8);
+ rule->r_sources = $4;
+ rule->r_senders = $5;
+ rule->r_destination = $7;
+ rule->r_mapping = $8;
if ($3) {
if (strlcpy(rule->r_tag, $3, sizeof rule->r_tag)
>= sizeof rule->r_tag) {
@@ -961,6 +964,7 @@ lookup(char *s)
{ "backup", BACKUP },
{ "bounce-warn", BOUNCEWARN },
{ "certificate", CERTIFICATE },
+ { "compression", COMPRESSION },
{ "deliver", DELIVER },
{ "domain", DOMAIN },
{ "expire", EXPIRE },
@@ -972,6 +976,7 @@ lookup(char *s)
{ "include", INCLUDE },
{ "key", KEY },
{ "listen", LISTEN },
+ { "lmtp", LMTP },
{ "local", LOCAL },
{ "maildir", MAILDIR },
{ "max-message-size", MAXMESSAGESIZE },
@@ -1324,7 +1329,7 @@ parse_config(struct smtpd *x_conf, const char *filename, int opts)
{
struct sym *sym, *next;
struct table *t;
- char hostname[MAXHOSTNAMELEN];
+ char hostname[SMTPD_MAXHOSTNAMELEN];
if (gethostname(hostname, sizeof hostname) == -1) {
fprintf(stderr, "invalid hostname: gethostname() failed\n");
@@ -1337,7 +1342,6 @@ parse_config(struct smtpd *x_conf, const char *filename, int opts)
conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE;
conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict));
- conf->sc_tables_tree = calloc(1, sizeof(*conf->sc_tables_tree));
conf->sc_rules = calloc(1, sizeof(*conf->sc_rules));
conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners));
conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict));
@@ -1346,13 +1350,11 @@ parse_config(struct smtpd *x_conf, const char *filename, int opts)
conf->sc_bounce_warn[0] = 3600 * 4;
if (conf->sc_tables_dict == NULL ||
- conf->sc_tables_tree == NULL ||
conf->sc_rules == NULL ||
conf->sc_listeners == NULL ||
conf->sc_ssl_dict == NULL) {
log_warn("warn: cannot allocate memory");
free(conf->sc_tables_dict);
- free(conf->sc_tables_tree);
free(conf->sc_rules);
free(conf->sc_listeners);
free(conf->sc_ssl_dict);
@@ -1368,7 +1370,6 @@ parse_config(struct smtpd *x_conf, const char *filename, int opts)
dict_init(conf->sc_ssl_dict);
dict_init(conf->sc_tables_dict);
- tree_init(conf->sc_tables_tree);
TAILQ_INIT(conf->sc_listeners);
TAILQ_INIT(conf->sc_rules);
@@ -1387,12 +1388,12 @@ parse_config(struct smtpd *x_conf, const char *filename, int opts)
*/
set_localaddrs();
- t = table_create("static", "<localnames>", NULL);
+ t = table_create("static", "<localnames>", NULL, NULL);
t->t_type = T_LIST;
table_add(t, "localhost", NULL);
table_add(t, hostname, NULL);
- table_create("getpwnam", "<getpwnam>", NULL);
+ table_create("getpwnam", "<getpwnam>", NULL, NULL);
/*
* parse configuration
@@ -1735,7 +1736,7 @@ set_localaddrs(void)
struct sockaddr_in6 *sin6;
struct table *t;
- t = table_create("static", "<anyhost>", NULL);
+ t = table_create("static", "<anyhost>", NULL, NULL);
table_add(t, "local", NULL);
table_add(t, "0.0.0.0/0", NULL);
table_add(t, "::/0", NULL);
@@ -1743,7 +1744,7 @@ set_localaddrs(void)
if (getifaddrs(&ifap) == -1)
fatal("getifaddrs");
- t = table_create("static", "<localhost>", NULL);
+ t = table_create("static", "<localhost>", NULL, NULL);
table_add(t, "local", NULL);
for (p = ifap; p != NULL; p = p->ifa_next) {
diff --git a/usr.sbin/smtpd/parser.c b/usr.sbin/smtpd/parser.c
index 0e1922c251d..a0e75473210 100644
--- a/usr.sbin/smtpd/parser.c
+++ b/usr.sbin/smtpd/parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.33 2013/02/14 12:30:49 gilles Exp $ */
+/* $OpenBSD: parser.c,v 1.34 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -22,7 +22,6 @@
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <event.h>
#include <imsg.h>
@@ -149,7 +148,7 @@ static const struct token t_trace[] = {
{KEYWORD, "lookup", LOG_TRACE_LOOKUP, NULL},
{KEYWORD, "stat", LOG_TRACE_STAT, NULL},
{KEYWORD, "rules", LOG_TRACE_RULES, NULL},
- {KEYWORD, "msg-size", LOG_TRACE_IMSG_SIZE, NULL},
+ {KEYWORD, "mproc", LOG_TRACE_MPROC, NULL},
{KEYWORD, "expand", LOG_TRACE_EXPAND, NULL},
{KEYWORD, "all", LOG_TRACE_ALL, NULL},
{ENDTOKEN, "", NONE, NULL}
@@ -166,7 +165,7 @@ static const struct token t_untrace[] = {
{KEYWORD, "lookup", LOG_UNTRACE_LOOKUP, NULL},
{KEYWORD, "stat", LOG_UNTRACE_STAT, NULL},
{KEYWORD, "rules", LOG_UNTRACE_RULES, NULL},
- {KEYWORD, "msg-size", LOG_UNTRACE_IMSG_SIZE, NULL},
+ {KEYWORD, "mproc", LOG_UNTRACE_MPROC, NULL},
{KEYWORD, "expand", LOG_UNTRACE_EXPAND, NULL},
{KEYWORD, "all", LOG_UNTRACE_ALL, NULL},
{ENDTOKEN, "", NONE, NULL}
diff --git a/usr.sbin/smtpd/parser.h b/usr.sbin/smtpd/parser.h
index a6d5ad00385..ffdcc49c08a 100644
--- a/usr.sbin/smtpd/parser.h
+++ b/usr.sbin/smtpd/parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.26 2013/02/14 12:30:49 gilles Exp $ */
+/* $OpenBSD: parser.h,v 1.27 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -46,7 +46,7 @@ enum actions {
LOG_TRACE_LOOKUP,
LOG_TRACE_STAT,
LOG_TRACE_RULES,
- LOG_TRACE_IMSG_SIZE,
+ LOG_TRACE_MPROC,
LOG_TRACE_EXPAND,
LOG_TRACE_ALL,
LOG_UNTRACE_IMSG,
@@ -59,7 +59,7 @@ enum actions {
LOG_UNTRACE_LOOKUP,
LOG_UNTRACE_STAT,
LOG_UNTRACE_RULES,
- LOG_UNTRACE_IMSG_SIZE,
+ LOG_UNTRACE_MPROC,
LOG_UNTRACE_EXPAND,
LOG_UNTRACE_ALL,
LOG_PROFILE_IMSG,
@@ -69,7 +69,7 @@ enum actions {
};
struct ctl_id {
- objid_t id;
+ uint32_t id;
char name[MAX_NAME_SIZE];
};
diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c
index ffb956e1766..e2517fdac2a 100644
--- a/usr.sbin/smtpd/queue.c
+++ b/usr.sbin/smtpd/queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.c,v 1.147 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: queue.c,v 1.148 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -82,7 +81,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
ret = queue_message_create(&msgid);
- m_create(p, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, 24);
+ m_create(p, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1);
m_add_id(p, reqid);
if (ret == 0)
m_add_int(p, 0);
@@ -101,7 +100,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
queue_message_delete(msgid);
m_create(p_scheduler, IMSG_QUEUE_REMOVE_MESSAGE,
- 0, 0, -1, 5);
+ 0, 0, -1);
m_add_msgid(p_scheduler, msgid);
m_close(p_scheduler);
return;
@@ -114,14 +113,14 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
ret = queue_message_commit(msgid);
- m_create(p, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, 16);
+ m_create(p, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1);
m_add_id(p, reqid);
m_add_int(p, (ret == 0) ? 0 : 1);
m_close(p);
if (ret) {
m_create(p_scheduler, IMSG_QUEUE_COMMIT_MESSAGE,
- 0, 0, -1, 5);
+ 0, 0, -1);
m_add_msgid(p_scheduler, msgid);
m_close(p_scheduler);
}
@@ -135,7 +134,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
fd = queue_message_fd_rw(msgid);
- m_create(p, IMSG_QUEUE_MESSAGE_FILE, 0, 0, fd, 16);
+ m_create(p, IMSG_QUEUE_MESSAGE_FILE, 0, 0, fd);
m_add_id(p, reqid);
m_add_int(p, (fd == -1) ? 0 : 1);
m_close(p);
@@ -156,13 +155,12 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_end(&m);
if (evp.id == 0)
- log_warn("warn: imsg_queue_submit_envelope: evpid=0");
+ log_warnx("warn: imsg_queue_submit_envelope: evpid=0");
if (evpid_to_msgid(evp.id) == 0)
- log_warn("warn: imsg_queue_submit_envelope: msgid=0, "
+ log_warnx("warn: imsg_queue_submit_envelope: msgid=0, "
"evpid=%016"PRIx64, evp.id);
ret = queue_envelope_create(&evp);
- m_create(p_smtp, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
- 24);
+ m_create(p_smtp, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1);
m_add_id(p_smtp, reqid);
if (ret == 0)
m_add_int(p_smtp, 0);
@@ -173,8 +171,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_close(p_smtp);
if (ret) {
m_create(p_scheduler,
- IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
- MSZ_EVP);
+ IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1);
m_add_envelope(p_scheduler, &evp);
m_close(p_scheduler);
@@ -185,8 +182,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_id(&m, &reqid);
m_end(&m);
- m_create(p_smtp, IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1,
- 16);
+ m_create(p_smtp, IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1);
m_add_id(p_smtp, reqid);
m_add_int(p_smtp, 1);
m_close(p_smtp);
@@ -200,8 +196,10 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_evpid(&m, &evpid);
m_end(&m);
+
+ /* already removed by scheduler */
if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+ return;
queue_log(&evp, "Remove", "Removed by administrator");
queue_envelope_delete(evpid);
return;
@@ -210,8 +208,11 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_evpid(&m, &evpid);
m_end(&m);
+
+ /* already removed by scheduler*/
if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+ return;
+
bounce.type = B_ERROR;
bounce.delay = 0;
bounce.expire = 0;
@@ -224,8 +225,15 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
case IMSG_QUEUE_BOUNCE:
req_bounce = imsg->data;
evpid = req_bounce->evpid;
- if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+
+ if (queue_envelope_load(evpid, &evp) == 0) {
+ log_warnx("queue: bounce: failed to load envelope");
+ m_create(p_scheduler, IMSG_QUEUE_REMOVE, 0, 0, -1);
+ m_add_evpid(p_scheduler, evpid);
+ m_add_u32(p_scheduler, 0); /* not in-flight */
+ m_close(p_scheduler);
+ return;
+ }
queue_bounce(&evp, &req_bounce->bounce);
evp.lastbounce = req_bounce->timestamp;
queue_envelope_update(&evp);
@@ -235,10 +243,16 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_evpid(&m, &evpid);
m_end(&m);
- if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+ if (queue_envelope_load(evpid, &evp) == 0) {
+ log_warnx("queue: deliver: failed to load envelope");
+ m_create(p_scheduler, IMSG_QUEUE_REMOVE, 0, 0, -1);
+ m_add_evpid(p_scheduler, evpid);
+ m_add_u32(p_scheduler, 1); /* in-flight */
+ m_close(p_scheduler);
+ return;
+ }
evp.lasttry = time(NULL);
- m_create(p_mda, IMSG_MDA_DELIVER, 0, 0, -1, MSZ_EVP);
+ m_create(p_mda, IMSG_MDA_DELIVER, 0, 0, -1);
m_add_envelope(p_mda, &evp);
m_close(p_mda);
return;
@@ -252,7 +266,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
case IMSG_MTA_BATCH:
batch_id = generate_uid();
- m_create(p_mta, IMSG_MTA_BATCH, 0, 0, -1, 9);
+ m_create(p_mta, IMSG_MTA_BATCH, 0, 0, -1);
m_add_id(p_mta, batch_id);
m_close(p_mta);
return;
@@ -261,17 +275,23 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_evpid(&m, &evpid);
m_end(&m);
- if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+ if (queue_envelope_load(evpid, &evp) == 0) {
+ log_warnx("queue: batch: failed to load envelope");
+ m_create(p_scheduler, IMSG_QUEUE_REMOVE, 0, 0, -1);
+ m_add_evpid(p_scheduler, evpid);
+ m_add_u32(p_scheduler, 1); /* in-flight */
+ m_close(p_scheduler);
+ return;
+ }
evp.lasttry = time(NULL);
- m_create(p_mta, IMSG_MTA_BATCH_ADD, 0, 0, -1, MSZ_EVP);
+ m_create(p_mta, IMSG_MTA_BATCH_ADD, 0, 0, -1);
m_add_id(p_mta, batch_id);
m_add_envelope(p_mta, &evp);
m_close(p_mta);
return;
case IMSG_MTA_BATCH_END:
- m_create(p_mta, IMSG_MTA_BATCH_END, 0, 0, -1, 9);
+ m_create(p_mta, IMSG_MTA_BATCH_END, 0, 0, -1);
m_add_id(p_mta, batch_id);
m_close(p_mta);
return;
@@ -321,7 +341,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_get_msgid(&m, &msgid);
m_end(&m);
fd = queue_message_fd_r(msgid);
- m_create(p, IMSG_QUEUE_MESSAGE_FD, 0, 0, fd, 25);
+ m_create(p, IMSG_QUEUE_MESSAGE_FD, 0, 0, fd);
m_add_id(p, reqid);
m_close(p);
return;
@@ -331,7 +351,7 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_get_evpid(&m, &evpid);
m_end(&m);
queue_envelope_delete(evpid);
- m_create(p_scheduler, IMSG_DELIVERY_OK, 0, 0, -1, 9);
+ m_create(p_scheduler, IMSG_DELIVERY_OK, 0, 0, -1);
m_add_evpid(p_scheduler, evpid);
m_close(p_scheduler);
return;
@@ -341,13 +361,18 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_get_evpid(&m, &evpid);
m_get_string(&m, &reason);
m_end(&m);
- if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+ if (queue_envelope_load(evpid, &evp) == 0) {
+ log_warnx("queue: tempfail: failed to load envelope");
+ m_create(p_scheduler, IMSG_QUEUE_REMOVE, 0, 0, -1);
+ m_add_evpid(p_scheduler, evpid);
+ m_add_u32(p_scheduler, 1); /* in-flight */
+ m_close(p_scheduler);
+ return;
+ }
envelope_set_errormsg(&evp, "%s", reason);
evp.retry++;
queue_envelope_update(&evp);
- m_create(p_scheduler, IMSG_DELIVERY_TEMPFAIL, 0, 0, -1,
- MSZ_EVP);
+ m_create(p_scheduler, IMSG_DELIVERY_TEMPFAIL, 0, 0, -1);
m_add_envelope(p_scheduler, &evp);
m_close(p_scheduler);
return;
@@ -357,16 +382,21 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_get_evpid(&m, &evpid);
m_get_string(&m, &reason);
m_end(&m);
- if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+ if (queue_envelope_load(evpid, &evp) == 0) {
+ log_warnx("queue: permfail: failed to load envelope");
+ m_create(p_scheduler, IMSG_QUEUE_REMOVE, 0, 0, -1);
+ m_add_evpid(p_scheduler, evpid);
+ m_add_u32(p_scheduler, 1); /* in-flight */
+ m_close(p_scheduler);
+ return;
+ }
bounce.type = B_ERROR;
bounce.delay = 0;
bounce.expire = 0;
envelope_set_errormsg(&evp, "%s", reason);
queue_bounce(&evp, &bounce);
queue_envelope_delete(evpid);
- m_create(p_scheduler, IMSG_DELIVERY_PERMFAIL, 0, 0, -1,
- 9);
+ m_create(p_scheduler, IMSG_DELIVERY_PERMFAIL, 0, 0, -1);
m_add_evpid(p_scheduler, evpid);
m_close(p_scheduler);
return;
@@ -375,15 +405,21 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_evpid(&m, &evpid);
m_end(&m);
- if (queue_envelope_load(evpid, &evp) == 0)
- errx(1, "cannot load evp:%016" PRIx64, evpid);
+ if (queue_envelope_load(evpid, &evp) == 0) {
+ log_warnx("queue: loop: failed to load envelope");
+ m_create(p_scheduler, IMSG_QUEUE_REMOVE, 0, 0, -1);
+ m_add_evpid(p_scheduler, evpid);
+ m_add_u32(p_scheduler, 1); /* in-flight */
+ m_close(p_scheduler);
+ return;
+ }
envelope_set_errormsg(&evp, "%s", "Loop detected");
bounce.type = B_ERROR;
bounce.delay = 0;
bounce.expire = 0;
queue_bounce(&evp, &bounce);
queue_envelope_delete(evp.id);
- m_create(p_scheduler, IMSG_DELIVERY_LOOP, 0, 0, -1, 9);
+ m_create(p_scheduler, IMSG_DELIVERY_LOOP, 0, 0, -1);
m_add_evpid(p_scheduler, evp.id);
m_close(p_scheduler);
return;
@@ -438,9 +474,9 @@ queue_bounce(struct envelope *e, struct delivery_bounce *d)
b.expire = 3600 * 24 * 7;
if (b.id == 0)
- log_warn("warn: queue_bounce: evpid=0");
+ log_warnx("warn: queue_bounce: evpid=0");
if (evpid_to_msgid(b.id) == 0)
- log_warn("warn: queue_bounce: msgid=0, evpid=%016"PRIx64,
+ log_warnx("warn: queue_bounce: msgid=0, evpid=%016"PRIx64,
b.id);
if (e->type == D_BOUNCE) {
log_warnx("warn: queue: double bounce!");
@@ -452,12 +488,11 @@ queue_bounce(struct envelope *e, struct delivery_bounce *d)
log_debug("debug: queue: bouncing evp:%016" PRIx64
" as evp:%016" PRIx64, e->id, b.id);
- m_create(p_scheduler, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
- MSZ_EVP);
+ m_create(p_scheduler, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1);
m_add_envelope(p_scheduler, &b);
m_close(p_scheduler);
- m_create(p_scheduler, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, 5);
+ m_create(p_scheduler, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1);
m_add_msgid(p_scheduler, evpid_to_msgid(b.id));
m_close(p_scheduler);
@@ -571,7 +606,7 @@ queue_timeout(int fd, short event, void *p)
if (r == -1) {
if (msgid) {
m_create(p_scheduler, IMSG_QUEUE_COMMIT_MESSAGE,
- 0, 0, -1, 5);
+ 0, 0, -1);
m_add_msgid(p_scheduler, msgid);
m_close(p_scheduler);
}
@@ -582,13 +617,12 @@ queue_timeout(int fd, short event, void *p)
if (r) {
if (msgid && evpid_to_msgid(evp.id) != msgid) {
m_create(p_scheduler, IMSG_QUEUE_COMMIT_MESSAGE,
- 0, 0, -1, 5);
+ 0, 0, -1);
m_add_msgid(p_scheduler, msgid);
m_close(p_scheduler);
}
msgid = evpid_to_msgid(evp.id);
- m_create(p_scheduler, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
- MSZ_EVP);
+ m_create(p_scheduler, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1);
m_add_envelope(p_scheduler, &evp);
m_close(p_scheduler);
}
@@ -601,7 +635,7 @@ queue_timeout(int fd, short event, void *p)
void
queue_ok(uint64_t evpid)
{
- m_create(p_queue, IMSG_DELIVERY_OK, 0, 0, -1, sizeof(evpid) + 1);
+ m_create(p_queue, IMSG_DELIVERY_OK, 0, 0, -1);
m_add_evpid(p_queue, evpid);
m_close(p_queue);
}
@@ -609,8 +643,7 @@ queue_ok(uint64_t evpid)
void
queue_tempfail(uint64_t evpid, const char *reason)
{
- m_create(p_queue, IMSG_DELIVERY_TEMPFAIL, 0, 0, -1,
- sizeof(evpid) + strlen(reason) + 2);
+ m_create(p_queue, IMSG_DELIVERY_TEMPFAIL, 0, 0, -1);
m_add_evpid(p_queue, evpid);
m_add_string(p_queue, reason);
m_close(p_queue);
@@ -619,8 +652,7 @@ queue_tempfail(uint64_t evpid, const char *reason)
void
queue_permfail(uint64_t evpid, const char *reason)
{
- m_create(p_queue, IMSG_DELIVERY_PERMFAIL, 0, 0, -1,
- sizeof(evpid) + strlen(reason) + 2);
+ m_create(p_queue, IMSG_DELIVERY_PERMFAIL, 0, 0, -1);
m_add_evpid(p_queue, evpid);
m_add_string(p_queue, reason);
m_close(p_queue);
@@ -629,7 +661,7 @@ queue_permfail(uint64_t evpid, const char *reason)
void
queue_loop(uint64_t evpid)
{
- m_create(p_queue, IMSG_DELIVERY_LOOP, 0, 0, -1, sizeof(evpid) + 1);
+ m_create(p_queue, IMSG_DELIVERY_LOOP, 0, 0, -1);
m_add_evpid(p_queue, evpid);
m_close(p_queue);
}
diff --git a/usr.sbin/smtpd/queue_backend.c b/usr.sbin/smtpd/queue_backend.c
index 9eb9693e0e6..5fc1cd1994d 100644
--- a/usr.sbin/smtpd/queue_backend.c
+++ b/usr.sbin/smtpd/queue_backend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue_backend.c,v 1.43 2013/04/17 15:02:38 deraadt Exp $ */
+/* $OpenBSD: queue_backend.c,v 1.44 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -73,8 +72,8 @@ static inline void profile_leave(void)
clock_gettime(CLOCK_MONOTONIC, &t1);
timespecsub(&t1, &profile.t0, &dt);
- log_debug("profile-queue: %s %lld.%06li", profile.name,
- (long long)dt.tv_sec * 1000000 + dt.tv_nsec / 1000000,
+ log_debug("profile-queue: %s %li.%06li", profile.name,
+ dt.tv_sec * 1000000 + dt.tv_nsec / 1000000,
dt.tv_nsec % 1000000);
}
#else
@@ -93,6 +92,8 @@ queue_message_incoming_path(uint32_t msgid, char *buf, size_t len)
int
queue_init(const char *name, int server)
{
+ int r;
+
if (!strcmp(name, "fs"))
backend = &queue_backend_fs;
if (!strcmp(name, "null"))
@@ -105,7 +106,11 @@ queue_init(const char *name, int server)
return (0);
}
- return backend->init(server);
+ r = backend->init(server);
+
+ log_trace(TRACE_QUEUE, "queue-backend: queue_init(%i) -> %i", server, r);
+
+ return (r);
}
int
@@ -117,6 +122,10 @@ queue_message_create(uint32_t *msgid)
r = backend->message(QOP_CREATE, msgid);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_message_create() -> %i (%08"PRIx32")",
+ r, *msgid);
+
return (r);
}
@@ -129,6 +138,9 @@ queue_message_delete(uint32_t msgid)
r = backend->message(QOP_DELETE, &msgid);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_message_delete(%08"PRIx32") -> %i", msgid, r);
+
return (r);
}
@@ -136,12 +148,51 @@ int
queue_message_commit(uint32_t msgid)
{
int r;
+ char msgpath[MAXPATHLEN];
+ char tmppath[MAXPATHLEN];
+ FILE *ifp = NULL;
+ FILE *ofp = NULL;
profile_enter("queue_message_commit");
+ queue_message_incoming_path(msgid, msgpath, sizeof msgpath);
+ strlcat(msgpath, PATH_MESSAGE, sizeof(msgpath));
+
+ if (env->sc_queue_flags & QUEUE_COMPRESSION) {
+
+ bsnprintf(tmppath, sizeof tmppath, "%s.comp", msgpath);
+ ifp = fopen(msgpath, "r");
+ ofp = fopen(tmppath, "w+");
+ if (ifp == NULL || ofp == NULL)
+ goto err;
+ if (! compress_file(ifp, ofp))
+ goto err;
+ fclose(ifp);
+ fclose(ofp);
+ ifp = NULL;
+ ofp = NULL;
+
+ if (rename(tmppath, msgpath) == -1) {
+ if (errno == ENOSPC)
+ return (0);
+ fatal("queue_message_commit: rename");
+ }
+ }
+
r = backend->message(QOP_COMMIT, &msgid);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_message_commit(%08"PRIx32") -> %i",
+ msgid, r);
+
return (r);
+
+err:
+ if (ifp)
+ fclose(ifp);
+ if (ofp)
+ fclose(ofp);
+ return 0;
}
int
@@ -153,6 +204,9 @@ queue_message_corrupt(uint32_t msgid)
r = backend->message(QOP_CORRUPT, &msgid);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_message_corrupt(%08"PRIx32") -> %i", msgid, r);
+
return (r);
}
@@ -167,10 +221,13 @@ queue_message_fd_r(uint32_t msgid)
fdin = backend->message(QOP_FD_R, &msgid);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_message_fd_r(%08"PRIx32") -> %i", msgid, fdin);
+
if (fdin == -1)
return (-1);
- if (env->sc_queue_flags & QUEUE_COMPRESS) {
+ if (env->sc_queue_flags & QUEUE_COMPRESSION) {
if ((fdout = mktmpfile()) == -1)
goto err;
if ((fd = dup(fdout)) == -1)
@@ -181,8 +238,10 @@ queue_message_fd_r(uint32_t msgid)
fd = -1;
if ((ofp = fdopen(fdout, "w+")) == NULL)
goto err;
+
if (! uncompress_file(ifp, ofp))
goto err;
+
fclose(ifp);
fclose(ofp);
lseek(fdin, SEEK_SET, 0);
@@ -213,27 +272,31 @@ queue_message_fd_rw(uint32_t msgid)
r = backend->message(QOP_FD_RW, &msgid);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_message_fd_rw(%08"PRIx32") -> %i", msgid, r);
+
return (r);
}
static int
queue_envelope_dump_buffer(struct envelope *ep, char *evpbuf, size_t evpbufsize)
{
- char evpbufcom[sizeof(struct envelope)];
- char *evp;
- size_t evplen;
+ char *evp;
+ size_t evplen;
+ size_t complen;
+ char compbuf[sizeof(struct envelope)];
evp = evpbuf;
evplen = envelope_dump_buffer(ep, evpbuf, evpbufsize);
if (evplen == 0)
return (0);
- if (env->sc_queue_flags & QUEUE_COMPRESS) {
- evplen = compress_buffer(evp, evplen, evpbufcom,
- sizeof evpbufcom);
- if (evplen == 0)
+ if (env->sc_queue_flags & QUEUE_COMPRESSION) {
+ complen = compress_chunk(evp, evplen, compbuf, sizeof compbuf);
+ if (complen == 0)
return (0);
- evp = evpbufcom;
+ evp = compbuf;
+ evplen = complen;
}
memmove(evpbuf, evp, evplen);
@@ -244,19 +307,20 @@ queue_envelope_dump_buffer(struct envelope *ep, char *evpbuf, size_t evpbufsize)
static int
queue_envelope_load_buffer(struct envelope *ep, char *evpbuf, size_t evpbufsize)
{
- char evpbufcom[sizeof(struct envelope)];
char *evp;
size_t evplen;
+ char compbuf[sizeof(struct envelope)];
+ size_t complen;
evp = evpbuf;
evplen = evpbufsize;
- if (env->sc_queue_flags & QUEUE_COMPRESS) {
- evplen = uncompress_buffer(evp, evplen, evpbufcom,
- sizeof evpbufcom);
- if (evplen == 0)
+ if (env->sc_queue_flags & QUEUE_COMPRESSION) {
+ complen = uncompress_chunk(evp, evplen, compbuf, sizeof compbuf);
+ if (complen == 0)
return (0);
- evp = evpbufcom;
+ evp = compbuf;
+ evplen = complen;
}
return (envelope_load_buffer(ep, evp, evplen));
@@ -268,19 +332,28 @@ queue_envelope_create(struct envelope *ep)
int r;
char evpbuf[sizeof(struct envelope)];
size_t evplen;
+ uint64_t evpid;
ep->creation = time(NULL);
evplen = queue_envelope_dump_buffer(ep, evpbuf, sizeof evpbuf);
if (evplen == 0)
return (0);
+ evpid = ep->id;
+
profile_enter("queue_envelope_create");
r = backend->envelope(QOP_CREATE, &ep->id, evpbuf, evplen);
profile_leave();
+
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_envelope_create(%016"PRIx64", %zu) -> %i (%016"PRIx64")",
+ evpid, evplen, r, ep->id);
+
if (!r) {
ep->creation = 0;
ep->id = 0;
}
+
return (r);
}
@@ -293,6 +366,10 @@ queue_envelope_delete(uint64_t evpid)
r = backend->envelope(QOP_DELETE, &evpid, NULL, 0);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_envelope_delete(%016"PRIx64") -> %i",
+ evpid, r);
+
return (r);
}
@@ -307,6 +384,11 @@ queue_envelope_load(uint64_t evpid, struct envelope *ep)
profile_enter("queue_envelope_load");
evplen = backend->envelope(QOP_LOAD, &ep->id, evpbuf, sizeof evpbuf);
profile_leave();
+
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_envelope_load(%016"PRIx64") -> %zu",
+ evpid, evplen);
+
if (evplen == 0)
return (0);
@@ -318,6 +400,8 @@ queue_envelope_load(uint64_t evpid, struct envelope *ep)
log_debug("debug: invalid envelope %016" PRIx64 ": %s",
ep->id, e);
}
+
+ (void)queue_message_corrupt(evpid_to_msgid(evpid));
return (0);
}
@@ -336,6 +420,10 @@ queue_envelope_update(struct envelope *ep)
r = backend->envelope(QOP_UPDATE, &ep->id, evpbuf, evplen);
profile_leave();
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_envelope_update(%016"PRIx64") -> %i",
+ ep->id, r);
+
return (r);
}
@@ -350,10 +438,15 @@ queue_envelope_walk(struct envelope *ep)
profile_enter("queue_envelope_walk");
r = backend->envelope(QOP_WALK, &evpid, evpbuf, sizeof evpbuf);
profile_leave();
- if (r == -1 || r == 0)
+
+ log_trace(TRACE_QUEUE,
+ "queue-backend: queue_envelope_walk() -> %i (%016"PRIx64")",
+ r, evpid);
+
+ if (r == -1)
return (r);
- if (queue_envelope_load_buffer(ep, evpbuf, (size_t)r)) {
+ if (r && queue_envelope_load_buffer(ep, evpbuf, (size_t)r)) {
if ((e = envelope_validate(ep)) == NULL) {
ep->id = evpid;
return (1);
@@ -361,6 +454,8 @@ queue_envelope_walk(struct envelope *ep)
log_debug("debug: invalid envelope %016" PRIx64 ": %s",
ep->id, e);
}
+
+ (void)queue_message_corrupt(evpid_to_msgid(evpid));
return (0);
}
diff --git a/usr.sbin/smtpd/queue_fsqueue.c b/usr.sbin/smtpd/queue_fsqueue.c
index 2c27f426d60..85e6e233c2e 100644
--- a/usr.sbin/smtpd/queue_fsqueue.c
+++ b/usr.sbin/smtpd/queue_fsqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue_fsqueue.c,v 1.61 2013/04/02 09:17:14 gilles Exp $ */
+/* $OpenBSD: queue_fsqueue.c,v 1.62 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/param.h>
@@ -79,8 +78,8 @@ struct tree evpcount;
#define PATH_EVPTMP PATH_INCOMING "/envelope.tmp"
/* percentage of remaining space / inodes required to accept new messages */
-#define MINSPACE 10
-#define MININODES 10
+#define MINSPACE 5
+#define MININODES 5
struct queue_backend queue_backend_fs = {
fsqueue_init,
@@ -110,6 +109,7 @@ fsqueue_check_space(void)
used = 100;
if (100 - used < MINSPACE) {
log_warnx("warn: not enough disk space: %llu%% left", 100 - used);
+ log_warnx("warn: temporarily rejecting messages");
return 0;
}
@@ -121,6 +121,7 @@ fsqueue_check_space(void)
used = 100;
if (100 - used < MININODES) {
log_warnx("warn: not enough inodes: %llu%% left", 100 - used);
+ log_warnx("warn: temporarily rejecting messages");
return 0;
}
@@ -227,7 +228,7 @@ tempfail:
static int
fsqueue_envelope_create(uint64_t *evpid, char *buf, size_t len)
{
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
uint32_t msgid;
int queued = 0, i, r = 0;
struct stat sb;
@@ -271,7 +272,7 @@ done:
static int
fsqueue_envelope_load(uint64_t evpid, char *buf, size_t len)
{
- char pathname[MAXPATHLEN];
+ char pathname[SMTPD_MAXPATHLEN];
FILE *fp;
size_t r;
@@ -301,7 +302,7 @@ fsqueue_envelope_load(uint64_t evpid, char *buf, size_t len)
static int
fsqueue_envelope_update(uint64_t evpid, char *buf, size_t len)
{
- char dest[MAXPATHLEN];
+ char dest[SMTPD_MAXPATHLEN];
fsqueue_envelope_path(evpid, dest, sizeof(dest));
@@ -311,7 +312,7 @@ fsqueue_envelope_update(uint64_t evpid, char *buf, size_t len)
static int
fsqueue_envelope_delete(uint64_t evpid)
{
- char pathname[MAXPATHLEN];
+ char pathname[SMTPD_MAXPATHLEN];
uint32_t msgid;
uintptr_t *n;
@@ -339,7 +340,6 @@ fsqueue_envelope_walk(uint64_t *evpid, char *buf, size_t len)
uintptr_t *n;
int r;
uint32_t msgid;
- struct envelope ep;
if (done)
return (-1);
@@ -352,13 +352,9 @@ fsqueue_envelope_walk(uint64_t *evpid, char *buf, size_t len)
r = fsqueue_envelope_load(*evpid, buf, len);
if (r) {
msgid = evpid_to_msgid(*evpid);
- if (! envelope_load_buffer(&ep, buf, r))
- (void)fsqueue_message_corrupt(msgid);
- else {
- n = tree_pop(&evpcount, msgid);
- n += 1;
- tree_xset(&evpcount, msgid, n);
- }
+ n = tree_pop(&evpcount, msgid);
+ n += 1;
+ tree_xset(&evpcount, msgid, n);
}
return (r);
}
@@ -371,8 +367,8 @@ fsqueue_envelope_walk(uint64_t *evpid, char *buf, size_t len)
static int
fsqueue_message_create(uint32_t *msgid)
{
- char rootdir[MAXPATHLEN];
- struct stat sb;
+ char rootdir[SMTPD_MAXPATHLEN];
+ struct stat sb;
if (! fsqueue_check_space())
return 0;
@@ -382,9 +378,15 @@ again:
/* prevent possible collision later when moving to Q_QUEUE */
fsqueue_message_path(*msgid, rootdir, sizeof(rootdir));
- if (stat(rootdir, &sb) != -1 || errno != ENOENT)
+ if (stat(rootdir, &sb) != -1)
goto again;
+ /* we hit an unexpected error, temporarily fail */
+ if (errno != ENOENT) {
+ *msgid = 0;
+ return 0;
+ }
+
queue_message_incoming_path(*msgid, rootdir, sizeof(rootdir));
if (mkdir(rootdir, 0700) == -1) {
if (errno == EEXIST)
@@ -406,9 +408,9 @@ again:
static int
fsqueue_message_commit(uint32_t msgid)
{
- char incomingdir[MAXPATHLEN];
- char queuedir[MAXPATHLEN];
- char msgdir[MAXPATHLEN];
+ char incomingdir[SMTPD_MAXPATHLEN];
+ char queuedir[SMTPD_MAXPATHLEN];
+ char msgdir[SMTPD_MAXPATHLEN];
queue_message_incoming_path(msgid, incomingdir, sizeof(incomingdir));
fsqueue_message_path(msgid, msgdir, sizeof(msgdir));
@@ -450,7 +452,7 @@ static int
fsqueue_message_fd_r(uint32_t msgid)
{
int fd;
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
fsqueue_message_path(msgid, path, sizeof(path));
strlcat(path, PATH_MESSAGE, sizeof(path));
@@ -466,7 +468,7 @@ fsqueue_message_fd_r(uint32_t msgid)
static int
fsqueue_message_fd_rw(uint32_t msgid)
{
- char msgpath[MAXPATHLEN];
+ char msgpath[SMTPD_MAXPATHLEN];
queue_message_incoming_path(msgid, msgpath, sizeof msgpath);
strlcat(msgpath, PATH_MESSAGE, sizeof(msgpath));
@@ -477,7 +479,7 @@ fsqueue_message_fd_rw(uint32_t msgid)
static int
fsqueue_message_delete(uint32_t msgid)
{
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
struct stat sb;
queue_message_incoming_path(msgid, path, sizeof(path));
@@ -496,8 +498,8 @@ static int
fsqueue_message_corrupt(uint32_t msgid)
{
struct stat sb;
- char rootdir[MAXPATHLEN];
- char corruptdir[MAXPATHLEN];
+ char rootdir[SMTPD_MAXPATHLEN];
+ char corruptdir[SMTPD_MAXPATHLEN];
char buf[64];
int retry = 0;
@@ -519,6 +521,8 @@ again:
return 0;
}
+ tree_pop(&evpcount, msgid);
+
return 1;
}
@@ -527,7 +531,7 @@ fsqueue_init(int server)
{
unsigned int n;
char *paths[] = { PATH_QUEUE, PATH_CORRUPT };
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
int ret;
struct timeval tv;
@@ -602,7 +606,7 @@ struct qwalk {
static void *
fsqueue_qwalk_new(void)
{
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
char * const path_argv[] = { path, NULL };
struct qwalk *q;
diff --git a/usr.sbin/smtpd/queue_null.c b/usr.sbin/smtpd/queue_null.c
index 770111239dc..e6f1ed279e9 100644
--- a/usr.sbin/smtpd/queue_null.c
+++ b/usr.sbin/smtpd/queue_null.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue_null.c,v 1.1 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: queue_null.c,v 1.2 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
diff --git a/usr.sbin/smtpd/queue_ram.c b/usr.sbin/smtpd/queue_ram.c
index ab80811435e..55b3c3fd08d 100644
--- a/usr.sbin/smtpd/queue_ram.c
+++ b/usr.sbin/smtpd/queue_ram.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue_ram.c,v 1.2 2013/01/31 18:34:43 eric Exp $ */
+/* $OpenBSD: queue_ram.c,v 1.3 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -76,7 +75,7 @@ queue_ram_init(int server)
static int
queue_ram_message(enum queue_op qop, uint32_t *msgid)
{
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
uint64_t evpid;
struct qr_envelope *evp;
struct qr_message *msg;
diff --git a/usr.sbin/smtpd/ruleset.c b/usr.sbin/smtpd/ruleset.c
index 04ffe2cdfe5..7042ee090ca 100644
--- a/usr.sbin/smtpd/ruleset.c
+++ b/usr.sbin/smtpd/ruleset.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ruleset.c,v 1.27 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: ruleset.c,v 1.28 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
diff --git a/usr.sbin/smtpd/scheduler.c b/usr.sbin/smtpd/scheduler.c
index 1d114b457a4..6c2d8da476f 100644
--- a/usr.sbin/smtpd/scheduler.c
+++ b/usr.sbin/smtpd/scheduler.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler.c,v 1.27 2013/02/10 15:01:16 eric Exp $ */
+/* $OpenBSD: scheduler.c,v 1.28 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -22,7 +22,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -57,6 +56,7 @@ static void scheduler_process_mda(struct scheduler_batch *);
static void scheduler_process_mta(struct scheduler_batch *);
static struct scheduler_backend *backend = NULL;
+static struct event ev;
extern const char *backend_scheduler;
@@ -75,6 +75,7 @@ scheduler_imsg(struct mproc *p, struct imsg *imsg)
struct msg m;
uint64_t evpid, id;
uint32_t msgid, msgids[MSGBATCHSIZE];
+ uint32_t inflight;
size_t n, i;
time_t timestamp;
int v;
@@ -115,6 +116,23 @@ scheduler_imsg(struct mproc *p, struct imsg *imsg)
scheduler_reset_events();
return;
+ case IMSG_QUEUE_REMOVE:
+ m_msg(&m, imsg);
+ m_get_evpid(&m, &evpid);
+ m_get_u32(&m, &inflight);
+ m_end(&m);
+ log_trace(TRACE_SCHEDULER,
+ "scheduler: queue requested removal of evp:%016" PRIx64,
+ evpid);
+ stat_decrement("scheduler.envelope", 1);
+ if (! inflight)
+ backend->remove(evpid);
+ else
+ backend->delete(evpid);
+
+ scheduler_reset_events();
+ return;
+
case IMSG_DELIVERY_OK:
m_msg(&m, imsg);
m_get_evpid(&m, &evpid);
@@ -225,7 +243,7 @@ scheduler_imsg(struct mproc *p, struct imsg *imsg)
n = backend->envelopes(id, state, EVPBATCHSIZE);
for (i = 0; i < n; i++) {
m_create(p_queue, IMSG_CTL_LIST_ENVELOPES,
- imsg->hdr.peerid, 0, -1, 32);
+ imsg->hdr.peerid, 0, -1);
m_add_evpid(p_queue, state[i].evpid);
m_add_int(p_queue, state[i].flags);
m_add_time(p_queue, state[i].time);
@@ -289,10 +307,10 @@ scheduler_reset_events(void)
{
struct timeval tv;
- evtimer_del(&env->sc_ev);
+ evtimer_del(&ev);
tv.tv_sec = 0;
tv.tv_usec = 0;
- evtimer_add(&env->sc_ev, &tv);
+ evtimer_add(&ev, &tv);
}
pid_t
@@ -303,6 +321,11 @@ scheduler(void)
struct event ev_sigint;
struct event ev_sigterm;
+ backend = scheduler_backend_lookup(backend_scheduler);
+ if (backend == NULL)
+ errx(1, "cannot find scheduler backend \"%s\"",
+ backend_scheduler);
+
switch (pid = fork()) {
case -1:
fatal("scheduler: cannot fork");
@@ -315,29 +338,23 @@ scheduler(void)
purge_config(PURGE_EVERYTHING);
+ config_process(PROC_SCHEDULER);
+
+ fdlimit(1.0);
+
+ backend->init();
+
pw = env->sc_pw;
if (chroot(pw->pw_dir) == -1)
fatal("scheduler: chroot");
if (chdir("/") == -1)
fatal("scheduler: chdir(\"/\")");
- config_process(PROC_SCHEDULER);
-
if (setgroups(1, &pw->pw_gid) ||
setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
fatal("scheduler: cannot drop privileges");
- fdlimit(1.0);
-
- env->sc_scheduler = scheduler_backend_lookup(backend_scheduler);
- if (env->sc_scheduler == NULL)
- errx(1, "cannot find scheduler backend \"%s\"",
- backend_scheduler);
- backend = env->sc_scheduler;
-
- backend->init();
-
imsg_callback = scheduler_imsg;
event_init();
@@ -352,7 +369,7 @@ scheduler(void)
config_peer(PROC_QUEUE);
config_done();
- evtimer_set(&env->sc_ev, scheduler_timeout, NULL);
+ evtimer_set(&ev, scheduler_timeout, NULL);
scheduler_reset_events();
if (event_dispatch() < 0)
fatal("event_dispatch");
@@ -431,7 +448,7 @@ scheduler_timeout(int fd, short event, void *p)
fatalx("scheduler_timeout: unknown batch type");
}
- evtimer_add(&env->sc_ev, &tv);
+ evtimer_add(&ev, &tv);
}
static void
@@ -442,7 +459,7 @@ scheduler_process_remove(struct scheduler_batch *batch)
for (i = 0; i < batch->evpcount; i++) {
log_debug("debug: scheduler: evp:%016" PRIx64 " removed",
batch->evpids[i]);
- m_create(p_queue, IMSG_QUEUE_REMOVE, 0, 0, -1, 9);
+ m_create(p_queue, IMSG_QUEUE_REMOVE, 0, 0, -1);
m_add_evpid(p_queue, batch->evpids[i]);
m_close(p_queue);
}
@@ -459,7 +476,7 @@ scheduler_process_expire(struct scheduler_batch *batch)
for (i = 0; i < batch->evpcount; i++) {
log_debug("debug: scheduler: evp:%016" PRIx64 " expired",
batch->evpids[i]);
- m_create(p_queue, IMSG_QUEUE_EXPIRE, 0, 0, -1, 9);
+ m_create(p_queue, IMSG_QUEUE_EXPIRE, 0, 0, -1);
m_add_evpid(p_queue, batch->evpids[i]);
m_close(p_queue);
}
@@ -476,7 +493,7 @@ scheduler_process_bounce(struct scheduler_batch *batch)
for (i = 0; i < batch->evpcount; i++) {
log_debug("debug: scheduler: evp:%016" PRIx64
" scheduled (bounce)", batch->evpids[i]);
- m_create(p_queue, IMSG_BOUNCE_INJECT, 0, 0, -1, 9);
+ m_create(p_queue, IMSG_BOUNCE_INJECT, 0, 0, -1);
m_add_evpid(p_queue, batch->evpids[i]);
m_close(p_queue);
}
@@ -492,7 +509,7 @@ scheduler_process_mda(struct scheduler_batch *batch)
for (i = 0; i < batch->evpcount; i++) {
log_debug("debug: scheduler: evp:%016" PRIx64
" scheduled (mda)", batch->evpids[i]);
- m_create(p_queue, IMSG_MDA_DELIVER, 0, 0, -1, 9);
+ m_create(p_queue, IMSG_MDA_DELIVER, 0, 0, -1);
m_add_evpid(p_queue, batch->evpids[i]);
m_close(p_queue);
}
@@ -510,7 +527,7 @@ scheduler_process_mta(struct scheduler_batch *batch)
for (i = 0; i < batch->evpcount; i++) {
log_debug("debug: scheduler: evp:%016" PRIx64
" scheduled (mta)", batch->evpids[i]);
- m_create(p_queue, IMSG_MTA_BATCH_ADD, 0, 0, -1, 9);
+ m_create(p_queue, IMSG_MTA_BATCH_ADD, 0, 0, -1);
m_add_evpid(p_queue, batch->evpids[i]);
m_close(p_queue);
}
diff --git a/usr.sbin/smtpd/scheduler_backend.c b/usr.sbin/smtpd/scheduler_backend.c
index 2c0a83c8e56..fbe4cb9197d 100644
--- a/usr.sbin/smtpd/scheduler_backend.c
+++ b/usr.sbin/smtpd/scheduler_backend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler_backend.c,v 1.8 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: scheduler_backend.c,v 1.9 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
diff --git a/usr.sbin/smtpd/scheduler_null.c b/usr.sbin/smtpd/scheduler_null.c
index f9e6e272704..6cd7a70e2e7 100644
--- a/usr.sbin/smtpd/scheduler_null.c
+++ b/usr.sbin/smtpd/scheduler_null.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler_null.c,v 1.1 2013/01/26 09:37:23 gilles Exp $ */
+/* $OpenBSD: scheduler_null.c,v 1.2 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -31,17 +30,17 @@
#include "smtpd.h"
-static void scheduler_null_init(void);
-static void scheduler_null_insert(struct scheduler_info *);
+static int scheduler_null_init(void);
+static int scheduler_null_insert(struct scheduler_info *);
static size_t scheduler_null_commit(uint32_t);
static size_t scheduler_null_rollback(uint32_t);
-static void scheduler_null_update(struct scheduler_info *);
-static void scheduler_null_delete(uint64_t);
-static void scheduler_null_batch(int, struct scheduler_batch *);
+static int scheduler_null_update(struct scheduler_info *);
+static int scheduler_null_delete(uint64_t);
+static int scheduler_null_batch(int, struct scheduler_batch *);
static size_t scheduler_null_messages(uint32_t, uint32_t *, size_t);
static size_t scheduler_null_envelopes(uint64_t, struct evpstate *, size_t);
-static void scheduler_null_schedule(uint64_t);
-static void scheduler_null_remove(uint64_t);
+static int scheduler_null_schedule(uint64_t);
+static int scheduler_null_remove(uint64_t);
struct scheduler_backend scheduler_backend_null = {
scheduler_null_init,
@@ -61,14 +60,16 @@ struct scheduler_backend scheduler_backend_null = {
scheduler_null_remove,
};
-static void
+static int
scheduler_null_init(void)
{
+ return (1);
}
-static void
+static int
scheduler_null_insert(struct scheduler_info *si)
{
+ return (0);
}
static size_t
@@ -83,30 +84,37 @@ scheduler_null_rollback(uint32_t msgid)
return (0);
}
-static void
+static int
scheduler_null_update(struct scheduler_info *si)
{
+ return (0);
}
-static void
+static int
scheduler_null_delete(uint64_t evpid)
{
+ return (0);
}
-static void
+static int
scheduler_null_batch(int typemask, struct scheduler_batch *ret)
{
ret->type = SCHED_NONE;
+ ret->evpcount = 0;
+
+ return (0);
}
-static void
+static int
scheduler_null_schedule(uint64_t evpid)
{
+ return (0);
}
-static void
+static int
scheduler_null_remove(uint64_t evpid)
{
+ return (0);
}
static size_t
diff --git a/usr.sbin/smtpd/scheduler_ramqueue.c b/usr.sbin/smtpd/scheduler_ramqueue.c
index 7ee0a4a341b..f8a896b2540 100644
--- a/usr.sbin/smtpd/scheduler_ramqueue.c
+++ b/usr.sbin/smtpd/scheduler_ramqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler_ramqueue.c,v 1.27 2013/02/10 15:01:16 eric Exp $ */
+/* $OpenBSD: scheduler_ramqueue.c,v 1.28 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -82,17 +81,17 @@ struct rq_queue {
struct evplist q_removed;
};
-static void scheduler_ramqueue_init(void);
-static void scheduler_ramqueue_insert(struct scheduler_info *);
-static size_t scheduler_ramqueue_commit(uint32_t);
-static size_t scheduler_ramqueue_rollback(uint32_t);
-static void scheduler_ramqueue_update(struct scheduler_info *);
-static void scheduler_ramqueue_delete(uint64_t);
-static void scheduler_ramqueue_batch(int, struct scheduler_batch *);
-static size_t scheduler_ramqueue_messages(uint32_t, uint32_t *, size_t);
-static size_t scheduler_ramqueue_envelopes(uint64_t, struct evpstate *, size_t);
-static void scheduler_ramqueue_schedule(uint64_t);
-static void scheduler_ramqueue_remove(uint64_t);
+static int scheduler_ram_init(void);
+static int scheduler_ram_insert(struct scheduler_info *);
+static size_t scheduler_ram_commit(uint32_t);
+static size_t scheduler_ram_rollback(uint32_t);
+static int scheduler_ram_update(struct scheduler_info *);
+static int scheduler_ram_delete(uint64_t);
+static int scheduler_ram_batch(int, struct scheduler_batch *);
+static size_t scheduler_ram_messages(uint32_t, uint32_t *, size_t);
+static size_t scheduler_ram_envelopes(uint64_t, struct evpstate *, size_t);
+static int scheduler_ram_schedule(uint64_t);
+static int scheduler_ram_remove(uint64_t);
static void sorted_insert(struct evplist *, struct rq_envelope *);
static void sorted_merge(struct evplist *, struct evplist *);
@@ -102,26 +101,26 @@ static void rq_queue_merge(struct rq_queue *, struct rq_queue *);
static void rq_queue_dump(struct rq_queue *, const char *);
static void rq_queue_schedule(struct rq_queue *rq);
static void rq_envelope_schedule(struct rq_queue *, struct rq_envelope *);
-static void rq_envelope_remove(struct rq_queue *, struct rq_envelope *);
+static int rq_envelope_remove(struct rq_queue *, struct rq_envelope *);
static void rq_envelope_delete(struct rq_queue *, struct rq_envelope *);
static const char *rq_envelope_to_text(struct rq_envelope *);
struct scheduler_backend scheduler_backend_ramqueue = {
- scheduler_ramqueue_init,
+ scheduler_ram_init,
- scheduler_ramqueue_insert,
- scheduler_ramqueue_commit,
- scheduler_ramqueue_rollback,
+ scheduler_ram_insert,
+ scheduler_ram_commit,
+ scheduler_ram_rollback,
- scheduler_ramqueue_update,
- scheduler_ramqueue_delete,
+ scheduler_ram_update,
+ scheduler_ram_delete,
- scheduler_ramqueue_batch,
+ scheduler_ram_batch,
- scheduler_ramqueue_messages,
- scheduler_ramqueue_envelopes,
- scheduler_ramqueue_schedule,
- scheduler_ramqueue_remove,
+ scheduler_ram_messages,
+ scheduler_ram_envelopes,
+ scheduler_ram_schedule,
+ scheduler_ram_remove,
};
static struct rq_queue ramqueue;
@@ -129,15 +128,17 @@ static struct tree updates;
static time_t currtime;
-static void
-scheduler_ramqueue_init(void)
+static int
+scheduler_ram_init(void)
{
rq_queue_init(&ramqueue);
tree_init(&updates);
+
+ return (1);
}
-static void
-scheduler_ramqueue_insert(struct scheduler_info *si)
+static int
+scheduler_ram_insert(struct scheduler_info *si)
{
uint32_t msgid;
struct rq_queue *update;
@@ -182,10 +183,12 @@ scheduler_ramqueue_insert(struct scheduler_info *si)
sorted_insert(&update->q_pending, envelope);
si->nexttry = envelope->sched;
+
+ return (1);
}
static size_t
-scheduler_ramqueue_commit(uint32_t msgid)
+scheduler_ram_commit(uint32_t msgid)
{
struct rq_queue *update;
size_t r;
@@ -212,7 +215,7 @@ scheduler_ramqueue_commit(uint32_t msgid)
}
static size_t
-scheduler_ramqueue_rollback(uint32_t msgid)
+scheduler_ram_rollback(uint32_t msgid)
{
struct rq_queue *update;
struct rq_envelope *evp;
@@ -235,8 +238,8 @@ scheduler_ramqueue_rollback(uint32_t msgid)
return (r);
}
-static void
-scheduler_ramqueue_update(struct scheduler_info *si)
+static int
+scheduler_ram_update(struct scheduler_info *si)
{
struct rq_message *msg;
struct rq_envelope *evp;
@@ -261,10 +264,12 @@ scheduler_ramqueue_update(struct scheduler_info *si)
evp->flags |= RQ_ENVELOPE_PENDING;
si->nexttry = evp->sched;
+
+ return (1);
}
-static void
-scheduler_ramqueue_delete(uint64_t evpid)
+static int
+scheduler_ram_delete(uint64_t evpid)
{
struct rq_message *msg;
struct rq_envelope *evp;
@@ -283,10 +288,12 @@ scheduler_ramqueue_delete(uint64_t evpid)
TAILQ_REMOVE(&ramqueue.q_inflight, evp, entry);
evp->flags &= ~RQ_ENVELOPE_INFLIGHT;
rq_envelope_delete(&ramqueue, evp);
+
+ return (1);
}
-static void
-scheduler_ramqueue_batch(int typemask, struct scheduler_batch *ret)
+static int
+scheduler_ram_batch(int typemask, struct scheduler_batch *ret)
{
struct evplist *q;
struct rq_envelope *evp;
@@ -297,7 +304,7 @@ scheduler_ramqueue_batch(int typemask, struct scheduler_batch *ret)
rq_queue_schedule(&ramqueue);
if (verbose & TRACE_SCHEDULER)
- rq_queue_dump(&ramqueue, "scheduler_ramqueue_batch()");
+ rq_queue_dump(&ramqueue, "scheduler_ram_batch()");
if (typemask & SCHED_REMOVE && TAILQ_FIRST(&ramqueue.q_removed)) {
q = &ramqueue.q_removed;
@@ -324,15 +331,17 @@ scheduler_ramqueue_batch(int typemask, struct scheduler_batch *ret)
}
else if ((evp = TAILQ_FIRST(&ramqueue.q_pending))) {
ret->type = SCHED_DELAY;
+ ret->evpcount = 0;
if (evp->sched < evp->expire)
ret->delay = evp->sched - currtime;
else
ret->delay = evp->expire - currtime;
- return;
+ return (1);
}
else {
ret->type = SCHED_NONE;
- return;
+ ret->evpcount = 0;
+ return (0);
}
for (n = 0; (evp = TAILQ_FIRST(q)) && n < ret->evpcount; n++) {
@@ -356,68 +365,12 @@ scheduler_ramqueue_batch(int typemask, struct scheduler_batch *ret)
}
ret->evpcount = n;
-}
-static void
-scheduler_ramqueue_schedule(uint64_t evpid)
-{
- struct rq_message *msg;
- struct rq_envelope *evp;
- uint32_t msgid;
- void *i;
-
- currtime = time(NULL);
-
- if (evpid > 0xffffffff) {
- msgid = evpid_to_msgid(evpid);
- if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
- return;
- if ((evp = tree_get(&msg->envelopes, evpid)) == NULL)
- return;
- if (evp->flags & RQ_ENVELOPE_PENDING)
- rq_envelope_schedule(&ramqueue, evp);
- }
- else {
- msgid = evpid;
- if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
- return;
- i = NULL;
- while (tree_iter(&msg->envelopes, &i, NULL, (void*)(&evp)))
- if (evp->flags & RQ_ENVELOPE_PENDING)
- rq_envelope_schedule(&ramqueue, evp);
- }
-}
-
-static void
-scheduler_ramqueue_remove(uint64_t evpid)
-{
- struct rq_message *msg;
- struct rq_envelope *evp;
- uint32_t msgid;
- void *i;
-
- currtime = time(NULL);
-
- if (evpid > 0xffffffff) {
- msgid = evpid_to_msgid(evpid);
- if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
- return;
- if ((evp = tree_get(&msg->envelopes, evpid)) == NULL)
- return;
- rq_envelope_remove(&ramqueue, evp);
- }
- else {
- msgid = evpid;
- if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
- return;
- i = NULL;
- while (tree_iter(&msg->envelopes, &i, NULL, (void*)(&evp)))
- rq_envelope_remove(&ramqueue, evp);
- }
+ return (1);
}
static size_t
-scheduler_ramqueue_messages(uint32_t from, uint32_t *dst, size_t size)
+scheduler_ram_messages(uint32_t from, uint32_t *dst, size_t size)
{
uint64_t id;
size_t n;
@@ -433,7 +386,7 @@ scheduler_ramqueue_messages(uint32_t from, uint32_t *dst, size_t size)
}
static size_t
-scheduler_ramqueue_envelopes(uint64_t from, struct evpstate *dst, size_t size)
+scheduler_ram_envelopes(uint64_t from, struct evpstate *dst, size_t size)
{
struct rq_message *msg;
struct rq_envelope *evp;
@@ -472,6 +425,78 @@ scheduler_ramqueue_envelopes(uint64_t from, struct evpstate *dst, size_t size)
return (n);
}
+static int
+scheduler_ram_schedule(uint64_t evpid)
+{
+ struct rq_message *msg;
+ struct rq_envelope *evp;
+ uint32_t msgid;
+ void *i;
+ int r;
+
+ currtime = time(NULL);
+
+ if (evpid > 0xffffffff) {
+ msgid = evpid_to_msgid(evpid);
+ if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
+ return (0);
+ if ((evp = tree_get(&msg->envelopes, evpid)) == NULL)
+ return (0);
+ if (evp->flags & RQ_ENVELOPE_PENDING) {
+ rq_envelope_schedule(&ramqueue, evp);
+ return (1);
+ }
+ return (0);
+ }
+ else {
+ msgid = evpid;
+ if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
+ return (0);
+ i = NULL;
+ r = 0;
+ while (tree_iter(&msg->envelopes, &i, NULL, (void*)(&evp)))
+ if (evp->flags & RQ_ENVELOPE_PENDING) {
+ rq_envelope_schedule(&ramqueue, evp);
+ r++;
+ }
+ return (r);
+ }
+}
+
+static int
+scheduler_ram_remove(uint64_t evpid)
+{
+ struct rq_message *msg;
+ struct rq_envelope *evp;
+ uint32_t msgid;
+ void *i;
+ int r;
+
+ currtime = time(NULL);
+
+ if (evpid > 0xffffffff) {
+ msgid = evpid_to_msgid(evpid);
+ if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
+ return (0);
+ if ((evp = tree_get(&msg->envelopes, evpid)) == NULL)
+ return (0);
+ if (rq_envelope_remove(&ramqueue, evp))
+ return (1);
+ return (0);
+ }
+ else {
+ msgid = evpid;
+ if ((msg = tree_get(&ramqueue.messages, msgid)) == NULL)
+ return (0);
+ i = NULL;
+ r = 0;
+ while (tree_iter(&msg->envelopes, &i, NULL, (void*)(&evp)))
+ if (rq_envelope_remove(&ramqueue, evp))
+ r++;
+ return (r);
+ }
+}
+
static void
sorted_insert(struct evplist *list, struct rq_envelope *evp)
{
@@ -591,20 +616,20 @@ rq_envelope_schedule(struct rq_queue *rq, struct rq_envelope *evp)
evp->t_scheduled = currtime;
}
-static void
+static int
rq_envelope_remove(struct rq_queue *rq, struct rq_envelope *evp)
{
struct rq_message *m;
struct evplist *q = NULL;
if (evp->flags & (RQ_ENVELOPE_REMOVED | RQ_ENVELOPE_EXPIRED))
- return;
+ return (0);
/*
* For now we just ignore it, but we could mark the envelope for
* removal and possibly send a cancellation to the agent.
*/
if (evp->flags & (RQ_ENVELOPE_INFLIGHT))
- return;
+ return (0);
if (evp->flags & RQ_ENVELOPE_SCHEDULED) {
if (evp->type == D_MTA)
@@ -639,6 +664,8 @@ rq_envelope_remove(struct rq_queue *rq, struct rq_envelope *evp)
}
evp->message->q_next = NULL;
}
+
+ return (1);
}
static void
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c
index 0874c38b272..92d0c553d36 100644
--- a/usr.sbin/smtpd/smtp.c
+++ b/usr.sbin/smtpd/smtp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp.c,v 1.124 2013/03/11 17:40:11 deraadt Exp $ */
+/* $OpenBSD: smtp.c,v 1.125 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <err.h>
@@ -354,7 +353,7 @@ static int
smtp_enqueue(uid_t *euid)
{
static struct listener local, *listener = NULL;
- char buf[MAXHOSTNAMELEN], *hostname;
+ char buf[SMTPD_MAXHOSTNAMELEN], *hostname;
int fd[2];
if (listener == NULL) {
@@ -429,6 +428,7 @@ smtp_accept(int fd, short event, void *p)
close(sock);
return;
}
+ io_set_blocking(sock, 0);
sessions++;
stat_increment("smtp.session", 1);
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index 4f008eaecd8..d9bb2faa10a 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp_session.c,v 1.182 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.183 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -22,7 +22,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
@@ -78,6 +77,7 @@ enum session_flags {
SF_KICK = 0x0020,
SF_VERIFIED = 0x0040,
SF_MFACONNSENT = 0x0080,
+ SF_BADINPUT = 0x0100,
};
enum message_flags {
@@ -107,7 +107,7 @@ struct smtp_session {
struct io io;
struct listener *listener;
struct sockaddr_storage ss;
- char hostname[MAXHOSTNAMELEN];
+ char hostname[SMTPD_MAXHOSTNAMELEN];
int flags;
int phase;
@@ -117,7 +117,7 @@ struct smtp_session {
char helo[SMTPD_MAXLINESIZE];
char cmd[SMTPD_MAXLINESIZE];
- char username[MAXLOGNAME];
+ char username[SMTPD_MAXLOGNAME];
struct envelope evp;
@@ -132,6 +132,8 @@ struct smtp_session {
size_t datalen;
FILE *ofile;
+
+ struct event pause;
};
#define ADVERTISE_TLS(s) \
@@ -160,6 +162,8 @@ static void smtp_wait_mfa(struct smtp_session *s, int);
static void smtp_free(struct smtp_session *, const char *);
static const char *smtp_strstate(int);
static int smtp_verify_certificate(struct smtp_session *);
+static void smtp_auth_failure_pause(struct smtp_session *);
+static void smtp_auth_failure_resume(int, short, void *);
static struct { int code; const char *cmd; } commands[] = {
{ CMD_HELO, "HELO" },
@@ -256,7 +260,7 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
struct ca_vrfy_resp_msg *resp_ca_vrfy;
struct smtp_session *s;
void *ssl;
- char user[MAXLOGNAME];
+ char user[SMTPD_MAXLOGNAME];
struct msg m;
const char *line;
uint64_t reqid, evpid;
@@ -282,13 +286,14 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_id(&m, &reqid);
m_get_int(&m, &status);
+ m_get_string(&m, &line);
m_end(&m);
s = tree_xpop(&wait_lka_rcpt, reqid);
switch (status) {
case LKA_OK:
fatalx("unexpected ok");
case LKA_PERMFAIL:
- smtp_reply(s, "550 Invalid recipient");
+ smtp_reply(s, "%s", line);
s->rcptfail += 1;
if (s->rcptfail >= SMTP_KICK_RCPTFAIL) {
log_info("smtp-in: Ending session %016"PRIx64
@@ -297,9 +302,7 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
}
break;
case LKA_TEMPFAIL:
- smtp_reply(s, "421 Temporary failure");
- smtp_enter_state(s, STATE_QUIT);
- break;
+ smtp_reply(s, "%s", line);
}
io_reload(&s->io);
return;
@@ -340,6 +343,7 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
smtp_reply(s, "250 Ok");
} else {
smtp_reply(s, "421 Temporary Error");
+ smtp_enter_state(s, STATE_QUIT);
}
m_end(&m);
io_reload(&s->io);
@@ -364,13 +368,15 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
fprintf(s->ofile,
"Received: from %s (%s [%s]);\n"
- "\tby %s (%s) with %sSMTP id %08x;\n",
+ "\tby %s (%s) with %sSMTP%s%s id %08x;\n",
s->evp.helo,
s->hostname,
ss_to_text(&s->ss),
s->listener->helo[0] ? s->listener->helo : env->sc_hostname,
SMTPD_NAME,
s->flags & SF_EHLO ? "E" : "",
+ s->flags & SF_SECURE ? "S" : "",
+ s->flags & SF_AUTHENTICATED ? "A" : "",
evpid_to_msgid(s->evp.id));
if (s->flags & SF_SECURE) {
@@ -449,7 +455,7 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
m_end(&m);
s = tree_xpop(&wait_queue_commit, reqid);
if (!success) {
- m_create(p_mfa, IMSG_MFA_EVENT_ROLLBACK, 0, 0, -1, 8);
+ m_create(p_mfa, IMSG_MFA_EVENT_ROLLBACK, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_close(p_mfa);
smtp_reply(s, "421 Temporary failure");
@@ -458,7 +464,7 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
return;
}
- m_create(p_mfa, IMSG_MFA_EVENT_COMMIT, 0, 0, -1, 16);
+ m_create(p_mfa, IMSG_MFA_EVENT_COMMIT, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_close(p_mfa);
@@ -502,7 +508,8 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
else if (success == LKA_PERMFAIL) {
log_info("smtp-in: Authentication failed for user %s "
"on session %016"PRIx64, user, s->id);
- smtp_reply(s, "535 Authentication failed");
+ smtp_auth_failure_pause(s);
+ return;
}
else if (success == LKA_TEMPFAIL) {
log_info("smtp-in: Authentication temporarily failed "
@@ -511,6 +518,7 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
}
else
fatalx("bad lka response");
+
smtp_enter_state(s, STATE_HELO);
io_reload(&s->io);
return;
@@ -645,7 +653,7 @@ smtp_mfa_response(struct smtp_session *s, int status, uint32_t code,
return;
}
- m_create(p_queue, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, 32);
+ m_create(p_queue, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1);
m_add_id(p_queue, s->id);
m_close(p_queue);
tree_xset(&wait_queue_msg, s->id, s);
@@ -667,7 +675,7 @@ smtp_mfa_response(struct smtp_session *s, int status, uint32_t code,
return;
}
- m_create(p_lka, IMSG_LKA_EXPAND_RCPT, 0, 0, -1, MSZ_EVP);
+ m_create(p_lka, IMSG_LKA_EXPAND_RCPT, 0, 0, -1);
m_add_id(p_lka, s->id);
m_add_envelope(p_lka, &s->evp);
m_close(p_lka);
@@ -682,7 +690,7 @@ smtp_mfa_response(struct smtp_session *s, int status, uint32_t code,
io_reload(&s->io);
return;
}
- m_create(p_queue, IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1, 16);
+ m_create(p_queue, IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1);
m_add_id(p_queue, s->id);
m_add_msgid(p_queue, evpid_to_msgid(s->evp.id));
m_close(p_queue);
@@ -756,6 +764,7 @@ smtp_io(struct io *io, int evt)
line = iobuf_getline(&s->iobuf, &len);
if ((line == NULL && iobuf_len(&s->iobuf) >= SMTPD_MAXLINESIZE) ||
(line && len >= SMTPD_MAXLINESIZE)) {
+ s->flags |= SF_BADINPUT;
smtp_reply(s, "500 Line too long");
smtp_enter_state(s, STATE_QUIT);
io_set_write(io);
@@ -787,6 +796,7 @@ smtp_io(struct io *io, int evt)
/* Pipelining not supported */
if (iobuf_len(&s->iobuf)) {
+ s->flags |= SF_BADINPUT;
smtp_reply(s, "500 Pipelining not supported");
smtp_enter_state(s, STATE_QUIT);
io_set_write(io);
@@ -798,7 +808,7 @@ smtp_io(struct io *io, int evt)
iobuf_normalize(&s->iobuf);
io_set_write(io);
- m_create(p_mfa, IMSG_MFA_REQ_EOM, 0, 0, -1, 16);
+ m_create(p_mfa, IMSG_MFA_REQ_EOM, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_close(p_mfa);
smtp_wait_mfa(s, IMSG_MFA_REQ_EOM);
@@ -940,8 +950,7 @@ smtp_command(struct smtp_session *s, char *line)
smtp_message_reset(s, 1);
- m_create(p_mfa, IMSG_MFA_REQ_HELO, 0, 0, -1,
- 32 + strlen(s->helo));
+ m_create(p_mfa, IMSG_MFA_REQ_HELO, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_add_string(p_mfa, s->helo);
m_close(p_mfa);
@@ -1044,8 +1053,7 @@ smtp_command(struct smtp_session *s, char *line)
if (args && smtp_parse_mail_args(s, args) == -1)
break;
- m_create(p_mfa, IMSG_MFA_REQ_MAIL, 0, 0, -1,
- 32 + sizeof(struct mailaddr));
+ m_create(p_mfa, IMSG_MFA_REQ_MAIL, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_add_mailaddr(p_mfa, &s->evp.sender);
m_close(p_mfa);
@@ -1076,8 +1084,7 @@ smtp_command(struct smtp_session *s, char *line)
break;
}
- m_create(p_mfa, IMSG_MFA_REQ_RCPT, 0, 0, -1,
- 32 + sizeof(struct mailaddr));
+ m_create(p_mfa, IMSG_MFA_REQ_RCPT, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_add_mailaddr(p_mfa, &s->evp.rcpt);
m_close(p_mfa);
@@ -1090,13 +1097,12 @@ smtp_command(struct smtp_session *s, char *line)
break;
}
- m_create(p_mfa, IMSG_MFA_EVENT_RSET, 0, 0, -1, 8);
+ m_create(p_mfa, IMSG_MFA_EVENT_RSET, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_close(p_mfa);
if (s->evp.id) {
- m_create(p_queue, IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1,
- 4);
+ m_create(p_queue, IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1);
m_add_msgid(p_queue, evpid_to_msgid(s->evp.id));
m_close(p_queue);
}
@@ -1116,7 +1122,7 @@ smtp_command(struct smtp_session *s, char *line)
break;
}
- m_create(p_mfa, IMSG_MFA_REQ_DATA, 0, 0, -1, 16);
+ m_create(p_mfa, IMSG_MFA_REQ_DATA, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_close(p_mfa);
smtp_wait_mfa(s, IMSG_MFA_REQ_DATA);
@@ -1187,7 +1193,7 @@ smtp_rfc4954_auth_plain(struct smtp_session *s, char *arg)
goto abort;
pass++; /* skip NUL */
- m_create(p_lka, IMSG_LKA_AUTHENTICATE, 0, 0, -1, 128);
+ m_create(p_lka, IMSG_LKA_AUTHENTICATE, 0, 0, -1);
m_add_id(p_lka, s->id);
m_add_string(p_lka, s->listener->authtable);
m_add_string(p_lka, user);
@@ -1231,7 +1237,7 @@ smtp_rfc4954_auth_login(struct smtp_session *s, char *arg)
if (__b64_pton(arg, (unsigned char *)buf, sizeof(buf)-1) == -1)
goto abort;
- m_create(p_lka, IMSG_LKA_AUTHENTICATE, 0, 0, -1, 128);
+ m_create(p_lka, IMSG_LKA_AUTHENTICATE, 0, 0, -1);
m_add_id(p_lka, s->id);
m_add_string(p_lka, s->listener->authtable);
m_add_string(p_lka, s->username);
@@ -1293,7 +1299,7 @@ smtp_connected(struct smtp_session *s)
return;
}
- m_create(p_mfa, IMSG_MFA_REQ_CONNECT, 0, 0, -1, 64 + strlen(s->hostname));
+ m_create(p_mfa, IMSG_MFA_REQ_CONNECT, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_add_sockaddr(p_mfa, (struct sockaddr *)&ss);
m_add_sockaddr(p_mfa, (struct sockaddr *)&s->ss);
@@ -1352,7 +1358,7 @@ smtp_message_end(struct smtp_session *s)
s->ofile = NULL;
if (s->msgflags & (MF_ERROR_SIZE | MF_ERROR_MFA | MF_ERROR_IO)) {
- m_create(p_queue, IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, 4);
+ m_create(p_queue, IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1);
m_add_msgid(p_queue, evpid_to_msgid(s->evp.id));
m_close(p_queue);
if (s->msgflags & MF_ERROR_SIZE)
@@ -1364,7 +1370,7 @@ smtp_message_end(struct smtp_session *s)
return;
}
- m_create(p_queue, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, 16);
+ m_create(p_queue, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1);
m_add_id(p_queue, s->id);
m_add_msgid(p_queue, evpid_to_msgid(s->evp.id));
m_close(p_queue);
@@ -1415,9 +1421,19 @@ smtp_reply(struct smtp_session *s, char *fmt, ...)
switch (buf[0]) {
case '5':
case '4':
- strnvis(tmp, s->cmd, sizeof tmp, VIS_SAFE | VIS_CSTYLE);
- log_info("smtp-in: Failed command on session %016" PRIx64
- ": \"%s\" => %.*s", s->id, tmp, n, buf);
+ if (s->flags & SF_BADINPUT) {
+ log_info("smtp-in: Bad input on session %016"PRIx64
+ ": %.*s", s->id, n, buf);
+ }
+ else if (strstr(s->cmd, "AUTH ") == s->cmd) {
+ log_info("smtp-in: Failed command on session %016"PRIx64
+ ": \"AUTH [...]\" => %.*s", s->id, n, buf);
+ }
+ else {
+ strnvis(tmp, s->cmd, sizeof tmp, VIS_SAFE | VIS_CSTYLE);
+ log_info("smtp-in: Failed command on session %016"PRIx64
+ ": \"%s\" => %.*s", s->id, tmp, n, buf);
+ }
break;
}
}
@@ -1441,13 +1457,13 @@ smtp_free(struct smtp_session *s, const char * reason)
fclose(s->ofile);
if (s->evp.id) {
- m_create(p_queue, IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, 5);
+ m_create(p_queue, IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1);
m_add_msgid(p_queue, evpid_to_msgid(s->evp.id));
m_close(p_queue);
}
if (s->flags & SF_MFACONNSENT) {
- m_create(p_mfa, IMSG_MFA_EVENT_DISCONNECT, 0, 0, -1, 16);
+ m_create(p_mfa, IMSG_MFA_EVENT_DISCONNECT, 0, 0, -1);
m_add_id(p_mfa, s->id);
m_close(p_mfa);
}
@@ -1493,7 +1509,7 @@ smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args)
}
if (!valid_localpart(maddr->user) ||
- !valid_localpart(maddr->domain)) {
+ !valid_domainpart(maddr->domain)) {
/* We accept empty sender for MAIL FROM */
if (mailfrom &&
maddr->user[0] == '\0' &&
@@ -1569,6 +1585,30 @@ smtp_verify_certificate(struct smtp_session *s)
return 1;
}
+static void
+smtp_auth_failure_resume(int fd, short event, void *p)
+{
+ struct smtp_session *s = p;
+
+ smtp_reply(s, "535 Authentication failed");
+ smtp_enter_state(s, STATE_HELO);
+ io_reload(&s->io);
+}
+
+static void
+smtp_auth_failure_pause(struct smtp_session *s)
+{
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = arc4random_uniform(1000000);
+ log_trace(TRACE_SMTP, "smtp: timing-attack protection triggered, "
+ "will defer answer for %lu microseconds", tv.tv_usec);
+ evtimer_set(&s->pause, smtp_auth_failure_resume, s);
+ evtimer_add(&s->pause, &tv);
+}
+
+
#define CASE(x) case x : return #x
const char *
diff --git a/usr.sbin/smtpd/smtpctl.8 b/usr.sbin/smtpd/smtpctl.8
index d7b2dac6e05..6b107f44e27 100644
--- a/usr.sbin/smtpd/smtpctl.8
+++ b/usr.sbin/smtpd/smtpctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: smtpctl.8,v 1.40 2013/02/14 13:21:16 gilles Exp $
+.\" $OpenBSD: smtpctl.8,v 1.41 2013/05/24 17:03:14 eric Exp $
.\"
.\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
.\" Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: February 14 2013 $
+.Dd $Mdocdate: May 24 2013 $
.Dt SMTPCTL 8
.Os
.Sh NAME
@@ -188,7 +188,7 @@ stat
.It
rules (matched by incoming sessions)
.It
-imsg-size
+mproc
.It
all
.El
diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c
index 78aaa26ab12..d0ee54a419e 100644
--- a/usr.sbin/smtpd/smtpctl.c
+++ b/usr.sbin/smtpd/smtpctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpctl.c,v 1.103 2013/04/17 15:02:38 deraadt Exp $ */
+/* $OpenBSD: smtpctl.c,v 1.104 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2006 Gilles Chehade <gilles@poolp.org>
@@ -25,7 +25,7 @@
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/un.h>
-#include <sys/param.h>
+#include <sys/wait.h>
#include <err.h>
#include <errno.h>
@@ -44,7 +44,7 @@
#include "log.h"
#define PATH_CAT "/bin/cat"
-#define PATH_GZCAT "/bin/gzcat"
+#define PATH_GZCAT "/usr/bin/gzcat"
#define PATH_QUEUE "/queue"
void usage(void);
@@ -237,51 +237,51 @@ main(int argc, char *argv[])
if ((ulval = text_to_evpid(res->data)) == 0)
errx(1, "invalid msgid/evpid");
- imsg_compose(ibuf, IMSG_CTL_SCHEDULE, 0, 0, -1, &ulval,
+ imsg_compose(ibuf, IMSG_CTL_SCHEDULE, IMSG_VERSION, 0, -1, &ulval,
sizeof(ulval));
break;
case REMOVE:
if ((ulval = text_to_evpid(res->data)) == 0)
errx(1, "invalid msgid/evpid");
- imsg_compose(ibuf, IMSG_CTL_REMOVE, 0, 0, -1, &ulval,
+ imsg_compose(ibuf, IMSG_CTL_REMOVE, IMSG_VERSION, 0, -1, &ulval,
sizeof(ulval));
break;
case SHOW_QUEUE:
return action_show_queue();
case SHUTDOWN:
- imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, IMSG_VERSION, 0, -1, NULL, 0);
break;
case PAUSE_MDA:
- imsg_compose(ibuf, IMSG_CTL_PAUSE_MDA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CTL_PAUSE_MDA, IMSG_VERSION, 0, -1, NULL, 0);
break;
case PAUSE_MTA:
- imsg_compose(ibuf, IMSG_CTL_PAUSE_MTA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CTL_PAUSE_MTA, IMSG_VERSION, 0, -1, NULL, 0);
break;
case PAUSE_SMTP:
- imsg_compose(ibuf, IMSG_CTL_PAUSE_SMTP, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CTL_PAUSE_SMTP, IMSG_VERSION, 0, -1, NULL, 0);
break;
case RESUME_MDA:
- imsg_compose(ibuf, IMSG_CTL_RESUME_MDA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CTL_RESUME_MDA, IMSG_VERSION, 0, -1, NULL, 0);
break;
case RESUME_MTA:
- imsg_compose(ibuf, IMSG_CTL_RESUME_MTA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CTL_RESUME_MTA, IMSG_VERSION, 0, -1, NULL, 0);
break;
case RESUME_SMTP:
- imsg_compose(ibuf, IMSG_CTL_RESUME_SMTP, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CTL_RESUME_SMTP, IMSG_VERSION, 0, -1, NULL, 0);
break;
case SHOW_STATS:
- imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_STATS, IMSG_VERSION, 0, -1, NULL, 0);
break;
case UPDATE_TABLE:
if (strlcpy(name, res->data, sizeof name) >= sizeof name)
errx(1, "table name too long.");
- imsg_compose(ibuf, IMSG_LKA_UPDATE_TABLE, 0, 0, -1,
+ imsg_compose(ibuf, IMSG_LKA_UPDATE_TABLE, IMSG_VERSION, 0, -1,
name, strlen(name) + 1);
done = 1;
break;
case MONITOR:
while (1) {
- imsg_compose(ibuf, IMSG_DIGEST, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_DIGEST, IMSG_VERSION, 0, -1, NULL, 0);
flush();
next_message(&imsg);
show_monitor(imsg.data);
@@ -290,10 +290,10 @@ main(int argc, char *argv[])
}
break;
case LOG_VERBOSE:
- verb = TRACE_VERBOSE;
+ verb = TRACE_DEBUG;
/* FALLTHROUGH */
case LOG_BRIEF:
- imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &verb,
+ imsg_compose(ibuf, IMSG_CTL_VERBOSE, IMSG_VERSION, 0, -1, &verb,
sizeof(verb));
printf("logging request sent.\n");
done = 1;
@@ -309,11 +309,11 @@ main(int argc, char *argv[])
case LOG_TRACE_LOOKUP:
case LOG_TRACE_STAT:
case LOG_TRACE_RULES:
- case LOG_TRACE_IMSG_SIZE:
+ case LOG_TRACE_MPROC:
case LOG_TRACE_EXPAND:
case LOG_TRACE_ALL:
verb = trace_convert(action);
- imsg_compose(ibuf, IMSG_CTL_TRACE, 0, 0, -1, &verb,
+ imsg_compose(ibuf, IMSG_CTL_TRACE, IMSG_VERSION, 0, -1, &verb,
sizeof(verb));
done = 1;
break;
@@ -328,11 +328,11 @@ main(int argc, char *argv[])
case LOG_UNTRACE_LOOKUP:
case LOG_UNTRACE_STAT:
case LOG_UNTRACE_RULES:
- case LOG_UNTRACE_IMSG_SIZE:
+ case LOG_UNTRACE_MPROC:
case LOG_UNTRACE_EXPAND:
case LOG_UNTRACE_ALL:
verb = trace_convert(action);
- imsg_compose(ibuf, IMSG_CTL_UNTRACE, 0, 0, -1, &verb,
+ imsg_compose(ibuf, IMSG_CTL_UNTRACE, IMSG_VERSION, 0, -1, &verb,
sizeof(verb));
done = 1;
break;
@@ -340,7 +340,7 @@ main(int argc, char *argv[])
case LOG_PROFILE_IMSG:
case LOG_PROFILE_QUEUE:
profile = profile_convert(action);
- imsg_compose(ibuf, IMSG_CTL_PROFILE, 0, 0, -1, &profile,
+ imsg_compose(ibuf, IMSG_CTL_PROFILE, IMSG_VERSION, 0, -1, &profile,
sizeof(profile));
done = 1;
break;
@@ -348,7 +348,7 @@ main(int argc, char *argv[])
case LOG_UNPROFILE_IMSG:
case LOG_UNPROFILE_QUEUE:
profile = profile_convert(action);
- imsg_compose(ibuf, IMSG_CTL_UNPROFILE, 0, 0, -1, &profile,
+ imsg_compose(ibuf, IMSG_CTL_UNPROFILE, IMSG_VERSION, 0, -1, &profile,
sizeof(profile));
done = 1;
break;
@@ -361,6 +361,12 @@ main(int argc, char *argv[])
flush();
next_message(&imsg);
+ /* ANY command can return IMSG_CTL_FAIL if version mismatch */
+ if (imsg.hdr.type == IMSG_CTL_FAIL) {
+ show_command_output(&imsg);
+ break;
+ }
+
switch (action) {
case REMOVE:
case SCHEDULE:
@@ -383,7 +389,7 @@ main(int argc, char *argv[])
case LOG_TRACE_LOOKUP:
case LOG_TRACE_STAT:
case LOG_TRACE_RULES:
- case LOG_TRACE_IMSG_SIZE:
+ case LOG_TRACE_MPROC:
case LOG_TRACE_EXPAND:
case LOG_TRACE_ALL:
case LOG_UNTRACE_IMSG:
@@ -396,7 +402,7 @@ main(int argc, char *argv[])
case LOG_UNTRACE_LOOKUP:
case LOG_UNTRACE_STAT:
case LOG_UNTRACE_RULES:
- case LOG_UNTRACE_IMSG_SIZE:
+ case LOG_UNTRACE_MPROC:
case LOG_UNTRACE_EXPAND:
case LOG_UNTRACE_ALL:
case LOG_PROFILE_IMSG:
@@ -440,7 +446,7 @@ action_show_queue_message(uint32_t msgid)
nextbatch:
found = 0;
- imsg_compose(ibuf, IMSG_CTL_LIST_ENVELOPES, 0, 0, -1,
+ imsg_compose(ibuf, IMSG_CTL_LIST_ENVELOPES, IMSG_VERSION, 0, -1,
&evpid, sizeof evpid);
flush();
@@ -475,7 +481,7 @@ action_show_queue(void)
now = time(NULL);
do {
- imsg_compose(ibuf, IMSG_CTL_LIST_MESSAGES, 0, 0, -1,
+ imsg_compose(ibuf, IMSG_CTL_LIST_MESSAGES, IMSG_VERSION, 0, -1,
&msgid, sizeof msgid);
flush();
next_message(&imsg);
@@ -508,7 +514,7 @@ action_schedule_all(void)
from = 0;
while (1) {
- imsg_compose(ibuf, IMSG_CTL_LIST_MESSAGES, 0, 0, -1,
+ imsg_compose(ibuf, IMSG_CTL_LIST_MESSAGES, IMSG_VERSION, 0, -1,
&from, sizeof from);
flush();
next_message(&imsg);
@@ -521,7 +527,7 @@ action_schedule_all(void)
for (i = 0; i < n; i++) {
evpid = msgids[i];
- imsg_compose(ibuf, IMSG_CTL_SCHEDULE, 0,
+ imsg_compose(ibuf, IMSG_CTL_SCHEDULE, IMSG_VERSION,
0, -1, &evpid, sizeof(evpid));
}
from = msgids[n - 1] + 1;
@@ -551,7 +557,10 @@ show_command_output(struct imsg *imsg)
printf("command succeeded\n");
break;
case IMSG_CTL_FAIL:
- printf("command failed\n");
+ if (imsg->hdr.peerid != IMSG_VERSION)
+ printf("command failed: incompatible smtpctl and smtpd\n");
+ else
+ printf("command failed\n");
break;
default:
errx(1, "wrong message in summary: %u", imsg->hdr.type);
@@ -569,7 +578,7 @@ show_stats_output(void)
bzero(&kv, sizeof kv);
while (1) {
- imsg_compose(ibuf, IMSG_STATS_GET, 0, 0, -1, &kv, sizeof kv);
+ imsg_compose(ibuf, IMSG_STATS_GET, IMSG_VERSION, 0, -1, &kv, sizeof kv);
flush();
next_message(&imsg);
if (imsg.hdr.type != IMSG_STATS_GET)
@@ -583,7 +592,7 @@ show_stats_output(void)
if (strcmp(kvp->key, "uptime") == 0) {
duration = time(NULL) - kvp->val.u.counter;
- printf("uptime=%lld\n", (long long)duration);
+ printf("uptime=%zd\n", (size_t)duration);
printf("uptime.human=%s\n",
duration_to_text(duration));
}
@@ -598,8 +607,8 @@ show_stats_output(void)
kvp->key, (int64_t)kvp->val.u.timestamp);
break;
case STAT_TIMEVAL:
- printf("%s=%lld.%ld\n",
- kvp->key, (long long)kvp->val.u.tv.tv_sec,
+ printf("%s=%zd.%zd\n",
+ kvp->key, kvp->val.u.tv.tv_sec,
kvp->val.u.tv.tv_usec);
break;
case STAT_TIMESPEC:
@@ -717,25 +726,37 @@ getflag(uint *bitmap, int bit, char *bitstr, char *buf, size_t len)
static void
display(const char *s)
{
+ pid_t pid;
arglist args;
char *cmd;
+ int status;
- if (env->sc_queue_flags & QUEUE_COMPRESS)
+ pid = fork();
+ if (pid < 0)
+ err(1, "fork");
+ if (pid == 0) {
cmd = PATH_GZCAT;
- else
- cmd = PATH_CAT;
-
+ bzero(&args, sizeof(args));
+ addargs(&args, "%s", cmd);
+ addargs(&args, "%s", s);
+ execvp(cmd, args.list);
+ err(1, "execvp");
+ }
+ wait(&status);
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ exit(0);
+ cmd = PATH_CAT;
bzero(&args, sizeof(args));
addargs(&args, "%s", cmd);
addargs(&args, "%s", s);
execvp(cmd, args.list);
- errx(1, "execvp");
+ err(1, "execvp");
}
static void
show_envelope(const char *s)
{
- char buf[MAXPATHLEN];
+ char buf[SMTPD_MAXPATHLEN];
uint64_t evpid;
if ((evpid = text_to_evpid(s)) == 0)
@@ -755,7 +776,7 @@ show_envelope(const char *s)
static void
show_message(const char *s)
{
- char buf[MAXPATHLEN];
+ char buf[SMTPD_MAXPATHLEN];
uint32_t msgid;
uint64_t evpid;
@@ -764,10 +785,10 @@ show_message(const char *s)
msgid = evpid_to_msgid(evpid);
if (! bsnprintf(buf, sizeof(buf), "%s%s/%02x/%08x/message",
- PATH_SPOOL,
- PATH_QUEUE,
- msgid & 0xff,
- msgid))
+ PATH_SPOOL,
+ PATH_QUEUE,
+ (evpid_to_msgid(evpid) & 0xff000000) >> 24,
+ msgid))
errx(1, "unable to retrieve message");
display(buf);
@@ -866,9 +887,9 @@ trace_convert(uint32_t trace)
case LOG_UNTRACE_RULES:
return TRACE_RULES;
- case LOG_TRACE_IMSG_SIZE:
- case LOG_UNTRACE_IMSG_SIZE:
- return TRACE_IMSGSIZE;
+ case LOG_TRACE_MPROC:
+ case LOG_UNTRACE_MPROC:
+ return TRACE_MPROC;
case LOG_TRACE_EXPAND:
case LOG_UNTRACE_EXPAND:
@@ -876,7 +897,7 @@ trace_convert(uint32_t trace)
case LOG_TRACE_ALL:
case LOG_UNTRACE_ALL:
- return ~TRACE_VERBOSE;
+ return ~TRACE_DEBUG;
}
return 0;
diff --git a/usr.sbin/smtpd/smtpctl/Makefile b/usr.sbin/smtpd/smtpctl/Makefile
index 44f4fe17314..e61249f252a 100644
--- a/usr.sbin/smtpd/smtpctl/Makefile
+++ b/usr.sbin/smtpd/smtpctl/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.30 2013/01/26 09:37:24 gilles Exp $
+# $OpenBSD: Makefile,v 1.31 2013/05/24 17:03:14 eric Exp $
.PATH: ${.CURDIR}/..
diff --git a/usr.sbin/smtpd/smtpd-api.h b/usr.sbin/smtpd/smtpd-api.h
index ac43bc095d8..579b3f2e001 100644
--- a/usr.sbin/smtpd/smtpd-api.h
+++ b/usr.sbin/smtpd/smtpd-api.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd-api.h,v 1.3 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: smtpd-api.h,v 1.4 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -28,17 +28,23 @@
#define FILTER_API_VERSION 50
-#define SMTPD_MAXLINESIZE 2048
-#define MAX_LOCALPART_SIZE (64 + 1)
-#define MAX_DOMAINPART_SIZE (255 + 1)
-
struct mailaddr {
- char user[MAX_LOCALPART_SIZE];
- char domain[MAX_DOMAINPART_SIZE];
+ char user[SMTPD_MAXLOCALPARTSIZE];
+ char domain[SMTPD_MAXDOMAINPARTSIZE];
};
-SPLAY_HEAD(dict, dictentry);
-SPLAY_HEAD(tree, treeentry);
+SPLAY_HEAD(_dict, dictentry);
+SPLAY_HEAD(_tree, treeentry);
+
+struct tree {
+ struct _tree tree;
+ size_t count;
+};
+
+struct dict {
+ struct _dict dict;
+ size_t count;
+};
enum filter_status {
FILTER_OK,
@@ -81,8 +87,9 @@ struct filter_connect {
};
/* dict.c */
-#define dict_init(d) SPLAY_INIT((d))
-#define dict_empty(d) SPLAY_EMPTY((d))
+#define dict_init(d) do { SPLAY_INIT(&((d)->dict)); (d)->count = 0; } while(0)
+#define dict_empty(d) SPLAY_EMPTY(&((d)->dict))
+#define dict_count(d) ((d)->count)
int dict_check(struct dict *, const char *);
void *dict_set(struct dict *, const char *, void *);
void dict_xset(struct dict *, const char *, void *);
@@ -116,8 +123,9 @@ void filter_api_on_eom(void(*)(uint64_t, uint64_t));
void filter_api_on_event(void(*)(uint64_t, enum filter_hook));
/* tree.c */
-#define tree_init(t) SPLAY_INIT((t))
-#define tree_empty(t) SPLAY_EMPTY((t))
+#define tree_init(t) do { SPLAY_INIT(&((t)->tree)); (t)->count = 0; } while(0)
+#define tree_empty(t) SPLAY_EMPTY(&((t)->tree))
+#define tree_count(t) ((t)->count)
int tree_check(struct tree *, uint64_t);
void *tree_set(struct tree *, uint64_t, void *);
void tree_xset(struct tree *, uint64_t, void *);
diff --git a/usr.sbin/smtpd/smtpd-defines.h b/usr.sbin/smtpd/smtpd-defines.h
new file mode 100644
index 00000000000..c0c78f4bc51
--- /dev/null
+++ b/usr.sbin/smtpd/smtpd-defines.h
@@ -0,0 +1,29 @@
+/* $OpenBSD: smtpd-defines.h,v 1.1 2013/05/24 17:03:14 eric Exp $ */
+
+/*
+ * Copyright (c) 2013 Gilles Chehade <gilles@poolp.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef nitems
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+#define SMTPD_MAXLOCALPARTSIZE (255 + 1)
+#define SMTPD_MAXDOMAINPARTSIZE (255 + 1)
+
+#define SMTPD_MAXLOGNAME 32
+#define SMTPD_MAXPATHLEN 1024
+#define SMTPD_MAXHOSTNAMELEN 256
+#define SMTPD_MAXLINESIZE 2048
diff --git a/usr.sbin/smtpd/smtpd.8 b/usr.sbin/smtpd/smtpd.8
index bfbdfeb8052..37b46237f42 100644
--- a/usr.sbin/smtpd/smtpd.8
+++ b/usr.sbin/smtpd/smtpd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: smtpd.8,v 1.21 2013/05/08 14:22:38 jmc Exp $
+.\" $OpenBSD: smtpd.8,v 1.22 2013/05/24 17:03:14 eric Exp $
.\"
.\" Copyright (c) 2012, Eric Faurot <eric@openbsd.org>
.\" Copyright (c) 2008, Gilles Chehade <gilles@poolp.org>
@@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: May 8 2013 $
+.Dd $Mdocdate: May 24 2013 $
.Dt SMTPD 8
.Os
.Sh NAME
diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c
index 0788c81c6d8..7599f2bf298 100644
--- a/usr.sbin/smtpd/smtpd.c
+++ b/usr.sbin/smtpd/smtpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.c,v 1.190 2013/04/17 15:02:38 deraadt Exp $ */
+/* $OpenBSD: smtpd.c,v 1.191 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
@@ -75,6 +74,7 @@ static int offline_enqueue(char *);
static void purge_task(int, short, void *);
static void log_imsg(int, int, struct imsg *);
static int parent_auth_user(const char *, const char *);
+static void load_ssl_trees(void);
enum child_type {
CHILD_DAEMON,
@@ -102,6 +102,7 @@ struct offline {
static size_t offline_running = 0;
TAILQ_HEAD(, offline) offline_q;
+static struct event config_ev;
static struct event offline_ev;
static struct timeval offline_timeout;
@@ -133,6 +134,7 @@ const char *backend_stat = "ram";
int profiling = 0;
int verbose = 0;
int debug = 0;
+int foreground = 0;
struct tree children;
@@ -150,14 +152,6 @@ parent_imsg(struct mproc *p, struct imsg *imsg)
void *i;
int fd, n, v, ret;
- if (p->proc == PROC_SMTP) {
- switch (imsg->hdr.type) {
- case IMSG_PARENT_SEND_CONFIG:
- parent_send_config_smtp();
- return;
- }
- }
-
if (p->proc == PROC_LKA) {
switch (imsg->hdr.type) {
case IMSG_PARENT_FORWARD_OPEN:
@@ -188,7 +182,7 @@ parent_imsg(struct mproc *p, struct imsg *imsg)
ret = parent_auth_user(username, password);
- m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1, 128);
+ m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1);
m_add_id(p, reqid);
m_add_int(p, ret);
m_close(p);
@@ -222,13 +216,13 @@ parent_imsg(struct mproc *p, struct imsg *imsg)
c->cause == NULL)
break;
if (!n) {
- log_debug("debug: smptd: "
+ log_debug("debug: smtpd: "
"kill request: proc not found");
return;
}
c->cause = xstrdup(cause, "parent_imsg");
- log_debug("debug: smptd: kill requested for %u: %s",
+ log_debug("debug: smtpd: kill requested for %u: %s",
c->pid, c->cause);
kill(c->pid, SIGTERM);
return;
@@ -426,7 +420,7 @@ parent_send_config_lka()
}
iter_tree = NULL;
- while (tree_iter(env->sc_tables_tree, &iter_tree, NULL,
+ while (dict_iter(env->sc_tables_dict, &iter_tree, NULL,
(void **)&t)) {
m_compose(p_lka, IMSG_CONF_TABLE, 0, 0, -1, t, sizeof(*t));
@@ -547,7 +541,7 @@ parent_sig_handler(int sig, short event, void *p)
"for session %016"PRIx64 ": %s",
child->mda_id, cause);
m_create(p_mda, IMSG_MDA_DONE, 0, 0,
- child->mda_out, 32 + strlen(cause));
+ child->mda_out);
m_add_id(p_mda, child->mda_id);
m_add_string(p_mda, cause);
m_close(p_mda);
@@ -595,9 +589,6 @@ main(int argc, char *argv[])
struct event ev_sighup;
struct timeval tv;
struct passwd *pwq;
- struct listener *l;
- struct rule *r;
- struct ssl *ssl;
env = &smtpd;
@@ -625,8 +616,7 @@ main(int argc, char *argv[])
optarg);
break;
case 'd':
- debug = 2;
- verbose |= TRACE_VERBOSE;
+ foreground = 1;
break;
case 'D':
if (cmdline_symset(optarg) < 0)
@@ -662,12 +652,16 @@ main(int argc, char *argv[])
verbose |= TRACE_STAT;
else if (!strcmp(optarg, "rules"))
verbose |= TRACE_RULES;
- else if (!strcmp(optarg, "imsg-size"))
- verbose |= TRACE_IMSGSIZE;
+ else if (!strcmp(optarg, "mproc"))
+ verbose |= TRACE_MPROC;
else if (!strcmp(optarg, "expand"))
verbose |= TRACE_EXPAND;
+ else if (!strcmp(optarg, "tables"))
+ verbose |= TRACE_TABLES;
+ else if (!strcmp(optarg, "queue"))
+ verbose |= TRACE_QUEUE;
else if (!strcmp(optarg, "all"))
- verbose |= ~TRACE_VERBOSE;
+ verbose |= ~TRACE_DEBUG;
else if (!strcmp(optarg, "profstat"))
profiling |= PROFILE_TOSTAT;
else if (!strcmp(optarg, "profile-imsg"))
@@ -687,16 +681,13 @@ main(int argc, char *argv[])
flags |= SMTPD_MDA_PAUSED;
break;
case 'v':
- verbose |= TRACE_VERBOSE;
+ verbose |= TRACE_DEBUG;
break;
default:
usage();
}
}
- if (!(verbose & TRACE_VERBOSE))
- verbose = 0;
-
argv += optind;
argc -= optind;
@@ -708,10 +699,12 @@ main(int argc, char *argv[])
if (parse_config(&smtpd, conffile, opts))
exit(1);
- if (strlcpy(env->sc_conffile, conffile, MAXPATHLEN) >= MAXPATHLEN)
- errx(1, "config file exceeds MAXPATHLEN");
+ if (strlcpy(env->sc_conffile, conffile, SMTPD_MAXPATHLEN)
+ >= SMTPD_MAXPATHLEN)
+ errx(1, "config file exceeds SMTPD_MAXPATHLEN");
if (env->sc_opts & SMTPD_OPT_NOACTION) {
+ load_ssl_trees();
fprintf(stderr, "configuration OK\n");
exit(0);
}
@@ -756,12 +749,15 @@ main(int argc, char *argv[])
if (env->sc_stat == NULL)
errx(1, "could not find stat backend \"%s\"", backend_stat);
- log_init(debug);
+ if (env->sc_queue_flags & QUEUE_COMPRESSION)
+ env->sc_comp = compress_backend_lookup("gzip");
+
+ log_init(foreground);
log_verbose(verbose);
log_info("info: %s %s starting", SMTPD_NAME, SMTPD_VERSION);
- if (!debug)
+ if (! foreground)
if (daemon(0, 0) == -1)
err(1, "failed to daemonize");
@@ -775,35 +771,13 @@ main(int argc, char *argv[])
log_debug("debug: using \"%s\" queue backend", backend_queue);
log_debug("debug: using \"%s\" scheduler backend", backend_scheduler);
log_debug("debug: using \"%s\" stat backend", backend_stat);
- log_info("info: startup%s", (debug > 1)?" [debug mode]":"");
+ log_info("info: startup%s", (verbose & TRACE_DEBUG)?" [debug mode]":"");
if (env->sc_hostname[0] == '\0')
errx(1, "machine does not have a hostname set");
env->sc_uptime = time(NULL);
- log_debug("debug: init server-ssl tree");
- TAILQ_FOREACH(l, env->sc_listeners, entry) {
- if (!(l->flags & F_SSL))
- continue;
- ssl = NULL;
- if (! ssl_load_certfile(&ssl, "/etc/mail/certs",
- l->ssl_cert_name, F_SCERT))
- errx(1, "cannot load certificate: %s", l->ssl_cert_name);
- dict_set(env->sc_ssl_dict, ssl->ssl_name, ssl);
- }
-
- log_debug("debug: init client-ssl tree");
- TAILQ_FOREACH(r, env->sc_rules, r_entry) {
- if (r->r_action != A_RELAY && r->r_action != A_RELAYVIA)
- continue;
- if (! r->r_value.relayhost.cert[0])
- continue;
- ssl = NULL;
- if (! ssl_load_certfile(&ssl, "/etc/mail/certs",
- r->r_value.relayhost.cert, F_CCERT))
- errx(1, "cannot load certificate: %s", r->r_value.relayhost.cert);
- dict_set(env->sc_ssl_dict, ssl->ssl_name, ssl);
- }
+ load_ssl_trees();
fork_peers();
@@ -831,9 +805,9 @@ main(int argc, char *argv[])
config_peer(PROC_QUEUE);
config_done();
- evtimer_set(&env->sc_ev, parent_send_config, NULL);
+ evtimer_set(&config_ev, parent_send_config, NULL);
bzero(&tv, sizeof(tv));
- evtimer_add(&env->sc_ev, &tv);
+ evtimer_add(&config_ev, &tv);
/* defer offline scanning for a second */
evtimer_set(&offline_ev, offline_scan, NULL);
@@ -854,6 +828,40 @@ main(int argc, char *argv[])
}
static void
+load_ssl_trees(void)
+{
+ struct listener *l;
+ struct ssl *ssl;
+ struct rule *r;
+
+ log_debug("debug: init server-ssl tree");
+ TAILQ_FOREACH(l, env->sc_listeners, entry) {
+ if (!(l->flags & F_SSL))
+ continue;
+ ssl = NULL;
+ if (! ssl_load_certfile(&ssl, "/etc/mail/certs",
+ l->ssl_cert_name, F_SCERT))
+ errx(1, "cannot load certificate: %s",
+ l->ssl_cert_name);
+ dict_set(env->sc_ssl_dict, ssl->ssl_name, ssl);
+ }
+
+ log_debug("debug: init client-ssl tree");
+ TAILQ_FOREACH(r, env->sc_rules, r_entry) {
+ if (r->r_action != A_RELAY && r->r_action != A_RELAYVIA)
+ continue;
+ if (! r->r_value.relayhost.cert[0])
+ continue;
+ ssl = NULL;
+ if (! ssl_load_certfile(&ssl, "/etc/mail/certs",
+ r->r_value.relayhost.cert, F_CCERT))
+ errx(1, "cannot load certificate: %s",
+ r->r_value.relayhost.cert);
+ dict_set(env->sc_ssl_dict, ssl->ssl_name, ssl);
+ }
+}
+
+static void
fork_peers(void)
{
tree_init(&children);
@@ -968,7 +976,7 @@ forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
if (deliver->userinfo.uid == 0 && ! db->allow_root) {
snprintf(ebuf, sizeof ebuf, "not allowed to deliver to: %s",
deliver->user);
- m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1, 128);
+ m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1);
m_add_id(p_mda, id);
m_add_string(p_mda, ebuf);
m_close(p_mda);
@@ -983,7 +991,7 @@ forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
n = snprintf(ebuf, sizeof ebuf, "pipe: %s", strerror(errno));
if (seteuid(0) < 0)
fatal("smtpd: forkmda: cannot restore privileges");
- m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1, 128);
+ m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1);
m_add_id(p_mda, id);
m_add_string(p_mda, ebuf);
m_close(p_mda);
@@ -999,7 +1007,7 @@ forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
n = snprintf(ebuf, sizeof ebuf, "mkstemp: %s", strerror(errno));
if (seteuid(0) < 0)
fatal("smtpd: forkmda: cannot restore privileges");
- m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1, 128);
+ m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1);
m_add_id(p_mda, id);
m_add_string(p_mda, ebuf);
m_close(p_mda);
@@ -1014,7 +1022,7 @@ forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
n = snprintf(ebuf, sizeof ebuf, "fork: %s", strerror(errno));
if (seteuid(0) < 0)
fatal("smtpd: forkmda: cannot restore privileges");
- m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1, 128);
+ m_create(p_mda, IMSG_MDA_DONE, 0, 0, -1);
m_add_id(p_mda, id);
m_add_string(p_mda, ebuf);
m_close(p_mda);
@@ -1032,7 +1040,7 @@ forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
child->mda_out = allout;
child->mda_id = id;
close(pipefd[0]);
- m_create(p, IMSG_PARENT_FORK_MDA, 0, 0, pipefd[1], 9);
+ m_create(p, IMSG_PARENT_FORK_MDA, 0, 0, pipefd[1]);
m_add_id(p, id);
m_close(p);
return;
@@ -1110,7 +1118,7 @@ offline_scan(int fd, short ev, void *arg)
static int
offline_enqueue(char *name)
{
- char t[MAXPATHLEN], *path;
+ char t[SMTPD_MAXPATHLEN], *path;
struct stat sb;
pid_t pid;
struct child *child;
@@ -1250,7 +1258,7 @@ offline_done(void)
static int
parent_forward_open(char *username, char *directory, uid_t uid, gid_t gid)
{
- char pathname[MAXPATHLEN];
+ char pathname[SMTPD_MAXPATHLEN];
int fd;
if (! bsnprintf(pathname, sizeof (pathname), "%s/.forward",
@@ -1286,7 +1294,6 @@ imsg_dispatch(struct mproc *p, struct imsg *imsg)
struct timespec t0, t1, dt;
if (imsg == NULL) {
- log_warnx("warn: pipe error with %s", p->name);
exit(1);
return;
}
@@ -1302,12 +1309,12 @@ imsg_dispatch(struct mproc *p, struct imsg *imsg)
clock_gettime(CLOCK_MONOTONIC, &t1);
timespecsub(&t1, &t0, &dt);
- log_debug("profile-imsg: %s %s %s %i %lld.%06li",
+ log_debug("profile-imsg: %s %s %s %i %li.%06li",
proc_name(smtpd_process),
proc_name(p->proc),
imsg_to_str(imsg->hdr.type),
(int)imsg->hdr.len,
- (long long)dt.tv_sec * 1000000 + dt.tv_nsec / 1000000,
+ dt.tv_sec * 1000000 + dt.tv_nsec / 1000000,
dt.tv_nsec % 1000000);
if (profiling & PROFILE_TOSTAT) {
@@ -1352,24 +1359,24 @@ const char *
proc_title(enum smtp_proc_type proc)
{
switch (proc) {
- case PROC_CONTROL:
- return "control";
+ case PROC_PARENT:
+ return "[priv]";
+ case PROC_SMTP:
+ return "smtp";
+ case PROC_MFA:
+ return "filter";
case PROC_LKA:
return "lookup";
+ case PROC_QUEUE:
+ return "queue";
case PROC_MDA:
return "delivery";
- case PROC_MFA:
- return "filter";
case PROC_MTA:
return "transfer";
- case PROC_PARENT:
- return "[priv]";
- case PROC_QUEUE:
- return "queue";
+ case PROC_CONTROL:
+ return "control";
case PROC_SCHEDULER:
return "scheduler";
- case PROC_SMTP:
- return "smtp";
default:
return "unknown";
}
@@ -1397,6 +1404,11 @@ proc_name(enum smtp_proc_type proc)
return "control";
case PROC_SCHEDULER:
return "scheduler";
+
+ case PROC_FILTER:
+ return "filter-proc";
+ case PROC_CLIENT:
+ return "client-proc";
default:
return "unknown";
}
@@ -1498,7 +1510,6 @@ imsg_to_str(int type)
CASE(IMSG_PARENT_FORWARD_OPEN);
CASE(IMSG_PARENT_FORK_MDA);
CASE(IMSG_PARENT_KILL_MDA);
- CASE(IMSG_PARENT_SEND_CONFIG);
CASE(IMSG_SMTP_ENQUEUE_FD);
@@ -1526,7 +1537,7 @@ imsg_to_str(int type)
int
parent_auth_user(const char *username, const char *password)
{
- char user[MAXLOGNAME];
+ char user[SMTPD_MAXLOGNAME];
char pass[SMTPD_MAXLINESIZE];
int ret;
@@ -1542,27 +1553,27 @@ parent_auth_user(const char *username, const char *password)
static void
parent_broadcast_verbose(uint32_t v)
{
- m_create(p_lka, IMSG_CTL_VERBOSE, 0, 0, -1, sizeof v);
+ m_create(p_lka, IMSG_CTL_VERBOSE, 0, 0, -1);
m_add_int(p_lka, v);
m_close(p_lka);
- m_create(p_mda, IMSG_CTL_VERBOSE, 0, 0, -1, sizeof v);
+ m_create(p_mda, IMSG_CTL_VERBOSE, 0, 0, -1);
m_add_int(p_mda, v);
m_close(p_mda);
- m_create(p_mfa, IMSG_CTL_VERBOSE, 0, 0, -1, sizeof v);
+ m_create(p_mfa, IMSG_CTL_VERBOSE, 0, 0, -1);
m_add_int(p_mfa, v);
m_close(p_mfa);
- m_create(p_mta, IMSG_CTL_VERBOSE, 0, 0, -1, sizeof v);
+ m_create(p_mta, IMSG_CTL_VERBOSE, 0, 0, -1);
m_add_int(p_mta, v);
m_close(p_mta);
- m_create(p_queue, IMSG_CTL_VERBOSE, 0, 0, -1, sizeof v);
+ m_create(p_queue, IMSG_CTL_VERBOSE, 0, 0, -1);
m_add_int(p_queue, v);
m_close(p_queue);
- m_create(p_smtp, IMSG_CTL_VERBOSE, 0, 0, -1, sizeof v);
+ m_create(p_smtp, IMSG_CTL_VERBOSE, 0, 0, -1);
m_add_int(p_smtp, v);
m_close(p_smtp);
}
@@ -1570,27 +1581,27 @@ parent_broadcast_verbose(uint32_t v)
static void
parent_broadcast_profile(uint32_t v)
{
- m_create(p_lka, IMSG_CTL_PROFILE, 0, 0, -1, sizeof v);
+ m_create(p_lka, IMSG_CTL_PROFILE, 0, 0, -1);
m_add_int(p_lka, v);
m_close(p_lka);
- m_create(p_mda, IMSG_CTL_PROFILE, 0, 0, -1, sizeof v);
+ m_create(p_mda, IMSG_CTL_PROFILE, 0, 0, -1);
m_add_int(p_mda, v);
m_close(p_mda);
- m_create(p_mfa, IMSG_CTL_PROFILE, 0, 0, -1, sizeof v);
+ m_create(p_mfa, IMSG_CTL_PROFILE, 0, 0, -1);
m_add_int(p_mfa, v);
m_close(p_mfa);
- m_create(p_mta, IMSG_CTL_PROFILE, 0, 0, -1, sizeof v);
+ m_create(p_mta, IMSG_CTL_PROFILE, 0, 0, -1);
m_add_int(p_mta, v);
m_close(p_mta);
- m_create(p_queue, IMSG_CTL_PROFILE, 0, 0, -1, sizeof v);
+ m_create(p_queue, IMSG_CTL_PROFILE, 0, 0, -1);
m_add_int(p_queue, v);
m_close(p_queue);
- m_create(p_smtp, IMSG_CTL_PROFILE, 0, 0, -1, sizeof v);
+ m_create(p_smtp, IMSG_CTL_PROFILE, 0, 0, -1);
m_add_int(p_smtp, v);
m_close(p_smtp);
}
diff --git a/usr.sbin/smtpd/smtpd.conf.5 b/usr.sbin/smtpd/smtpd.conf.5
index 20f2272646d..0b0a7404298 100644
--- a/usr.sbin/smtpd/smtpd.conf.5
+++ b/usr.sbin/smtpd/smtpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: smtpd.conf.5,v 1.92 2013/02/17 17:45:01 jmc Exp $
+.\" $OpenBSD: smtpd.conf.5,v 1.93 2013/05/24 17:03:14 eric Exp $
.\"
.\" Copyright (c) 2008 Janne Johansson <jj@openbsd.org>
.\" Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
@@ -17,7 +17,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.\"
-.Dd $Mdocdate: February 17 2013 $
+.Dd $Mdocdate: May 24 2013 $
.Dt SMTPD.CONF 5
.Os
.Sh NAME
@@ -241,6 +241,12 @@ function.
.Pp
Finally, the method of delivery is specified:
.Bl -tag -width Ds
+.It Ic deliver to lmtp Ar [host:port|socket]
+Mail is delivered to
+.Pa host:port
+or to the unix socket
+.Pa socket
+over LMTP.
.It Ic deliver to maildir Ar path
Mail is added to a maildir.
Its location,
@@ -525,6 +531,14 @@ bytes.
The argument may contain a multiplier, as documented in
.Xr scan_scaled 3 .
The default maximum message size is 35MB if none is specified.
+.It Ic queue compression
+Enable transparent compression of envelopes and messages.
+The only supported algorithm at the moment is gzip.
+Envelopes and messages may be inspected using the
+.Xr smtpctl 8
+or
+.Xr gzcat 1
+utilities.
.It Ic table Ar name Oo Ar type : Oc Ns Ar config
Tables are used to provide additional configuration information for
.Xr smtpd 8
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index dd013c10ea0..5b05e52d6c8 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.409 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: smtpd.h,v 1.410 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -22,11 +22,13 @@
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
+#include "smtpd-defines.h"
#include "smtpd-api.h"
#include "ioev.h"
#include "iobuf.h"
#define CONF_FILE "/etc/mail/smtpd.conf"
+#define CA_FILE "/etc/ssl/cert.pem"
#define MAX_LISTEN 16
#define PROC_COUNT 10
#define MAX_NAME_SIZE 64
@@ -40,8 +42,7 @@
/* return and forward path size */
#define MAX_FILTER_NAME 32
-#define MAX_PATH_SIZE 256
-/*#define MAX_RULEBUFFER_LEN 512*/
+
#define EXPAND_BUFFER 1024
#define SMTPD_QUEUE_INTERVAL (15 * 60)
@@ -54,7 +55,7 @@
#ifndef SMTPD_NAME
#define SMTPD_NAME "OpenSMTPD"
#endif
-#define SMTPD_VERSION "5.3"
+#define SMTPD_VERSION "5.3.2"
#define SMTPD_BANNER "220 %s ESMTP %s"
#define SMTPD_SESSION_TIMEOUT 300
#define SMTPD_BACKLOG 5
@@ -70,16 +71,6 @@
#define PATH_FILTERS "/usr/libexec/smtpd"
-
-/* number of MX records to lookup */
-#define MAX_MX_COUNT 10
-
-/* max response delay under flood conditions */
-#define MAX_RESPONSE_DELAY 60
-
-/* how many responses per state are undelayed */
-#define FAST_RESPONSES 2
-
#define F_STARTTLS 0x01
#define F_SMTPS 0x02
#define F_TLS_OPTIONAL 0x04
@@ -103,11 +94,9 @@
#define RELAY_MX 0x20
#define RELAY_LMTP 0x80
-typedef uint32_t objid_t;
-
struct userinfo {
- char username[MAXLOGNAME];
- char directory[MAXPATHLEN];
+ char username[SMTPD_MAXLOGNAME];
+ char directory[SMTPD_MAXPATHLEN];
uid_t uid;
gid_t gid;
};
@@ -117,20 +106,15 @@ struct netaddr {
int bits;
};
-union sockaddr_any {
- struct in6_addr in6;
- struct in_addr in4;
-};
-
struct relayhost {
uint8_t flags;
- char hostname[MAXHOSTNAMELEN];
+ char hostname[SMTPD_MAXHOSTNAMELEN];
uint16_t port;
- char cert[PATH_MAX];
- char authtable[MAX_PATH_SIZE];
- char authlabel[MAX_PATH_SIZE];
- char sourcetable[MAX_PATH_SIZE];
- char helotable[MAX_PATH_SIZE];
+ char cert[SMTPD_MAXPATHLEN];
+ char authtable[SMTPD_MAXPATHLEN];
+ char authlabel[SMTPD_MAXPATHLEN];
+ char sourcetable[SMTPD_MAXPATHLEN];
+ char helotable[SMTPD_MAXPATHLEN];
};
struct credentials {
@@ -139,18 +123,36 @@ struct credentials {
};
struct destination {
- char name[MAXHOSTNAMELEN];
+ char name[SMTPD_MAXHOSTNAMELEN];
};
struct source {
- union sockaddr_any addr;
+ struct sockaddr_storage addr;
};
struct addrname {
- union sockaddr_any addr;
- char name[MAXHOSTNAMELEN];
+ struct sockaddr_storage addr;
+ char name[SMTPD_MAXHOSTNAMELEN];
};
+union lookup {
+ struct expand *expand;
+ struct credentials creds;
+ struct netaddr netaddr;
+ struct source source;
+ struct destination domain;
+ struct userinfo userinfo;
+ struct mailaddr mailaddr;
+ struct addrname addrname;
+};
+
+/* XXX */
+/*
+ * Bump IMSG_VERSION whenever a change is made to enum imsg_type.
+ * This will ensure that we can never use a wrong version of smtpctl with smtpd.
+ */
+#define IMSG_VERSION 2
+
enum imsg_type {
IMSG_NONE,
IMSG_CTL_OK, /* answer to smtpctl requests */
@@ -240,7 +242,6 @@ enum imsg_type {
IMSG_PARENT_FORWARD_OPEN,
IMSG_PARENT_FORK_MDA,
IMSG_PARENT_KILL_MDA,
- IMSG_PARENT_SEND_CONFIG,
IMSG_SMTP_ENQUEUE_FD,
@@ -274,6 +275,9 @@ enum smtp_proc_type {
PROC_MTA,
PROC_CONTROL,
PROC_SCHEDULER,
+
+ PROC_FILTER,
+ PROC_CLIENT,
};
enum table_type {
@@ -297,28 +301,24 @@ enum table_service {
struct table {
char t_name[SMTPD_MAXLINESIZE];
- objid_t t_id;
enum table_type t_type;
- char t_src[MAX_TABLE_BACKEND_SIZE];
- char t_config[MAXPATHLEN];
+ char t_config[SMTPD_MAXPATHLEN];
struct dict t_dict;
void *t_handle;
struct table_backend *t_backend;
- void *t_payload;
void *t_iter;
- char t_cfgtable[MAXPATHLEN];
};
struct table_backend {
const unsigned int services;
- int (*config)(struct table *, const char *);
- void *(*open)(struct table *);
+ int (*config)(struct table *);
+ void *(*open)(struct table *);
int (*update)(struct table *);
void (*close)(void *);
- int (*lookup)(void *, const char *, enum table_service, void **);
- int (*fetch)(void *, enum table_service, char **);
+ int (*lookup)(void *, const char *, enum table_service, union lookup *);
+ int (*fetch)(void *, enum table_service, union lookup *);
};
@@ -333,7 +333,8 @@ enum action_type {
A_MAILDIR,
A_MBOX,
A_FILENAME,
- A_MDA
+ A_MDA,
+ A_LMTP
};
enum decision {
@@ -371,8 +372,8 @@ enum delivery_type {
struct delivery_mda {
enum action_type method;
- char usertable[MAX_PATH_SIZE];
- char username[MAXLOGNAME];
+ char usertable[SMTPD_MAXPATHLEN];
+ char username[SMTPD_MAXLOGNAME];
char buffer[EXPAND_BUFFER];
};
@@ -397,7 +398,8 @@ enum expand_type {
EXPAND_FILENAME,
EXPAND_FILTER,
EXPAND_INCLUDE,
- EXPAND_ADDRESS
+ EXPAND_ADDRESS,
+ EXPAND_ERROR
};
struct expandnode {
@@ -416,7 +418,7 @@ struct expandnode {
* user field handles both expansion user and system user
* so we MUST make it large enough to fit a mailaddr user
*/
- char user[MAX_LOCALPART_SIZE];
+ char user[SMTPD_MAXLOCALPARTSIZE];
char buffer[EXPAND_BUFFER];
struct mailaddr mailaddr;
} u;
@@ -452,8 +454,8 @@ struct envelope {
uint64_t id;
enum envelope_flags flags;
- char helo[MAXHOSTNAMELEN];
- char hostname[MAXHOSTNAMELEN];
+ char helo[SMTPD_MAXHOSTNAMELEN];
+ char hostname[SMTPD_MAXHOSTNAMELEN];
char errorline[SMTPD_MAXLINESIZE];
struct sockaddr_storage ss;
@@ -515,17 +517,17 @@ struct listener {
in_port_t port;
struct timeval timeout;
struct event ev;
- char ssl_cert_name[PATH_MAX];
+ char ssl_cert_name[SMTPD_MAXPATHLEN];
struct ssl *ssl;
void *ssl_ctx;
char tag[MAX_TAG_SIZE];
char authtable[SMTPD_MAXLINESIZE];
- char helo[MAXHOSTNAMELEN];
+ char helo[SMTPD_MAXHOSTNAMELEN];
TAILQ_ENTRY(listener) entry;
};
struct smtpd {
- char sc_conffile[MAXPATHLEN];
+ char sc_conffile[SMTPD_MAXPATHLEN];
size_t sc_maxsize;
pid_t sc_pid;
@@ -533,6 +535,7 @@ struct smtpd {
#define SMTPD_OPT_VERBOSE 0x00000001
#define SMTPD_OPT_NOACTION 0x00000002
uint32_t sc_opts;
+
#define SMTPD_CONFIGURING 0x00000001
#define SMTPD_EXITING 0x00000002
#define SMTPD_MDA_PAUSED 0x00000004
@@ -543,18 +546,18 @@ struct smtpd {
#define SMTPD_BOUNCE_BUSY 0x00000080
#define SMTPD_SMTP_DISABLED 0x00000100
uint32_t sc_flags;
+
+#define QUEUE_COMPRESSION 0x00000001
uint32_t sc_queue_flags;
-#define QUEUE_COMPRESS 0x00000001
- char *sc_queue_compress_algo;
+
int sc_qexpire;
#define MAX_BOUNCE_WARN 4
time_t sc_bounce_warn[MAX_BOUNCE_WARN];
- struct event sc_ev;
struct passwd *sc_pw;
struct passwd *sc_pwqueue;
- char sc_hostname[MAXHOSTNAMELEN];
- struct scheduler_backend *sc_scheduler;
+ char sc_hostname[SMTPD_MAXHOSTNAMELEN];
struct stat_backend *sc_stat;
+ struct compress_backend *sc_comp;
time_t sc_uptime;
@@ -565,13 +568,12 @@ struct smtpd {
struct dict *sc_ssl_dict;
struct dict *sc_tables_dict; /* keyed lookup */
- struct tree *sc_tables_tree; /* id lookup */
struct dict sc_filters;
uint32_t filtermask;
};
-#define TRACE_VERBOSE 0x0001
+#define TRACE_DEBUG 0x0001
#define TRACE_IMSG 0x0002
#define TRACE_IO 0x0004
#define TRACE_SMTP 0x0008
@@ -582,8 +584,10 @@ struct smtpd {
#define TRACE_LOOKUP 0x0100
#define TRACE_STAT 0x0200
#define TRACE_RULES 0x0400
-#define TRACE_IMSGSIZE 0x0800
+#define TRACE_MPROC 0x0800
#define TRACE_EXPAND 0x1000
+#define TRACE_TABLES 0x2000
+#define TRACE_QUEUE 0x4000
#define PROFILE_TOSTAT 0x0001
#define PROFILE_IMSG 0x0002
@@ -593,16 +597,16 @@ struct forward_req {
uint64_t id;
uint8_t status;
- char user[MAXLOGNAME];
+ char user[SMTPD_MAXLOGNAME];
uid_t uid;
gid_t gid;
- char directory[MAXPATHLEN];
+ char directory[SMTPD_MAXPATHLEN];
};
struct deliver {
- char to[PATH_MAX];
- char from[PATH_MAX];
- char user[MAXLOGNAME];
+ char to[SMTPD_MAXPATHLEN];
+ char from[SMTPD_MAXPATHLEN];
+ char user[SMTPD_MAXLOGNAME];
short mode;
struct userinfo userinfo;
@@ -611,7 +615,7 @@ struct deliver {
struct filter {
struct imsgproc *process;
char name[MAX_FILTER_NAME];
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
};
struct mta_host {
@@ -740,6 +744,7 @@ struct mta_relay {
struct mta_envelope {
TAILQ_ENTRY(mta_envelope) entry;
uint64_t id;
+ uint64_t session;
time_t creation;
char *dest;
char *rcpt;
@@ -773,12 +778,10 @@ struct queue_backend {
};
struct compress_backend {
- void * (*compress_new)(void);
- size_t (*compress_chunk)(void *, void *, size_t, void *, size_t);
- size_t (*compress_finalize)(void *, void *, size_t);
- void * (*uncompress_new)(void);
- size_t (*uncompress_chunk)(void *, void *, size_t, void *, size_t);
- size_t (*uncompress_finalize)(void *, void *, size_t);
+ size_t (*compress_chunk)(void *, size_t, void *, size_t);
+ size_t (*uncompress_chunk)(void *, size_t, void *, size_t);
+ int (*compress_file)(FILE *, FILE *);
+ int (*uncompress_file)(FILE *, FILE *);
};
/* auth structures */
@@ -832,21 +835,21 @@ struct scheduler_batch {
};
struct scheduler_backend {
- void (*init)(void);
+ int (*init)(void);
- void (*insert)(struct scheduler_info *);
+ int (*insert)(struct scheduler_info *);
size_t (*commit)(uint32_t);
size_t (*rollback)(uint32_t);
- void (*update)(struct scheduler_info *);
- void (*delete)(uint64_t);
+ int (*update)(struct scheduler_info *);
+ int (*delete)(uint64_t);
- void (*batch)(int, struct scheduler_batch *);
+ int (*batch)(int, struct scheduler_batch *);
size_t (*messages)(uint32_t, uint32_t *, size_t);
size_t (*envelopes)(uint64_t, struct evpstate *, size_t);
- void (*schedule)(uint64_t);
- void (*remove)(uint64_t);
+ int (*schedule)(uint64_t);
+ int (*remove)(uint64_t);
};
@@ -903,8 +906,6 @@ struct stat_digest {
size_t dlv_loop;
};
-#define MSZ_EVP 512
-
struct mproc {
pid_t pid;
@@ -912,8 +913,15 @@ struct mproc {
int proc;
void (*handler)(struct mproc *, struct imsg *);
struct imsgbuf imsgbuf;
- struct ibuf *ibuf;
- int ibuferror;
+
+ char *m_buf;
+ size_t m_alloc;
+ size_t m_pos;
+ uint32_t m_type;
+ uint32_t m_peerid;
+ pid_t m_pid;
+ int m_fd;
+
int enable;
short events;
struct event ev;
@@ -995,7 +1003,7 @@ enum ca_resp_status {
struct ca_cert_req_msg {
uint64_t reqid;
- char name[MAXPATHLEN];
+ char name[SMTPD_MAXPATHLEN];
};
struct ca_cert_resp_msg {
@@ -1044,15 +1052,10 @@ int ca_X509_verify(void *, void *, const char *, const char *, const char **);
/* compress_backend.c */
-int compress_backend_init(const char *);
-void* compress_new(void);
-size_t compress_chunk(void *, void *, size_t, void *, size_t);
-size_t compress_finalize(void *, void *, size_t);
-size_t compress_buffer(char *, size_t, char *, size_t);
-void* uncompress_new(void);
-size_t uncompress_chunk(void *, void *, size_t, void *, size_t);
-size_t uncompress_finalize(void *, void *, size_t);
-size_t uncompress_buffer(char *, size_t, char *, size_t);
+struct compress_backend *compress_backend_lookup(const char *);
+size_t compress_chunk(void *, size_t, void *, size_t);
+size_t uncompress_chunk(void *, size_t, void *, size_t);
+int compress_file(FILE *, FILE *);
int uncompress_file(FILE *, FILE *);
/* config.c */
@@ -1106,6 +1109,7 @@ struct expandnode *expand_lookup(struct expand *, struct expandnode *);
void expand_clear(struct expand *);
void expand_free(struct expand *);
int expand_line(struct expand *, const char *, int);
+int expand_to_text(struct expand *, char *, size_t);
RB_PROTOTYPE(expandtree, expandnode, nodes, expand_cmp);
@@ -1127,15 +1131,15 @@ void imsgproc_reset_callback(struct imsgproc *, void (*)(struct imsg *, void *),
pid_t lka(void);
-/* log.c */
-void vlog(int, const char *, va_list);
-
-
/* lka_session.c */
void lka_session(uint64_t, struct envelope *);
void lka_session_forward_reply(struct forward_req *, int);
+/* log.c */
+void vlog(int, const char *, va_list);
+
+
/* mda.c */
pid_t mda(void);
@@ -1164,7 +1168,7 @@ void m_compose(struct mproc *, uint32_t, uint32_t, pid_t, int, void *, size_t);
void m_composev(struct mproc *, uint32_t, uint32_t, pid_t, int,
const struct iovec *, int);
void m_forward(struct mproc *, struct imsg *);
-void m_create(struct mproc *, uint32_t, uint32_t, pid_t, int, size_t);
+void m_create(struct mproc *, uint32_t, uint32_t, pid_t, int);
void m_add(struct mproc *, const void *, size_t);
void m_add_int(struct mproc *, int);
void m_add_u32(struct mproc *, uint32_t);
@@ -1201,7 +1205,7 @@ void mta_route_ok(struct mta_relay *, struct mta_route *);
void mta_route_error(struct mta_relay *, struct mta_route *);
void mta_route_collect(struct mta_relay *, struct mta_route *);
void mta_source_error(struct mta_relay *, struct mta_route *, const char *);
-void mta_delivery(struct mta_envelope *, const char *, int, const char *);
+void mta_delivery(struct mta_envelope *, const char *, const char *, int, const char *);
struct mta_task *mta_route_next_task(struct mta_relay *, struct mta_route *);
const char *mta_host_to_text(struct mta_host *);
const char *mta_relay_to_text(struct mta_relay *);
@@ -1292,37 +1296,31 @@ struct stat_value *stat_timespec(struct timespec *);
/* table.c */
+struct table *table_find(const char *, const char *);
+struct table *table_create(const char *, const char *, const char *,
+ const char *);
+int table_config(struct table *);
int table_open(struct table *);
-void table_update(struct table *);
+int table_update(struct table *);
void table_close(struct table *);
int table_check_use(struct table *, uint32_t, uint32_t);
int table_check_type(struct table *, uint32_t);
int table_check_service(struct table *, uint32_t);
-int table_lookup(struct table *, const char *, enum table_service, void **);
-int table_fetch(struct table *, enum table_service, char **);
-struct table *table_find(objid_t);
-struct table *table_findbyname(const char *);
-struct table *table_create(const char *, const char *, const char *);
+int table_lookup(struct table *, const char *, enum table_service,
+ union lookup *);
+int table_fetch(struct table *, enum table_service, union lookup *);
void table_destroy(struct table *);
void table_add(struct table *, const char *, const char *);
void table_delete(struct table *, const char *);
-void table_delete_all(struct table *);
-void table_replace(struct table *, struct table *);
int table_domain_match(const char *, const char *);
int table_netaddr_match(const char *, const char *);
int table_mailaddr_match(const char *, const char *);
void table_open_all(void);
+void table_dump_all(void);
void table_close_all(void);
-void table_set_payload(struct table *, void *);
-void *table_get_payload(struct table *);
-void table_set_configuration(struct table *, struct table *);
-struct table *table_get_configuration(struct table *);
const void *table_get(struct table *, const char *);
-
-void *table_config_create(void);
-const char *table_config_get(void *, const char *);
-void table_config_destroy(void *);
-int table_config_parse(void *, const char *, enum table_type);
+int table_parse_lookup(enum table_service, const char *, const char *,
+ union lookup *);
/* to.c */
diff --git a/usr.sbin/smtpd/smtpd/Makefile b/usr.sbin/smtpd/smtpd/Makefile
index 0ebdd33e8e2..47dd0b14b96 100644
--- a/usr.sbin/smtpd/smtpd/Makefile
+++ b/usr.sbin/smtpd/smtpd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.59 2013/03/27 07:48:42 eric Exp $
+# $OpenBSD: Makefile,v 1.60 2013/05/24 17:03:14 eric Exp $
.PATH: ${.CURDIR}/.. ${.CURDIR}/../../../lib/libc/asr
@@ -20,6 +20,7 @@ SRCS+= delivery_filename.c
SRCS+= delivery_maildir.c
SRCS+= delivery_mbox.c
SRCS+= delivery_mda.c
+SRCS+= delivery_lmtp.c
SRCS+= table_db.c
SRCS+= table_getpwnam.c
SRCS+= table_static.c
@@ -46,7 +47,6 @@ BINDIR= /usr/sbin
LDADD+= -levent -lutil -lssl -lcrypto -lm -lz -lsqlite3
DPADD+= ${LIBEVENT} ${LIBUTIL} ${LIBSSL} ${LIBCRYPTO} ${LIBM} ${LIBZ} ${LIBSQLITE3}
CFLAGS+= -g3 -ggdb -I${.CURDIR}/.. -I${.CURDIR}/../../../lib/libc/asr
-
CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
diff --git a/usr.sbin/smtpd/ssl.c b/usr.sbin/smtpd/ssl.c
index 1a5e051c4dd..b814f71b4a4 100644
--- a/usr.sbin/smtpd/ssl.c
+++ b/usr.sbin/smtpd/ssl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl.c,v 1.52 2013/01/26 09:37:24 gilles Exp $ */
+/* $OpenBSD: ssl.c,v 1.53 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -29,6 +28,7 @@
#include <event.h>
#include <fcntl.h>
#include <imsg.h>
+#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -320,11 +320,8 @@ ssl_error(const char *where)
{
unsigned long code;
char errbuf[128];
- extern int debug;
for (; (code = ERR_get_error()) != 0 ;) {
- if (!debug)
- continue;
ERR_error_string_n(code, errbuf, sizeof(errbuf));
log_debug("debug: SSL library error: %s: %s", where, errbuf);
}
diff --git a/usr.sbin/smtpd/ssl_smtpd.c b/usr.sbin/smtpd/ssl_smtpd.c
index e1cea87eee1..20aa6ad313f 100644
--- a/usr.sbin/smtpd/ssl_smtpd.c
+++ b/usr.sbin/smtpd/ssl_smtpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_smtpd.c,v 1.1 2013/01/26 09:37:24 gilles Exp $ */
+/* $OpenBSD: ssl_smtpd.c,v 1.2 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
diff --git a/usr.sbin/smtpd/stat_backend.c b/usr.sbin/smtpd/stat_backend.c
index 4b8c7cc6f4f..d145b10c33e 100644
--- a/usr.sbin/smtpd/stat_backend.c
+++ b/usr.sbin/smtpd/stat_backend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: stat_backend.c,v 1.7 2013/03/08 19:11:52 chl Exp $ */
+/* $OpenBSD: stat_backend.c,v 1.8 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -20,7 +20,6 @@
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <event.h>
#include <imsg.h>
@@ -48,13 +47,11 @@ stat_backend_lookup(const char *name)
void
stat_increment(const char *key, size_t count)
{
- size_t len;
struct stat_value *value;
value = stat_counter(count);
- len = 32 + strlen(key) + sizeof(*value);
- m_create(p_control, IMSG_STAT_INCREMENT, 0, 0, -1, len);
+ m_create(p_control, IMSG_STAT_INCREMENT, 0, 0, -1);
m_add_string(p_control, key);
m_add_data(p_control, value, sizeof(*value));
m_close(p_control);
@@ -63,13 +60,11 @@ stat_increment(const char *key, size_t count)
void
stat_decrement(const char *key, size_t count)
{
- size_t len;
struct stat_value *value;
value = stat_counter(count);
- len = 32 + strlen(key) + sizeof(*value);
- m_create(p_control, IMSG_STAT_DECREMENT, 0, 0, -1, len);
+ m_create(p_control, IMSG_STAT_DECREMENT, 0, 0, -1);
m_add_string(p_control, key);
m_add_data(p_control, value, sizeof(*value));
m_close(p_control);
@@ -78,10 +73,7 @@ stat_decrement(const char *key, size_t count)
void
stat_set(const char *key, const struct stat_value *value)
{
- size_t len;
-
- len = 32 + strlen(key) + sizeof(*value);
- m_create(p_control, IMSG_STAT_SET, 0, 0, -1, len);
+ m_create(p_control, IMSG_STAT_SET, 0, 0, -1);
m_add_string(p_control, key);
m_add_data(p_control, value, sizeof(*value));
m_close(p_control);
diff --git a/usr.sbin/smtpd/stat_ramstat.c b/usr.sbin/smtpd/stat_ramstat.c
index fccd5f9cc4f..910a8e170f2 100644
--- a/usr.sbin/smtpd/stat_ramstat.c
+++ b/usr.sbin/smtpd/stat_ramstat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: stat_ramstat.c,v 1.7 2013/03/08 19:11:52 chl Exp $ */
+/* $OpenBSD: stat_ramstat.c,v 1.8 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -20,7 +20,6 @@
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <event.h>
#include <imsg.h>
diff --git a/usr.sbin/smtpd/table.c b/usr.sbin/smtpd/table.c
index d58ebbf8a45..4da759384e2 100644
--- a/usr.sbin/smtpd/table.c
+++ b/usr.sbin/smtpd/table.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: table.c,v 1.3 2013/02/05 15:23:40 gilles Exp $ */
+/* $OpenBSD: table.c,v 1.4 2013/05/24 17:03:14 eric Exp $ */
/*
+ * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -19,10 +20,11 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
#include <ctype.h>
#include <err.h>
@@ -44,7 +46,12 @@ extern struct table_backend table_backend_getpwnam;
extern struct table_backend table_backend_sqlite;
extern struct table_backend table_backend_ldap;
-static objid_t last_table_id = 0;
+static const char * table_service_name(enum table_service);
+static const char * table_backend_name(struct table_backend *);
+static const char * table_dump_lookup(enum table_service, union lookup *);
+static int parse_sockaddr(struct sockaddr *, int, const char *);
+
+static unsigned int last_table_id = 0;
struct table_backend *
table_backend_lookup(const char *backend)
@@ -62,39 +69,140 @@ table_backend_lookup(const char *backend)
return NULL;
}
-struct table *
-table_findbyname(const char *name)
-{
- return dict_get(env->sc_tables_dict, name);
+static const char *
+table_backend_name(struct table_backend *backend)
+{
+ if (backend == &table_backend_static)
+ return "static";
+ if (backend == &table_backend_db)
+ return "db";
+ if (backend == &table_backend_getpwnam)
+ return "getpwnam";
+ if (backend == &table_backend_sqlite)
+ return "sqlite";
+ if (backend == &table_backend_ldap)
+ return "ldap";
+ return "???";
+}
+
+static const char *
+table_service_name(enum table_service s)
+{
+ switch (s) {
+ case K_NONE: return "NONE";
+ case K_ALIAS: return "ALIAS";
+ case K_DOMAIN: return "DOMAIN";
+ case K_CREDENTIALS: return "CREDENTIALS";
+ case K_NETADDR: return "NETADDR";
+ case K_USERINFO: return "USERINFO";
+ case K_SOURCE: return "SOURCE";
+ case K_MAILADDR: return "MAILADDR";
+ case K_ADDRNAME: return "ADDRNAME";
+ default: return "???";
+ }
}
struct table *
-table_find(objid_t id)
+table_find(const char *name, const char *tag)
{
- return tree_get(env->sc_tables_tree, id);
+ char buf[SMTPD_MAXLINESIZE];
+
+ if (tag == NULL)
+ return dict_get(env->sc_tables_dict, name);
+
+ if (snprintf(buf, sizeof(buf), "%s#%s", name, tag) >= (int)sizeof(buf)) {
+ log_warnx("warn: table name too long: %s#%s", name, tag);
+ return (NULL);
+ }
+
+ return dict_get(env->sc_tables_dict, buf);
}
int
table_lookup(struct table *table, const char *key, enum table_service kind,
- void **retp)
+ union lookup *lk)
{
- return table->t_backend->lookup(table->t_handle, key, kind, retp);
+ int r;
+ char lkey[1024];
+
+ if (table->t_backend->lookup == NULL)
+ return (-1);
+
+ if (! lowercase(lkey, key, sizeof lkey)) {
+ log_warnx("warn: lookup key too long: %s", key);
+ return -1;
+ }
+
+ r = table->t_backend->lookup(table->t_handle, lkey, kind, lk);
+
+ if (r == 1)
+ log_trace(TRACE_LOOKUP, "lookup: %s \"%s\" as %s in table %s:%s -> %s%s%s",
+ lk ? "lookup" : "check",
+ lkey,
+ table_service_name(kind),
+ table_backend_name(table->t_backend),
+ table->t_name,
+ lk ? "\"" : "",
+ (lk) ? table_dump_lookup(kind, lk): "found",
+ lk ? "\"" : "");
+ else
+ log_trace(TRACE_LOOKUP, "lookup: %s \"%s\" as %s in table %s:%s -> %i",
+ lk ? "lookup" : "check",
+ lkey,
+ table_service_name(kind),
+ table_backend_name(table->t_backend),
+ table->t_name,
+ r);
+
+ return (r);
}
int
-table_fetch(struct table *table, enum table_service kind, char **retp)
+table_fetch(struct table *table, enum table_service kind, union lookup *lk)
{
- return table->t_backend->fetch(table->t_handle, kind, retp);
+ int r;
+
+ if (table->t_backend->fetch == NULL)
+ return (-1);
+
+ r = table->t_backend->fetch(table->t_handle, kind, lk);
+
+ if (r == 1)
+ log_trace(TRACE_LOOKUP, "lookup: fetch %s from table %s:%s -> %s%s%s",
+ table_service_name(kind),
+ table_backend_name(table->t_backend),
+ table->t_name,
+ lk ? "\"" : "",
+ (lk) ? table_dump_lookup(kind, lk): "found",
+ lk ? "\"" : "");
+ else
+ log_trace(TRACE_LOOKUP, "lookup: fetch %s from table %s:%s -> %i",
+ table_service_name(kind),
+ table_backend_name(table->t_backend),
+ table->t_name,
+ r);
+
+ return (r);
}
struct table *
-table_create(const char *backend, const char *name, const char *config)
+table_create(const char *backend, const char *name, const char *tag,
+ const char *config)
{
struct table *t;
struct table_backend *tb;
- size_t n;
+ char buf[SMTPD_MAXLINESIZE];
+ size_t n;
+
+ if (name && tag) {
+ if (snprintf(buf, sizeof(buf), "%s#%s", name, tag)
+ >= (int)sizeof(buf))
+ errx(1, "table_create: name too long \"%s#%s\"",
+ name, tag);
+ name = buf;
+ }
- if (name && table_findbyname(name))
+ if (name && table_find(name, NULL))
errx(1, "table_create: table \"%s\" already defined", name);
if ((tb = table_backend_lookup(backend)) == NULL)
@@ -110,26 +218,19 @@ table_create(const char *backend, const char *name, const char *config)
if (!strcmp(backend, "file"))
backend = "static";
- if (strlcpy(t->t_src, backend, sizeof t->t_src) >= sizeof t->t_src)
- errx(1, "table_create: table backend \"%s\" too large",
- t->t_src);
-
- if (config && *config) {
+ if (config) {
if (strlcpy(t->t_config, config, sizeof t->t_config)
>= sizeof t->t_config)
errx(1, "table_create: table config \"%s\" too large",
t->t_config);
}
- if (strcmp(t->t_src, "static") != 0)
+ if (strcmp(backend, "static") != 0)
t->t_type = T_DYNAMIC;
- t->t_id = ++last_table_id;
- if (t->t_id == INT_MAX)
- errx(1, "table_create: too many tables defined");
-
if (name == NULL)
- snprintf(t->t_name, sizeof(t->t_name), "<dynamic:%u>", t->t_id);
+ snprintf(t->t_name, sizeof(t->t_name), "<dynamic:%u>",
+ last_table_id++);
else {
n = strlcpy(t->t_name, name, sizeof(t->t_name));
if (n >= sizeof(t->t_name))
@@ -138,7 +239,6 @@ table_create(const char *backend, const char *name, const char *config)
dict_init(&t->t_dict);
dict_set(env->sc_tables_dict, t->t_name, t);
- tree_set(env->sc_tables_tree, t->t_id, t);
return (t);
}
@@ -152,49 +252,21 @@ table_destroy(struct table *t)
free(p);
dict_xpop(env->sc_tables_dict, t->t_name);
- tree_xpop(env->sc_tables_tree, t->t_id);
free(t);
}
-void
-table_replace(struct table *orig, struct table *tnew)
-{
- void *p = NULL;
-
- while (dict_poproot(&orig->t_dict, NULL, (void **)&p))
- free(p);
- dict_merge(&orig->t_dict, &tnew->t_dict);
- table_destroy(tnew);
-}
-
-void
-table_set_configuration(struct table *t, struct table *config)
-{
- strlcpy(t->t_cfgtable, config->t_name, sizeof t->t_cfgtable);
-}
-
-struct table *
-table_get_configuration(struct table *t)
-{
- return table_findbyname(t->t_cfgtable);
-}
-
-void
-table_set_payload(struct table *t, void *payload)
-{
- t->t_payload = payload;
-}
-
-void *
-table_get_payload(struct table *t)
+int
+table_config(struct table *t)
{
- return t->t_payload;
+ if (t->t_backend->config == NULL)
+ return (1);
+ return (t->t_backend->config(t));
}
void
table_add(struct table *t, const char *key, const char *val)
{
- if (strcmp(t->t_src, "static") != 0)
+ if (t->t_type & T_DYNAMIC)
errx(1, "table_add: cannot add to table");
dict_set(&t->t_dict, key, val ? xstrdup(val, "table_add") : NULL);
}
@@ -202,16 +274,16 @@ table_add(struct table *t, const char *key, const char *val)
const void *
table_get(struct table *t, const char *key)
{
- if (strcmp(t->t_src, "static") != 0)
- errx(1, "table_add: cannot get from table");
+ if (t->t_type & T_DYNAMIC)
+ errx(1, "table_get: cannot get from table");
return dict_get(&t->t_dict, key);
}
void
table_delete(struct table *t, const char *key)
{
- if (strcmp(t->t_src, "static") != 0)
- errx(1, "map_add: cannot delete from map");
+ if (t->t_type & T_DYNAMIC)
+ errx(1, "table_delete: cannot delete from table");
free(dict_pop(&t->t_dict, key));
}
@@ -236,112 +308,28 @@ table_check_use(struct table *t, uint32_t tmask, uint32_t smask)
int
table_open(struct table *t)
{
+ t->t_handle = NULL;
+ if (t->t_backend->open == NULL)
+ return (1);
t->t_handle = t->t_backend->open(t);
if (t->t_handle == NULL)
- return 0;
- return 1;
+ return (0);
+ return (1);
}
void
table_close(struct table *t)
{
- t->t_backend->close(t->t_handle);
-}
-
-
-void
-table_update(struct table *t)
-{
- t->t_backend->update(t);
-}
-
-void *
-table_config_create(void)
-{
- return table_create("static", NULL, NULL);
-}
-
-const char *
-table_config_get(void *p, const char *key)
-{
- return (const char *)table_get(p, key);
-}
-
-void
-table_config_destroy(void *p)
-{
- table_destroy(p);
+ if (t->t_backend->close)
+ t->t_backend->close(t->t_handle);
}
int
-table_config_parse(void *p, const char *config, enum table_type type)
+table_update(struct table *t)
{
- struct table *t = p;
- FILE *fp;
- char *buf, *lbuf;
- size_t flen;
- char *keyp;
- char *valp;
- size_t ret = 0;
-
- if (strcmp("static", t->t_src) != 0) {
- log_warn("table_config_parser: config table must be static");
- return 0;
- }
-
- fp = fopen(config, "r");
- if (fp == NULL)
- return 0;
-
- lbuf = NULL;
- while ((buf = fgetln(fp, &flen))) {
- if (buf[flen - 1] == '\n')
- buf[flen - 1] = '\0';
- else {
- lbuf = xmalloc(flen + 1, "table_stdio_get_entry");
- memcpy(lbuf, buf, flen);
- lbuf[flen] = '\0';
- buf = lbuf;
- }
-
- keyp = buf;
- while (isspace((int)*keyp))
- ++keyp;
- if (*keyp == '\0' || *keyp == '#')
- continue;
- valp = keyp;
- strsep(&valp, " \t:");
- if (valp) {
- while (*valp) {
- if (!isspace(*valp) &&
- !(*valp == ':' && isspace(*(valp + 1))))
- break;
- ++valp;
- }
- if (*valp == '\0')
- valp = NULL;
- }
-
- /**/
- if (t->t_type == 0)
- t->t_type = (valp == keyp || valp == NULL) ? T_LIST :
- T_HASH;
-
- if (!(t->t_type & type))
- goto end;
-
- if ((valp == keyp || valp == NULL) && t->t_type == T_LIST)
- table_add(t, keyp, NULL);
- else if ((valp != keyp && valp != NULL) && t->t_type == T_HASH)
- table_add(t, keyp, valp);
- else
- goto end;
- }
- ret = 1;
-end:
- free(lbuf);
- fclose(fp);
- return ret;
+ if (t->t_backend->update == NULL)
+ return (1);
+ return (t->t_backend->update(t));
}
int
@@ -380,7 +368,7 @@ table_netaddr_match(const char *s1, const char *s2)
struct netaddr n1;
struct netaddr n2;
- if (strcmp(s1, s2) == 0)
+ if (strcasecmp(s1, s2) == 0)
return 1;
if (! text_to_netaddr(&n1, s1))
return 0;
@@ -453,13 +441,52 @@ table_inet6_match(struct sockaddr_in6 *ss, struct netaddr *ssmask)
}
void
+table_dump_all(void)
+{
+ struct table *t;
+ void *iter, *i2;
+ const char *key, *sep;
+ char *value;
+ char buf[1024];
+
+ iter = NULL;
+ while (dict_iter(env->sc_tables_dict, &iter, NULL, (void **)&t)) {
+ i2 = NULL;
+ sep = "";
+ buf[0] = '\0';
+ if (t->t_type & T_DYNAMIC) {
+ strlcat(buf, "DYNAMIC", sizeof(buf));
+ sep = ",";
+ }
+ if (t->t_type & T_LIST) {
+ strlcat(buf, sep, sizeof(buf));
+ strlcat(buf, "LIST", sizeof(buf));
+ sep = ",";
+ }
+ if (t->t_type & T_HASH) {
+ strlcat(buf, sep, sizeof(buf));
+ strlcat(buf, "HASH", sizeof(buf));
+ sep = ",";
+ }
+ log_debug("TABLE \"%s\" type=%s config=\"%s\"",
+ t->t_name, buf, t->t_config);
+ while(dict_iter(&t->t_dict, &i2, &key, (void**)&value)) {
+ if (value)
+ log_debug(" \"%s\" -> \"%s\"", key, value);
+ else
+ log_debug(" \"%s\"", key);
+ }
+ }
+}
+
+void
table_open_all(void)
{
struct table *t;
void *iter;
iter = NULL;
- while (tree_iter(env->sc_tables_tree, &iter, NULL, (void **)&t))
+ while (dict_iter(env->sc_tables_dict, &iter, NULL, (void **)&t))
if (! table_open(t))
errx(1, "failed to open table %s", t->t_name);
}
@@ -471,6 +498,222 @@ table_close_all(void)
void *iter;
iter = NULL;
- while (tree_iter(env->sc_tables_tree, &iter, NULL, (void **)&t))
+ while (dict_iter(env->sc_tables_dict, &iter, NULL, (void **)&t))
table_close(t);
}
+
+int
+table_parse_lookup(enum table_service service, const char *key,
+ const char *line, union lookup *lk)
+{
+ char buffer[SMTPD_MAXLINESIZE], *p;
+ size_t len;
+
+ len = strlen(line);
+
+ switch (service) {
+ case K_ALIAS:
+ lk->expand = calloc(1, sizeof(*lk->expand));
+ if (lk->expand == NULL)
+ return (-1);
+ if (!expand_line(lk->expand, line, 1)) {
+ expand_free(lk->expand);
+ return (-1);
+ }
+ return (1);
+
+ case K_DOMAIN:
+ if (strlcpy(lk->domain.name, line, sizeof(lk->domain.name))
+ >= sizeof(lk->domain.name))
+ return (-1);
+ return (1);
+
+ case K_CREDENTIALS:
+
+ /* credentials are stored as user:password */
+ if (len < 3)
+ return (-1);
+
+ /* too big to fit in a smtp session line */
+ if (len >= SMTPD_MAXLINESIZE)
+ return (-1);
+
+ p = strchr(line, ':');
+ if (p == NULL || p == line || p == line + len - 1)
+ return (-1);
+
+ memmove(lk->creds.username, line, p - line);
+ lk->creds.username[p - line] = '\0';
+
+ if (strlcpy(lk->creds.password, p+1, sizeof(lk->creds.password))
+ >= sizeof(lk->creds.password))
+ return (-1);
+
+ return (1);
+
+ case K_NETADDR:
+ if (!text_to_netaddr(&lk->netaddr, line))
+ return (-1);
+ return (1);
+
+ case K_USERINFO:
+ if (!bsnprintf(buffer, sizeof(buffer), "%s:%s", key, line))
+ return (-1);
+ if (!text_to_userinfo(&lk->userinfo, buffer))
+ return (-1);
+ return (1);
+
+ case K_SOURCE:
+ if (parse_sockaddr((struct sockaddr *)&lk->source.addr,
+ PF_UNSPEC, line) == -1)
+ return (-1);
+ return (1);
+
+ case K_MAILADDR:
+ if (!text_to_mailaddr(&lk->mailaddr, line))
+ return (-1);
+ return (1);
+
+ case K_ADDRNAME:
+ if (parse_sockaddr((struct sockaddr *)&lk->addrname.addr,
+ PF_UNSPEC, key) == -1)
+ return (-1);
+ if (strlcpy(lk->addrname.name, line, sizeof(lk->addrname.name))
+ >= sizeof(lk->addrname.name))
+ return (-1);
+ return (1);
+
+ default:
+ return (-1);
+ }
+}
+
+static const char *
+table_dump_lookup(enum table_service s, union lookup *lk)
+{
+ static char buf[SMTPD_MAXLINESIZE];
+
+ switch (s) {
+ case K_NONE:
+ break;
+
+ case K_ALIAS:
+ expand_to_text(lk->expand, buf, sizeof(buf));
+ break;
+
+ case K_DOMAIN:
+ snprintf(buf, sizeof(buf), "%s", lk->domain.name);
+ break;
+
+ case K_CREDENTIALS:
+ snprintf(buf, sizeof(buf), "%s:%s",
+ lk->creds.username, lk->creds.password);
+ break;
+
+ case K_NETADDR:
+ snprintf(buf, sizeof(buf), "%s/%i",
+ sockaddr_to_text((struct sockaddr *)&lk->netaddr.ss),
+ lk->netaddr.bits);
+ break;
+
+ case K_USERINFO:
+ snprintf(buf, sizeof(buf), "%s:%i:%i:%s",
+ lk->userinfo.username,
+ lk->userinfo.uid,
+ lk->userinfo.gid,
+ lk->userinfo.directory);
+ break;
+
+ case K_SOURCE:
+ snprintf(buf, sizeof(buf), "%s",
+ ss_to_text(&lk->source.addr));
+ break;
+
+ case K_MAILADDR:
+ snprintf(buf, sizeof(buf), "%s@%s",
+ lk->mailaddr.user,
+ lk->mailaddr.domain);
+ break;
+
+ case K_ADDRNAME:
+ snprintf(buf, sizeof(buf), "%s",
+ lk->addrname.name);
+ break;
+
+ default:
+ break;
+ }
+
+ return (buf);
+}
+
+
+static int
+parse_sockaddr(struct sockaddr *sa, int family, const char *str)
+{
+ struct in_addr ina;
+ struct in6_addr in6a;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ char *cp, *str2;
+ const char *errstr;
+
+ switch (family) {
+ case PF_UNSPEC:
+ if (parse_sockaddr(sa, PF_INET, str) == 0)
+ return (0);
+ return parse_sockaddr(sa, PF_INET6, str);
+
+ case PF_INET:
+ if (inet_pton(PF_INET, str, &ina) != 1)
+ return (-1);
+
+ sin = (struct sockaddr_in *)sa;
+ memset(sin, 0, sizeof *sin);
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_family = PF_INET;
+ sin->sin_addr.s_addr = ina.s_addr;
+ return (0);
+
+ case PF_INET6:
+ cp = strchr(str, SCOPE_DELIMITER);
+ if (cp) {
+ str2 = strdup(str);
+ if (str2 == NULL)
+ return (-1);
+ str2[cp - str] = '\0';
+ if (inet_pton(PF_INET6, str2, &in6a) != 1) {
+ free(str2);
+ return (-1);
+ }
+ cp++;
+ free(str2);
+ } else if (inet_pton(PF_INET6, str, &in6a) != 1)
+ return (-1);
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ memset(sin6, 0, sizeof *sin6);
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ sin6->sin6_family = PF_INET6;
+ sin6->sin6_addr = in6a;
+
+ if (cp == NULL)
+ return (0);
+
+ if (IN6_IS_ADDR_LINKLOCAL(&in6a) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&in6a) ||
+ IN6_IS_ADDR_MC_INTFACELOCAL(&in6a))
+ if ((sin6->sin6_scope_id = if_nametoindex(cp)))
+ return (0);
+
+ sin6->sin6_scope_id = strtonum(cp, 0, UINT32_MAX, &errstr);
+ if (errstr)
+ return (-1);
+ return (0);
+
+ default:
+ break;
+ }
+
+ return (-1);
+}
diff --git a/usr.sbin/smtpd/table_db.c b/usr.sbin/smtpd/table_db.c
index 23030422817..853654dfcb0 100644
--- a/usr.sbin/smtpd/table_db.c
+++ b/usr.sbin/smtpd/table_db.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table_db.c,v 1.4 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: table_db.c,v 1.5 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -20,9 +20,11 @@
#include <sys/stat.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include <db.h>
#include <ctype.h>
#include <err.h>
@@ -38,25 +40,19 @@
/* db(3) backend */
-static int table_db_config(struct table *, const char *);
+static int table_db_config(struct table *);
static int table_db_update(struct table *);
static void *table_db_open(struct table *);
-static int table_db_lookup(void *, const char *, enum table_service, void **);
-static int table_db_fetch(void *, enum table_service, char **);
+static int table_db_lookup(void *, const char *, enum table_service, union lookup *);
+static int table_db_fetch(void *, enum table_service, union lookup *);
static void table_db_close(void *);
static char *table_db_get_entry(void *, const char *, size_t *);
static char *table_db_get_entry_match(void *, const char *, size_t *,
int(*)(const char *, const char *));
-static int table_db_credentials(const char *, char *, size_t, void **);
-static int table_db_alias(const char *, char *, size_t, void **);
-static int table_db_domain(const char *, char *, size_t, void **);
-static int table_db_netaddr(const char *, char *, size_t, void **);
-static int table_db_userinfo(const char *, char *, size_t, void **);
-
struct table_backend table_backend_db = {
- K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_NETADDR|K_USERINFO|K_SOURCE,
+ K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_NETADDR|K_USERINFO|K_SOURCE|K_ADDRNAME,
table_db_config,
table_db_open,
table_db_update,
@@ -75,13 +71,13 @@ static struct keycmp {
struct dbhandle {
DB *db;
- char pathname[MAXPATHLEN];
+ char pathname[SMTPD_MAXPATHLEN];
time_t mtime;
struct table *table;
};
static int
-table_db_config(struct table *table, const char *config)
+table_db_config(struct table *table)
{
struct dbhandle *handle;
@@ -146,9 +142,10 @@ table_db_close(void *hdl)
static int
table_db_lookup(void *hdl, const char *key, enum table_service service,
- void **retp)
+ union lookup *lk)
{
struct dbhandle *handle = hdl;
+ struct table *table = NULL;
char *line;
size_t len = 0;
int ret;
@@ -160,58 +157,33 @@ table_db_lookup(void *hdl, const char *key, enum table_service service,
return -1;
/* DB has changed, close and reopen */
- if (sb.st_mtime != handle->mtime)
+ if (sb.st_mtime != handle->mtime) {
+ table = handle->table;
table_db_update(handle->table);
+ handle = table->t_handle;
+ }
for (i = 0; i < nitems(keycmp); ++i)
if (keycmp[i].service == service)
match = keycmp[i].func;
if (match == NULL)
- line = table_db_get_entry(hdl, key, &len);
+ line = table_db_get_entry(handle, key, &len);
else
- line = table_db_get_entry_match(hdl, key, &len, match);
+ line = table_db_get_entry_match(handle, key, &len, match);
if (line == NULL)
return 0;
- if (retp == NULL) {
- free(line);
- return 1;
- }
-
- ret = 0;
- switch (service) {
- case K_ALIAS:
- ret = table_db_alias(key, line, len, retp);
- break;
-
- case K_CREDENTIALS:
- ret = table_db_credentials(key, line, len, retp);
- break;
-
- case K_DOMAIN:
- ret = table_db_domain(key, line, len, retp);
- break;
-
- case K_NETADDR:
- ret = table_db_netaddr(key, line, len, retp);
- break;
-
- case K_USERINFO:
- ret = table_db_userinfo(key, line, len, retp);
- break;
-
- default:
- break;
- }
-
+ ret = 1;
+ if (lk)
+ ret = table_parse_lookup(service, key, line, lk);
free(line);
return ret;
}
static int
-table_db_fetch(void *hdl, enum table_service service, char **retp)
+table_db_fetch(void *hdl, enum table_service service, union lookup *lk)
{
struct dbhandle *handle = hdl;
struct table *table = handle->table;
@@ -229,8 +201,8 @@ table_db_fetch(void *hdl, enum table_service service, char **retp)
if (!r)
return 0;
}
- *retp = xmemdup(dbk.data, dbk.size, "table_db_get_entry_cmp");
- return 1;
+
+ return table_parse_lookup(service, NULL, dbk.data, lk);
}
@@ -278,117 +250,3 @@ table_db_get_entry(void *hdl, const char *key, size_t *len)
return xmemdup(dbv.data, dbv.size, "table_db_get_entry");
}
-
-static int
-table_db_credentials(const char *key, char *line, size_t len, void **retp)
-{
- struct credentials *credentials = NULL;
- char *p;
-
- /* credentials are stored as user:password */
- if (len < 3)
- return -1;
-
- /* too big to fit in a smtp session line */
- if (len >= SMTPD_MAXLINESIZE)
- return -1;
-
- p = strchr(line, ':');
- if (p == NULL)
- return -1;
-
- if (p == line || p == line + len - 1)
- return -1;
- *p++ = '\0';
-
- credentials = xcalloc(1, sizeof *credentials,
- "table_db_credentials");
- if (strlcpy(credentials->username, line, sizeof(credentials->username))
- >= sizeof(credentials->username))
- goto err;
-
- if (strlcpy(credentials->password, p, sizeof(credentials->password))
- >= sizeof(credentials->password))
- goto err;
-
- *retp = credentials;
- return 1;
-
-err:
- *retp = NULL;
- free(credentials);
- return -1;
-}
-
-static int
-table_db_alias(const char *key, char *line, size_t len, void **retp)
-{
- struct expand *xp = NULL;
-
- xp = xcalloc(1, sizeof *xp, "table_db_alias");
- if (! expand_line(xp, line, 1))
- goto error;
- *retp = xp;
- return 1;
-
-error:
- *retp = NULL;
- expand_free(xp);
- return -1;
-}
-
-static int
-table_db_netaddr(const char *key, char *line, size_t len, void **retp)
-{
- struct netaddr *netaddr;
-
- netaddr = xcalloc(1, sizeof *netaddr, "table_db_netaddr");
- if (! text_to_netaddr(netaddr, line))
- goto error;
- *retp = netaddr;
- return 1;
-
-error:
- *retp = NULL;
- free(netaddr);
- return -1;
-}
-
-static int
-table_db_domain(const char *key, char *line, size_t len, void **retp)
-{
- struct destination *destination;
-
- destination = xcalloc(1, sizeof *destination, "table_db_domain");
- if (strlcpy(destination->name, line, sizeof destination->name)
- >= sizeof destination->name)
- goto error;
- *retp = destination;
- return 1;
-
-error:
- *retp = NULL;
- free(destination);
- return -1;
-}
-
-static int
-table_db_userinfo(const char *key, char *line, size_t len, void **retp)
-{
- struct userinfo *userinfo = NULL;
- char buffer[1024];
-
- if (! bsnprintf(buffer, sizeof buffer, "%s:%s", key, line))
- goto error;
-
- userinfo = xcalloc(1, sizeof *userinfo, "table_db_userinfo");
- if (! text_to_userinfo(userinfo, buffer))
- goto error;
- *retp = userinfo;
- return 1;
-
-error:
- *retp = NULL;
- free(userinfo);
- return -1;
-}
diff --git a/usr.sbin/smtpd/table_getpwnam.c b/usr.sbin/smtpd/table_getpwnam.c
index 25c2cbf3da0..f66effbf414 100644
--- a/usr.sbin/smtpd/table_getpwnam.c
+++ b/usr.sbin/smtpd/table_getpwnam.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table_getpwnam.c,v 1.1 2013/01/26 09:37:24 gilles Exp $ */
+/* $OpenBSD: table_getpwnam.c,v 1.2 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -38,11 +37,11 @@
/* getpwnam(3) backend */
-static int table_getpwnam_config(struct table *, const char *);
+static int table_getpwnam_config(struct table *);
static int table_getpwnam_update(struct table *);
static void *table_getpwnam_open(struct table *);
static int table_getpwnam_lookup(void *, const char *, enum table_service,
- void **);
+ union lookup *);
static void table_getpwnam_close(void *);
struct table_backend table_backend_getpwnam = {
@@ -56,9 +55,9 @@ struct table_backend table_backend_getpwnam = {
static int
-table_getpwnam_config(struct table *table, const char *config)
+table_getpwnam_config(struct table *table)
{
- if (config)
+ if (table->t_config[0])
return 0;
return 1;
}
@@ -83,9 +82,8 @@ table_getpwnam_close(void *hdl)
static int
table_getpwnam_lookup(void *hdl, const char *key, enum table_service kind,
- void **ret)
+ union lookup *lk)
{
- struct userinfo *userinfo;
struct passwd *pw;
size_t s;
@@ -102,25 +100,19 @@ table_getpwnam_lookup(void *hdl, const char *key, enum table_service kind,
return -1;
return 0;
}
- if (ret == NULL)
+ if (lk == NULL)
return 1;
- userinfo = xcalloc(1, sizeof *userinfo, "table_getpwnam_lookup");
- userinfo->uid = pw->pw_uid;
- userinfo->gid = pw->pw_gid;
- s = strlcpy(userinfo->username, pw->pw_name,
- sizeof(userinfo->username));
- if (s >= sizeof(userinfo->username))
- goto error;
- s = strlcpy(userinfo->directory, pw->pw_dir,
- sizeof(userinfo->directory));
- if (s >= sizeof(userinfo->directory))
- goto error;
-
- *ret = userinfo;
- return 1;
-
-error:
- free(userinfo);
- return -1;
+ lk->userinfo.uid = pw->pw_uid;
+ lk->userinfo.gid = pw->pw_gid;
+ s = strlcpy(lk->userinfo.username, pw->pw_name,
+ sizeof(lk->userinfo.username));
+ if (s >= sizeof(lk->userinfo.username))
+ return (-1);
+ s = strlcpy(lk->userinfo.directory, pw->pw_dir,
+ sizeof(lk->userinfo.directory));
+ if (s >= sizeof(lk->userinfo.directory))
+ return (-1);
+
+ return (1);
}
diff --git a/usr.sbin/smtpd/table_ldap.c b/usr.sbin/smtpd/table_ldap.c
index 02569ad8552..f3aff8b43a7 100644
--- a/usr.sbin/smtpd/table_ldap.c
+++ b/usr.sbin/smtpd/table_ldap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table_ldap.c,v 1.3 2013/03/08 19:11:52 chl Exp $ */
+/* $OpenBSD: table_ldap.c,v 1.4 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2010-2012 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -48,13 +47,13 @@
#define MAX_LDAP_FILTERLEN 1024
#define MAX_LDAP_FIELDLEN 128
-static void *table_ldap_open(struct table *);
-static int table_ldap_update(struct table *);
-static int table_ldap_config(struct table *, const char *);
-static int table_ldap_lookup(void *, const char *, enum table_service, void **);
-static int table_ldap_fetch(void *, enum table_service, char **);
-static void table_ldap_close(void *);
-static struct aldap *ldap_client_connect(const char *);
+static void *table_ldap_open(struct table *);
+static int table_ldap_update(struct table *);
+static int table_ldap_config(struct table *);
+static int table_ldap_lookup(void *, const char *, enum table_service, union lookup *);
+static int table_ldap_fetch(void *, enum table_service, union lookup *);
+static void table_ldap_close(void *);
+static struct aldap *ldap_client_connect(const char *);
struct table_backend table_backend_ldap = {
K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_USERINFO, /* K_NETADDR|K_SOURCE,*/
@@ -75,37 +74,36 @@ static int parse_attributes(char **, const char *, size_t);
static int table_ldap_internal_query(struct aldap *, const char *,
const char *, char **, char ***, size_t);
-static int table_ldap_alias(struct table_ldap_handle *, const char *, void **);
-static int table_ldap_credentials(struct table_ldap_handle *, const char *, void **);
-static int table_ldap_domain(struct table_ldap_handle *, const char *, void **);
-static int table_ldap_userinfo(struct table_ldap_handle *, const char *, void **);
+static int table_ldap_alias(struct table_ldap_handle *, const char *, union lookup *);
+static int table_ldap_credentials(struct table_ldap_handle *, const char *, union lookup *);
+static int table_ldap_domain(struct table_ldap_handle *, const char *, union lookup *);
+static int table_ldap_userinfo(struct table_ldap_handle *, const char *, union lookup *);
static int
-table_ldap_config(struct table *table, const char *config)
+table_ldap_config(struct table *table)
{
- void *cfg = NULL;
+ struct table *cfg = NULL;
/* no config ? broken */
- if (config == NULL)
+ if (table->t_config[0] == '\0')
return 0;
- cfg = table_config_create();
- if (! table_config_parse(cfg, config, T_HASH))
+ cfg = table_create("static", table->t_name, "conf", table->t_config);
+ if (!table_config(cfg))
goto err;
/* sanity checks */
- if (table_config_get(cfg, "url") == NULL) {
+ if (table_get(cfg, "url") == NULL) {
log_warnx("table_ldap: missing 'url' configuration");
goto err;
}
- if (table_config_get(cfg, "basedn") == NULL) {
+ if (table_get(cfg, "basedn") == NULL) {
log_warnx("table_ldap: missing 'basedn' configuration");
goto err;
}
- table_set_configuration(table, cfg);
return 1;
err:
@@ -130,7 +128,7 @@ table_ldap_open(struct table *table)
char *username = NULL;
char *password = NULL;
- cfg = table_get_configuration(table);
+ cfg = table_find(table->t_name, "conf");
if (table_get(cfg, "url") == NULL ||
table_get(cfg, "username") == NULL ||
table_get(cfg, "password") == NULL)
@@ -194,22 +192,22 @@ table_ldap_close(void *hdl)
static int
table_ldap_lookup(void *hdl, const char *key, enum table_service service,
- void **retp)
+ union lookup *lk)
{
struct table_ldap_handle *tlh = hdl;
switch (service) {
case K_ALIAS:
- return table_ldap_alias(tlh, key, retp);
+ return table_ldap_alias(tlh, key, lk);
case K_CREDENTIALS:
- return table_ldap_credentials(tlh, key, retp);
+ return table_ldap_credentials(tlh, key, lk);
case K_DOMAIN:
- return table_ldap_domain(tlh, key, retp);
+ return table_ldap_domain(tlh, key, lk);
case K_USERINFO:
- return table_ldap_userinfo(tlh, key, retp);
+ return table_ldap_userinfo(tlh, key, lk);
default:
break;
@@ -219,7 +217,7 @@ table_ldap_lookup(void *hdl, const char *key, enum table_service service,
}
static int
-table_ldap_fetch(void *hdl, enum table_service service, char **retp)
+table_ldap_fetch(void *hdl, enum table_service service, union lookup *lk)
{
/* fetch not support for LDAP at this point */
return -1;
@@ -300,20 +298,19 @@ end:
static int
-table_ldap_credentials(struct table_ldap_handle *tlh, const char *key, void **retp)
+table_ldap_credentials(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_get_configuration(tlh->table);
- const char *filter = NULL;
- const char *basedn = NULL;
- struct credentials credentials;
- char *expfilter = NULL;
- char *attributes[4];
- char **ret_attr[4];
- const char *attr;
- char line[1024];
- int ret = -1;
- size_t i;
+ struct aldap *aldap = tlh->aldap;
+ struct table *cfg = table_find(tlh->table->t_name, "conf");
+ const char *filter = NULL;
+ const char *basedn = NULL;
+ char *expfilter = NULL;
+ char *attributes[4];
+ char **ret_attr[4];
+ const char *attr;
+ char line[1024];
+ int ret = -1;
+ size_t i;
bzero(&attributes, sizeof attributes);
bzero(&ret_attr, sizeof ret_attr);
@@ -343,7 +340,7 @@ table_ldap_credentials(struct table_ldap_handle *tlh, const char *key, void **re
ret_attr, nitems(attributes))) <= 0)
goto end;
- if (retp == NULL)
+ if (lk == NULL)
goto end;
if (! bsnprintf(line, sizeof line, "%s:%s", ret_attr[0][0], ret_attr[0][1])) {
@@ -351,13 +348,9 @@ table_ldap_credentials(struct table_ldap_handle *tlh, const char *key, void **re
goto end;
}
- bzero(&credentials, sizeof credentials);
- if (! text_to_credentials(&credentials, line)) {
+ bzero(&lk->creds, sizeof(lk->creds));
+ if (! text_to_credentials(&lk->creds, line))
ret = -1;
- goto end;
- }
-
- *retp = xmemdup(&credentials, sizeof credentials, "table_ldap_credentials");
end:
for (i = 0; i < nitems(attributes); ++i) {
@@ -372,19 +365,18 @@ end:
}
static int
-table_ldap_domain(struct table_ldap_handle *tlh, const char *key, void **retp)
+table_ldap_domain(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_get_configuration(tlh->table);
- const char *filter = NULL;
- const char *basedn = NULL;
- struct destination destination;
- char *expfilter = NULL;
- char *attributes[1];
- char **ret_attr[1];
- const char *attr;
- int ret = -1;
- size_t i;
+ struct aldap *aldap = tlh->aldap;
+ struct table *cfg = table_find(tlh->table->t_name, "conf");
+ const char *filter = NULL;
+ const char *basedn = NULL;
+ char *expfilter = NULL;
+ char *attributes[1];
+ char **ret_attr[1];
+ const char *attr;
+ int ret = -1;
+ size_t i;
bzero(&attributes, sizeof attributes);
bzero(&ret_attr, sizeof ret_attr);
@@ -415,13 +407,13 @@ table_ldap_domain(struct table_ldap_handle *tlh, const char *key, void **retp)
ret_attr, nitems(attributes))) <= 0)
goto end;
- if (retp == NULL)
+ if (lk == NULL)
goto end;
- bzero(&destination, sizeof destination);
- if (strlcpy(destination.name, ret_attr[0][0], sizeof destination.name)
- >= sizeof destination.name);
- *retp = xmemdup(&destination, sizeof destination, "table_ldap_destination");
+ bzero(&lk->domain, sizeof(lk->domain));
+ if (strlcpy(lk->domain.name, ret_attr[0][0], sizeof(lk->domain.name))
+ >= sizeof(lk->domain.name))
+ ret = -1;
end:
for (i = 0; i < nitems(attributes); ++i) {
@@ -430,25 +422,24 @@ end:
aldap_free_attr(ret_attr[i]);
}
free(expfilter);
- log_debug("debug: table_ldap_destination: ret=%d", ret);
+ log_debug("debug: table_ldap_domain: ret=%d", ret);
return ret;
}
static int
-table_ldap_userinfo(struct table_ldap_handle *tlh, const char *key, void **retp)
+table_ldap_userinfo(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_get_configuration(tlh->table);
- const char *filter = NULL;
- const char *basedn = NULL;
- struct userinfo userinfo;
- char *expfilter = NULL;
- char *attributes[4];
- char **ret_attr[4];
- const char *attr;
- char line[1024];
- int ret = -1;
- size_t i;
+ struct aldap *aldap = tlh->aldap;
+ struct table *cfg = table_find(tlh->table->t_name, "conf");
+ const char *filter = NULL;
+ const char *basedn = NULL;
+ char *expfilter = NULL;
+ char *attributes[4];
+ char **ret_attr[4];
+ const char *attr;
+ char line[1024];
+ int ret = -1;
+ size_t i;
bzero(&attributes, sizeof attributes);
bzero(&ret_attr, sizeof ret_attr);
@@ -478,7 +469,7 @@ table_ldap_userinfo(struct table_ldap_handle *tlh, const char *key, void **retp)
ret_attr, nitems(attributes))) <= 0)
goto end;
- if (retp == NULL)
+ if (lk == NULL)
goto end;
if (! bsnprintf(line, sizeof line, "%s:%s:%s:%s",
@@ -487,13 +478,9 @@ table_ldap_userinfo(struct table_ldap_handle *tlh, const char *key, void **retp)
goto end;
}
- bzero(&userinfo, sizeof userinfo);
- if (! text_to_userinfo(&userinfo, line)) {
+ bzero(&lk->userinfo, sizeof(lk->userinfo));
+ if (!text_to_userinfo(&(lk->userinfo), line))
ret = -1;
- goto end;
- }
-
- *retp = xmemdup(&userinfo, sizeof userinfo, "table_ldap_userinfo");
end:
for (i = 0; i < nitems(attributes); ++i) {
@@ -507,22 +494,23 @@ end:
}
static int
-table_ldap_alias(struct table_ldap_handle *tlh, const char *key, void **retp)
+table_ldap_alias(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_get_configuration(tlh->table);
- const char *filter = NULL;
- const char *basedn = NULL;
- struct expand *xp = NULL;
- char *expfilter = NULL;
- char *attributes[1];
- char **ret_attr[1];
- const char *attr;
- int ret = -1;
- size_t i;
+ struct aldap *aldap = tlh->aldap;
+ struct table *cfg = table_find(tlh->table->t_name, "conf");
+ const char *filter = NULL;
+ const char *basedn = NULL;
+ char *expfilter = NULL;
+ char *attributes[1];
+ char **ret_attr[1];
+ const char *attr;
+ int ret = -1;
+ size_t i;
bzero(&attributes, sizeof attributes);
bzero(&ret_attr, sizeof ret_attr);
+ if (lk)
+ lk->expand = NULL;
basedn = table_get(cfg, "basedn");
if ((filter = table_get(cfg, "alias_filter")) == NULL) {
@@ -549,17 +537,16 @@ table_ldap_alias(struct table_ldap_handle *tlh, const char *key, void **retp)
ret_attr, nitems(attributes))) <= 0)
goto end;
- if (retp == NULL)
+ if (lk == NULL)
goto end;
- xp = xcalloc(1, sizeof *xp, "table_ldap_alias");
+ lk->expand = xcalloc(1, sizeof(*lk->expand), "table_ldap_alias");
for (i = 0; ret_attr[0][i]; ++i) {
- if (! expand_line(xp, ret_attr[0][i], 1)) {
+ if (! expand_line(lk->expand, ret_attr[0][i], 1)) {
ret = -1;
goto end;
}
}
- *retp = xp;
end:
for (i = 0; i < nitems(attributes); ++i) {
@@ -567,12 +554,9 @@ end:
if (ret_attr[i])
aldap_free_attr(ret_attr[i]);
}
- if (ret != 1) {
- if (retp)
- *retp = NULL;
- if (xp)
- expand_free(xp);
- }
+ if (ret != 1 && lk && lk->expand)
+ expand_free(lk->expand);
+
free(expfilter);
log_debug("debug: table_ldap_alias: ret=%d", ret);
return ret;
diff --git a/usr.sbin/smtpd/table_sqlite.c b/usr.sbin/smtpd/table_sqlite.c
index b2ec3141452..bfcf11fa4d4 100644
--- a/usr.sbin/smtpd/table_sqlite.c
+++ b/usr.sbin/smtpd/table_sqlite.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table_sqlite.c,v 1.2 2013/01/31 18:34:43 eric Exp $ */
+/* $OpenBSD: table_sqlite.c,v 1.3 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -36,11 +35,11 @@
#include "log.h"
/* sqlite(3) backend */
-static int table_sqlite_config(struct table *, const char *);
+static int table_sqlite_config(struct table *);
static int table_sqlite_update(struct table *);
static void *table_sqlite_open(struct table *);
static int table_sqlite_lookup(void *, const char *, enum table_service,
- void **);
+ union lookup *);
static void table_sqlite_close(void *);
struct table_backend table_backend_sqlite = {
@@ -57,36 +56,35 @@ struct table_sqlite_handle {
struct table *table;
};
-static int table_sqlite_alias(struct table_sqlite_handle *, const char *, void **);
-static int table_sqlite_domain(struct table_sqlite_handle *, const char *, void **);
-static int table_sqlite_userinfo(struct table_sqlite_handle *, const char *, void **);
-static int table_sqlite_credentials(struct table_sqlite_handle *, const char *, void **);
-static int table_sqlite_netaddr(struct table_sqlite_handle *, const char *, void **);
+static int table_sqlite_alias(struct table_sqlite_handle *, const char *, union lookup *);
+static int table_sqlite_domain(struct table_sqlite_handle *, const char *, union lookup *);
+static int table_sqlite_userinfo(struct table_sqlite_handle *, const char *, union lookup *);
+static int table_sqlite_credentials(struct table_sqlite_handle *, const char *, union lookup *);
+static int table_sqlite_netaddr(struct table_sqlite_handle *, const char *, union lookup *);
static int
-table_sqlite_config(struct table *table, const char *config)
+table_sqlite_config(struct table *table)
{
- void *cfg;
+ struct table *cfg;
/* no config ? broken */
- if (config == NULL)
+ if (table->t_config[0] == '\0')
return 0;
- cfg = table_config_create();
- if (! table_config_parse(cfg, config, T_HASH))
+ cfg = table_create("static", table->t_name, "conf", table->t_config);
+ if (!table_config(cfg))
goto err;
/* sanity checks */
- if (table_config_get(cfg, "dbpath") == NULL) {
+ if (table_get(cfg, "dbpath") == NULL) {
log_warnx("table_sqlite: missing 'dbpath' configuration");
return 0;
}
- table_set_configuration(table, cfg);
return 1;
err:
- table_config_destroy(cfg);
+ table_destroy(cfg);
return 0;
}
@@ -101,13 +99,13 @@ static void *
table_sqlite_open(struct table *table)
{
struct table_sqlite_handle *tsh;
- void *cfg;
+ struct table *cfg;
const char *dbpath;
tsh = xcalloc(1, sizeof *tsh, "table_sqlite_open");
tsh->table = table;
- cfg = table_get_configuration(table);
+ cfg = table_find(table->t_name, "conf");
dbpath = table_get(cfg, "dbpath");
if (sqlite3_open(dbpath, &tsh->ppDb) != SQLITE_OK) {
@@ -127,21 +125,21 @@ table_sqlite_close(void *hdl)
static int
table_sqlite_lookup(void *hdl, const char *key, enum table_service service,
- void **retp)
+ union lookup *lk)
{
struct table_sqlite_handle *tsh = hdl;
switch (service) {
case K_ALIAS:
- return table_sqlite_alias(tsh, key, retp);
+ return table_sqlite_alias(tsh, key, lk);
case K_DOMAIN:
- return table_sqlite_domain(tsh, key, retp);
+ return table_sqlite_domain(tsh, key, lk);
case K_USERINFO:
- return table_sqlite_userinfo(tsh, key, retp);
+ return table_sqlite_userinfo(tsh, key, lk);
case K_CREDENTIALS:
- return table_sqlite_credentials(tsh, key, retp);
+ return table_sqlite_credentials(tsh, key, lk);
case K_NETADDR:
- return table_sqlite_netaddr(tsh, key, retp);
+ return table_sqlite_netaddr(tsh, key, lk);
default:
log_warnx("table_sqlite: lookup: unsupported lookup service");
return -1;
@@ -151,13 +149,12 @@ table_sqlite_lookup(void *hdl, const char *key, enum table_service service,
}
static int
-table_sqlite_alias(struct table_sqlite_handle *tsh, const char *key, void **retp)
+table_sqlite_alias(struct table_sqlite_handle *tsh, const char *key, union lookup *lk)
{
- struct table *cfg = table_get_configuration(tsh->table);
+ struct table *cfg = table_find(tsh->table->t_name, "conf");
const char *query = table_get(cfg, "query_alias");
sqlite3_stmt *stmt;
- struct expand *xp = NULL;
struct expandnode xn;
int nrows;
@@ -177,43 +174,38 @@ table_sqlite_alias(struct table_sqlite_handle *tsh, const char *key, void **retp
return -1;
}
- if (retp)
- xp = xcalloc(1, sizeof *xp, "table_sqlite_alias");
+ if (lk)
+ lk->expand = xcalloc(1, sizeof(*lk->expand), "table_sqlite_alias");
nrows = 0;
sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
while (sqlite3_step(stmt) == SQLITE_ROW) {
- if (retp == NULL) {
+ if (lk == NULL) {
sqlite3_finalize(stmt);
return 1;
}
if (! text_to_expandnode(&xn, sqlite3_column_text(stmt, 0)))
goto error;
- expand_insert(xp, &xn);
+ expand_insert(lk->expand, &xn);
nrows++;
}
sqlite3_finalize(stmt);
- if (retp)
- *retp = xp;
return nrows ? 1 : 0;
error:
- if (retp)
- *retp = NULL;
- if (xp)
- expand_free(xp);
+ if (lk && lk->expand)
+ expand_free(lk->expand);
return -1;
}
static int
-table_sqlite_domain(struct table_sqlite_handle *tsh, const char *key, void **retp)
+table_sqlite_domain(struct table_sqlite_handle *tsh, const char *key, union lookup *lk)
{
- struct table *cfg = table_get_configuration(tsh->table);
+ struct table *cfg = table_find(tsh->table->t_name, "conf");
const char *query = table_get(cfg, "query_domain");
sqlite3_stmt *stmt;
- struct destination *domain = NULL;
if (query == NULL) {
log_warnx("table_sqlite: lookup: no query configured for domain");
@@ -235,11 +227,8 @@ table_sqlite_domain(struct table_sqlite_handle *tsh, const char *key, void **ret
switch (sqlite3_step(stmt)) {
case SQLITE_ROW:
- if (retp) {
- domain = xcalloc(1, sizeof *domain, "table_sqlite_domain");
- strlcpy(domain->name, sqlite3_column_text(stmt, 0), sizeof domain->name);
- *retp = domain;
- }
+ if (lk)
+ strlcpy(lk->domain.name, sqlite3_column_text(stmt, 0), sizeof(lk->domain.name));
sqlite3_finalize(stmt);
return 1;
@@ -251,19 +240,15 @@ table_sqlite_domain(struct table_sqlite_handle *tsh, const char *key, void **ret
sqlite3_finalize(stmt);
}
- free(domain);
- if (retp)
- *retp = NULL;
return -1;
}
static int
-table_sqlite_userinfo(struct table_sqlite_handle *tsh, const char *key, void **retp)
+table_sqlite_userinfo(struct table_sqlite_handle *tsh, const char *key, union lookup *lk)
{
- struct table *cfg = table_get_configuration(tsh->table);
+ struct table *cfg = table_find(tsh->table->t_name, "conf");
const char *query = table_get(cfg, "query_userinfo");
sqlite3_stmt *stmt;
- struct userinfo *userinfo = NULL;
size_t s;
if (query == NULL) {
@@ -286,19 +271,17 @@ table_sqlite_userinfo(struct table_sqlite_handle *tsh, const char *key, void **r
switch (sqlite3_step(stmt)) {
case SQLITE_ROW:
- if (retp) {
- userinfo = xcalloc(1, sizeof *userinfo, "table_sqlite_userinfo");
- s = strlcpy(userinfo->username, sqlite3_column_text(stmt, 0),
- sizeof(userinfo->username));
- if (s >= sizeof(userinfo->username))
+ if (lk) {
+ s = strlcpy(lk->userinfo.username, sqlite3_column_text(stmt, 0),
+ sizeof(lk->userinfo.username));
+ if (s >= sizeof(lk->userinfo.username))
goto error;
- userinfo->uid = sqlite3_column_int(stmt, 1);
- userinfo->gid = sqlite3_column_int(stmt, 2);
- s = strlcpy(userinfo->directory, sqlite3_column_text(stmt, 3),
- sizeof(userinfo->directory));
- if (s >= sizeof(userinfo->directory))
+ lk->userinfo.uid = sqlite3_column_int(stmt, 1);
+ lk->userinfo.gid = sqlite3_column_int(stmt, 2);
+ s = strlcpy(lk->userinfo.directory, sqlite3_column_text(stmt, 3),
+ sizeof(lk->userinfo.directory));
+ if (s >= sizeof(lk->userinfo.directory))
goto error;
- *retp = userinfo;
}
sqlite3_finalize(stmt);
return 1;
@@ -313,19 +296,15 @@ table_sqlite_userinfo(struct table_sqlite_handle *tsh, const char *key, void **r
error:
sqlite3_finalize(stmt);
- free(userinfo);
- if (retp)
- *retp = NULL;
return -1;
}
static int
-table_sqlite_credentials(struct table_sqlite_handle *tsh, const char *key, void **retp)
+table_sqlite_credentials(struct table_sqlite_handle *tsh, const char *key, union lookup *lk)
{
- struct table *cfg = table_get_configuration(tsh->table);
+ struct table *cfg = table_find(tsh->table->t_name, "conf");
const char *query = table_get(cfg, "query_credentials");
sqlite3_stmt *stmt;
- struct credentials *creds = NULL;
size_t s;
if (query == NULL) {
@@ -347,17 +326,15 @@ table_sqlite_credentials(struct table_sqlite_handle *tsh, const char *key, void
sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
switch (sqlite3_step(stmt)) {
case SQLITE_ROW:
- if (retp) {
- creds = xcalloc(1, sizeof *creds, "table_sqlite_credentials");
- s = strlcpy(creds->username, sqlite3_column_text(stmt, 0),
- sizeof(creds->username));
- if (s >= sizeof(creds->username))
+ if (lk) {
+ s = strlcpy(lk->creds.username, sqlite3_column_text(stmt, 0),
+ sizeof(lk->creds.username));
+ if (s >= sizeof(lk->creds.username))
goto error;
- s = strlcpy(creds->password, sqlite3_column_text(stmt, 1),
- sizeof(creds->password));
- if (s >= sizeof(creds->password))
+ s = strlcpy(lk->creds.password, sqlite3_column_text(stmt, 1),
+ sizeof(lk->creds.password));
+ if (s >= sizeof(lk->creds.password))
goto error;
- *retp = creds;
}
sqlite3_finalize(stmt);
return 1;
@@ -372,20 +349,16 @@ table_sqlite_credentials(struct table_sqlite_handle *tsh, const char *key, void
error:
sqlite3_finalize(stmt);
- free(creds);
- if (retp)
- *retp = NULL;
return -1;
}
static int
-table_sqlite_netaddr(struct table_sqlite_handle *tsh, const char *key, void **retp)
+table_sqlite_netaddr(struct table_sqlite_handle *tsh, const char *key, union lookup *lk)
{
- struct table *cfg = table_get_configuration(tsh->table);
+ struct table *cfg = table_find(tsh->table->t_name, "conf");
const char *query = table_get(cfg, "query_netaddr");
sqlite3_stmt *stmt;
- struct netaddr *netaddr = NULL;
if (query == NULL) {
log_warnx("table_sqlite: lookup: no query configured for netaddr");
@@ -406,11 +379,9 @@ table_sqlite_netaddr(struct table_sqlite_handle *tsh, const char *key, void **re
sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
switch (sqlite3_step(stmt)) {
case SQLITE_ROW:
- if (retp) {
- netaddr = xcalloc(1, sizeof *netaddr, "table_sqlite_netaddr");
- if (! text_to_netaddr(netaddr, sqlite3_column_text(stmt, 0)))
+ if (lk) {
+ if (! text_to_netaddr(&lk->netaddr, sqlite3_column_text(stmt, 0)))
goto error;
- *retp = netaddr;
}
sqlite3_finalize(stmt);
return 1;
@@ -425,8 +396,5 @@ table_sqlite_netaddr(struct table_sqlite_handle *tsh, const char *key, void **re
error:
sqlite3_finalize(stmt);
- free(netaddr);
- if (retp)
- *retp = NULL;
return -1;
}
diff --git a/usr.sbin/smtpd/table_static.c b/usr.sbin/smtpd/table_static.c
index cd77677ab02..9fe1ceae9f9 100644
--- a/usr.sbin/smtpd/table_static.c
+++ b/usr.sbin/smtpd/table_static.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: table_static.c,v 1.4 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: table_static.c,v 1.5 2013/05/24 17:03:14 eric Exp $ */
/*
+ * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -19,7 +20,6 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -38,22 +38,14 @@
#include "log.h"
/* static backend */
-static int table_static_config(struct table *, const char *);
+static int table_static_config(struct table *);
static int table_static_update(struct table *);
static void *table_static_open(struct table *);
static int table_static_lookup(void *, const char *, enum table_service,
- void **);
-static int table_static_fetch(void *, enum table_service, char **);
+ union lookup *);
+static int table_static_fetch(void *, enum table_service, union lookup *);
static void table_static_close(void *);
-
-static int table_static_credentials(const char *, char *, size_t, void **);
-static int table_static_alias(const char *, char *, size_t, void **);
-static int table_static_domain(const char *, char *, size_t, void **);
-static int table_static_netaddr(const char *, char *, size_t, void **);
-static int table_static_source(const char *, char *, size_t, void **);
-static int table_static_userinfo(const char *, char *, size_t, void **);
-static int table_static_mailaddr(const char *, char *, size_t, void **);
-static int table_static_addrname(const char *, char *, size_t, void **);
+static int table_static_parse(struct table *, const char *, enum table_type);
struct table_backend table_backend_static = {
K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_NETADDR|K_USERINFO|K_SOURCE|K_MAILADDR|K_ADDRNAME,
@@ -76,30 +68,99 @@ static struct keycmp {
static int
-table_static_config(struct table *table, const char *config)
+table_static_config(struct table *table)
{
/* no config ? ok */
- if (config == NULL)
+ if (*table->t_config == '\0')
return 1;
- return table_config_parse(table, config, T_LIST|T_HASH);
+ return table_static_parse(table, table->t_config, T_LIST|T_HASH);
+}
+
+static int
+table_static_parse(struct table *t, const char *config, enum table_type type)
+{
+ FILE *fp;
+ char *buf, *lbuf;
+ size_t flen;
+ char *keyp;
+ char *valp;
+ size_t ret = 0;
+
+ fp = fopen(config, "r");
+ if (fp == NULL)
+ return 0;
+
+ lbuf = NULL;
+ while ((buf = fgetln(fp, &flen))) {
+ if (buf[flen - 1] == '\n')
+ buf[flen - 1] = '\0';
+ else {
+ lbuf = xmalloc(flen + 1, "table_config_parse");
+ memcpy(lbuf, buf, flen);
+ lbuf[flen] = '\0';
+ buf = lbuf;
+ }
+
+ keyp = buf;
+ while (isspace((int)*keyp))
+ ++keyp;
+ if (*keyp == '\0' || *keyp == '#')
+ continue;
+ valp = keyp;
+ strsep(&valp, " \t:");
+ if (valp) {
+ while (*valp) {
+ if (!isspace(*valp) &&
+ !(*valp == ':' && isspace(*(valp + 1))))
+ break;
+ ++valp;
+ }
+ if (*valp == '\0')
+ valp = NULL;
+ }
+
+ /**/
+ if (t->t_type == 0)
+ t->t_type = (valp == keyp || valp == NULL) ? T_LIST :
+ T_HASH;
+
+ if (!(t->t_type & type))
+ goto end;
+
+ if ((valp == keyp || valp == NULL) && t->t_type == T_LIST)
+ table_add(t, keyp, NULL);
+ else if ((valp != keyp && valp != NULL) && t->t_type == T_HASH)
+ table_add(t, keyp, valp);
+ else
+ goto end;
+ }
+ ret = 1;
+end:
+ free(lbuf);
+ fclose(fp);
+ return ret;
}
static int
table_static_update(struct table *table)
{
- struct table *t;
+ struct table *t;
+ void *p = NULL;
/* no config ? ok */
if (table->t_config[0] == '\0')
goto ok;
- t = table_create(table->t_src, NULL, table->t_config);
- if (! t->t_backend->config(t, table->t_config))
+ t = table_create("static", table->t_name, "update", table->t_config);
+ if (!table_config(t))
goto err;
/* replace former table, frees t */
- table_replace(table, t);
+ while (dict_poproot(&table->t_dict, NULL, (void **)&p))
+ free(p);
+ dict_merge(&table->t_dict, &t->t_dict);
+ table_destroy(t);
ok:
log_info("info: Table \"%s\" successfully updated", table->t_name);
@@ -125,11 +186,10 @@ table_static_close(void *hdl)
static int
table_static_lookup(void *hdl, const char *key, enum table_service service,
- void **retp)
+ union lookup *lk)
{
struct table *m = hdl;
char *line;
- size_t len;
int ret;
int (*match)(const char *, const char *) = NULL;
size_t i;
@@ -161,65 +221,20 @@ table_static_lookup(void *hdl, const char *key, enum table_service service,
break;
}
- if (retp == NULL)
+ if (lk == NULL)
return ret ? 1 : 0;
- if (ret == 0) {
- *retp = NULL;
+ if (ret == 0)
return 0;
- }
-
- if ((line = strdup(line)) == NULL)
- return -1;
- len = strlen(line);
- switch (service) {
- case K_ALIAS:
- ret = table_static_alias(key, line, len, retp);
- break;
-
- case K_CREDENTIALS:
- ret = table_static_credentials(key, line, len, retp);
- break;
-
- case K_DOMAIN:
- ret = table_static_domain(key, line, len, retp);
- break;
-
- case K_NETADDR:
- ret = table_static_netaddr(key, line, len, retp);
- break;
-
- case K_SOURCE:
- ret = table_static_source(key, line, len, retp);
- break;
-
- case K_USERINFO:
- ret = table_static_userinfo(key, line, len, retp);
- break;
-
- case K_MAILADDR:
- ret = table_static_mailaddr(key, line, len, retp);
- break;
-
- case K_ADDRNAME:
- ret = table_static_addrname(key, line, len, retp);
- break;
- default:
- ret = -1;
- }
-
- free(line);
-
- return ret;
+ return table_parse_lookup(service, key, line, lk);
}
static int
-table_static_fetch(void *hdl, enum table_service service, char **retp)
+table_static_fetch(void *hdl, enum table_service service, union lookup *lk)
{
struct table *t = hdl;
const char *k;
- char *line;
if (! dict_iter(&t->t_dict, &t->t_iter, &k, (void **)NULL)) {
t->t_iter = NULL;
@@ -227,185 +242,8 @@ table_static_fetch(void *hdl, enum table_service service, char **retp)
return 0;
}
- if (retp == NULL)
+ if (lk == NULL)
return 1;
- if ((line = strdup(k)) == NULL)
- return -1;
-
- *retp = line;
-
- return 1;
-}
-
-static int
-table_static_credentials(const char *key, char *line, size_t len, void **retp)
-{
- struct credentials *creds;
- char *p;
-
- /* credentials are stored as user:password */
- if (len < 3)
- return -1;
-
- /* too big to fit in a smtp session line */
- if (len >= SMTPD_MAXLINESIZE)
- return -1;
-
- p = strchr(line, ':');
- if (p == NULL)
- return -1;
-
- if (p == line || p == line + len - 1)
- return -1;
- *p++ = '\0';
-
- creds = xcalloc(1, sizeof *creds, "table_static_credentials");
- if (strlcpy(creds->username, line, sizeof(creds->username))
- >= sizeof(creds->username))
- goto err;
-
- if (strlcpy(creds->password, p, sizeof(creds->password))
- >= sizeof(creds->password))
- goto err;
-
- *retp = creds;
- return 1;
-
-err:
- *retp = NULL;
- free(creds);
- return -1;
-}
-
-static int
-table_static_alias(const char *key, char *line, size_t len, void **retp)
-{
- struct expand *xp;
-
- xp = xcalloc(1, sizeof *xp, "table_static_alias");
- if (! expand_line(xp, line, 1))
- goto error;
- *retp = xp;
- return 1;
-
-error:
- *retp = NULL;
- expand_free(xp);
- return -1;
-}
-
-static int
-table_static_netaddr(const char *key, char *line, size_t len, void **retp)
-{
- struct netaddr *netaddr;
-
- netaddr = xcalloc(1, sizeof *netaddr, "table_static_netaddr");
- if (! text_to_netaddr(netaddr, line))
- goto error;
- *retp = netaddr;
- return 1;
-
-error:
- *retp = NULL;
- free(netaddr);
- return -1;
-}
-
-static int
-table_static_source(const char *key, char *line, size_t len, void **retp)
-{
- struct source *source = NULL;
-
- source = xcalloc(1, sizeof *source, "table_static_source");
- if (inet_pton(AF_INET6, line, &source->addr.in6) != 1)
- if (inet_pton(AF_INET, line, &source->addr.in4) != 1)
- goto error;
- *retp = source;
- return 1;
-
-error:
- *retp = NULL;
- free(source);
- return 0;
-}
-
-static int
-table_static_domain(const char *key, char *line, size_t len, void **retp)
-{
- struct destination *destination;
-
- destination = xcalloc(1, sizeof *destination, "table_static_domain");
- if (strlcpy(destination->name, line, sizeof destination->name)
- >= sizeof destination->name)
- goto error;
- *retp = destination;
- return 1;
-
-error:
- *retp = NULL;
- free(destination);
- return -1;
-}
-
-static int
-table_static_userinfo(const char *key, char *line, size_t len, void **retp)
-{
- struct userinfo *userinfo = NULL;
- char buffer[1024];
-
- if (! bsnprintf(buffer, sizeof buffer, "%s:%s", key, line))
- goto error;
-
- userinfo = xcalloc(1, sizeof *userinfo, "table_static_userinfo");
- if (! text_to_userinfo(userinfo, buffer))
- goto error;
- *retp = userinfo;
- return 1;
-
-error:
- *retp = NULL;
- free(userinfo);
- return -1;
-}
-
-static int
-table_static_mailaddr(const char *key, char *line, size_t len, void **retp)
-{
- struct mailaddr *mailaddr;
-
- mailaddr = xcalloc(1, sizeof *mailaddr, "table_static_mailaddr");
- if (! text_to_mailaddr(mailaddr, line))
- goto error;
- *retp = mailaddr;
- return 1;
-
-error:
- *retp = NULL;
- free(mailaddr);
- return -1;
-}
-
-static int
-table_static_addrname(const char *key, char *line, size_t len, void **retp)
-{
- struct addrname *addrname;
-
- addrname = xcalloc(1, sizeof *addrname, "table_static_addrname");
-
- if (inet_pton(AF_INET6, key, &addrname->addr.in6) != 1)
- if (inet_pton(AF_INET, key, &addrname->addr.in4) != 1)
- goto error;
-
- if (strlcpy(addrname->name, line, sizeof addrname->name)
- >= sizeof addrname->name)
- goto error;
-
- *retp = addrname;
- return 1;
-
-error:
- *retp = NULL;
- free(addrname);
- return -1;
+ return table_parse_lookup(service, NULL, k, lk);
}
diff --git a/usr.sbin/smtpd/to.c b/usr.sbin/smtpd/to.c
index 0d23103c395..862c25af45d 100644
--- a/usr.sbin/smtpd/to.c
+++ b/usr.sbin/smtpd/to.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: to.c,v 1.6 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: to.c,v 1.7 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
@@ -19,7 +19,6 @@
*/
#include <sys/types.h>
-#include <sys/param.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/socket.h>
@@ -56,6 +55,7 @@ static int alias_is_username(struct expandnode *, const char *, size_t);
static int alias_is_address(struct expandnode *, const char *, size_t);
static int alias_is_filename(struct expandnode *, const char *, size_t);
static int alias_is_include(struct expandnode *, const char *, size_t);
+static int alias_is_error(struct expandnode *, const char *, size_t);
const char *
sockaddr_to_text(struct sockaddr *sa)
@@ -270,7 +270,7 @@ text_to_netaddr(struct netaddr *netaddr, const char *s)
bzero(&ssin, sizeof(struct sockaddr_in));
bzero(&ssin6, sizeof(struct sockaddr_in6));
- if (strncmp("IPv6:", s, 5) == 0)
+ if (strncasecmp("IPv6:", s, 5) == 0)
s += 5;
if (strchr(s, '/') != NULL) {
@@ -571,6 +571,11 @@ rule_to_text(struct rule *r)
strlcat(buf, r->r_value.buffer, sizeof buf);
strlcat(buf, "\"", sizeof buf);
break;
+ case A_LMTP:
+ strlcat(buf, " deliver to lmtp \"", sizeof buf);
+ strlcat(buf, r->r_value.buffer, sizeof buf);
+ strlcat(buf, "\"", sizeof buf);
+ break;
}
return buf;
@@ -579,7 +584,7 @@ rule_to_text(struct rule *r)
int
text_to_userinfo(struct userinfo *userinfo, const char *s)
{
- char buf[MAXPATHLEN];
+ char buf[SMTPD_MAXPATHLEN];
char *p;
const char *errstr;
@@ -664,7 +669,8 @@ text_to_expandnode(struct expandnode *expandnode, const char *s)
size_t l;
l = strlen(s);
- if (alias_is_include(expandnode, s, l) ||
+ if (alias_is_error(expandnode, s, l) ||
+ alias_is_include(expandnode, s, l) ||
alias_is_filter(expandnode, s, l) ||
alias_is_filename(expandnode, s, l) ||
alias_is_address(expandnode, s, l) ||
@@ -681,6 +687,7 @@ expandnode_to_text(struct expandnode *expandnode)
case EXPAND_FILTER:
case EXPAND_FILENAME:
case EXPAND_INCLUDE:
+ case EXPAND_ERROR:
return expandnode->u.buffer;
case EXPAND_USERNAME:
return expandnode->u.user;
@@ -807,3 +814,34 @@ alias_is_include(struct expandnode *alias, const char *line, size_t len)
alias->type = EXPAND_INCLUDE;
return 1;
}
+
+static int
+alias_is_error(struct expandnode *alias, const char *line, size_t len)
+{
+ size_t skip;
+
+ bzero(alias, sizeof *alias);
+
+ if (strncasecmp(":error:", line, 7) == 0)
+ skip = 7;
+ else if (strncasecmp("error:", line, 6) == 0)
+ skip = 6;
+ else
+ return 0;
+
+ if (strlcpy(alias->u.buffer, line + skip,
+ sizeof(alias->u.buffer)) >= sizeof(alias->u.buffer))
+ return 0;
+
+ if (strlen(alias->u.buffer) < 5)
+ return 0;
+
+ /* [45][0-9]{2} [a-zA-Z0-9].* */
+ if (alias->u.buffer[3] != ' ' || !isalnum(alias->u.buffer[4]) ||
+ (alias->u.buffer[0] != '4' && alias->u.buffer[0] != '5') ||
+ !isdigit(alias->u.buffer[1]) || !isdigit(alias->u.buffer[2]))
+ return 0;
+
+ alias->type = EXPAND_ERROR;
+ return 1;
+}
diff --git a/usr.sbin/smtpd/tree.c b/usr.sbin/smtpd/tree.c
index e972839b6ee..796b1f26721 100644
--- a/usr.sbin/smtpd/tree.c
+++ b/usr.sbin/smtpd/tree.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tree.c,v 1.3 2013/01/26 09:37:24 gilles Exp $ */
+/* $OpenBSD: tree.c,v 1.4 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
@@ -38,7 +38,7 @@ struct treeentry {
static int treeentry_cmp(struct treeentry *, struct treeentry *);
-SPLAY_PROTOTYPE(tree, treeentry, entry, treeentry_cmp);
+SPLAY_PROTOTYPE(_tree, treeentry, entry, treeentry_cmp);
int
tree_check(struct tree *t, uint64_t id)
@@ -46,7 +46,7 @@ tree_check(struct tree *t, uint64_t id)
struct treeentry key;
key.id = id;
- return (SPLAY_FIND(tree, t, &key) != NULL);
+ return (SPLAY_FIND(_tree, &t->tree, &key) != NULL);
}
void *
@@ -56,11 +56,13 @@ tree_set(struct tree *t, uint64_t id, void *data)
char *old;
key.id = id;
- if ((entry = SPLAY_FIND(tree, t, &key)) == NULL) {
- entry = xmalloc(sizeof *entry, "tree_set");
+ if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL) {
+ if ((entry = malloc(sizeof *entry)) == NULL)
+ err(1, "tree_set: malloc");
entry->id = id;
- SPLAY_INSERT(tree, t, entry);
+ SPLAY_INSERT(_tree, &t->tree, entry);
old = NULL;
+ t->count += 1;
} else
old = entry->data;
@@ -74,11 +76,13 @@ tree_xset(struct tree *t, uint64_t id, void *data)
{
struct treeentry *entry;
- entry = xmalloc(sizeof *entry, "tree_xset");
+ if ((entry = malloc(sizeof *entry)) == NULL)
+ err(1, "tree_xset: malloc");
entry->id = id;
entry->data = data;
- if (SPLAY_INSERT(tree, t, entry))
+ if (SPLAY_INSERT(_tree, &t->tree, entry))
errx(1, "tree_xset(%p, 0x%016"PRIx64 ")", t, id);
+ t->count += 1;
}
void *
@@ -87,7 +91,7 @@ tree_get(struct tree *t, uint64_t id)
struct treeentry key, *entry;
key.id = id;
- if ((entry = SPLAY_FIND(tree, t, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
return (NULL);
return (entry->data);
@@ -99,7 +103,7 @@ tree_xget(struct tree *t, uint64_t id)
struct treeentry key, *entry;
key.id = id;
- if ((entry = SPLAY_FIND(tree, t, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
errx(1, "tree_get(%p, 0x%016"PRIx64 ")", t, id);
return (entry->data);
@@ -112,12 +116,13 @@ tree_pop(struct tree *t, uint64_t id)
void *data;
key.id = id;
- if ((entry = SPLAY_FIND(tree, t, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
return (NULL);
data = entry->data;
- SPLAY_REMOVE(tree, t, entry);
+ SPLAY_REMOVE(_tree, &t->tree, entry);
free(entry);
+ t->count -= 1;
return (data);
}
@@ -129,12 +134,13 @@ tree_xpop(struct tree *t, uint64_t id)
void *data;
key.id = id;
- if ((entry = SPLAY_FIND(tree, t, &key)) == NULL)
+ if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
errx(1, "tree_xpop(%p, 0x%016" PRIx64 ")", t, id);
data = entry->data;
- SPLAY_REMOVE(tree, t, entry);
+ SPLAY_REMOVE(_tree, &t->tree, entry);
free(entry);
+ t->count -= 1;
return (data);
}
@@ -144,15 +150,17 @@ tree_poproot(struct tree *t, uint64_t *id, void **data)
{
struct treeentry *entry;
- entry = SPLAY_ROOT(t);
+ entry = SPLAY_ROOT(&t->tree);
if (entry == NULL)
return (0);
if (id)
*id = entry->id;
if (data)
*data = entry->data;
- SPLAY_REMOVE(tree, t, entry);
+ SPLAY_REMOVE(_tree, &t->tree, entry);
free(entry);
+ t->count -= 1;
+
return (1);
}
@@ -161,7 +169,7 @@ tree_root(struct tree *t, uint64_t *id, void **data)
{
struct treeentry *entry;
- entry = SPLAY_ROOT(t);
+ entry = SPLAY_ROOT(&t->tree);
if (entry == NULL)
return (0);
if (id)
@@ -177,9 +185,9 @@ tree_iter(struct tree *t, void **hdl, uint64_t *id, void **data)
struct treeentry *curr = *hdl;
if (curr == NULL)
- curr = SPLAY_MIN(tree, t);
+ curr = SPLAY_MIN(_tree, &t->tree);
else
- curr = SPLAY_NEXT(tree, t, curr);
+ curr = SPLAY_NEXT(_tree, &t->tree, curr);
if (curr) {
*hdl = curr;
@@ -200,18 +208,18 @@ tree_iterfrom(struct tree *t, void **hdl, uint64_t k, uint64_t *id, void **data)
if (curr == NULL) {
if (k == 0)
- curr = SPLAY_MIN(tree, t);
+ curr = SPLAY_MIN(_tree, &t->tree);
else {
key.id = k;
- curr = SPLAY_FIND(tree, t, &key);
+ curr = SPLAY_FIND(_tree, &t->tree, &key);
if (curr == NULL) {
- SPLAY_INSERT(tree, t, &key);
- curr = SPLAY_NEXT(tree, t, &key);
- SPLAY_REMOVE(tree, t, &key);
+ SPLAY_INSERT(_tree, &t->tree, &key);
+ curr = SPLAY_NEXT(_tree, &t->tree, &key);
+ SPLAY_REMOVE(_tree, &t->tree, &key);
}
}
} else
- curr = SPLAY_NEXT(tree, t, curr);
+ curr = SPLAY_NEXT(_tree, &t->tree, curr);
if (curr) {
*hdl = curr;
@@ -230,12 +238,14 @@ tree_merge(struct tree *dst, struct tree *src)
{
struct treeentry *entry;
- while (!SPLAY_EMPTY(src)) {
- entry = SPLAY_ROOT(src);
- SPLAY_REMOVE(tree, src, entry);
- if (SPLAY_INSERT(tree, dst, entry))
+ while (!SPLAY_EMPTY(&src->tree)) {
+ entry = SPLAY_ROOT(&src->tree);
+ SPLAY_REMOVE(_tree, &src->tree, entry);
+ if (SPLAY_INSERT(_tree, &dst->tree, entry))
errx(1, "tree_merge: duplicate");
}
+ dst->count += src->count;
+ src->count = 0;
}
static int
@@ -248,4 +258,4 @@ treeentry_cmp(struct treeentry *a, struct treeentry *b)
return (0);
}
-SPLAY_GENERATE(tree, treeentry, entry, treeentry_cmp);
+SPLAY_GENERATE(_tree, treeentry, entry, treeentry_cmp);
diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c
index 93c7aff31b0..97078c766db 100644
--- a/usr.sbin/smtpd/util.c
+++ b/usr.sbin/smtpd/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.93 2013/04/12 18:22:49 eric Exp $ */
+/* $OpenBSD: util.c,v 1.94 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2000,2001 Markus Friedl. All rights reserved.
@@ -20,7 +20,6 @@
*/
#include <sys/types.h>
-#include <sys/param.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/socket.h>
@@ -175,7 +174,7 @@ mkdirs_component(char *path, mode_t mode)
int
mkdirs(char *path, mode_t mode)
{
- char buf[MAXPATHLEN];
+ char buf[SMTPD_MAXPATHLEN];
int i = 0;
int done = 0;
char *p;
@@ -184,7 +183,7 @@ mkdirs(char *path, mode_t mode)
if (*path != '/')
return 0;
- /* make sure we don't exceed MAXPATHLEN */
+ /* make sure we don't exceed SMTPD_MAXPATHLEN */
if (strlen(path) >= sizeof buf)
return 0;
@@ -333,7 +332,7 @@ mvpurge(char *from, char *to)
size_t n;
int retry;
const char *sep;
- char buf[MAXPATHLEN];
+ char buf[SMTPD_MAXPATHLEN];
if ((n = strlen(to)) == 0)
fatalx("to is empty");
@@ -341,7 +340,7 @@ mvpurge(char *from, char *to)
sep = (to[n - 1] == '/') ? "" : "/";
retry = 0;
- again:
+again:
snprintf(buf, sizeof buf, "%s%s%u", to, sep, arc4random());
if (rename(from, buf) == -1) {
/* ENOTDIR has actually 2 meanings, and incorrect input
@@ -363,12 +362,12 @@ mvpurge(char *from, char *to)
int
mktmpfile(void)
{
- char path[MAXPATHLEN];
+ char path[SMTPD_MAXPATHLEN];
int fd;
mode_t omode;
if (! bsnprintf(path, sizeof(path), "%s/smtpd.XXXXXXXXXX",
- PATH_TEMPORARY))
+ PATH_TEMPORARY))
err(1, "snprintf");
omode = umask(7077);
@@ -454,25 +453,32 @@ valid_domainpart(const char *s)
{
struct in_addr ina;
struct in6_addr ina6;
- char *c, domain[MAX_DOMAINPART_SIZE];
+ char *c, domain[SMTPD_MAXDOMAINPARTSIZE];
+ const char *p;
if (*s == '[') {
- strlcpy(domain, s + 1, sizeof domain);
+ if (strncasecmp("[IPv6:", s, 6) == 0)
+ p = s + 6;
+ else
+ p = s + 1;
+
+ if (strlcpy(domain, p, sizeof domain) >= sizeof domain)
+ return 0;
c = strchr(domain, (int)']');
if (!c || c[1] != '\0')
return 0;
-
+
*c = '\0';
-
+
if (inet_pton(AF_INET6, domain, &ina6) == 1)
return 1;
if (inet_pton(AF_INET, domain, &ina) == 1)
return 1;
-
+
return 0;
}
-
+
nextsub:
if (!isalnum((int)*s))
return 0;
@@ -492,15 +498,14 @@ nextsub:
return 1;
}
-
/*
* Check file for security. Based on usr.bin/ssh/auth.c.
*/
int
secure_file(int fd, char *path, char *userdir, uid_t uid, int mayread)
{
- char buf[MAXPATHLEN];
- char homedir[MAXPATHLEN];
+ char buf[PATH_MAX];
+ char homedir[PATH_MAX];
struct stat st;
char *cp;
diff --git a/usr.sbin/smtpd/waitq.c b/usr.sbin/smtpd/waitq.c
index 9adbaa986cd..09793624941 100644
--- a/usr.sbin/smtpd/waitq.c
+++ b/usr.sbin/smtpd/waitq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: waitq.c,v 1.3 2013/01/26 09:37:24 gilles Exp $ */
+/* $OpenBSD: waitq.c,v 1.4 2013/05/24 17:03:14 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
@@ -17,8 +17,8 @@
*/
#include <sys/types.h>
-#include <sys/tree.h>
#include <sys/queue.h>
+#include <sys/tree.h>
#include <sys/uio.h>
#include <imsg.h>