untrusted comment: signature from openbsd 5.7 base secret key
RWSvUZXnw9gUb8smQUXkRDAGHvHDTOQFniVsBdx+zL0f0wobZgQ5MJ+GmXI7mYqlrg+ZRNLfW4NqrSzaoiQmhupoxxr/Di/zPww=

OpenBSD 5.7 errata 4, Apr 19, 2015

Incorrect logic in smtpd(8) can lead to unexpected client disconnect, invalid
certificate in SNI negotiation or server crash.

Apply by doing:
    signify -Vep /etc/signify/openbsd-57-base.pub -x 004_smtpd.patch.sig \
	-m - | (cd /usr/src && patch -p0)

And then rebuild and install smtpd:
    cd /usr/src/usr.sbin/smtpd
    make clean
    make obj
    make
    make install

Index: usr.sbin/smtpd/smtp_session.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtp_session.c,v
retrieving revision 1.227
diff -u -p -r1.227 smtp_session.c
--- usr.sbin/smtpd/smtp_session.c	20 Jan 2015 17:37:54 -0000	1.227
+++ usr.sbin/smtpd/smtp_session.c	16 Apr 2015 21:53:47 -0000
@@ -191,6 +191,7 @@ static uint8_t dsn_notify_str_to_uint8(c
 static void smtp_auth_failure_pause(struct smtp_session *);
 static void smtp_auth_failure_resume(int, short, void *);
 static int smtp_sni_callback(SSL *, int *, void *);
+static const char *smtp_sni_get_servername(struct smtp_session *);
 
 static void smtp_filter_connect(struct smtp_session *, struct sockaddr *);
 static void smtp_filter_rset(struct smtp_session *);
@@ -852,7 +853,7 @@ smtp_session_imsg(struct mproc *p, struc
 			pkiname = s->smtpname;
 		ssl_ctx = dict_get(env->sc_ssl_dict, pkiname);
 
-		ssl = ssl_smtp_init(ssl_ctx, smtp_sni_callback, s);
+		ssl = ssl_smtp_init(ssl_ctx, smtp_sni_callback);
 		io_set_read(&s->io);
 		io_start_tls(&s->io, ssl);
 
@@ -1031,6 +1032,7 @@ smtp_io(struct io *io, int evt)
 {
 	struct ca_cert_req_msg	req_ca_cert;
 	struct smtp_session    *s = io->arg;
+	const char	       *sn;
 	char		       *line;
 	size_t			len, i;
 	X509		       *x;
@@ -1048,6 +1050,14 @@ smtp_io(struct io *io, int evt)
 		s->kickcount = 0;
 		s->phase = PHASE_INIT;
 
+		sn = smtp_sni_get_servername(s);
+		if (sn) {
+			if (strlcpy(s->sni, sn, sizeof s->sni) >= sizeof s->sni) {
+				smtp_free(s, "client SNI exceeds max hostname length");
+				return;
+			}
+		}
+
 		if (smtp_verify_certificate(s)) {
 			io_pause(&s->io, IO_PAUSE_IN);
 			break;
@@ -2139,26 +2149,24 @@ smtp_auth_failure_pause(struct smtp_sess
 	evtimer_add(&s->pause, &tv);
 }
 
+static const char *
+smtp_sni_get_servername(struct smtp_session *s)
+{
+	return SSL_get_servername(s->io.ssl, TLSEXT_NAMETYPE_host_name);
+}
+
 static int
 smtp_sni_callback(SSL *ssl, int *ad, void *arg)
 {
 	const char		*sn;
-	struct smtp_session	*s = arg;
 	void			*ssl_ctx;
 
 	sn = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
 	if (sn == NULL)
 		return SSL_TLSEXT_ERR_NOACK;
-	if (strlcpy(s->sni, sn, sizeof s->sni) >= sizeof s->sni) {
-		log_warnx("warn: client SNI exceeds max hostname length");
-		return SSL_TLSEXT_ERR_NOACK;
-	}
 	ssl_ctx = dict_get(env->sc_ssl_dict, sn);
-	if (ssl_ctx == NULL) {
-		log_info("smtp-in: No PKI entry for requested SNI \"%s\""
-		    "on session %016"PRIx64, sn, s->id);
+	if (ssl_ctx == NULL)
 		return SSL_TLSEXT_ERR_NOACK;
-	}
 	SSL_set_SSL_CTX(ssl, ssl_ctx);
 	return SSL_TLSEXT_ERR_OK;
 }
Index: usr.sbin/smtpd/smtpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
retrieving revision 1.473
diff -u -p -r1.473 smtpd.h
--- usr.sbin/smtpd/smtpd.h	20 Jan 2015 17:37:54 -0000	1.473
+++ usr.sbin/smtpd/smtpd.h	16 Apr 2015 21:53:47 -0000
@@ -1322,7 +1322,7 @@ int fork_proc_backend(const char *, cons
 
 /* ssl_smtpd.c */
 void   *ssl_mta_init(void *, char *, off_t);
-void   *ssl_smtp_init(void *, void *, void *);
+void   *ssl_smtp_init(void *, void *);
 
 
 /* stat_backend.c */
Index: usr.sbin/smtpd/ssl_smtpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/ssl_smtpd.c,v
retrieving revision 1.8
diff -u -p -r1.8 ssl_smtpd.c
--- usr.sbin/smtpd/ssl_smtpd.c	16 Jan 2015 06:40:21 -0000	1.8
+++ usr.sbin/smtpd/ssl_smtpd.c	16 Apr 2015 21:53:47 -0000
@@ -82,7 +82,7 @@ dummy_verify(int ok, X509_STORE_CTX *sto
 }
 
 void *
-ssl_smtp_init(void *ssl_ctx, void *sni, void *arg)
+ssl_smtp_init(void *ssl_ctx, void *sni)
 {
 	SSL	*ssl = NULL;
 	int	(*cb)(SSL *,int *,void *) = sni;
@@ -91,10 +91,8 @@ ssl_smtp_init(void *ssl_ctx, void *sni, 
 
 	SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, dummy_verify);
 
-	if (cb) {
+	if (cb)
 		SSL_CTX_set_tlsext_servername_callback(ssl_ctx, cb);
-		SSL_CTX_set_tlsext_servername_arg(ssl_ctx, arg);
-	}
 
 	if ((ssl = SSL_new(ssl_ctx)) == NULL)
 		goto err;
