summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/control.c23
-rw-r--r--usr.sbin/smtpd/lka.c84
-rw-r--r--usr.sbin/smtpd/mfa.c84
-rw-r--r--usr.sbin/smtpd/parse.y4
-rw-r--r--usr.sbin/smtpd/smtp.c21
-rw-r--r--usr.sbin/smtpd/smtp_session.c26
-rw-r--r--usr.sbin/smtpd/smtpd.c54
-rw-r--r--usr.sbin/smtpd/smtpd.h15
8 files changed, 293 insertions, 18 deletions
diff --git a/usr.sbin/smtpd/control.c b/usr.sbin/smtpd/control.c
index 8085c8a13e8..0eaf0e72757 100644
--- a/usr.sbin/smtpd/control.c
+++ b/usr.sbin/smtpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.26 2009/05/19 11:24:24 jacekm Exp $ */
+/* $OpenBSD: control.c,v 1.27 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -352,6 +352,23 @@ control_dispatch_ext(int fd, short event, void *arg)
imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_RUNNER_SCHEDULE, 0, 0, -1, s, sizeof(*s));
break;
}
+ case IMSG_CONF_RELOAD:
+ log_debug("received reload request");
+
+ if (euid)
+ goto badcred;
+
+ if (env->sc_flags & SMTPD_CONFIGURING) {
+ imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
+ NULL, 0);
+ break;
+ }
+ env->sc_flags |= SMTPD_CONFIGURING;
+
+ imsg_compose(env->sc_ibufs[PROC_PARENT], IMSG_CONF_RELOAD, 0, 0, -1, NULL, 0);
+
+ imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
+ break;
case IMSG_CTL_SHUTDOWN:
/* NEEDS_FIX */
log_debug("received shutdown request");
@@ -503,6 +520,10 @@ control_dispatch_parent(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_CONF_RELOAD: {
+ env->sc_flags &= ~SMTPD_CONFIGURING;
+ break;
+ }
case IMSG_STATS: {
struct stats *s = imsg.data;
struct ctl_conn *c;
diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c
index 2a0ea909437..640e37560b2 100644
--- a/usr.sbin/smtpd/lka.c
+++ b/usr.sbin/smtpd/lka.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka.c,v 1.47 2009/05/19 11:24:24 jacekm Exp $ */
+/* $OpenBSD: lka.c,v 1.48 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -129,6 +129,86 @@ lka_dispatch_parent(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_CONF_START:
+ if ((env->sc_rules_reload = calloc(1, sizeof(*env->sc_rules))) == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ if ((env->sc_maps_reload = calloc(1, sizeof(*env->sc_maps))) == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ TAILQ_INIT(env->sc_rules_reload);
+ TAILQ_INIT(env->sc_maps_reload);
+ break;
+ case IMSG_CONF_RULE: {
+ struct rule *rule = imsg.data;
+
+ IMSG_SIZE_CHECK(rule);
+
+ rule = calloc(1, sizeof(*rule));
+ if (rule == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ *rule = *(struct rule *)imsg.data;
+
+ TAILQ_INSERT_TAIL(env->sc_rules_reload, rule, r_entry);
+ break;
+ }
+ case IMSG_CONF_CONDITION: {
+ struct rule *r = TAILQ_LAST(env->sc_rules_reload, rulelist);
+ struct cond *cond = imsg.data;
+
+ IMSG_SIZE_CHECK(cond);
+
+ cond = calloc(1, sizeof(*cond));
+ if (cond == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ *cond = *(struct cond *)imsg.data;
+
+ TAILQ_INSERT_TAIL(&r->r_conditions, cond, c_entry);
+ break;
+ }
+ case IMSG_CONF_MAP: {
+ struct map *m = imsg.data;
+
+ IMSG_SIZE_CHECK(m);
+
+ m = calloc(1, sizeof(*m));
+ if (m == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ *m = *(struct map *)imsg.data;
+
+ TAILQ_INSERT_TAIL(env->sc_maps_reload, m, m_entry);
+ break;
+ }
+ case IMSG_CONF_END: {
+ void *temp;
+ struct rule *r;
+ struct map *m;
+
+ /* switch and destroy old ruleset */
+ temp = env->sc_rules;
+ env->sc_rules = env->sc_rules_reload;
+ env->sc_rules_reload = temp;
+
+ temp = env->sc_maps;
+ env->sc_maps = env->sc_maps_reload;
+ env->sc_maps_reload = temp;
+
+ if (env->sc_rules_reload) {
+ TAILQ_FOREACH(r, env->sc_rules_reload, r_entry) {
+ free(r);
+ }
+ free(env->sc_rules_reload);
+ env->sc_rules_reload = NULL;
+ }
+
+ if (env->sc_maps_reload) {
+ TAILQ_FOREACH(m, env->sc_maps_reload, m_entry) {
+ free(m);
+ }
+ free(env->sc_maps_reload);
+ env->sc_maps_reload = NULL;
+ }
+
+ break;
+ }
case IMSG_PARENT_FORWARD_OPEN: {
int fd;
struct forward_req *fwreq = imsg.data;
@@ -600,7 +680,7 @@ lka(struct smtpd *env)
return (pid);
}
-// purge_config(env, PURGE_EVERYTHING);
+ purge_config(env, PURGE_EVERYTHING);
pw = env->sc_pw;
diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c
index 8114619dbd9..b88d4d0f746 100644
--- a/usr.sbin/smtpd/mfa.c
+++ b/usr.sbin/smtpd/mfa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa.c,v 1.26 2009/05/19 11:24:24 jacekm Exp $ */
+/* $OpenBSD: mfa.c,v 1.27 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -103,6 +103,86 @@ mfa_dispatch_parent(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_CONF_START:
+ if ((env->sc_rules_reload = calloc(1, sizeof(*env->sc_rules))) == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ if ((env->sc_maps_reload = calloc(1, sizeof(*env->sc_maps))) == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ TAILQ_INIT(env->sc_rules_reload);
+ TAILQ_INIT(env->sc_maps_reload);
+ break;
+ case IMSG_CONF_RULE: {
+ struct rule *rule = imsg.data;
+
+ IMSG_SIZE_CHECK(rule);
+
+ rule = calloc(1, sizeof(*rule));
+ if (rule == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ *rule = *(struct rule *)imsg.data;
+
+ TAILQ_INSERT_TAIL(env->sc_rules_reload, rule, r_entry);
+ break;
+ }
+ case IMSG_CONF_CONDITION: {
+ struct rule *r = TAILQ_LAST(env->sc_rules_reload, rulelist);
+ struct cond *cond = imsg.data;
+
+ IMSG_SIZE_CHECK(cond);
+
+ cond = calloc(1, sizeof(*cond));
+ if (cond == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ *cond = *(struct cond *)imsg.data;
+
+ TAILQ_INSERT_TAIL(&r->r_conditions, cond, c_entry);
+ break;
+ }
+ case IMSG_CONF_MAP: {
+ struct map *m = imsg.data;
+
+ IMSG_SIZE_CHECK(m);
+
+ m = calloc(1, sizeof(*m));
+ if (m == NULL)
+ fatal("mfa_dispatch_parent: calloc");
+ *m = *(struct map *)imsg.data;
+
+ TAILQ_INSERT_TAIL(env->sc_maps_reload, m, m_entry);
+ break;
+ }
+ case IMSG_CONF_END: {
+ void *temp;
+ struct rule *r;
+ struct map *m;
+
+ /* switch and destroy old ruleset */
+ temp = env->sc_rules;
+ env->sc_rules = env->sc_rules_reload;
+ env->sc_rules_reload = temp;
+
+ temp = env->sc_maps;
+ env->sc_maps = env->sc_maps_reload;
+ env->sc_maps_reload = temp;
+
+ if (env->sc_rules_reload) {
+ TAILQ_FOREACH(r, env->sc_rules_reload, r_entry) {
+ free(r);
+ }
+ free(env->sc_rules_reload);
+ env->sc_rules_reload = NULL;
+ }
+
+ if (env->sc_maps_reload) {
+ TAILQ_FOREACH(m, env->sc_maps_reload, m_entry) {
+ free(m);
+ }
+ free(env->sc_maps_reload);
+ env->sc_maps_reload = NULL;
+ }
+
+ break;
+ }
default:
log_warnx("mfa_dispatch_parent: got imsg %d",
imsg.hdr.type);
@@ -329,7 +409,7 @@ mfa(struct smtpd *env)
return (pid);
}
-// purge_config(env, PURGE_EVERYTHING);
+ purge_config(env, PURGE_EVERYTHING);
pw = env->sc_pw;
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index 8d58b555fd9..0a4413fac7c 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.32 2009/04/12 16:03:01 gilles Exp $ */
+/* $OpenBSD: parse.y,v 1.33 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -1588,6 +1588,7 @@ interface(const char *s, const char *cert, struct listenerlist *al, int max, in_
sain->sin_len = sizeof(struct sockaddr_in);
sain->sin_port = port;
+ h->fd = -1;
h->port = port;
h->flags = flags;
h->ssl = NULL;
@@ -1608,6 +1609,7 @@ interface(const char *s, const char *cert, struct listenerlist *al, int max, in_
sin6->sin6_len = sizeof(struct sockaddr_in6);
sin6->sin6_port = port;
+ h->fd = -1;
h->port = port;
h->flags = flags;
h->ssl = NULL;
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c
index 15232e8fd85..f9c9bcc5e18 100644
--- a/usr.sbin/smtpd/smtp.c
+++ b/usr.sbin/smtpd/smtp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp.c,v 1.47 2009/05/19 11:24:24 jacekm Exp $ */
+/* $OpenBSD: smtp.c,v 1.48 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -103,11 +103,27 @@ smtp_dispatch_parent(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_CONF_RELOAD: {
+ struct session *s;
+
+ /* reloading may invalidate various pointers our
+ * sessions rely upon, we better tell clients we
+ * want them to retry.
+ */
+ SPLAY_FOREACH(s, sessiontree, &env->sc_sessions) {
+ s->s_l = NULL;
+ s->s_msg.status |= S_MESSAGE_TEMPFAILURE;
+ }
+
+ smtp_disable_events(env);
+ imsg_compose(ibuf, IMSG_PARENT_SEND_CONFIG, 0, 0, -1,
+ NULL, 0);
+ break;
+ }
case IMSG_CONF_START:
if (env->sc_flags & SMTPD_CONFIGURING)
break;
env->sc_flags |= SMTPD_CONFIGURING;
- smtp_disable_events(env);
break;
case IMSG_CONF_SSL: {
struct ssl *s;
@@ -143,6 +159,7 @@ smtp_dispatch_parent(int sig, short event, void *p)
if ((l = calloc(1, sizeof(*l))) == NULL)
fatal(NULL);
memcpy(l, imsg.data, sizeof(*l));
+
if ((l->fd = imsg_get_fd(ibuf, &imsg)) == -1)
fatal("cannot get fd");
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index c144576310d..0c0cc520a25 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.91 2009/05/19 12:33:53 jacekm Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.92 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -756,6 +756,10 @@ session_read(struct bufferevent *bev, void *p)
case S_AUTH_USERNAME:
case S_AUTH_PASSWORD:
case S_AUTH_FINALIZE:
+ if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) {
+ free(line);
+ goto tempfail;
+ }
session_auth_pickup(s, line, nr);
break;
@@ -763,6 +767,10 @@ session_read(struct bufferevent *bev, void *p)
case S_HELO:
case S_MAIL:
case S_RCPT:
+ if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) {
+ free(line);
+ goto tempfail;
+ }
session_command(s, line, nr);
break;
@@ -778,6 +786,12 @@ session_read(struct bufferevent *bev, void *p)
free(line);
}
+ return;
+
+tempfail:
+ session_respond(s, "421 Service temporarily unavailable");
+ s_smtp.tempfail++;
+ s->s_flags |= F_QUIT;
}
void
@@ -951,8 +965,14 @@ session_destroy(struct session *s)
s_smtp.sessions_active--;
if (s_smtp.sessions_active < s->s_env->sc_maxconn &&
- !(s->s_msg.flags & F_MESSAGE_ENQUEUED))
- event_add(&s->s_l->ev, NULL);
+ !(s->s_msg.flags & F_MESSAGE_ENQUEUED)) {
+ /*
+ * if our session_destroy occurs because of a configuration
+ * reload, our listener no longer exist and s->s_l is NULL.
+ */
+ if (s->s_l != NULL)
+ event_add(&s->s_l->ev, NULL);
+ }
SPLAY_REMOVE(sessiontree, &s->s_env->sc_sessions, s);
bzero(s, sizeof(*s));
diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c
index b688f61ac80..2ed5eaa0549 100644
--- a/usr.sbin/smtpd/smtpd.c
+++ b/usr.sbin/smtpd/smtpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.c,v 1.61 2009/05/19 22:54:46 gilles Exp $ */
+/* $OpenBSD: smtpd.c,v 1.62 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -53,6 +53,8 @@
__dead void usage(void);
void parent_shutdown(void);
void parent_send_config(int, short, void *);
+void parent_send_config_listeners(struct smtpd *);
+void parent_send_config_ruleset(struct smtpd *, int);
void parent_dispatch_lka(int, short, void *);
void parent_dispatch_mda(int, short, void *);
void parent_dispatch_mfa(int, short, void *);
@@ -131,10 +133,17 @@ parent_shutdown(void)
void
parent_send_config(int fd, short event, void *p)
{
- struct smtpd *env = p;
- struct iovec iov[3];
+ parent_send_config_listeners(p);
+ parent_send_config_ruleset(p, PROC_MFA);
+ parent_send_config_ruleset(p, PROC_LKA);
+}
+
+void
+parent_send_config_listeners(struct smtpd *env)
+{
struct listener *l;
struct ssl *s;
+ struct iovec iov[3];
log_debug("parent_send_config: configuring smtp");
imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_CONF_START,
@@ -162,6 +171,35 @@ parent_send_config(int fd, short event, void *p)
}
void
+parent_send_config_ruleset(struct smtpd *env, int proc)
+{
+ struct rule *r;
+ struct cond *cond;
+ struct map *m;
+
+ log_debug("parent_send_config_ruleset: reloading rules and maps");
+ imsg_compose(env->sc_ibufs[proc], IMSG_CONF_START,
+ 0, 0, -1, NULL, 0);
+
+ TAILQ_FOREACH(r, env->sc_rules, r_entry) {
+ imsg_compose(env->sc_ibufs[proc], IMSG_CONF_RULE,
+ 0, 0, -1, r, sizeof(*r));
+ TAILQ_FOREACH(cond, &r->r_conditions, c_entry) {
+ imsg_compose(env->sc_ibufs[proc], IMSG_CONF_CONDITION,
+ 0, 0, -1, cond, sizeof(*cond));
+ }
+ }
+
+ TAILQ_FOREACH(m, env->sc_maps, m_entry) {
+ imsg_compose(env->sc_ibufs[proc], IMSG_CONF_MAP,
+ 0, 0, -1, m, sizeof(*m));
+ }
+
+ imsg_compose(env->sc_ibufs[proc], IMSG_CONF_END,
+ 0, 0, -1, NULL, 0);
+}
+
+void
parent_dispatch_lka(int fd, short event, void *p)
{
struct smtpd *env = p;
@@ -452,7 +490,7 @@ parent_dispatch_smtp(int fd, short event, void *p)
switch (imsg.hdr.type) {
case IMSG_PARENT_SEND_CONFIG: {
- parent_send_config(-1, -1, env);
+ parent_send_config_listeners(env);
break;
}
case IMSG_PARENT_AUTHENTICATE: {
@@ -594,6 +632,14 @@ parent_dispatch_control(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_CONF_RELOAD: {
+ parent_send_config_ruleset(env, PROC_MFA);
+ parent_send_config_ruleset(env, PROC_LKA);
+ imsg_compose(env->sc_ibufs[PROC_SMTP],
+ IMSG_CONF_RELOAD, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_CONF_RELOAD, 0, 0, -1, NULL, 0);
+ break;
+ }
case IMSG_STATS: {
struct stats *s = imsg.data;
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index c2e785db5d5..11d9e0ac147 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.111 2009/05/19 11:42:52 jacekm Exp $ */
+/* $OpenBSD: smtpd.h,v 1.112 2009/05/20 14:29:44 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -167,7 +167,9 @@ enum imsg_type {
IMSG_CONF_SSL_KEY,
IMSG_CONF_LISTENER,
IMSG_CONF_MAP,
+ IMSG_CONF_MAP_CONTENT,
IMSG_CONF_RULE,
+ IMSG_CONF_RULE_SOURCE,
IMSG_CONF_CONDITION,
IMSG_CONF_OPTION,
IMSG_CONF_END,
@@ -637,6 +639,8 @@ struct session {
};
struct smtpd {
+ char sc_config[MAXPATHLEN];
+
#define SMTPD_OPT_VERBOSE 0x00000001
#define SMTPD_OPT_NOACTION 0x00000002
u_int32_t sc_opts;
@@ -657,8 +661,8 @@ struct smtpd {
struct passwd *sc_pw;
char sc_hostname[MAXHOSTNAMELEN];
TAILQ_HEAD(listenerlist, listener) sc_listeners;
- TAILQ_HEAD(maplist, map) *sc_maps;
- TAILQ_HEAD(rulelist, rule) *sc_rules;
+ TAILQ_HEAD(maplist, map) *sc_maps, *sc_maps_reload;
+ TAILQ_HEAD(rulelist, rule) *sc_rules, *sc_rules_reload;
SPLAY_HEAD(sessiontree, session) sc_sessions;
SPLAY_HEAD(msgtree, message) sc_messages;
SPLAY_HEAD(ssltree, ssl) sc_ssl;
@@ -719,6 +723,11 @@ struct sched {
int ret;
};
+struct reload {
+ int fd;
+ int ret;
+};
+
struct submit_status {
u_int64_t id;
int code;