(original) (raw)
untrusted comment: signature from openbsd 5.5 base secret key RWRGy8gxk9N931CONa3Rep7IsqK0x8/o5LJou3kfXmvowPYqjSiZsKvrcB2jyLssTopiAdrOsPuO+BweIGzb9yHwSafmoYgkEAQ= OpenBSD 5.5 errata 25, 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-55-base.pub -x 025_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.196 diff -u -p -r1.196 smtp_session.c --- usr.sbin/smtpd/smtp_session.c 17 Feb 2014 11:06:54 -0000 1.196 +++ usr.sbin/smtpd/smtp_session.c 16 Apr 2015 21:53:25 -0000 @@ -181,6 +181,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 struct { int code; const char *cmd; } commands[] = { { CMD_HELO, "HELO" }, @@ -607,7 +608,7 @@ smtp_session_imsg(struct mproc *p, struc ssl = ssl_smtp_init(ssl_ctx, resp_ca_cert->cert, resp_ca_cert->cert_len, resp_ca_cert->key, resp_ca_cert->key_len, - smtp_sni_callback, s); + smtp_sni_callback); io_set_read(&s->io); io_start_tls(&s->io, ssl); @@ -787,6 +788,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; @@ -804,6 +806,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; @@ -1901,25 +1911,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_warnx("warn: SNI name not found in PKI"); + 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.450 diff -u -p -r1.450 smtpd.h --- usr.sbin/smtpd/smtpd.h 17 Feb 2014 13:33:56 -0000 1.450 +++ usr.sbin/smtpd/smtpd.h 16 Apr 2015 21:53:25 -0000 @@ -1307,7 +1307,7 @@ const char *imsg_to_str(int); /* ssl_smtpd.c */ void *ssl_mta_init(char *, off_t, char *, off_t); -void *ssl_smtp_init(void *, char *, off_t, char *, off_t, void *, void *); +void *ssl_smtp_init(void *, char *, off_t, char *, off_t, 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.4 diff -u -p -r1.4 ssl_smtpd.c --- usr.sbin/smtpd/ssl_smtpd.c 4 Feb 2014 13:44:41 -0000 1.4 +++ usr.sbin/smtpd/ssl_smtpd.c 16 Apr 2015 21:53:26 -0000 @@ -90,7 +90,7 @@ dummy_verify(int ok, X509_STORE_CTX *sto } void * -ssl_smtp_init(void *ssl_ctx, char *cert, off_t cert_len, char *key, off_t key_len, void *sni, void *arg) +ssl_smtp_init(void *ssl_ctx, char *cert, off_t cert_len, char *key, off_t key_len, void *sni) { SSL *ssl = NULL; int (*cb)(SSL *,int *,void *) = sni; @@ -105,10 +105,8 @@ ssl_smtp_init(void *ssl_ctx, char *cert, 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;