summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/mta_session.c
diff options
context:
space:
mode:
authorEric Faurot <eric@cvs.openbsd.org>2013-02-15 22:43:22 +0000
committerEric Faurot <eric@cvs.openbsd.org>2013-02-15 22:43:22 +0000
commit89010678e6c18afb34622a621fe9bc1db6d59ade (patch)
tree753734a1f67a2d6dbf585e5d3d957cb66aa644bf /usr.sbin/smtpd/mta_session.c
parent79bcd4dfe34962b8fd02ab9e6d6c1785f5d4ce1c (diff)
add missing bits for lmtp support (from Ashish SHUKLA).
ok gilles@
Diffstat (limited to 'usr.sbin/smtpd/mta_session.c')
-rw-r--r--usr.sbin/smtpd/mta_session.c74
1 files changed, 59 insertions, 15 deletions
diff --git a/usr.sbin/smtpd/mta_session.c b/usr.sbin/smtpd/mta_session.c
index 10cfe380aa3..65665867ebf 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.32 2013/02/05 10:53:57 nicm Exp $ */
+/* $OpenBSD: mta_session.c,v 1.33 2013/02/15 22:43:21 eric Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -55,6 +55,7 @@ enum mta_state {
MTA_BANNER,
MTA_EHLO,
MTA_HELO,
+ MTA_LHLO,
MTA_STARTTLS,
MTA_AUTH,
MTA_READY,
@@ -63,6 +64,7 @@ enum mta_state {
MTA_DATA,
MTA_BODY,
MTA_EOM,
+ MTA_LMTP_EOM,
MTA_RSET,
MTA_QUIT,
};
@@ -82,6 +84,7 @@ enum mta_state {
#define MTA_FREE 0x0400
+#define MTA_LMTP 0x0800
#define MTA_EXT_STARTTLS 0x01
#define MTA_EXT_AUTH 0x02
@@ -107,6 +110,7 @@ struct mta_session {
int ext;
int msgcount;
+ int rcptcount;
enum mta_state state;
struct mta_task *task;
@@ -121,7 +125,7 @@ static void mta_free(struct mta_session *);
static void mta_on_ptr(void *, void *, void *);
static void mta_connect(struct mta_session *);
static void mta_enter_state(struct mta_session *, int);
-static void mta_flush_task(struct mta_session *, int, const char *);
+static void mta_flush_task(struct mta_session *, int, const char *, size_t);
static void mta_error(struct mta_session *, const char *, ...);
static void mta_send(struct mta_session *, char *, ...);
static ssize_t mta_queue_data(struct mta_session *);
@@ -170,6 +174,8 @@ mta_session(struct mta_relay *relay, struct mta_route *route)
s->flags |= MTA_USE_AUTH;
if (relay->cert)
s->flags |= MTA_USE_CERT;
+ if (relay->flags & RELAY_LMTP)
+ s->flags |= MTA_LMTP;
switch (relay->flags & (RELAY_SSL|RELAY_TLS_OPTIONAL)) {
case RELAY_SSL:
s->flags |= MTA_FORCE_ANYSSL;
@@ -240,7 +246,7 @@ mta_session_imsg(struct mproc *p, struct imsg *imsg)
fclose(s->datafp);
s->datafp = NULL;
mta_flush_task(s, IMSG_DELIVERY_LOOP,
- "Loop detected");
+ "Loop detected", 0);
mta_enter_state(s, MTA_READY);
} else {
mta_enter_state(s, MTA_MAIL);
@@ -441,6 +447,8 @@ mta_connect(struct mta_session *s)
schema = "tls://";
else if (s->use_smtps)
schema = "smtps://";
+ else if (s->flags & MTA_LMTP)
+ schema = "lmtp://";
else
schema = "smtp://";
@@ -505,6 +513,11 @@ mta_enter_state(struct mta_session *s, int newstate)
mta_send(s, "HELO %s", s->helo);
break;
+ case MTA_LHLO:
+ s->ext = 0;
+ mta_send(s, "LHLO %s", s->helo);
+ break;
+
case MTA_STARTTLS:
if (s->flags & MTA_TLS) /* already started */
mta_enter_state(s, MTA_AUTH);
@@ -571,13 +584,14 @@ mta_enter_state(struct mta_session *s, int newstate)
break;
case MTA_MAIL:
- mta_send(s, "MAIL FROM: <%s>", s->task->sender);
+ mta_send(s, "MAIL FROM:<%s>", s->task->sender);
break;
case MTA_RCPT:
if (s->currevp == NULL)
s->currevp = TAILQ_FIRST(&s->task->envelopes);
- mta_send(s, "RCPT TO: <%s>", s->currevp->dest);
+ mta_send(s, "RCPT TO:<%s>", s->currevp->dest);
+ s->rcptcount++;
break;
case MTA_DATA:
@@ -604,6 +618,11 @@ mta_enter_state(struct mta_session *s, int newstate)
mta_send(s, ".");
break;
+ case MTA_LMTP_EOM:
+ /* LMTP reports status of each delivery, so enable read */
+ io_set_read(&s->io);
+ break;
+
case MTA_RSET:
if (s->datafp) {
fclose(s->datafp);
@@ -635,7 +654,10 @@ mta_response(struct mta_session *s, char *line)
switch (s->state) {
case MTA_BANNER:
- mta_enter_state(s, MTA_EHLO);
+ if (s->flags & MTA_LMTP)
+ mta_enter_state(s, MTA_LHLO);
+ else
+ mta_enter_state(s, MTA_EHLO);
break;
case MTA_EHLO:
@@ -665,6 +687,15 @@ mta_response(struct mta_session *s, char *line)
mta_enter_state(s, MTA_READY);
break;
+ case MTA_LHLO:
+ if (line[0] != '2') {
+ mta_error(s, "LHLO rejected: %s", line);
+ s->flags |= MTA_FREE;
+ return;
+ }
+ mta_enter_state(s, MTA_READY);
+ break;
+
case MTA_STARTTLS:
if (line[0] != '2') {
if (!(s->flags & MTA_WANT_SECURE)) {
@@ -695,7 +726,7 @@ mta_response(struct mta_session *s, char *line)
delivery = IMSG_DELIVERY_PERMFAIL;
else
delivery = IMSG_DELIVERY_TEMPFAIL;
- mta_flush_task(s, delivery, line);
+ mta_flush_task(s, delivery, line, 0);
mta_enter_state(s, MTA_RSET);
return;
}
@@ -722,7 +753,7 @@ mta_response(struct mta_session *s, char *line)
if (TAILQ_EMPTY(&s->task->envelopes)) {
mta_flush_task(s, IMSG_DELIVERY_OK,
- "No envelope");
+ "No envelope", 0);
mta_enter_state(s, MTA_RSET);
break;
}
@@ -742,10 +773,11 @@ mta_response(struct mta_session *s, char *line)
delivery = IMSG_DELIVERY_PERMFAIL;
else
delivery = IMSG_DELIVERY_TEMPFAIL;
- mta_flush_task(s, delivery, line);
+ mta_flush_task(s, delivery, line, 0);
mta_enter_state(s, MTA_RSET);
break;
+ case MTA_LMTP_EOM:
case MTA_EOM:
if (line[0] == '2') {
delivery = IMSG_DELIVERY_OK;
@@ -755,8 +787,14 @@ mta_response(struct mta_session *s, char *line)
delivery = IMSG_DELIVERY_PERMFAIL;
else
delivery = IMSG_DELIVERY_TEMPFAIL;
- mta_flush_task(s, delivery, line);
- mta_enter_state(s, MTA_READY);
+ mta_flush_task(s, delivery, line, (s->flags & MTA_LMTP) ? 1 : 0 );
+ if (s->task) {
+ s->rcptcount--;
+ mta_enter_state(s, MTA_LMTP_EOM);
+ } else {
+ s->rcptcount = 0;
+ mta_enter_state(s, MTA_READY);
+ }
break;
case MTA_RSET:
@@ -871,7 +909,6 @@ mta_io(struct io *io, int evt)
mta_free(s);
return;
}
-
io_set_write(io);
mta_response(s, line);
if (s->flags & MTA_FREE) {
@@ -975,7 +1012,7 @@ mta_queue_data(struct mta_session *s)
if (ferror(s->datafp)) {
mta_flush_task(s, IMSG_DELIVERY_TEMPFAIL,
- "Error reading content file");
+ "Error reading content file", 0);
return (-1);
}
@@ -988,7 +1025,7 @@ mta_queue_data(struct mta_session *s)
}
static void
-mta_flush_task(struct mta_session *s, int delivery, const char *error)
+mta_flush_task(struct mta_session *s, int delivery, const char *error, size_t count)
{
struct mta_envelope *e;
char relay[MAX_LINE_SIZE];
@@ -998,6 +1035,12 @@ mta_flush_task(struct mta_session *s, int delivery, const char *error)
n = 0;
while ((e = TAILQ_FIRST(&s->task->envelopes))) {
+
+ if (count && n == count) {
+ stat_decrement("mta.envelope", n);
+ return;
+ }
+
TAILQ_REMOVE(&s->task->envelopes, e, entry);
mta_delivery(e, relay, delivery, error);
free(e->dest);
@@ -1053,7 +1096,7 @@ mta_error(struct mta_session *s, const char *fmt, ...)
mta_route_error(s->relay, s->route);
if (s->task)
- mta_flush_task(s, IMSG_DELIVERY_TEMPFAIL, error);
+ mta_flush_task(s, IMSG_DELIVERY_TEMPFAIL, error, 0);
free(error);
}
@@ -1203,6 +1246,7 @@ mta_strstate(int state)
CASE(MTA_DATA);
CASE(MTA_BODY);
CASE(MTA_EOM);
+ CASE(MTA_LMTP_EOM);
CASE(MTA_RSET);
CASE(MTA_QUIT);
default: