diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2009-01-29 14:25:56 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2009-01-29 14:25:56 +0000 |
commit | 813bf8297c6faabefd6be200241e585fc37d20c3 (patch) | |
tree | df10d7c9aa02faa81a228678a5d3dd6ac61355c8 | |
parent | 6b77a74991237d6fb8714007089d8bf544fd3704 (diff) |
initial starttls support in mta, this allows:
accept for domain "openbsd.org" relay via tls "mx.example.org"
to ensure the relaying of mail for whoever@openbsd.org will happen through
a secure tls (STARTTLS) session. failure to establish a tls session will be
considered as a permanent failure. As a side effect:
accept for domain "openbsd.org" relay via ssl "mx.example.org"
can now work as well and ensure that the relaying happens through ssmtp OR
tls, but never through an unsafe channel. no need to specify a port, they
are automatically detected if not specified.
still a work in progress, don't expect that it will work flawlessly.
-rw-r--r-- | usr.sbin/smtpd/mta.c | 36 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 5 | ||||
-rw-r--r-- | usr.sbin/smtpd/ssl.c | 9 |
3 files changed, 45 insertions, 5 deletions
diff --git a/usr.sbin/smtpd/mta.c b/usr.sbin/smtpd/mta.c index 5a13c33b37e..3bda0eb63a3 100644 --- a/usr.sbin/smtpd/mta.c +++ b/usr.sbin/smtpd/mta.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta.c,v 1.22 2009/01/29 13:00:12 gilles Exp $ */ +/* $OpenBSD: mta.c,v 1.23 2009/01/29 14:25:55 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -546,10 +546,13 @@ mta_reply_handler(struct bufferevent *bev, void *arg) batchp->status |= S_BATCH_PERMFAILURE; strlcpy(batchp->errorline, line, MAX_LINE_SIZE); mta_batch_update_queue(batchp); + session_destroy(sessionp); return 0; } if (line[3] == '-') { + if (strcasecmp(&line[4], "STARTTLS") == 0) + sessionp->s_flags |= F_PEERHASTLS; return 1; } @@ -557,11 +560,38 @@ mta_reply_handler(struct bufferevent *bev, void *arg) case 250: if (sessionp->s_state == S_DONE) { mta_batch_update_queue(batchp); + session_destroy(sessionp); + return 0; + } + + if (sessionp->s_state == S_GREETED && + (sessionp->s_flags & F_PEERHASTLS) && + !(sessionp->s_flags & F_SECURE)) { + session_respond(sessionp, "STARTTLS"); + sessionp->s_state = S_TLS; + return 0; + } + + if (sessionp->s_state == S_GREETED && + !(sessionp->s_flags & F_PEERHASTLS) && + sessionp->mxarray[sessionp->mx_off].flags & F_STARTTLS) { + /* PERM - we want TLS but it is not advertised */ + batchp->status |= S_BATCH_PERMFAILURE; + mta_batch_update_queue(batchp); + session_destroy(sessionp); return 0; } + break; case 220: + if (sessionp->s_state == S_TLS) { + ssl_client_init(sessionp); + bufferevent_disable(bev, EV_READ|EV_WRITE); + sessionp->s_state = S_GREETED; + return 0; + } + session_respond(sessionp, "EHLO %s", env->sc_hostname); sessionp->s_state = S_GREETED; return 1; @@ -572,6 +602,7 @@ mta_reply_handler(struct bufferevent *bev, void *arg) batchp->status |= S_BATCH_TEMPFAILURE; strlcpy(batchp->errorline, line, MAX_LINE_SIZE); mta_batch_update_queue(batchp); + session_destroy(sessionp); return 0; /* The following codes are state dependant and will cause @@ -593,6 +624,7 @@ mta_reply_handler(struct bufferevent *bev, void *arg) case 221: if (sessionp->s_state == S_DONE) { mta_batch_update_queue(batchp); + session_destroy(sessionp); return 0; } @@ -607,6 +639,7 @@ mta_reply_handler(struct bufferevent *bev, void *arg) batchp->status |= S_BATCH_PERMFAILURE; strlcpy(batchp->errorline, line, MAX_LINE_SIZE); mta_batch_update_queue(batchp); + session_destroy(sessionp); return 0; } @@ -683,6 +716,7 @@ mta_reply_handler(struct bufferevent *bev, void *arg) if (messagep == NULL) { batchp->status |= S_BATCH_PERMFAILURE; mta_batch_update_queue(batchp); + session_destroy(sessionp); return 0; } } diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index ae124674101..c3a588594f5 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.58 2009/01/29 13:00:12 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.59 2009/01/29 14:25:55 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -568,7 +568,8 @@ enum session_flags { F_QUIT = 0x2, F_8BITMIME = 0x4, F_SECURE = 0x8, - F_AUTHENTICATED = 0x10 + F_AUTHENTICATED = 0x10, + F_PEERHASTLS = 0x20 }; struct session { diff --git a/usr.sbin/smtpd/ssl.c b/usr.sbin/smtpd/ssl.c index 49f7d1238c7..377bf726e1a 100644 --- a/usr.sbin/smtpd/ssl.c +++ b/usr.sbin/smtpd/ssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.c,v 1.6 2009/01/29 13:00:12 gilles Exp $ */ +/* $OpenBSD: ssl.c,v 1.7 2009/01/29 14:25:55 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -99,8 +99,13 @@ ssl_connect(int fd, short event, void *p) event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); log_info("ssl_connect: connected to remote ssl server"); - bufferevent_enable(s->s_bev, EV_READ); + bufferevent_enable(s->s_bev, EV_READ|EV_WRITE); s->s_flags |= F_SECURE; + + if (s->s_flags & F_PEERHASTLS) { + session_respond(s, "EHLO %s", s->s_env->sc_hostname); + } + return; retry: event_add(&s->s_ev, &s->s_tv); |