diff options
-rw-r--r-- | usr.sbin/smtpd/control.c | 148 | ||||
-rw-r--r-- | usr.sbin/smtpd/enqueue.c | 363 | ||||
-rw-r--r-- | usr.sbin/smtpd/mda.c | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/mfa.c | 95 | ||||
-rw-r--r-- | usr.sbin/smtpd/queue.c | 125 | ||||
-rw-r--r-- | usr.sbin/smtpd/runner.c | 3 | ||||
-rw-r--r-- | usr.sbin/smtpd/sharedqueue.c | 78 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpctl.c | 57 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpctl/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 19 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/util.c | 3 |
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; |