summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2009-01-29 14:25:56 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2009-01-29 14:25:56 +0000
commit813bf8297c6faabefd6be200241e585fc37d20c3 (patch)
treedf10d7c9aa02faa81a228678a5d3dd6ac61355c8
parent6b77a74991237d6fb8714007089d8bf544fd3704 (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.c36
-rw-r--r--usr.sbin/smtpd/smtpd.h5
-rw-r--r--usr.sbin/smtpd/ssl.c9
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);