summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/control.c148
-rw-r--r--usr.sbin/smtpd/enqueue.c363
-rw-r--r--usr.sbin/smtpd/mda.c4
-rw-r--r--usr.sbin/smtpd/mfa.c95
-rw-r--r--usr.sbin/smtpd/queue.c125
-rw-r--r--usr.sbin/smtpd/runner.c3
-rw-r--r--usr.sbin/smtpd/sharedqueue.c78
-rw-r--r--usr.sbin/smtpd/smtpctl.c57
-rw-r--r--usr.sbin/smtpd/smtpctl/Makefile4
-rw-r--r--usr.sbin/smtpd/smtpd.h19
-rw-r--r--usr.sbin/smtpd/smtpd/Makefile4
-rw-r--r--usr.sbin/smtpd/util.c3
12 files changed, 809 insertions, 94 deletions
diff --git a/usr.sbin/smtpd/control.c b/usr.sbin/smtpd/control.c
index 3c738e177cb..f0c3da3b2d2 100644
--- a/usr.sbin/smtpd/control.c
+++ b/usr.sbin/smtpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.8 2009/01/27 14:32:19 gilles Exp $ */
+/* $OpenBSD: control.c,v 1.9 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -89,6 +89,7 @@ control(struct smtpd *env)
{ PROC_QUEUE, control_dispatch_queue },
{ PROC_RUNNER, control_dispatch_runner },
{ PROC_SMTP, control_dispatch_smtp },
+ { PROC_MFA, control_dispatch_mfa },
};
switch (pid = fork()) {
@@ -161,7 +162,7 @@ control(struct smtpd *env)
TAILQ_INIT(&ctl_conns);
- config_peers(env, peers, 3);
+ config_peers(env, peers, 4);
control_listen(env);
event_dispatch();
control_shutdown();
@@ -303,6 +304,43 @@ control_dispatch_ext(int fd, short event, void *arg)
break;
switch (imsg.hdr.type) {
+ case IMSG_MFA_RCPT: {
+ struct message_recipient *mr;
+
+ mr = imsg.data;
+ imsg_compose(env->sc_ibufs[PROC_MFA], IMSG_MFA_RCPT, 0, 0, -1,
+ mr, sizeof(*mr));
+
+ break;
+ }
+ case IMSG_QUEUE_CREATE_MESSAGE: {
+ struct message *messagep;
+
+ messagep = imsg.data;
+ messagep->session_id = fd;
+ imsg_compose(env->sc_ibufs[PROC_QUEUE], IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1,
+ messagep, sizeof(*messagep));
+
+ break;
+ }
+ case IMSG_QUEUE_MESSAGE_FILE: {
+ struct message *messagep;
+
+ messagep = imsg.data;
+ messagep->session_id = fd;
+ imsg_compose(env->sc_ibufs[PROC_QUEUE], IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1,
+ messagep, sizeof(*messagep));
+ break;
+ }
+ case IMSG_QUEUE_COMMIT_MESSAGE: {
+ struct message *messagep;
+
+ messagep = imsg.data;
+ messagep->session_id = fd;
+ imsg_compose(env->sc_ibufs[PROC_QUEUE], IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1,
+ messagep, sizeof(*messagep));
+ break;
+ }
case IMSG_CTL_SHUTDOWN:
/* NEEDS_FIX */
log_debug("received shutdown request");
@@ -427,6 +465,16 @@ control_dispatch_lka(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_QUEUE_TEMPFAIL: {
+ struct submit_status *ss;
+
+ log_debug("GOT LFA REPLY");
+ ss = imsg.data;
+ if (ss->code != 250)
+ log_debug("LKA FAILED WITH TEMPORARY ERROR");
+
+ break;
+ }
default:
log_debug("control_dispatch_lka: unexpected imsg %d",
imsg.hdr.type);
@@ -473,6 +521,24 @@ control_dispatch_mfa(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_MFA_RCPT: {
+ struct submit_status *ss;
+ struct ctl_conn *c;
+
+ ss = imsg.data;
+
+ if (ss->code == 250)
+ break;
+
+ if ((c = control_connbyfd(ss->id)) == NULL) {
+ log_warn("control_dispatch_queue: fd %lld: not found", ss->id);
+ return;
+ }
+
+ imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
+
+ break;
+ }
default:
log_debug("control_dispatch_mfa: unexpected imsg %d",
imsg.hdr.type);
@@ -519,6 +585,84 @@ control_dispatch_queue(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_QUEUE_CREATE_MESSAGE: {
+ struct submit_status *ss;
+ struct ctl_conn *c;
+
+ ss = imsg.data;
+ if ((c = control_connbyfd(ss->id)) == NULL) {
+ log_warn("control_dispatch_queue: fd %lld: not found", ss->id);
+ return;
+ }
+
+ if (ss->code != 250) {
+ imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
+ NULL, 0);
+ }
+ else {
+ ss->msg.session_id = ss->id;
+ strlcpy(ss->msg.message_id, ss->u.msgid, MAXPATHLEN);
+ imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
+ &ss->msg, sizeof(struct message));
+ }
+
+ break;
+ }
+ case IMSG_QUEUE_COMMIT_ENVELOPES: {
+ struct submit_status *ss;
+ struct ctl_conn *c;
+
+ ss = imsg.data;
+ if ((c = control_connbyfd(ss->id)) == NULL) {
+ log_warn("control_dispatch_queue: fd %lld: not found", ss->id);
+ return;
+ }
+
+ imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
+ NULL, 0);
+
+ break;
+ }
+ case IMSG_QUEUE_MESSAGE_FILE: {
+ struct submit_status *ss;
+ struct ctl_conn *c;
+ int fd;
+
+ ss = imsg.data;
+ if ((c = control_connbyfd(ss->id)) == NULL) {
+ log_warn("control_dispatch_queue: fd %lld: not found",
+ ss->id);
+ return;
+ }
+
+ fd = imsg_get_fd(ibuf, &imsg);
+ if (ss->code == 250)
+ imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, fd,
+ &ss->msg, sizeof(struct message));
+ else
+ imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
+ &ss->msg, sizeof(struct message));
+ break;
+ }
+ case IMSG_QUEUE_COMMIT_MESSAGE: {
+ struct submit_status *ss;
+ struct ctl_conn *c;
+
+ ss = imsg.data;
+ if ((c = control_connbyfd(ss->id)) == NULL) {
+ log_warn("control_dispatch_queue: fd %lld: not found",
+ ss->id);
+ return;
+ }
+
+ if (ss->code == 250)
+ imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
+ &ss->msg, sizeof(struct message));
+ else
+ imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
+ &ss->msg, sizeof(struct message));
+ break;
+ }
default:
log_debug("control_dispatch_queue: unexpected imsg %d",
imsg.hdr.type);
diff --git a/usr.sbin/smtpd/enqueue.c b/usr.sbin/smtpd/enqueue.c
new file mode 100644
index 00000000000..321875c7bfd
--- /dev/null
+++ b/usr.sbin/smtpd/enqueue.c
@@ -0,0 +1,363 @@
+/* $OpenBSD: enqueue.c,v 1.1 2009/01/27 22:48:29 gilles Exp $ */
+
+/*
+ * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.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.
+ */
+
+#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 <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+
+extern struct imsgbuf *ibuf;
+
+__dead void usage(void);
+int enqueue(int, char **);
+int enqueue_init(struct message *);
+int enqueue_add_recipient(struct message *, char *);
+int enqueue_messagefd(struct message *);
+int enqueue_write_message(FILE *, FILE *);
+int enqueue_commit(struct message *);
+
+int
+enqueue(int argc, char *argv[])
+{
+ int ch;
+ int fd;
+ FILE *fpout;
+ struct message message;
+ char sender[MAX_PATH_SIZE];
+
+ uid_t uid;
+ char *username;
+ char hostname[MAXHOSTNAMELEN];
+ struct passwd *pw;
+
+ uid = getuid();
+ pw = safe_getpwuid(uid);
+ if (pw == NULL)
+ errx(1, "you don't exist, go away.");
+
+ username = pw->pw_name;
+ gethostname(hostname, sizeof(hostname));
+
+ fprintf(stdout, "username: %s\n", username);
+ fprintf(stdout, "hostname: %s\n", hostname);
+
+ if (! bsnprintf(sender, MAX_PATH_SIZE, "%s@%s",
+ username, hostname))
+ errx(1, "sender address too long.");
+
+ while ((ch = getopt(argc, argv, "f:i")) != -1) {
+ switch (ch) {
+ case 'f':
+ if (strlcpy(sender, optarg, MAX_PATH_SIZE)
+ >= MAX_PATH_SIZE)
+ errx(1, "sender address too long.");
+ break;
+ case 'i':
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ bzero(&message, sizeof(struct message));
+
+ /* build sender */
+ if (! recipient_to_path(&message.sender, sender))
+ errx(1, "invalid sender address.");
+
+ if (! enqueue_init(&message)) {
+ return 1;
+ }
+
+ fprintf(stdout, "created layout with id: %s\n", message.message_id);
+
+ if (argc == 0) {
+ fprintf(stdout, "no recipient.\n");
+ return 1;
+ }
+
+ while (argc--) {
+ if (! enqueue_add_recipient(&message, *argv))
+ errx(1, "invalid recipient.");
+ ++argv;
+ }
+
+ fd = enqueue_messagefd(&message);
+ if (fd == -1 || (fpout = fdopen(fd, "w")) == NULL) {
+ errx(1, "failed to open message file for writing.");
+ return 1;
+ }
+
+ if (! enqueue_write_message(stdin, fpout)) {
+ errx(1, "failed to write message to message file.");
+ return 1;
+ }
+ safe_fclose(fpout);
+
+ if (! enqueue_commit(&message)) {
+ errx(1, "failed to commit message to queue.");
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+enqueue_add_recipient(struct message *messagep, char *recipient)
+{
+ char buffer[MAX_PATH_SIZE];
+ struct message_recipient mr;
+ struct sockaddr_in *ssin;
+ struct message message;
+ int done = 0;
+ int n;
+ struct imsg imsg;
+
+ bzero(&mr, sizeof(mr));
+
+ message = *messagep;
+
+ if (strlcpy(buffer, recipient, sizeof(buffer)) >= sizeof(buffer)) {
+ errx(1, "recipient address too long.");
+ return 0;
+ }
+
+ if (! recipient_to_path(&message.recipient, buffer)) {
+ errx(1, "invalid recipient address.");
+ return 0;
+ }
+
+ /* NEEDS_FIX */
+ mr.ss.ss_family = AF_INET;
+ mr.ss.ss_len = sizeof(ssin);
+ ssin = (struct sockaddr_in *)&mr.ss;
+ if (inet_pton(AF_INET, "127.0.0.1", &ssin->sin_addr) != 1)
+ return 0;
+
+ mr.path = message.recipient;
+ mr.id = message.session_id;
+ mr.msg = message;
+ mr.msg.flags |= F_MESSAGE_ENQUEUED;
+
+ imsg_compose(ibuf, IMSG_MFA_RCPT, 0, 0, -1, &mr, sizeof (mr));
+ while (ibuf->w.queued)
+ if (msgbuf_write(&ibuf->w) < 0)
+ err(1, "write error");
+
+ while (!done) {
+ if ((n = imsg_read(ibuf)) == -1)
+ errx(1, "imsg_read error");
+ if (n == 0)
+ errx(1, "pipe closed");
+
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ errx(1, "imsg_get error");
+
+ if (n == 0)
+ continue;
+
+ done = 1;
+ switch (imsg.hdr.type) {
+ case IMSG_CTL_OK: {
+ return 1;
+ }
+ case IMSG_CTL_FAIL:
+ return 0;
+ default:
+ err(1, "unexpected reply (%d)", imsg.hdr.type);
+ }
+ imsg_free(&imsg);
+ }
+
+
+ return 1;
+}
+
+int
+enqueue_write_message(FILE *fpin, FILE *fpout)
+{
+ char *buf, *lbuf;
+ size_t len;
+
+ lbuf = NULL;
+ while ((buf = fgetln(fpin, &len))) {
+ if (buf[len - 1] == '\n') {
+ buf[len - 1] = '\0';
+ len--;
+ }
+ else {
+ /* EOF without EOL, copy and add the NUL */
+ if ((lbuf = malloc(len + 1)) == NULL)
+ err(1, NULL);
+ memcpy(lbuf, buf, len);
+ lbuf[len] = '\0';
+ buf = lbuf;
+ }
+ if (fprintf(fpout, "%s\n", buf) != (int)len + 1)
+ return 0;
+ }
+ free(lbuf);
+ return 1;
+}
+
+int
+enqueue_init(struct message *messagep)
+{
+ int done = 0;
+ int n;
+ struct imsg imsg;
+
+ imsg_compose(ibuf, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, messagep, sizeof(*messagep));
+ while (ibuf->w.queued)
+ if (msgbuf_write(&ibuf->w) < 0)
+ err(1, "write error");
+
+ while (!done) {
+ if ((n = imsg_read(ibuf)) == -1)
+ errx(1, "imsg_read error");
+ if (n == 0)
+ errx(1, "pipe closed");
+
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ errx(1, "imsg_get error");
+
+ if (n == 0)
+ continue;
+
+ done = 1;
+ switch (imsg.hdr.type) {
+ case IMSG_CTL_OK: {
+ struct message *mp;
+
+ mp = imsg.data;
+ messagep->session_id = mp->session_id;
+ strlcpy(messagep->message_id, mp->message_id, MAXPATHLEN);
+
+ return 1;
+ }
+ case IMSG_CTL_FAIL:
+ return 0;
+ default:
+ err(1, "unexpected reply (%d)", imsg.hdr.type);
+ }
+ imsg_free(&imsg);
+ }
+
+ return 0;
+}
+
+int
+enqueue_messagefd(struct message *messagep)
+{
+ int done = 0;
+ int n;
+ struct imsg imsg;
+
+ imsg_compose(ibuf, IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1, messagep, sizeof(*messagep));
+ while (ibuf->w.queued)
+ if (msgbuf_write(&ibuf->w) < 0)
+ err(1, "write error");
+
+ while (!done) {
+ if ((n = imsg_read(ibuf)) == -1)
+ errx(1, "imsg_read error");
+ if (n == 0)
+ errx(1, "pipe closed");
+
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ errx(1, "imsg_get error");
+
+ if (n == 0)
+ continue;
+
+ done = 1;
+ switch (imsg.hdr.type) {
+ case IMSG_CTL_OK:
+ return imsg_get_fd(ibuf, &imsg);
+ case IMSG_CTL_FAIL:
+ return -1;
+ default:
+ err(1, "unexpected reply (%d)", imsg.hdr.type);
+ }
+ imsg_free(&imsg);
+ }
+
+ return -1;
+}
+
+
+int
+enqueue_commit(struct message *messagep)
+{
+ int done = 0;
+ int n;
+ struct imsg imsg;
+
+ imsg_compose(ibuf, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, messagep, sizeof(*messagep));
+ while (ibuf->w.queued)
+ if (msgbuf_write(&ibuf->w) < 0)
+ err(1, "write error");
+
+ while (!done) {
+ if ((n = imsg_read(ibuf)) == -1)
+ errx(1, "imsg_read error");
+ if (n == 0)
+ errx(1, "pipe closed");
+
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ errx(1, "imsg_get error");
+
+ if (n == 0)
+ continue;
+
+ done = 1;
+ switch (imsg.hdr.type) {
+ case IMSG_CTL_OK: {
+ return 1;
+ }
+ case IMSG_CTL_FAIL: {
+ return 0;
+ }
+ default:
+ err(1, "unexpected reply (%d)", imsg.hdr.type);
+ }
+ imsg_free(&imsg);
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/smtpd/mda.c b/usr.sbin/smtpd/mda.c
index 4f3fc862965..331f1eec8c3 100644
--- a/usr.sbin/smtpd/mda.c
+++ b/usr.sbin/smtpd/mda.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mda.c,v 1.6 2009/01/01 16:15:47 jacekm Exp $ */
+/* $OpenBSD: mda.c,v 1.7 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -159,7 +159,7 @@ mda_dispatch_parent(int sig, short event, void *p)
IMSG_PARENT_MAILBOX_RENAME, 0, 0, -1, batchp,
sizeof(struct batch));
}
-
+ else
if (messagep->mboxfd != -1)
close(messagep->mboxfd);
if (messagep->messagefd != -1)
diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c
index f03cbe7084b..4aec3aad6a1 100644
--- a/usr.sbin/smtpd/mfa.c
+++ b/usr.sbin/smtpd/mfa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa.c,v 1.9 2009/01/04 17:45:58 gilles Exp $ */
+/* $OpenBSD: mfa.c,v 1.10 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -40,6 +40,7 @@ void mfa_sig_handler(int, short, void *);
void mfa_dispatch_parent(int, short, void *);
void mfa_dispatch_smtp(int, short, void *);
void mfa_dispatch_lka(int, short, void *);
+void mfa_dispatch_control(int, short, void *);
void mfa_setup_events(struct smtpd *);
void mfa_disable_events(struct smtpd *);
void mfa_timeout(int, short, void *);
@@ -242,8 +243,16 @@ mfa_dispatch_lka(int sig, short event, void *p)
struct submit_status *ss;
ss = imsg.data;
- imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_MFA_RCPT,
- 0, 0, -1, ss, sizeof(*ss));
+ if (ss->msg.flags & F_MESSAGE_ENQUEUED) {
+ log_debug("FOOO");
+ imsg_compose(env->sc_ibufs[PROC_CONTROL], IMSG_MFA_RCPT,
+ 0, 0, -1, ss, sizeof(*ss));
+ }
+ else {
+ log_debug("BAAR");
+ imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_MFA_RCPT,
+ 0, 0, -1, ss, sizeof(*ss));
+ }
break;
}
default:
@@ -257,6 +266,78 @@ mfa_dispatch_lka(int sig, short event, void *p)
}
void
+mfa_dispatch_control(int sig, short event, void *p)
+{
+ struct smtpd *env = p;
+ struct imsgbuf *ibuf;
+ struct imsg imsg;
+ ssize_t n;
+
+ ibuf = env->sc_ibufs[PROC_CONTROL];
+ switch (event) {
+ case EV_READ:
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read_error");
+ if (n == 0) {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&ibuf->ev);
+ event_loopexit(NULL);
+ return;
+ }
+ break;
+ case EV_WRITE:
+ if (msgbuf_write(&ibuf->w) == -1)
+ fatal("msgbuf_write");
+ imsg_event_add(ibuf);
+ return;
+ default:
+ fatalx("unknown event");
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("mfa_dispatch_smtp: imsg_read error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_MFA_RCPT: {
+ struct message_recipient *mr;
+ struct submit_status ss;
+
+ mr = imsg.data;
+ log_debug("mfa_dispatch_control: testing forward path");
+ ss.id = mr->id;
+ ss.code = 530;
+ ss.u.path = mr->path;
+ ss.ss = mr->ss;
+ ss.msg = mr->msg;
+
+ ss.flags = mr->flags;
+
+ if (! mfa_check_rcpt(env, &ss.u.path, &ss.ss)) {
+ imsg_compose(ibuf, IMSG_MFA_RCPT, 0,
+ 0, -1, &ss, sizeof(ss));
+ }
+ else {
+ ss.code = 250;
+ imsg_compose(env->sc_ibufs[PROC_LKA], IMSG_LKA_RCPT, 0,
+ 0, -1, &ss, sizeof(ss));
+ }
+
+ break;
+ }
+ default:
+ log_debug("mfa_dispatch_smtp: unexpected imsg %d",
+ imsg.hdr.type);
+ break;
+ }
+ imsg_free(&imsg);
+ }
+ imsg_event_add(ibuf);
+}
+
+void
mfa_shutdown(void)
{
log_info("mail filter exiting");
@@ -304,6 +385,7 @@ mfa(struct smtpd *env)
{ PROC_PARENT, mfa_dispatch_parent },
{ PROC_SMTP, mfa_dispatch_smtp },
{ PROC_LKA, mfa_dispatch_lka },
+ { PROC_CONTROL, mfa_dispatch_control},
};
switch (pid = fork()) {
@@ -347,7 +429,7 @@ mfa(struct smtpd *env)
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_IGN);
- config_peers(env, peers, 3);
+ config_peers(env, peers, 4);
mfa_setup_events(env);
event_dispatch();
@@ -382,7 +464,6 @@ mfa_check_rcpt(struct smtpd *env, struct path *path, struct sockaddr_storage *ss
if (! mfa_check_source(r->r_sources, ss))
continue;
- log_debug("client authorized");
TAILQ_FOREACH(cond, &r->r_conditions, c_entry) {
if (cond->c_type == C_ALL) {
path->rule = *r;
@@ -396,6 +477,8 @@ mfa_check_rcpt(struct smtpd *env, struct path *path, struct sockaddr_storage *ss
map = cond->c_match;
TAILQ_FOREACH(me, &map->m_contents, me_entry) {
+ log_debug("matching: %s to %s",
+ path->domain, me->me_key.med_string);
if (hostname_match(path->domain, me->me_key.med_string)) {
path->rule = *r;
return 1;
@@ -429,8 +512,8 @@ mfa_check_source(struct map *map, struct sockaddr_storage *ss)
if (mfa_match_mask(ss, &me->me_key.med_addr))
return 1;
-
}
+
return 0;
}
diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c
index e351628273d..f1b41c8d800 100644
--- a/usr.sbin/smtpd/queue.c
+++ b/usr.sbin/smtpd/queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.c,v 1.47 2009/01/26 22:20:31 gilles Exp $ */
+/* $OpenBSD: queue.c,v 1.48 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -48,12 +48,6 @@ void queue_setup_events(struct smtpd *);
void queue_disable_events(struct smtpd *);
void queue_purge_incoming(void);
-int queue_create_incoming_layout(char *);
-void queue_delete_incoming_message(char *);
-int queue_record_incoming_envelope(struct message *);
-int queue_remove_incoming_envelope(struct message *);
-int queue_commit_incoming_message(struct message *);
-int queue_open_incoming_message_file(struct message *);
void queue_message_update(struct message *);
@@ -116,6 +110,59 @@ queue_dispatch_control(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_QUEUE_CREATE_MESSAGE: {
+ struct message *messagep;
+ struct submit_status ss;
+
+ log_debug("mfa_dispatch_control: creating message file");
+ messagep = imsg.data;
+
+ ss.id = messagep->session_id;
+ ss.code = 250;
+ bzero(ss.u.msgid, MAXPATHLEN);
+
+ if (! enqueue_create_layout(ss.u.msgid))
+ ss.code = 421;
+
+ imsg_compose(ibuf, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1,
+ &ss, sizeof(ss));
+
+ break;
+ }
+ case IMSG_QUEUE_MESSAGE_FILE: {
+ int fd;
+ struct submit_status ss;
+ struct message *messagep;
+
+ messagep = imsg.data;
+ ss.msg = *messagep;
+ ss.id = messagep->session_id;
+ ss.code = 250;
+ fd = enqueue_open_messagefile(messagep);
+ if (fd == -1)
+ ss.code = 421;
+
+ imsg_compose(ibuf, IMSG_QUEUE_MESSAGE_FILE, 0, 0, fd, &ss,
+ sizeof(ss));
+
+ break;
+ }
+ case IMSG_QUEUE_COMMIT_MESSAGE: {
+ struct message *messagep;
+ struct submit_status ss;
+
+ messagep = imsg.data;
+ ss.id = messagep->session_id;
+
+ ss.code = 250;
+ if (! enqueue_commit_message(messagep))
+ ss.code = 421;
+
+ imsg_compose(ibuf, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1,
+ &ss, sizeof(ss));
+
+ break;
+ }
default:
log_debug("queue_dispatch_control: unexpected imsg %d",
imsg.hdr.type);
@@ -367,7 +414,7 @@ queue_dispatch_lka(int sig, short event, void *p)
fatal("msgbuf_write");
imsg_event_add(ibuf);
return;
- default:
+ default:
fatalx("unknown event");
}
@@ -382,6 +429,8 @@ queue_dispatch_lka(int sig, short event, void *p)
case IMSG_QUEUE_SUBMIT_ENVELOPE: {
struct message *messagep;
struct submit_status ss;
+ int (*f)(struct message *);
+ enum smtp_proc_type peer;
messagep = imsg.data;
messagep->id = queue_generate_id();
@@ -394,11 +443,19 @@ queue_dispatch_lka(int sig, short event, void *p)
messagep->type = T_MTA_MESSAGE;
/* Write to disk */
- if (! queue_record_incoming_envelope(messagep)) {
+ if (messagep->flags & F_MESSAGE_ENQUEUED) {
+ f = enqueue_record_envelope;
+ peer = PROC_CONTROL;
+ }
+ else {
+ f = queue_record_incoming_envelope;
+ peer = PROC_SMTP;
+ }
+
+ if (! f(messagep)) {
ss.code = 421;
- imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_QUEUE_TEMPFAIL,
+ imsg_compose(env->sc_ibufs[peer], IMSG_QUEUE_TEMPFAIL,
0, 0, -1, &ss, sizeof(ss));
- break;
}
break;
@@ -407,13 +464,20 @@ queue_dispatch_lka(int sig, short event, void *p)
case IMSG_QUEUE_COMMIT_ENVELOPES: {
struct message *messagep;
struct submit_status ss;
+ enum smtp_proc_type peer;
messagep = imsg.data;
ss.id = messagep->session_id;
ss.code = 250;
- imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_QUEUE_COMMIT_ENVELOPES,
+ if (messagep->flags & F_MESSAGE_ENQUEUED)
+ peer = PROC_CONTROL;
+ else
+ peer = PROC_SMTP;
+
+ imsg_compose(env->sc_ibufs[peer], IMSG_QUEUE_COMMIT_ENVELOPES,
0, 0, -1, &ss, sizeof(ss));
+
break;
}
@@ -589,7 +653,6 @@ queue_remove_batch_message(struct smtpd *env, struct batch *batchp, struct messa
free(batchp);
return 1;
}
-
return 0;
}
@@ -647,42 +710,6 @@ queue_purge_incoming(void)
}
int
-queue_create_incoming_layout(char *msgid)
-{
- return queue_create_layout_message(PATH_INCOMING, msgid);
-}
-
-void
-queue_delete_incoming_message(char *msgid)
-{
- queue_delete_layout_message(PATH_INCOMING, msgid);
-}
-
-int
-queue_record_incoming_envelope(struct message *message)
-{
- return queue_record_layout_envelope(PATH_INCOMING, message);
-}
-
-int
-queue_remove_incoming_envelope(struct message *message)
-{
- return queue_remove_layout_envelope(PATH_INCOMING, message);
-}
-
-int
-queue_commit_incoming_message(struct message *message)
-{
- return queue_commit_layout_message(PATH_INCOMING, message);
-}
-
-int
-queue_open_incoming_message_file(struct message *message)
-{
- return queue_open_layout_messagefile(PATH_INCOMING, message);
-}
-
-int
queue_remove_envelope(struct message *messagep)
{
char pathname[MAXPATHLEN];
diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c
index 6eb3dd967eb..ba4f6891094 100644
--- a/usr.sbin/smtpd/runner.c
+++ b/usr.sbin/smtpd/runner.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: runner.c,v 1.22 2009/01/08 19:15:23 jacekm Exp $ */
+/* $OpenBSD: runner.c,v 1.23 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -347,7 +347,6 @@ runner_shutdown(void)
void
runner_setup_events(struct smtpd *env)
{
-
struct timeval tv;
evtimer_set(&env->sc_ev, runner_timeout, env);
diff --git a/usr.sbin/smtpd/sharedqueue.c b/usr.sbin/smtpd/sharedqueue.c
index 082db3498b4..ea7fc1fb0d3 100644
--- a/usr.sbin/smtpd/sharedqueue.c
+++ b/usr.sbin/smtpd/sharedqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sharedqueue.c,v 1.1 2009/01/26 22:20:31 gilles Exp $ */
+/* $OpenBSD: sharedqueue.c,v 1.2 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -55,7 +55,7 @@ queue_create_layout_message(char *queuepath, char *message_id)
if (strlcpy(message_id, rootdir + strlen(queuepath) + 1, MAXPATHLEN)
>= MAXPATHLEN)
fatalx("queue_create_layout_message: truncation");
-
+
if (! bsnprintf(evpdir, MAXPATHLEN, "%s%s", rootdir, PATH_ENVELOPES))
fatalx("queue_create_layout_message: snprintf");
@@ -66,7 +66,6 @@ queue_create_layout_message(char *queuepath, char *message_id)
}
fatal("queue_create_layout_message: mkdir");
}
-
return 1;
}
@@ -203,6 +202,79 @@ queue_open_layout_messagefile(char *queuepath, struct message *messagep)
return open(pathname, mode, 0600);
}
+int
+enqueue_create_layout(char *msgid)
+{
+ return queue_create_layout_message(PATH_ENQUEUE, msgid);
+}
+
+void
+enqueue_delete_message(char *msgid)
+{
+ queue_delete_layout_message(PATH_ENQUEUE, msgid);
+}
+
+int
+enqueue_record_envelope(struct message *message)
+{
+ return queue_record_layout_envelope(PATH_ENQUEUE, message);
+}
+
+int
+enqueue_remove_envelope(struct message *message)
+{
+ return queue_remove_layout_envelope(PATH_ENQUEUE, message);
+}
+
+int
+enqueue_commit_message(struct message *message)
+{
+ return queue_commit_layout_message(PATH_ENQUEUE, message);
+}
+
+int
+enqueue_open_messagefile(struct message *message)
+{
+ return queue_open_layout_messagefile(PATH_ENQUEUE, message);
+}
+
+
+int
+queue_create_incoming_layout(char *msgid)
+{
+ return queue_create_layout_message(PATH_INCOMING, msgid);
+}
+
+void
+queue_delete_incoming_message(char *msgid)
+{
+ queue_delete_layout_message(PATH_INCOMING, msgid);
+}
+
+int
+queue_record_incoming_envelope(struct message *message)
+{
+ return queue_record_layout_envelope(PATH_INCOMING, message);
+}
+
+int
+queue_remove_incoming_envelope(struct message *message)
+{
+ return queue_remove_layout_envelope(PATH_INCOMING, message);
+}
+
+int
+queue_commit_incoming_message(struct message *message)
+{
+ return queue_commit_layout_message(PATH_INCOMING, message);
+}
+
+int
+queue_open_incoming_message_file(struct message *message)
+{
+ return queue_open_layout_messagefile(PATH_INCOMING, message);
+}
+
u_int16_t
queue_hash(char *msgid)
{
diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c
index 534a3fe8235..056de4d1f03 100644
--- a/usr.sbin/smtpd/smtpctl.c
+++ b/usr.sbin/smtpd/smtpctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpctl.c,v 1.5 2009/01/04 22:35:09 gilles Exp $ */
+/* $OpenBSD: smtpctl.c,v 1.6 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -46,6 +46,7 @@ __dead void usage(void);
int show_command_output(struct imsg*);
void show_queue(int);
void show_runqueue(int);
+int enqueue(int, char **);
struct imsgname {
int type;
@@ -65,12 +66,18 @@ struct imsgname imsgunknown = {
int proctype;
struct imsgbuf *ibuf;
+int sendmail = 0;
+extern char *__progname;
+
__dead void
usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname);
+ if (sendmail)
+ fprintf(stderr, "usage: %s [-i] rcpt [...]]\n", __progname);
+ else
+ fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname);
exit(1);
}
@@ -85,32 +92,36 @@ int
main(int argc, char *argv[])
{
struct sockaddr_un sun;
- struct parse_result *res;
+ struct parse_result *res = NULL;
struct imsg imsg;
int ctl_sock;
int done = 0;
int n;
- /* check for root privileges */
- if (geteuid())
- errx(1, "need root privileges");
-
/* parse options */
- if ((res = parse(argc - 1, argv + 1)) == NULL)
- exit(1);
-
- /* handle "disconnected" commands */
- switch (res->action) {
- case SHOW_QUEUE:
- show_queue(0);
- break;
- case SHOW_RUNQUEUE:
- show_runqueue(0);
- break;
- default:
- goto connected;
+ if (strcmp(__progname, "sendmail") == 0 || strcmp(__progname, "send-mail") == 0)
+ sendmail = 1;
+ else {
+ /* check for root privileges */
+ if (geteuid())
+ errx(1, "need root privileges");
+
+ if ((res = parse(argc - 1, argv + 1)) == NULL)
+ exit(1);
+
+ /* handle "disconnected" commands */
+ switch (res->action) {
+ case SHOW_QUEUE:
+ show_queue(0);
+ break;
+ case SHOW_RUNQUEUE:
+ show_runqueue(0);
+ break;
+ default:
+ goto connected;
+ }
+ return 0;
}
- return 0;
connected:
/* connect to relayd control socket */
@@ -127,6 +138,9 @@ connected:
err(1, NULL);
imsg_init(ibuf, ctl_sock, NULL);
+ if (sendmail)
+ return enqueue(argc, argv);
+
/* process user request */
switch (res->action) {
case NONE:
@@ -222,4 +236,3 @@ show_command_output(struct imsg *imsg)
}
return (1);
}
-
diff --git a/usr.sbin/smtpd/smtpctl/Makefile b/usr.sbin/smtpd/smtpctl/Makefile
index bf7b10c2e7a..cce907ef8ca 100644
--- a/usr.sbin/smtpd/smtpctl/Makefile
+++ b/usr.sbin/smtpd/smtpctl/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.3 2008/12/21 13:06:43 jacekm Exp $
+# $OpenBSD: Makefile,v 1.4 2009/01/27 22:48:29 gilles Exp $
.PATH: ${.CURDIR}/..
@@ -16,6 +16,6 @@ CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare -Wbounded
-SRCS= smtpctl.c parser.c buffer.c imsg.c log.c showqueue.c
+SRCS= smtpctl.c parser.c buffer.c imsg.c log.c showqueue.c enqueue.c sharedqueue.c util.c
LDFLAGS= -lutil
.include <bsd.prog.mk>
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 86a31ea6933..44aeed5d1ca 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.47 2009/01/26 22:20:31 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.48 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -400,7 +400,8 @@ enum message_flags {
F_MESSAGE_RESOLVED = 0x1,
F_MESSAGE_SCHEDULED = 0x2,
F_MESSAGE_PROCESSING = 0x4,
- F_MESSAGE_AUTHENTICATED = 0x8
+ F_MESSAGE_AUTHENTICATED = 0x8,
+ F_MESSAGE_ENQUEUED = 0x10
};
struct message {
@@ -729,6 +730,18 @@ int queue_record_layout_envelope(char *, struct message *);
int queue_remove_layout_envelope(char *, struct message *);
int queue_commit_layout_message(char *, struct message *);
int queue_open_layout_messagefile(char *, struct message *);
+int enqueue_create_layout(char *);
+void enqueue_delete_message(char *);
+int enqueue_record_envelope(struct message *);
+int enqueue_remove_envelope(struct message *);
+int enqueue_commit_message(struct message *);
+int enqueue_open_messagefile(struct message *);
+int queue_create_incoming_layout(char *);
+void queue_delete_incoming_message(char *);
+int queue_record_incoming_envelope(struct message *);
+int queue_remove_incoming_envelope(struct message *);
+int queue_commit_incoming_message(struct message *);
+int queue_open_incoming_message_file(struct message *);
u_int16_t queue_hash(char *);
/* mda.c */
@@ -806,4 +819,6 @@ int bsnprintf(char *, size_t, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
int safe_fclose(FILE *);
struct passwd *safe_getpwnam(const char *);
+struct passwd *safe_getpwuid(uid_t);
int hostname_match(char *, char *);
+int recipient_to_path(struct path *, char *);
diff --git a/usr.sbin/smtpd/smtpd/Makefile b/usr.sbin/smtpd/smtpd/Makefile
index 9c1768cfd24..f1f17afe8ce 100644
--- a/usr.sbin/smtpd/smtpd/Makefile
+++ b/usr.sbin/smtpd/smtpd/Makefile
@@ -1,11 +1,11 @@
-# $OpenBSD: Makefile,v 1.4 2008/12/21 02:18:46 gilles Exp $
+# $OpenBSD: Makefile,v 1.5 2009/01/27 22:48:29 gilles Exp $
PROG= smtpd
SRCS= parse.y log.c config.c buffer.c imsg.c \
smtpd.c lka.c mfa.c queue.c mta.c mda.c control.c \
smtp.c smtp_session.c store.c \
ssl.c ssl_privsep.c dns.c aliases.c forward.c \
- map.c runner.c util.c
+ map.c runner.c util.c sharedqueue.c
MAN= smtpd.8 smtpd.conf.5
BINDIR= /usr/sbin
diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c
index edcaf7ef403..38226b36fc7 100644
--- a/usr.sbin/smtpd/util.c
+++ b/usr.sbin/smtpd/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.8 2009/01/27 15:57:01 gilles Exp $ */
+/* $OpenBSD: util.c,v 1.9 2009/01/27 22:48:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -114,7 +114,6 @@ hostname_match(char *hostname, char *pattern)
int
recipient_to_path(struct path *path, char *recipient)
{
- size_t len;
char *username;
char *hostname;