(original) (raw)

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;