diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2011-08-31 18:56:31 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2011-08-31 18:56:31 +0000 |
commit | 765bc1b5fffe5b0e2f82f824bc4a91bba12073cc (patch) | |
tree | 3c456ecef8ff07cd9845866125edf40ae731e6a7 /usr.sbin/smtpd/smtp_session.c | |
parent | 88fbf193fd2f3dc7446ff2da1e7d9f50366a84d1 (diff) |
add support for per-line DATA callbacks, this allows filters to take their
decisions *while* the message is being received by the client.
Diffstat (limited to 'usr.sbin/smtpd/smtp_session.c')
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c index 4351d98311d..4673c0caf20 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.143 2011/08/27 22:32:41 gilles Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.144 2011/08/31 18:56:30 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -589,6 +589,7 @@ session_pickup(struct session *s, struct submit_status *ss) return; } + log_debug("state: %d", s->s_state); switch (s->s_state) { case S_INIT: s->s_state = S_GREETED; @@ -714,6 +715,13 @@ session_pickup(struct session *s, struct submit_status *ss) fprintf(s->datafp, "%s\n", time_to_text(time(NULL))); break; + case S_DATACONTENT: + log_debug("line: %s\n", ss->u.dataline); + if (ss->code != 250) + s->s_msg.delivery.status |= DS_PERMFAILURE; + session_read_data(s, ss->u.dataline); + break; + case S_DONE: session_respond(s, "250 2.0.0 %08x Message accepted for delivery", (u_int32_t)(s->s_msg.delivery.id >> 32)); @@ -806,9 +814,22 @@ session_read(struct bufferevent *bev, void *p) session_command(s, line); break; - case S_DATACONTENT: - session_read_data(s, line); - break; + case S_DATACONTENT: { + struct submit_status ss; + + bzero(&ss, sizeof(ss)); + ss.id = s->s_id; + if (strlcpy(ss.u.dataline, line, + sizeof(ss.u.dataline)) >= sizeof(ss.u.dataline)) + fatal("session_read: data truncation"); + + session_imsg(s, PROC_MFA, IMSG_MFA_DATALINE, + 0, 0, -1, &ss, sizeof(ss)); + + free(line); + + return; + } default: fatalx("session_read: unexpected state"); @@ -850,12 +871,12 @@ session_read_data(struct session *s, char *line) 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); s->s_state = S_DONE; } - return; + goto end; } /* Don't waste resources on message if it's going to bin anyway. */ if (s->s_msg.delivery.status & (DS_PERMFAILURE|DS_TEMPFAILURE)) - return; + goto end; /* "If the first character is a period and there are other characters * on the line, the first character is deleted." [4.5.2] @@ -872,12 +893,12 @@ session_read_data(struct session *s, char *line) if (SIZE_MAX - datalen < len + 1 || datalen + len + 1 > env->sc_maxsize) { s->s_msg.delivery.status |= DS_PERMFAILURE; - return; + goto end; } if (fprintf(s->datafp, "%s\n", line) != (int)len + 1) { s->s_msg.delivery.status |= DS_TEMPFAILURE; - return; + goto end; } if (! (s->s_flags & F_8BITMIME)) { @@ -885,6 +906,10 @@ session_read_data(struct session *s, char *line) if (line[i] & 0x80) line[i] = line[i] & 0x7f; } + +end: + bufferevent_enable(s->s_bev, EV_READ); + session_read(s->s_bev, s); } static void |