From 6ff5d981ef950ce43909eb8b623729118cd89ffc Mon Sep 17 00:00:00 2001 From: Gilles Chehade Date: Thu, 20 Dec 2018 20:42:44 +0100 Subject: sync --- smtpd/mta_session.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++---- smtpd/smtp_session.c | 22 +++++++++- smtpd/ssl.c | 4 +- 3 files changed, 128 insertions(+), 12 deletions(-) diff --git a/smtpd/mta_session.c b/smtpd/mta_session.c index 644cac17..755ac86d 100644 --- a/smtpd/mta_session.c +++ b/smtpd/mta_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta_session.c,v 1.113 2018/10/31 15:13:21 gilles Exp $ */ +/* $OpenBSD: mta_session.c,v 1.114 2018/12/17 11:14:56 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -150,6 +150,10 @@ static void mta_response(struct mta_session *, char *); static const char * mta_strstate(int); static void mta_start_tls(struct mta_session *); static int mta_verify_certificate(struct mta_session *); +static void mta_cert_init(struct mta_session *); +static void mta_cert_init_cb(void *, int, const char *, const void *, size_t); +static void mta_cert_verify(struct mta_session *); +static void mta_cert_verify_cb(void *, int); static void mta_tls_verified(struct mta_session *); static struct mta_session *mta_tree_pop(struct tree *, uint64_t); static const char * dsn_strret(enum dsn_ret); @@ -937,7 +941,7 @@ mta_response(struct mta_session *s, char *line) return; } - mta_start_tls(s); + mta_cert_init(s); break; case MTA_AUTH_PLAIN: @@ -1149,7 +1153,7 @@ mta_io(struct io *io, int evt, void *arg) if (s->use_smtps) { io_set_write(io); - mta_start_tls(s); + mta_cert_init(s); } else { mta_enter_state(s, MTA_BANNER); @@ -1162,12 +1166,7 @@ mta_io(struct io *io, int evt, void *arg) s->id, ssl_to_text(io_ssl(s->io))); s->flags |= MTA_TLS; - if (mta_verify_certificate(s)) { - io_pause(s->io, IO_IN); - break; - } - - mta_tls_verified(s); + mta_cert_verify(s); break; case IO_DATAIN: @@ -1655,6 +1654,103 @@ mta_verify_certificate(struct mta_session *s) return res; } +static void +mta_cert_init(struct mta_session *s) +{ + const char *name; + int fallback; + + if (s->relay->pki_name) { + name = s->relay->pki_name; + fallback = 0; + } + else { + name = s->helo; + fallback = 1; + } + + if (cert_init(name, fallback, mta_cert_init_cb, s)) { + tree_xset(&wait_ssl_init, s->id, s); + s->flags |= MTA_WAIT; + } +} + +static void +mta_cert_init_cb(void *arg, int status, const char *name, const void *cert, + size_t cert_len) +{ + struct mta_session *s = arg; + void *ssl; + char *xname = NULL, *xcert = NULL; + + if (s->flags & MTA_WAIT) + mta_tree_pop(&wait_ssl_init, s->id); + + if (status == CA_FAIL && s->relay->pki_name) { + log_info("%016"PRIx64" mta closing reason=ca-failure", s->id); + mta_free(s); + return; + } + + if (name) + xname = xstrdup(name); + if (cert) + xcert = xmemdup(cert, cert_len); + ssl = ssl_mta_init(xname, xcert, cert_len, env->sc_tls_ciphers); + free(xname); + free(xcert); + if (ssl == NULL) + fatal("mta: ssl_mta_init"); + io_start_tls(s->io, ssl); +} + +static void +mta_cert_verify(struct mta_session *s) +{ + const char *name; + int fallback; + + if (s->relay->ca_name) { + name = s->relay->ca_name; + fallback = 0; + } + else { + name = s->helo; + fallback = 1; + } + + if (cert_verify(io_ssl(s->io), name, fallback, mta_cert_verify_cb, s)) { + tree_xset(&wait_ssl_verify, s->id, s); + io_pause(s->io, IO_IN); + s->flags |= MTA_WAIT; + } +} + +static void +mta_cert_verify_cb(void *arg, int status) +{ + struct mta_session *s = arg; + int resume = 0; + + if (s->flags & MTA_WAIT) { + mta_tree_pop(&wait_ssl_verify, s->id); + resume = 1; + } + + if (status == CERT_OK) + s->flags |= MTA_TLS_VERIFIED; + else if (s->relay->flags & RELAY_TLS_VERIFY) { + errno = 0; + mta_error(s, "SSL certificate check failed"); + mta_free(s); + return; + } + + mta_tls_verified(s); + if (resume) + io_resume(s->io, IO_IN); +} + static void mta_tls_verified(struct mta_session *s) { diff --git a/smtpd/smtp_session.c b/smtpd/smtp_session.c index 6928a5ce..80d6ab5c 100644 --- a/smtpd/smtp_session.c +++ b/smtpd/smtp_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp_session.c,v 1.375 2018/12/14 09:18:03 eric Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.376 2018/12/20 17:57:44 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -1314,18 +1314,26 @@ smtp_command(struct smtp_session *s, char *line) * ANY */ case CMD_QUIT: + if (!smtp_check_noparam(s, args)) + break; smtp_filter_phase(FILTER_QUIT, s, NULL); break; case CMD_NOOP: + if (!smtp_check_noparam(s, args)) + break; smtp_filter_phase(FILTER_NOOP, s, NULL); break; case CMD_HELP: + if (!smtp_check_noparam(s, args)) + break; smtp_proceed_help(s, NULL); break; case CMD_WIZ: + if (!smtp_check_noparam(s, args)) + break; smtp_proceed_wiz(s, NULL); break; @@ -1340,6 +1348,9 @@ smtp_command(struct smtp_session *s, char *line) static int smtp_check_rset(struct smtp_session *s, const char *args) { + if (!smtp_check_noparam(s, args)) + return 0; + if (s->helo[0] == '\0') { smtp_reply(s, "503 %s %s: Command not allowed at this point.", esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), @@ -1547,6 +1558,9 @@ smtp_check_rcpt_to(struct smtp_session *s, const char *args) static int smtp_check_data(struct smtp_session *s, const char *args) { + if (!smtp_check_noparam(s, args)) + return 0; + if (s->tx == NULL) { smtp_reply(s, "503 %s %s: Command not allowed at this point.", esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), @@ -1567,6 +1581,12 @@ smtp_check_data(struct smtp_session *s, const char *args) static int smtp_check_noparam(struct smtp_session *s, const char *args) { + if (args != NULL) { + smtp_reply(s, "500 %s %s: command does not accept arguments.", + esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), + esc_description(ESC_INVALID_COMMAND_ARGUMENTS)); + return 0; + } return 1; } diff --git a/smtpd/ssl.c b/smtpd/ssl.c index cd29f5cf..7cbee563 100644 --- a/smtpd/ssl.c +++ b/smtpd/ssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.c,v 1.89 2017/05/17 14:00:06 deraadt Exp $ */ +/* $OpenBSD: ssl.c,v 1.90 2018/12/20 19:40:13 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -328,7 +328,7 @@ ssl_to_text(const SSL *ssl) { static char buf[256]; - (void)snprintf(buf, sizeof buf, "version=%s, cipher=%s, bits=%d", + (void)snprintf(buf, sizeof buf, "%s:%s:%d", SSL_get_version(ssl), SSL_get_cipher_name(ssl), SSL_get_cipher_bits(ssl, NULL)); -- cgit v1.2.3-59-g8ed1b