Been running it for a few days, no regressions so far
> On 5 Feb 2021, at 09:35, Eric Faurot <e...@openbsd.org> wrote:
>
> No much report so far.
> Anybody had a chance to test this?
> Here is the same diff again with manpage update this time.
>
> Eric.
>
> Index: ca.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/ca.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 ca.c
> --- ca.c 31 Dec 2020 08:27:15 -0000 1.37
> +++ ca.c 19 Jan 2021 11:09:54 -0000
> @@ -69,6 +69,7 @@ static int ecdsae_do_verify(const unsign
> EC_KEY *);
>
>
> +static struct dict pkeys;
> static uint64_t reqid = 0;
>
> static void
> @@ -132,26 +133,29 @@ ca_init(void)
> struct pki *pki;
> const char *k;
> void *iter_dict;
> + char *hash;
>
> log_debug("debug: init private ssl-tree");
> + dict_init(&pkeys);
> iter_dict = NULL;
> while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
> if (pki->pki_key == NULL)
> continue;
>
> - if ((in = BIO_new_mem_buf(pki->pki_key,
> - pki->pki_key_len)) == NULL)
> - fatalx("ca_launch: key");
> -
> - if ((pkey = PEM_read_bio_PrivateKey(in,
> - NULL, NULL, NULL)) == NULL)
> - fatalx("ca_launch: PEM");
> + in = BIO_new_mem_buf(pki->pki_key, pki->pki_key_len);
> + if (in == NULL)
> + fatalx("ca_init: key");
> + pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
> + if (pkey == NULL)
> + fatalx("ca_init: PEM");
> BIO_free(in);
>
> - pki->pki_pkey = pkey;
> -
> - freezero(pki->pki_key, pki->pki_key_len);
> - pki->pki_key = NULL;
> + hash = ssl_pubkey_hash(pki->pki_cert, pki->pki_cert_len);
> + if (dict_check(&pkeys, hash))
> + EVP_PKEY_free(pkey);
> + else
> + dict_xset(&pkeys, hash, pkey);
> + free(hash);
> }
> }
>
> @@ -223,15 +227,15 @@ end:
> void
> ca_imsg(struct mproc *p, struct imsg *imsg)
> {
> + EVP_PKEY *pkey;
> RSA *rsa = NULL;
> EC_KEY *ecdsa = NULL;
> const void *from = NULL;
> unsigned char *to = NULL;
> struct msg m;
> - const char *pkiname;
> + const char *hash;
> size_t flen, tlen, padding;
> int buf_len;
> - struct pki *pki;
> int ret = 0;
> uint64_t id;
> int v;
> @@ -267,16 +271,15 @@ ca_imsg(struct mproc *p, struct imsg *im
> case IMSG_CA_RSA_PRIVDEC:
> m_msg(&m, imsg);
> m_get_id(&m, &id);
> - m_get_string(&m, &pkiname);
> + m_get_string(&m, &hash);
> m_get_data(&m, &from, &flen);
> m_get_size(&m, &tlen);
> m_get_size(&m, &padding);
> m_end(&m);
>
> - pki = dict_get(env->sc_pki_dict, pkiname);
> - if (pki == NULL || pki->pki_pkey == NULL ||
> - (rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL)
> - fatalx("ca_imsg: invalid pki");
> + pkey = dict_get(&pkeys, hash);
> + if (pkey == NULL || (rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
> + fatalx("ca_imsg: invalid pkey hash");
>
> if ((to = calloc(1, tlen)) == NULL)
> fatalx("ca_imsg: calloc");
> @@ -306,14 +309,14 @@ ca_imsg(struct mproc *p, struct imsg *im
> case IMSG_CA_ECDSA_SIGN:
> m_msg(&m, imsg);
> m_get_id(&m, &id);
> - m_get_string(&m, &pkiname);
> + m_get_string(&m, &hash);
> m_get_data(&m, &from, &flen);
> m_end(&m);
>
> - pki = dict_get(env->sc_pki_dict, pkiname);
> - if (pki == NULL || pki->pki_pkey == NULL ||
> - (ecdsa = EVP_PKEY_get1_EC_KEY(pki->pki_pkey)) == NULL)
> - fatalx("ca_imsg: invalid pki");
> + pkey = dict_get(&pkeys, hash);
> + if (pkey == NULL ||
> + (ecdsa = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
> + fatalx("ca_imsg: invalid pkey hash");
>
> buf_len = ECDSA_size(ecdsa);
> if ((to = calloc(1, buf_len)) == NULL)
> @@ -350,12 +353,12 @@ rsae_send_imsg(int flen, const unsigned
> struct imsg imsg;
> int n, done = 0;
> const void *toptr;
> - char *pkiname;
> + char *hash;
> size_t tlen;
> struct msg m;
> uint64_t id;
>
> - if ((pkiname = RSA_get_ex_data(rsa, 0)) == NULL)
> + if ((hash = RSA_get_ex_data(rsa, 0)) == NULL)
> return (0);
>
> /*
> @@ -365,7 +368,7 @@ rsae_send_imsg(int flen, const unsigned
> m_create(p_ca, cmd, 0, 0, -1);
> reqid++;
> m_add_id(p_ca, reqid);
> - m_add_string(p_ca, pkiname);
> + m_add_string(p_ca, hash);
> m_add_data(p_ca, (const void *)from, (size_t)flen);
> m_add_size(p_ca, (size_t)RSA_size(rsa));
> m_add_size(p_ca, (size_t)padding);
> @@ -536,13 +539,13 @@ ecdsae_send_enc_imsg(const unsigned char
> struct imsg imsg;
> int n, done = 0;
> const void *toptr;
> - char *pkiname;
> + char *hash;
> size_t tlen;
> struct msg m;
> uint64_t id;
> ECDSA_SIG *sig = NULL;
>
> - if ((pkiname = ECDSA_get_ex_data(eckey, 0)) == NULL)
> + if ((hash = ECDSA_get_ex_data(eckey, 0)) == NULL)
> return (0);
>
> /*
> @@ -552,7 +555,7 @@ ecdsae_send_enc_imsg(const unsigned char
> m_create(p_ca, IMSG_CA_ECDSA_SIGN, 0, 0, -1);
> reqid++;
> m_add_id(p_ca, reqid);
> - m_add_string(p_ca, pkiname);
> + m_add_string(p_ca, hash);
> m_add_data(p_ca, (const void *)dgst, (size_t)dgst_len);
> m_flush(p_ca);
>
> Index: config.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/config.c,v
> retrieving revision 1.53
> diff -u -p -r1.53 config.c
> --- config.c 19 Jan 2021 09:16:20 -0000 1.53
> +++ config.c 19 Jan 2021 11:47:07 -0000
> @@ -252,6 +252,7 @@ purge_config(uint8_t what)
> if (what & PURGE_LISTENERS) {
> while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) {
> TAILQ_REMOVE(env->sc_listeners, l, entry);
> + free(l->pki);
> free(l);
> }
> free(env->sc_listeners);
> Index: dispatcher.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/dispatcher.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 dispatcher.c
> --- dispatcher.c 31 Dec 2020 08:27:15 -0000 1.1
> +++ dispatcher.c 19 Jan 2021 11:04:32 -0000
> @@ -154,6 +154,8 @@ dispatcher(void)
> {
> struct passwd *pw;
>
> + ca_engine_init();
> +
> mda_postfork();
> mta_postfork();
> smtp_postfork();
> @@ -195,8 +197,6 @@ dispatcher(void)
> config_peer(PROC_LKA);
> config_peer(PROC_CONTROL);
> config_peer(PROC_CA);
> -
> - ca_engine_init();
>
> if (pledge("stdio inet unix recvfd sendfd", NULL) == -1)
> err(1, "pledge");
> Index: iobuf.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/iobuf.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 iobuf.c
> --- iobuf.c 23 Jan 2021 16:11:11 -0000 1.14
> +++ iobuf.c 25 Jan 2021 11:14:58 -0000
> @@ -21,15 +21,14 @@
>
> #include <errno.h>
> #include <limits.h>
> +#include <stdarg.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> -#include <unistd.h>
> -
> #ifdef IO_TLS
> -#include <openssl/err.h>
> -#include <openssl/ssl.h>
> +#include <tls.h>
> #endif
> +#include <unistd.h>
>
> #include "iobuf.h"
>
> @@ -388,7 +387,7 @@ iobuf_flush(struct iobuf *io, int fd)
> #ifdef IO_TLS
>
> int
> -iobuf_flush_tls(struct iobuf *io, void *tls)
> +iobuf_flush_tls(struct iobuf *io, struct tls *tls)
> {
> ssize_t s;
>
> @@ -400,55 +399,42 @@ iobuf_flush_tls(struct iobuf *io, void *
> }
>
> ssize_t
> -iobuf_write_tls(struct iobuf *io, void *tls)
> +iobuf_write_tls(struct iobuf *io, struct tls *tls)
> {
> struct ioqbuf *q;
> ssize_t n;
>
> q = io->outq;
> - n = SSL_write(tls, q->buf + q->rpos, q->wpos - q->rpos);
> - if (n <= 0) {
> - switch (SSL_get_error(tls, n)) {
> - case SSL_ERROR_WANT_READ:
> - return (IOBUF_WANT_READ);
> - case SSL_ERROR_WANT_WRITE:
> - return (IOBUF_WANT_WRITE);
> - case SSL_ERROR_ZERO_RETURN: /* connection closed */
> - return (IOBUF_CLOSED);
> - case SSL_ERROR_SYSCALL:
> - if (ERR_peek_last_error())
> - return (IOBUF_TLSERROR);
> - return (IOBUF_ERROR);
> - default:
> - return (IOBUF_TLSERROR);
> - }
> - }
> +
> + n = tls_write(tls, q->buf + q->rpos, q->wpos - q->rpos);
> + if (n == TLS_WANT_POLLIN)
> + return (IOBUF_WANT_READ);
> + else if (n == TLS_WANT_POLLOUT)
> + return (IOBUF_WANT_WRITE);
> + else if (n == 0)
> + return (IOBUF_CLOSED);
> + else if (n == -1)
> + return (IOBUF_ERROR);
> +
> iobuf_drain(io, n);
>
> return (n);
> }
>
> ssize_t
> -iobuf_read_tls(struct iobuf *io, void *tls)
> +iobuf_read_tls(struct iobuf *io, struct tls *tls)
> {
> ssize_t n;
>
> - n = SSL_read(tls, io->buf + io->wpos, iobuf_left(io));
> - if (n < 0) {
> - switch (SSL_get_error(tls, n)) {
> - case SSL_ERROR_WANT_READ:
> - return (IOBUF_WANT_READ);
> - case SSL_ERROR_WANT_WRITE:
> - return (IOBUF_WANT_WRITE);
> - case SSL_ERROR_SYSCALL:
> - if (ERR_peek_last_error())
> - return (IOBUF_TLSERROR);
> - return (IOBUF_ERROR);
> - default:
> - return (IOBUF_TLSERROR);
> - }
> - } else if (n == 0)
> + n = tls_read(tls, io->buf + io->wpos, iobuf_left(io));
> + if (n == TLS_WANT_POLLIN)
> + return (IOBUF_WANT_READ);
> + else if (n == TLS_WANT_POLLOUT)
> + return (IOBUF_WANT_WRITE);
> + else if (n == 0)
> return (IOBUF_CLOSED);
> + else if (n == -1)
> + return (IOBUF_ERROR);
>
> io->wpos += n;
>
> Index: iobuf.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/iobuf.h,v
> retrieving revision 1.5
> diff -u -p -r1.5 iobuf.h
> --- iobuf.h 12 Jun 2019 17:42:53 -0000 1.5
> +++ iobuf.h 25 Jan 2021 11:14:33 -0000
> @@ -35,11 +35,12 @@ struct iobuf {
> struct ioqbuf *outqlast;
> };
>
> +struct tls;
> +
> #define IOBUF_WANT_READ -1
> #define IOBUF_WANT_WRITE -2
> #define IOBUF_CLOSED -3
> #define IOBUF_ERROR -4
> -#define IOBUF_TLSERROR -5
>
> int iobuf_init(struct iobuf *, size_t, size_t);
> void iobuf_clear(struct iobuf *);
> @@ -53,7 +54,7 @@ size_t iobuf_left(struct iobuf *);
> char *iobuf_data(struct iobuf *);
> char *iobuf_getline(struct iobuf *, size_t *);
> ssize_t iobuf_read(struct iobuf *, int);
> -ssize_t iobuf_read_tls(struct iobuf *, void *);
> +ssize_t iobuf_read_tls(struct iobuf *, struct tls *);
>
> size_t iobuf_queued(struct iobuf *);
> void* iobuf_reserve(struct iobuf *, size_t);
> @@ -62,6 +63,6 @@ int iobuf_queuev(struct iobuf *, const s
> int iobuf_fqueue(struct iobuf *, const char *, ...);
> int iobuf_vfqueue(struct iobuf *, const char *, va_list);
> int iobuf_flush(struct iobuf *, int);
> -int iobuf_flush_tls(struct iobuf *, void *);
> +int iobuf_flush_tls(struct iobuf *, struct tls *);
> ssize_t iobuf_write(struct iobuf *, int);
> -ssize_t iobuf_write_tls(struct iobuf *, void *);
> +ssize_t iobuf_write_tls(struct iobuf *, struct tls *);
> Index: ioev.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/ioev.c,v
> retrieving revision 1.43
> diff -u -p -r1.43 ioev.c
> --- ioev.c 23 Jan 2021 16:11:11 -0000 1.43
> +++ ioev.c 25 Jan 2021 11:16:47 -0000
> @@ -27,16 +27,14 @@
> #include <stdlib.h>
> #include <string.h>
> #include <stdio.h>
> +#ifdef IO_TLS
> +#include <tls.h>
> +#endif
> #include <unistd.h>
>
> #include "ioev.h"
> #include "iobuf.h"
>
> -#ifdef IO_TLS
> -#include <openssl/err.h>
> -#include <openssl/ssl.h>
> -#endif
> -
> enum {
> IO_STATE_NONE,
> IO_STATE_CONNECT,
> @@ -65,7 +63,9 @@ struct io {
> int flags;
> int state;
> struct event ev;
> - void *tls;
> + struct tls *tls;
> + char *name;
> +
> const char *error; /* only valid immediately on callback */
> };
>
> @@ -85,9 +85,7 @@ void io_frame_enter(const char *, struct
> void io_frame_leave(struct io *);
>
> #ifdef IO_TLS
> -void ssl_error(const char *); /* XXX external */
> -
> -static const char* io_tls_error(void);
> +void io_dispatch_handshake_tls(int, short, void *);
> void io_dispatch_accept_tls(int, short, void *);
> void io_dispatch_connect_tls(int, short, void *);
> void io_dispatch_read_tls(int, short, void *);
> @@ -111,10 +109,9 @@ io_strio(struct io *io)
> ssl[0] = '\0';
> #ifdef IO_TLS
> if (io->tls) {
> - (void)snprintf(ssl, sizeof ssl, " tls=%s:%s:%d",
> - SSL_get_version(io->tls),
> - SSL_get_cipher_name(io->tls),
> - SSL_get_cipher_bits(io->tls, NULL));
> + (void)snprintf(ssl, sizeof ssl, " tls=%s:%s",
> + tls_conn_version(io->tls),
> + tls_conn_cipher(io->tls));
> }
> #endif
>
> @@ -272,7 +269,7 @@ io_free(struct io *io)
> current = NULL;
>
> #ifdef IO_TLS
> - SSL_free(io->tls);
> + tls_free(io->tls);
> io->tls = NULL;
> #endif
>
> @@ -283,6 +280,7 @@ io_free(struct io *io)
> io->sock = -1;
> }
>
> + free(io->name);
> iobuf_clear(&io->iobuf);
> free(io);
> }
> @@ -397,7 +395,7 @@ io_error(struct io *io)
> return io->error;
> }
>
> -void *
> +struct tls *
> io_tls(struct io *io)
> {
> return io->tls;
> @@ -807,57 +805,85 @@ io_dispatch_connect(int fd, short ev, vo
> }
>
> #ifdef IO_TLS
> -
> -static const char*
> -io_tls_error(void)
> +int
> +io_connect_tls(struct io *io, struct tls *tls, const char *hostname)
> {
> - static char buf[128];
> - unsigned long e;
> + int mode;
> +
> + mode = io->flags & IO_RW;
> + if (mode != IO_WRITE)
> + errx(1, "io_connect_tls: expect IO_WRITE mode");
> +
> + if (io->tls)
> + errx(1, "io_connect_tls: TLS already started");
>
> - e = ERR_peek_last_error();
> - if (e) {
> - ERR_error_string(e, buf);
> - return (buf);
> + if (hostname) {
> + if ((io->name = strdup(hostname)) == NULL)
> + err(1, "io_connect_tls");
> }
>
> - return ("No TLS error");
> + io->tls = tls;
> + io->state = IO_STATE_CONNECT_TLS;
> + io_reset(io, EV_WRITE, io_dispatch_connect_tls);
> +
> + return (0);
> }
>
> int
> -io_start_tls(struct io *io, void *tls)
> +io_accept_tls(struct io *io, struct tls *tls)
> {
> int mode;
>
> mode = io->flags & IO_RW;
> - if (mode == 0 || mode == IO_RW)
> - errx(1, "io_start_tls(): full-duplex or unset");
> + if (mode != IO_READ)
> + errx(1, "io_connect_tls: expect IO_READ mode");
>
> if (io->tls)
> errx(1, "io_start_tls(): TLS already started");
> io->tls = tls;
> + io->state = IO_STATE_ACCEPT_TLS;
> + io_reset(io, EV_READ, io_dispatch_accept_tls);
> +
> + return (0);
> +}
>
> - if (SSL_set_fd(io->tls, io->sock) == 0) {
> - ssl_error("io_start_tls:SSL_set_fd");
> - return (-1);
> +void
> +io_dispatch_handshake_tls(int fd, short event, void *humppa)
> +{
> + struct io *io = humppa;
> + int ret;
> +
> + io_frame_enter("io_dispatch_handshake_tls", io, event);
> +
> + if (event == EV_TIMEOUT) {
> + io_callback(io, IO_TIMEOUT);
> + goto leave;
> }
>
> - if (mode == IO_WRITE) {
> - io->state = IO_STATE_CONNECT_TLS;
> - SSL_set_connect_state(io->tls);
> - io_reset(io, EV_WRITE, io_dispatch_connect_tls);
> - } else {
> - io->state = IO_STATE_ACCEPT_TLS;
> - SSL_set_accept_state(io->tls);
> - io_reset(io, EV_READ, io_dispatch_accept_tls);
> + if ((ret = tls_handshake(io->tls)) == 0) {
> + io->state = IO_STATE_UP;
> + io_callback(io, IO_TLSREADY);
> + goto leave;
> + }
> + if (ret == TLS_WANT_POLLIN)
> + io_reset(io, EV_READ, io_dispatch_handshake_tls);
> + else if (ret == TLS_WANT_POLLOUT)
> + io_reset(io, EV_WRITE, io_dispatch_handshake_tls);
> + else {
> + io->error = tls_error(io->tls);
> + io_callback(io, IO_ERROR);
> }
>
> - return (0);
> + leave:
> + io_frame_leave(io);
> + return;
> }
>
> void
> io_dispatch_accept_tls(int fd, short event, void *humppa)
> {
> struct io *io = humppa;
> + struct tls *cctx = NULL;
> int ret;
>
> io_frame_enter("io_dispatch_accept_tls", io, event);
> @@ -867,28 +893,17 @@ io_dispatch_accept_tls(int fd, short eve
> goto leave;
> }
>
> - if ((ret = SSL_accept(io->tls)) > 0) {
> - io->state = IO_STATE_UP;
> - io_callback(io, IO_TLSREADY);
> + if ((ret = tls_accept_socket(io->tls, &cctx, io->sock)) == 0) {
> + io->tls = cctx;
> + io_reset(io, EV_READ|EV_WRITE, io_dispatch_handshake_tls);
> goto leave;
> }
> + io->error = tls_error(io->tls);
> + io_callback(io, IO_ERROR);
>
> - switch (SSL_get_error(io->tls, ret)) {
> - case SSL_ERROR_WANT_READ:
> - io_reset(io, EV_READ, io_dispatch_accept_tls);
> - break;
> - case SSL_ERROR_WANT_WRITE:
> - io_reset(io, EV_WRITE, io_dispatch_accept_tls);
> - break;
> - default:
> - io->error = io_tls_error();
> - ssl_error("io_dispatch_accept_tls:SSL_accept");
> - io_callback(io, IO_ERROR);
> - break;
> - }
> -
> - leave:
> + leave:
> io_frame_leave(io);
> + return;
> }
>
> void
> @@ -904,27 +919,15 @@ io_dispatch_connect_tls(int fd, short ev
> goto leave;
> }
>
> - if ((ret = SSL_connect(io->tls)) > 0) {
> - io->state = IO_STATE_UP;
> - io_callback(io, IO_TLSREADY);
> + if ((ret = tls_connect_socket(io->tls, io->sock, io->name)) == 0) {
> + io_reset(io, EV_READ|EV_WRITE, io_dispatch_handshake_tls);
> goto leave;
> }
>
> - switch (SSL_get_error(io->tls, ret)) {
> - case SSL_ERROR_WANT_READ:
> - io_reset(io, EV_READ, io_dispatch_connect_tls);
> - break;
> - case SSL_ERROR_WANT_WRITE:
> - io_reset(io, EV_WRITE, io_dispatch_connect_tls);
> - break;
> - default:
> - io->error = io_tls_error();
> - ssl_error("io_dispatch_connect_ssl:SSL_connect");
> - io_callback(io, IO_TLSERROR);
> - break;
> - }
> + io->error = tls_error(io->tls);
> + io_callback(io, IO_ERROR);
>
> - leave:
> + leave:
> io_frame_leave(io);
> }
>
> @@ -932,7 +935,7 @@ void
> io_dispatch_read_tls(int fd, short event, void *humppa)
> {
> struct io *io = humppa;
> - int n, saved_errno;
> + int n;
>
> io_frame_enter("io_dispatch_read_tls", io, event);
>
> @@ -943,7 +946,7 @@ io_dispatch_read_tls(int fd, short event
>
> again:
> iobuf_normalize(&io->iobuf);
> - switch ((n = iobuf_read_tls(&io->iobuf, (SSL*)io->tls))) {
> + switch ((n = iobuf_read_tls(&io->iobuf, io->tls))) {
> case IOBUF_WANT_READ:
> io_reset(io, EV_READ, io_dispatch_read_tls);
> break;
> @@ -954,20 +957,13 @@ again:
> io_callback(io, IO_DISCONNECTED);
> break;
> case IOBUF_ERROR:
> - saved_errno = errno;
> - io->error = strerror(errno);
> - errno = saved_errno;
> - io_callback(io, IO_ERROR);
> - break;
> - case IOBUF_TLSERROR:
> - io->error = io_tls_error();
> - ssl_error("io_dispatch_read_tls:SSL_read");
> + io->error = tls_error(io->tls);
> io_callback(io, IO_ERROR);
> break;
> default:
> io_debug("io_dispatch_read_tls(...) -> r=%d\n", n);
> io_callback(io, IO_DATAIN);
> - if (current == io && IO_READING(io) && SSL_pending(io->tls))
> + if (current == io && IO_READING(io))
> goto again;
> }
>
> @@ -979,7 +975,7 @@ void
> io_dispatch_write_tls(int fd, short event, void *humppa)
> {
> struct io *io = humppa;
> - int n, saved_errno;
> + int n;
> size_t w2, w;
>
> io_frame_enter("io_dispatch_write_tls", io, event);
> @@ -990,7 +986,7 @@ io_dispatch_write_tls(int fd, short even
> }
>
> w = io_queued(io);
> - switch ((n = iobuf_write_tls(&io->iobuf, (SSL*)io->tls))) {
> + switch ((n = iobuf_write_tls(&io->iobuf, io->tls))) {
> case IOBUF_WANT_READ:
> io_reset(io, EV_READ, io_dispatch_write_tls);
> break;
> @@ -1001,14 +997,7 @@ io_dispatch_write_tls(int fd, short even
> io_callback(io, IO_DISCONNECTED);
> break;
> case IOBUF_ERROR:
> - saved_errno = errno;
> - io->error = strerror(errno);
> - errno = saved_errno;
> - io_callback(io, IO_ERROR);
> - break;
> - case IOBUF_TLSERROR:
> - io->error = io_tls_error();
> - ssl_error("io_dispatch_write_tls:SSL_write");
> + io->error = tls_error(io->tls);
> io_callback(io, IO_ERROR);
> break;
> default:
> Index: ioev.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/ioev.h,v
> retrieving revision 1.18
> diff -u -p -r1.18 ioev.h
> --- ioev.h 11 Sep 2019 04:19:19 -0000 1.18
> +++ ioev.h 18 Jan 2021 19:58:19 -0000
> @@ -18,7 +18,6 @@
> enum {
> IO_CONNECTED = 0, /* connection successful */
> IO_TLSREADY, /* TLS started successfully */
> - IO_TLSERROR, /* XXX - needs more work */
> IO_DATAIN, /* new data in input buffer */
> IO_LOWAT, /* output queue running low */
> IO_DISCONNECTED, /* error? */
> @@ -30,6 +29,7 @@ enum {
> #define IO_OUT 0x02
>
> struct io;
> +struct tls;
>
> void io_set_nonblocking(int);
> void io_set_nolinger(int);
> @@ -46,11 +46,12 @@ void io_pause(struct io *, int);
> void io_resume(struct io *, int);
> void io_reload(struct io *);
> int io_connect(struct io *, const struct sockaddr *, const struct sockaddr *);
> -int io_start_tls(struct io *, void *);
> +int io_connect_tls(struct io *, struct tls *, const char *);
> +int io_accept_tls(struct io *, struct tls *);
> const char* io_strio(struct io *);
> const char* io_strevent(int);
> const char* io_error(struct io *);
> -void* io_tls(struct io *);
> +struct tls* io_tls(struct io *);
> int io_fileno(struct io *);
> int io_paused(struct io *, int);
>
> Index: mta.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/mta.c,v
> retrieving revision 1.234
> diff -u -p -r1.234 mta.c
> --- mta.c 21 Dec 2019 10:34:07 -0000 1.234
> +++ mta.c 22 Jan 2021 09:00:21 -0000
> @@ -38,10 +38,12 @@
> #include <stdlib.h>
> #include <string.h>
> #include <time.h>
> +#include <tls.h>
> #include <unistd.h>
>
> #include "smtpd.h"
> #include "log.h"
> +#include "ssl.h"
>
> #define MAXERROR_PER_ROUTE 4
>
> @@ -57,6 +59,7 @@
> #define RELAY_ONHOLD 0x01
> #define RELAY_HOLDQ 0x02
>
> +static void mta_setup_dispatcher(struct dispatcher *);
> static void mta_handle_envelope(struct envelope *, const char *);
> static void mta_query_smarthost(struct envelope *);
> static void mta_on_smarthost(struct envelope *, const char *);
> @@ -138,6 +141,12 @@ int mta_is_blocked(struct mta_source *,
> static int mta_block_cmp(const struct mta_block *, const struct mta_block *);
> SPLAY_PROTOTYPE(mta_block_tree, mta_block, entry, mta_block_cmp);
>
> +/*
> + * This function is not publicy exported because it is a hack until libtls
> + * has a proper privsep setup
> + */
> +void tls_config_use_fake_private_key(struct tls_config *config);
> +
> static struct mta_relay_tree relays;
> static struct mta_domain_tree domains;
> static struct mta_host_tree hosts;
> @@ -463,6 +472,70 @@ mta_imsg(struct mproc *p, struct imsg *i
> void
> mta_postfork(void)
> {
> + struct dispatcher *dispatcher;
> + const char *key;
> + void *iter;
> +
> + iter = NULL;
> + while (dict_iter(env->sc_dispatchers, &iter, &key, (void
> **)&dispatcher)) {
> + log_debug("%s: %s", __func__, key);
> + mta_setup_dispatcher(dispatcher);
> + }
> +}
> +
> +static void
> +mta_setup_dispatcher(struct dispatcher *dispatcher)
> +{
> + struct dispatcher_remote *remote;
> + static const char *dheparams[] = { "none", "auto", "legacy" };
> + struct tls_config *config;
> + struct pki *pki;
> + struct ca *ca;
> +
> + if (dispatcher->type != DISPATCHER_REMOTE)
> + return;
> +
> + remote = &dispatcher->u.remote;
> +
> + if ((config = tls_config_new()) == NULL)
> + fatal("smtpd: tls_config_new");
> +
> + if (env->sc_tls_ciphers) {
> + if (tls_config_set_ciphers(config, env->sc_tls_ciphers) == -1)
> + err(1, "%s", tls_config_error(config));
> + }
> +
> + if (remote->pki) {
> + pki = dict_get(env->sc_pki_dict, remote->pki);
> + if (pki == NULL)
> + err(1, "client pki \"%s\" not found ", remote->pki);
> +
> + tls_config_set_dheparams(config, dheparams[pki->pki_dhe]);
> + tls_config_use_fake_private_key(config);
> + if (tls_config_set_keypair_mem(config, pki->pki_cert,
> + pki->pki_cert_len, NULL, 0) == -1)
> + fatal("tls_config_set_keypair_mem");
> + }
> +
> + if (remote->ca) {
> + ca = dict_get(env->sc_ca_dict, remote->ca);
> + if (tls_config_set_ca_mem(config, ca->ca_cert, ca->ca_cert_len)
> + == -1)
> + fatal("tls_config_set_ca_mem");
> + }
> + else if (tls_config_set_ca_file(config, tls_default_ca_cert_file())
> + == -1)
> + fatal("tls_config_set_ca_file");
> +
> + if (remote->tls_noverify) {
> + tls_config_insecure_noverifycert(config);
> + tls_config_insecure_noverifyname(config);
> + tls_config_insecure_noverifytime(config);
> + }
> + else
> + tls_config_verify(config);
> +
> + remote->tls_config = config;
> }
>
> void
> Index: mta_session.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/mta_session.c,v
> retrieving revision 1.138
> diff -u -p -r1.138 mta_session.c
> --- mta_session.c 21 Dec 2020 11:44:07 -0000 1.138
> +++ mta_session.c 19 Jan 2021 10:09:32 -0000
> @@ -43,6 +43,7 @@
> #include <stdlib.h>
> #include <string.h>
> #include <time.h>
> +#include <tls.h>
> #include <unistd.h>
>
> #include "smtpd.h"
> @@ -153,11 +154,8 @@ static void mta_send(struct mta_session
> static ssize_t mta_queue_data(struct mta_session *);
> static void mta_response(struct mta_session *, char *);
> static const char * mta_strstate(int);
> -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 void mta_tls_init(struct mta_session *);
> +static void mta_tls_started(struct mta_session *);
> static struct mta_session *mta_tree_pop(struct tree *, uint64_t);
> static const char * dsn_strret(enum dsn_ret);
> static const char * dsn_strnotify(uint8_t);
> @@ -974,7 +972,7 @@ mta_response(struct mta_session *s, char
> return;
> }
>
> - mta_cert_init(s);
> + mta_tls_init(s);
> break;
>
> case MTA_AUTH_PLAIN:
> @@ -1229,7 +1227,7 @@ mta_io(struct io *io, int evt, void *arg
>
> if (s->use_smtps) {
> io_set_write(io);
> - mta_cert_init(s);
> + mta_tls_init(s);
> }
> else {
> mta_enter_state(s, MTA_BANNER);
> @@ -1239,13 +1237,14 @@ mta_io(struct io *io, int evt, void *arg
>
> case IO_TLSREADY:
> log_info("%016"PRIx64" mta tls ciphers=%s",
> - s->id, ssl_to_text(io_tls(s->io)));
> + s->id, tls_to_text(io_tls(s->io)));
> s->flags |= MTA_TLS;
> + if (!s->relay->dispatcher->u.remote.tls_noverify)
> + s->flags |= MTA_TLS_VERIFIED;
>
> + mta_tls_started(s);
> mta_report_link_tls(s,
> - ssl_to_text(io_tls(s->io)));
> -
> - mta_cert_verify(s);
> + tls_to_text(io_tls(s->io)));
> break;
>
> case IO_DATAIN:
> @@ -1378,7 +1377,6 @@ mta_io(struct io *io, int evt, void *arg
> break;
>
> case IO_ERROR:
> - case IO_TLSERROR:
> log_debug("debug: mta: %p: IO error: %s", s, io_error(io));
>
> if (s->state == MTA_STARTTLS && s->use_smtp_tls) {
> @@ -1579,152 +1577,42 @@ mta_error(struct mta_session *s, const c
> }
>
> 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_tls_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)
> +mta_tls_init(struct mta_session *s)
> {
> - struct mta_session *s = arg;
> - void *ssl;
> - char *xname = NULL, *xcert = NULL;
> - union {
> - struct in_addr in4;
> - struct in6_addr in6;
> - } addrbuf;
> -
> - if (s->flags & MTA_WAIT)
> - mta_tree_pop(&wait_tls_init, s->id);
> + struct tls_config *tls_config;
> + struct tls *tls;
>
> - if (status == CA_FAIL && s->relay->pki_name) {
> - log_info("%016"PRIx64" mta closing reason=ca-failure", s->id);
> + if ((tls = tls_client()) == NULL) {
> + log_info("%016"PRIx64" mta closing reason=tls-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");
> -
> - /*
> - * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
> - * permitted in "HostName".
> - */
> - if (s->relay->domain->as_host == 1) {
> - if (inet_pton(AF_INET, s->relay->domain->name, &addrbuf) != 1 &&
> - inet_pton(AF_INET6, s->relay->domain->name, &addrbuf) != 1)
> {
> - log_debug("%016"PRIx64" mta tls setting SNI name=%s",
> - s->id, s->relay->domain->name);
> - if (SSL_set_tlsext_host_name(ssl,
> s->relay->domain->name) == 0)
> - log_warnx("%016"PRIx64" mta tls setting SNI
> failed",
> - s->id);
> - }
> - }
> -
> - 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_tls(s->io), name, fallback, mta_cert_verify_cb, s)) {
> - tree_xset(&wait_tls_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 match, resume = 0;
> - X509 *cert;
> -
> - if (s->flags & MTA_WAIT) {
> - mta_tree_pop(&wait_tls_verify, s->id);
> - resume = 1;
> - }
> -
> - if (status == CERT_OK) {
> - cert = SSL_get_peer_certificate(io_tls(s->io));
> - if (!cert)
> - status = CERT_NOCERT;
> - else {
> - match = 0;
> - (void)ssl_check_name(cert, s->mxname, &match);
> - X509_free(cert);
> - if (!match) {
> - log_info("%016"PRIx64" mta "
> - "ssl_check_name: no match for '%s' in cert",
> - s->id, s->mxname);
> - status = CERT_INVALID;
> - }
> - }
> - }
> -
> - 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");
> + tls_config = s->relay->dispatcher->u.remote.tls_config;
> + if (tls_configure(tls, tls_config) == -1) {
> + log_info("%016"PRIx64" mta closing reason=tls-failure", s->id);
> + tls_free(tls);
> mta_free(s);
> return;
> }
>
> - mta_tls_verified(s);
> - if (resume)
> - io_resume(s->io, IO_IN);
> + io_connect_tls(s->io, tls, s->route->dst->ptrname);
> }
>
> static void
> -mta_tls_verified(struct mta_session *s)
> +mta_tls_started(struct mta_session *s)
> {
> - X509 *x;
> -
> - x = SSL_get_peer_certificate(io_tls(s->io));
> - if (x) {
> - log_info("%016"PRIx64" mta "
> - "server-cert-check result=\"%s\"",
> - s->id,
> - (s->flags & MTA_TLS_VERIFIED) ? "success" : "failure");
> - X509_free(x);
> + if (tls_peer_cert_provided(io_tls(s->io))) {
> + log_info("%016"PRIx64" mta "
> + "cert-check result=\"%s\" fingerprint=\"%s\"",
> + s->id,
> + (s->flags & MTA_TLS_VERIFIED) ? "valid" : "unverified",
> + tls_peer_cert_hash(io_tls(s->io)));
> + }
> + else {
> + log_info("%016"PRIx64" smtp "
> + "cert-check result=\"no certificate presented\"",
> + s->id);
> }
>
> if (s->use_smtps) {
> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
> retrieving revision 1.284
> diff -u -p -r1.284 parse.y
> --- parse.y 23 Jan 2021 16:11:11 -0000 1.284
> +++ parse.y 25 Jan 2021 07:19:15 -0000
> @@ -128,13 +128,15 @@ enum listen_options {
> LO_PROXY = 0x008000,
> };
>
> +#define PKI_MAX 32
> static struct listen_opts {
> char *ifx;
> int family;
> in_port_t port;
> uint16_t ssl;
> char *filtername;
> - char *pki;
> + char *pki[PKI_MAX];
> + int pkicount;
> char *ca;
> uint16_t auth;
> struct table *authtable;
> @@ -2316,12 +2318,11 @@ opt_if_listen : INET4 {
> listen_opts.ssl =
> F_STARTTLS|F_STARTTLS_REQUIRE|F_TLS_VERIFY;
> }
> | PKI STRING {
> - if (listen_opts.options & LO_PKI) {
> - yyerror("pki already specified");
> + if (listen_opts.pkicount == PKI_MAX) {
> + yyerror("too many pki specified");
> YYERROR;
> }
> - listen_opts.options |= LO_PKI;
> - listen_opts.pki = $2;
> + listen_opts.pki[listen_opts.pkicount++] = $2;
> }
> | CA STRING {
> if (listen_opts.options & LO_CA) {
> @@ -3221,8 +3222,10 @@ create_if_listener(struct listen_opts *l
> if (lo->auth != 0 && !lo->ssl)
> errx(1, "invalid listen option: auth requires tls/smtps");
>
> - if (lo->pki && !lo->ssl)
> + if (lo->pkicount && !lo->ssl)
> errx(1, "invalid listen option: pki requires tls/smtps");
> + if (lo->pkicount == 0 && lo->ssl)
> + errx(1, "invalid listen option: pki required for tls/smtps");
>
> flags = lo->flags;
>
> @@ -3259,6 +3262,8 @@ create_if_listener(struct listen_opts *l
> static void
> config_listener(struct listener *h, struct listen_opts *lo)
> {
> + int i;
> +
> h->fd = -1;
> h->port = lo->port;
> h->flags = lo->flags;
> @@ -3273,17 +3278,19 @@ config_listener(struct listener *h, str
> sizeof(h->filter_name));
> }
>
> - h->pki_name[0] = '\0';
> -
> if (lo->authtable != NULL)
> (void)strlcpy(h->authtable, lo->authtable->t_name,
> sizeof(h->authtable));
> - if (lo->pki != NULL) {
> - if (!lowercase(h->pki_name, lo->pki, sizeof(h->pki_name))) {
> - log_warnx("pki name too long: %s", lo->pki);
> - fatalx(NULL);
> - }
> - if (dict_get(conf->sc_pki_dict, h->pki_name) == NULL) {
> - log_warnx("pki name not found: %s", lo->pki);
> +
> + h->pkicount = lo->pkicount;
> + if (h->pkicount) {
> + h->pki = calloc(h->pkicount, sizeof(*h->pki));
> + if (h->pki == NULL)
> + fatal("calloc");
> + }
> + for (i = 0; i < lo->pkicount; i++) {
> + h->pki[i] = dict_get(conf->sc_pki_dict, lo->pki[i]);
> + if (h->pki[i] == NULL) {
> + log_warnx("pki name not found: %s", lo->pki[i]);
> fatalx(NULL);
> }
> }
> Index: smtp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtp.c,v
> retrieving revision 1.166
> diff -u -p -r1.166 smtp.c
> --- smtp.c 10 Aug 2019 16:07:01 -0000 1.166
> +++ smtp.c 22 Jan 2021 09:00:46 -0000
> @@ -34,6 +34,7 @@
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> +#include <tls.h>
> #include <unistd.h>
>
> #include <openssl/ssl.h>
> @@ -50,7 +51,7 @@ static void smtp_dropped(struct listener
> static int smtp_enqueue(void);
> static int smtp_can_accept(void);
> static void smtp_setup_listeners(void);
> -static int smtp_sni_callback(SSL *, int *, void *);
> +static void smtp_setup_listener_tls(struct listener *);
>
> int
> proxy_session(struct listener *listener, int sock,
> @@ -62,6 +63,11 @@ proxy_session(struct listener *listener,
>
> static void smtp_accepted(struct listener *, int, const struct
> sockaddr_storage *, struct io *);
>
> +/*
> + * This function are not publicy exported because it is a hack until libtls
> + * has a proper privsep setup
> + */
> +void tls_config_use_fake_private_key(struct tls_config *config);
>
> #define SMTP_FD_RESERVE 5
> static size_t sessions;
> @@ -145,6 +151,10 @@ smtp_setup_listeners(void)
> }
> fatal("smtpd: socket");
> }
> +
> + if (l->flags & F_SSL)
> + smtp_setup_listener_tls(l);
> +
> opt = 1;
> if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, &opt,
> sizeof(opt)) == -1)
> @@ -155,19 +165,77 @@ smtp_setup_listeners(void)
> }
>
> static void
> +smtp_setup_listener_tls(struct listener *l)
> +{
> + static const char *dheparams[] = { "none", "auto", "legacy" };
> + struct tls_config *config;
> + struct pki *pki;
> + struct ca *ca;
> + int i;
> +
> + if ((config = tls_config_new()) == NULL)
> + fatal("smtpd: tls_config_new");
> +
> + if (env->sc_tls_ciphers &&
> + tls_config_set_ciphers(config, env->sc_tls_ciphers) == -1)
> + err(1, "%s", tls_config_error(config));
> +
> + pki = l->pki[0];
> + if (pki == NULL)
> + fatal("no pki defined");
> +
> + if (tls_config_set_dheparams(config, dheparams[pki->pki_dhe]) == -1)
> + fatal("tls_config_set_dheparams");
> +
> + tls_config_use_fake_private_key(config);
> + for (i = 0; i < l->pkicount; i++) {
> + pki = l->pki[i];
> + if (i == 0) {
> + if (tls_config_set_keypair_mem(config, pki->pki_cert,
> + pki->pki_cert_len, NULL, 0) == -1)
> + fatal("tls_config_set_keypair_mem");
> + } else {
> + if (tls_config_add_keypair_mem(config, pki->pki_cert,
> + pki->pki_cert_len, NULL, 0) == -1)
> + fatal("tls_config_add_keypair_mem");
> + }
> + }
> + free(l->pki);
> + l->pkicount = 0;
> +
> + if (l->ca_name[0]) {
> + ca = dict_get(env->sc_ca_dict, l->ca_name);
> + if (tls_config_set_ca_mem(config, ca->ca_cert, ca->ca_cert_len)
> + == -1)
> + fatal("tls_config_set_ca_mem");
> + }
> + else if (tls_config_set_ca_file(config, tls_default_ca_cert_file())
> + == -1)
> + fatal("tls_config_set_ca_file");
> +
> + if (l->flags & F_TLS_VERIFY)
> + tls_config_verify_client(config);
> + else
> + tls_config_verify_client_optional(config);
> +
> + l->tls = tls_server();
> + if (l->tls == NULL)
> + fatal("tls_server");
> + if (tls_configure(l->tls, config) == -1) {
> + fatal("tls_configure: %s", tls_error(l->tls));
> + }
> + tls_config_free(config);
> +}
> +
> +
> +static void
> smtp_setup_events(void)
> {
> struct listener *l;
> - struct pki *pki;
> - SSL_CTX *ssl_ctx;
> - void *iter;
> - const char *k;
>
> TAILQ_FOREACH(l, env->sc_listeners, entry) {
> - log_debug("debug: smtp: listen on %s port %d flags 0x%01x"
> - " pki \"%s\""
> - " ca \"%s\"", ss_to_text(&l->ss), ntohs(l->port),
> - l->flags, l->pki_name, l->ca_name);
> + log_debug("debug: smtp: listen on %s port %d flags 0x%01x",
> + ss_to_text(&l->ss), ntohs(l->port), l->flags);
>
> io_set_nonblocking(l->fd);
> if (listen(l->fd, SMTPD_BACKLOG) == -1)
> @@ -178,14 +246,6 @@ smtp_setup_events(void)
> event_add(&l->ev, NULL);
> }
>
> - iter = NULL;
> - while (dict_iter(env->sc_pki_dict, &iter, &k, (void **)&pki)) {
> - if (!ssl_setup((SSL_CTX **)&ssl_ctx, pki, smtp_sni_callback,
> - env->sc_tls_ciphers))
> - fatal("smtp_setup_events: ssl_setup failure");
> - dict_xset(env->sc_ssl_dict, k, ssl_ctx);
> - }
> -
> purge_config(PURGE_PKI_KEYS);
>
> maxsessions = (getdtablesize() - getdtablecount()) / 2 -
> SMTP_FD_RESERVE;
> @@ -317,22 +377,6 @@ smtp_collect(void)
> env->sc_flags &= ~SMTPD_SMTP_DISABLED;
> smtp_resume();
> }
> -}
> -
> -static int
> -smtp_sni_callback(SSL *ssl, int *ad, void *arg)
> -{
> - const char *sn;
> - void *ssl_ctx;
> -
> - sn = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
> - if (sn == NULL)
> - return SSL_TLSEXT_ERR_NOACK;
> - ssl_ctx = dict_get(env->sc_ssl_dict, sn);
> - if (ssl_ctx == NULL)
> - return SSL_TLSEXT_ERR_NOACK;
> - SSL_set_SSL_CTX(ssl, ssl_ctx);
> - return SSL_TLSEXT_ERR_OK;
> }
>
> static void
> Index: smtp.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtp.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 smtp.h
> --- smtp.h 2 Sep 2019 20:05:21 -0000 1.3
> +++ smtp.h 19 Jan 2021 09:41:16 -0000
> @@ -46,6 +46,7 @@ struct smtp_params {
> /* TLS options */
> int tls_req; /* requested TLS mode */
> int tls_verify; /* need valid server
> certificate */
> + const char *tls_servname; /* SNI */
>
> /* SMTP options */
> int lmtp; /* use LMTP protocol */
> Index: smtp_client.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtp_client.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 smtp_client.c
> --- smtp_client.c 24 Apr 2020 11:34:07 -0000 1.14
> +++ smtp_client.c 19 Jan 2021 09:44:34 -0000
> @@ -187,7 +187,7 @@ smtp_cert_verified(struct smtp_client *p
> void
> smtp_set_tls(struct smtp_client *proto, void *ctx)
> {
> - io_start_tls(proto->io, ctx);
> + io_connect_tls(proto->io, ctx, proto->params.tls_servname);
> }
>
> void
> @@ -624,8 +624,13 @@ smtp_client_io(struct io *io, int evt, v
>
> case IO_TLSREADY:
> proto->flags |= FLAG_TLS;
> - io_pause(proto->io, IO_IN);
> - smtp_verify_server_cert(proto->tag, proto, io_tls(proto->io));
> + if (proto->state == STATE_INIT)
> + smtp_client_state(proto, STATE_BANNER);
> + else {
> + /* Clear extensions before re-issueing an EHLO command.
> */
> + proto->ext = 0;
> + smtp_client_state(proto, STATE_EHLO);
> + }
> break;
>
> case IO_DATAIN:
> @@ -646,10 +651,6 @@ smtp_client_io(struct io *io, int evt, v
> break;
>
> case IO_ERROR:
> - smtp_client_abort(proto, FAIL_CONN, io_error(io));
> - break;
> -
> - case IO_TLSERROR:
> smtp_client_abort(proto, FAIL_CONN, io_error(io));
> break;
>
> Index: smtp_session.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtp_session.c,v
> retrieving revision 1.428
> diff -u -p -r1.428 smtp_session.c
> --- smtp_session.c 21 Dec 2020 11:44:07 -0000 1.428
> +++ smtp_session.c 19 Jan 2021 11:06:22 -0000
> @@ -38,6 +38,7 @@
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> +#include <tls.h>
> #include <unistd.h>
> #include <vis.h>
>
> @@ -184,7 +185,8 @@ static void smtp_getnameinfo_cb(void *,
> static void smtp_getaddrinfo_cb(void *, int, struct addrinfo *);
> static void smtp_connected(struct smtp_session *);
> static void smtp_send_banner(struct smtp_session *);
> -static void smtp_tls_verified(struct smtp_session *);
> +static void smtp_tls_init(struct smtp_session *);
> +static void smtp_tls_started(struct smtp_session *);
> static void smtp_io(struct io *, int, void *);
> static void smtp_enter_state(struct smtp_session *, int);
> static void smtp_reply(struct smtp_session *, char *, ...);
> @@ -193,10 +195,6 @@ static void smtp_rfc4954_auth_plain(stru
> static void smtp_rfc4954_auth_login(struct smtp_session *, char *);
> static void smtp_free(struct smtp_session *, const char *);
> static const char *smtp_strstate(int);
> -static void smtp_cert_init(struct smtp_session *);
> -static void smtp_cert_init_cb(void *, int, const char *, const void *,
> size_t);
> -static void smtp_cert_verify(struct smtp_session *);
> -static void smtp_cert_verify_cb(void *, int);
> static void smtp_auth_failure_pause(struct smtp_session *);
> static void smtp_auth_failure_resume(int, short, void *);
>
> @@ -1066,17 +1064,26 @@ smtp_session_imsg(struct mproc *p, struc
> }
>
> static void
> -smtp_tls_verified(struct smtp_session *s)
> +smtp_tls_init(struct smtp_session *s)
> {
> - X509 *x;
> + io_set_read(s->io);
> + io_accept_tls(s->io, s->listener->tls);
> +}
>
> - x = SSL_get_peer_certificate(io_tls(s->io));
> - if (x) {
> +static void
> +smtp_tls_started(struct smtp_session *s)
> +{
> + if (tls_peer_cert_provided(io_tls(s->io))) {
> log_info("%016"PRIx64" smtp "
> - "client-cert-check result=\"%s\"",
> + "cert-check result=\"%s\" fingerprint=\"%s\"",
> s->id,
> - (s->flags & SF_VERIFIED) ? "success" : "failure");
> - X509_free(x);
> + (s->flags & SF_VERIFIED) ? "verified" : "unchecked",
> + tls_peer_cert_hash(io_tls(s->io)));
> + }
> + else {
> + log_info("%016"PRIx64" smtp "
> + "cert-check result=\"no certificate presented\"",
> + s->id);
> }
>
> if (s->listener->flags & F_SMTPS) {
> @@ -1105,14 +1112,16 @@ smtp_io(struct io *io, int evt, void *ar
>
> case IO_TLSREADY:
> log_info("%016"PRIx64" smtp tls ciphers=%s",
> - s->id, ssl_to_text(io_tls(s->io)));
> + s->id, tls_to_text(io_tls(s->io)));
>
> - smtp_report_link_tls(s, ssl_to_text(io_tls(s->io)));
> + smtp_report_link_tls(s, tls_to_text(io_tls(s->io)));
>
> s->flags |= SF_SECURE;
> + if (s->listener->flags & F_TLS_VERIFY)
> + s->flags |= SF_VERIFIED;
> s->helo[0] = '\0';
>
> - smtp_cert_verify(s);
> + smtp_tls_started(s);
> break;
>
> case IO_DATAIN:
> @@ -1193,7 +1202,7 @@ smtp_io(struct io *io, int evt, void *ar
>
> /* Wait for the client to start tls */
> if (s->state == STATE_TLS) {
> - smtp_cert_init(s);
> + smtp_tls_init(s);
> break;
> }
>
> @@ -2071,7 +2080,7 @@ static void
> smtp_proceed_connected(struct smtp_session *s)
> {
> if (s->listener->flags & F_SMTPS)
> - smtp_cert_init(s);
> + smtp_tls_init(s);
> else
> smtp_send_banner(s);
> }
> @@ -2261,112 +2270,6 @@ smtp_mailaddr(struct mailaddr *maddr, ch
> }
>
> static void
> -smtp_cert_init(struct smtp_session *s)
> -{
> - const char *name;
> - int fallback;
> -
> - if (s->listener->pki_name[0]) {
> - name = s->listener->pki_name;
> - fallback = 0;
> - }
> - else {
> - name = s->smtpname;
> - fallback = 1;
> - }
> -
> - if (cert_init(name, fallback, smtp_cert_init_cb, s))
> - tree_xset(&wait_ssl_init, s->id, s);
> -}
> -
> -static void
> -smtp_cert_init_cb(void *arg, int status, const char *name, const void *cert,
> - size_t cert_len)
> -{
> - struct smtp_session *s = arg;
> - void *ssl, *ssl_ctx;
> -
> - tree_pop(&wait_ssl_init, s->id);
> -
> - if (status == CA_FAIL) {
> - log_info("%016"PRIx64" smtp disconnected "
> - "reason=ca-failure",
> - s->id);
> - smtp_free(s, "CA failure");
> - return;
> - }
> -
> - ssl_ctx = dict_get(env->sc_ssl_dict, name);
> - ssl = ssl_smtp_init(ssl_ctx, s->listener->flags & F_TLS_VERIFY);
> - io_set_read(s->io);
> - io_start_tls(s->io, ssl);
> -}
> -
> -static void
> -smtp_cert_verify(struct smtp_session *s)
> -{
> - const char *name;
> - int fallback;
> -
> - if (s->listener->ca_name[0]) {
> - name = s->listener->ca_name;
> - fallback = 0;
> - }
> - else {
> - name = s->smtpname;
> - fallback = 1;
> - }
> -
> - if (cert_verify(io_tls(s->io), name, fallback, smtp_cert_verify_cb, s))
> {
> - tree_xset(&wait_ssl_verify, s->id, s);
> - io_pause(s->io, IO_IN);
> - }
> -}
> -
> -static void
> -smtp_cert_verify_cb(void *arg, int status)
> -{
> - struct smtp_session *s = arg;
> - const char *reason = NULL;
> - int resume;
> -
> - resume = tree_pop(&wait_ssl_verify, s->id) != NULL;
> -
> - switch (status) {
> - case CERT_OK:
> - reason = "cert-ok";
> - s->flags |= SF_VERIFIED;
> - break;
> - case CERT_NOCA:
> - reason = "no-ca";
> - break;
> - case CERT_NOCERT:
> - reason = "no-client-cert";
> - break;
> - case CERT_INVALID:
> - reason = "cert-invalid";
> - break;
> - default:
> - reason = "cert-check-failed";
> - break;
> - }
> -
> - log_debug("smtp: %p: smtp_cert_verify_cb: %s", s, reason);
> -
> - if (!(s->flags & SF_VERIFIED) && (s->listener->flags & F_TLS_VERIFY)) {
> - log_info("%016"PRIx64" smtp disconnected "
> - " reason=%s", s->id,
> - reason);
> - smtp_free(s, "SSL certificate check failed");
> - return;
> - }
> -
> - smtp_tls_verified(s);
> - if (resume)
> - io_resume(s->io, IO_IN);
> -}
> -
> -static void
> smtp_auth_failure_resume(int fd, short event, void *p)
> {
> struct smtp_session *s = p;
> @@ -2844,7 +2747,6 @@ static void
> smtp_message_begin(struct smtp_tx *tx)
> {
> struct smtp_session *s;
> - X509 *x;
> int (*m_printf)(struct smtp_tx *, const char *, ...);
>
> m_printf = smtp_message_printf;
> @@ -2879,13 +2781,11 @@ smtp_message_begin(struct smtp_tx *tx)
> tx->msgid);
>
> if (s->flags & SF_SECURE) {
> - x = SSL_get_peer_certificate(io_tls(s->io));
> m_printf(tx, " (%s:%s:%d:%s)",
> - SSL_get_version(io_tls(s->io)),
> - SSL_get_cipher_name(io_tls(s->io)),
> - SSL_get_cipher_bits(io_tls(s->io), NULL),
> - (s->flags & SF_VERIFIED) ? "YES" : (x ? "FAIL" : "NO"));
> - X509_free(x);
> + tls_conn_version(io_tls(s->io)),
> + tls_conn_cipher(io_tls(s->io)),
> + tls_conn_cipher_strength(io_tls(s->io)),
> + (s->flags & SF_VERIFIED) ? "YES" : "NO");
>
> if (s->listener->flags & F_RECEIVEDAUTH) {
> m_printf(tx, " auth=%s",
> Index: smtpc.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpc.c,v
> retrieving revision 1.13
> diff -u -p -r1.13 smtpc.c
> --- smtpc.c 29 Dec 2020 12:17:54 -0000 1.13
> +++ smtpc.c 4 Feb 2021 19:56:51 -0000
> @@ -29,6 +29,7 @@
> #include <stdlib.h>
> #include <string.h>
> #include <syslog.h>
> +#include <tls.h>
> #include <unistd.h>
>
> #include <openssl/ssl.h>
> @@ -48,8 +49,7 @@ static struct addrinfo *res0, *ai;
> static struct smtp_params params;
> static struct smtp_mail mail;
> static const char *servname = NULL;
> -
> -static SSL_CTX *ssl_ctx;
> +static struct tls_config *tls_config;
>
> static void
> usage(void)
> @@ -156,16 +156,20 @@ main(int argc, char **argv)
> mail.rcptcount = argc;
> }
>
> - ssl_init();
> + tls_init();
> event_init();
>
> - ssl_ctx = ssl_ctx_create(NULL, NULL, 0, NULL);
> - if (!SSL_CTX_load_verify_locations(ssl_ctx,
> - X509_get_default_cert_file(), NULL))
> - fatal("SSL_CTX_load_verify_locations");
> - if (!SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_client_method()))
> - fatal("SSL_CTX_set_ssl_version");
> - SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE , NULL);
> + tls_config = tls_config_new();
> + if (tls_config == NULL)
> + fatal("tls_config_new");
> + if (tls_config_set_ca_file(tls_config, tls_default_ca_cert_file()) ==
> -1)
> + fatal("tls_set_ca_file");
> + if (!params.tls_verify) {
> + tls_config_insecure_noverifycert(tls_config);
> + tls_config_insecure_noverifyname(tls_config);
> + tls_config_insecure_noverifytime(tls_config);
> + } else
> + tls_config_verify(tls_config);
>
> if (pledge("stdio inet dns tmppath", NULL) == -1)
> fatal("pledge");
> @@ -282,6 +286,7 @@ parse_server(char *server)
>
> if (servname == NULL)
> servname = host;
> + params.tls_servname = servname;
>
> memset(&hints, 0, sizeof(hints));
> hints.ai_family = AF_UNSPEC;
> @@ -399,11 +404,16 @@ smtp_verify_server_cert(void *tag, struc
> void
> smtp_require_tls(void *tag, struct smtp_client *proto)
> {
> - SSL *ssl = NULL;
> + struct tls *tls;
> +
> + tls = tls_client();
> + if (tls == NULL)
> + fatal("tls_client");
> +
> + if (tls_configure(tls, tls_config) == -1)
> + fatal("tls_configure");
>
> - if ((ssl = SSL_new(ssl_ctx)) == NULL)
> - fatal("SSL_new");
> - smtp_set_tls(proto, ssl);
> + smtp_set_tls(proto, tls);
> }
>
> void
> Index: smtpd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd.c,v
> retrieving revision 1.336
> diff -u -p -r1.336 smtpd.c
> --- smtpd.c 31 Dec 2020 08:27:15 -0000 1.336
> +++ smtpd.c 19 Jan 2021 09:45:44 -0000
> @@ -49,6 +49,7 @@
> #include <string.h>
> #include <sysexits.h>
> #include <time.h>
> +#include <tls.h>
> #include <unistd.h>
>
> #include <openssl/ssl.h>
> @@ -609,7 +610,7 @@ main(int argc, char *argv[])
>
> env->sc_opts |= opts;
>
> - ssl_init();
> + tls_init();
>
> if (parse_config(conf, conffile, opts))
> exit(1);
> Index: smtpd.conf.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd.conf.5,v
> retrieving revision 1.256
> diff -u -p -r1.256 smtpd.conf.5
> --- smtpd.conf.5 27 Jan 2021 14:59:10 -0000 1.256
> +++ smtpd.conf.5 5 Feb 2021 08:24:11 -0000
> @@ -345,17 +345,9 @@ sending a single warning after four hour
> .It Ic ca Ar caname Cm cert Ar cafile
> Associate the Certificate Authority (CA) certificate file
> .Ar cafile
> -with host
> -.Ar caname ,
> -and use that file as the CA certificate for that host.
> -.Ar caname
> -is the server's name,
> -derived from the default hostname
> -or set using either
> -.Pa /etc/mail/mailname
> -or using the
> -.Ic hostname
> -directive.
> +with ca entry
> +.Ar caname .
> +The ca entry can be referenced in listener rules and relay actions.
> .It Ic filter Ar chain-name Ic chain Brq Ar filter-name Op , Ar ...
> Register a chain of filters
> .Ar chain-name ,
> @@ -479,6 +471,8 @@ use the certificate associated with
> .Ic pki
> directive)
> to prove a mail server's identity.
> +This option can be used multiple times to provide alternate
> +certificates for SNI.
> .It Cm port Op Ar port
> Listen on the given
> .Ar port
> @@ -800,21 +794,10 @@ The default is 100.
> .It Ic pki Ar pkiname Cm cert Ar certfile
> Associate certificate file
> .Ar certfile
> -with host
> -.Ar pkiname ,
> -and use that file to prove the identity of the mail server to clients.
> -.Ar pkiname
> -is the server's name,
> -derived from the default hostname
> -or set using either
> -.Pa /etc/mail/mailname
> -or using the
> -.Ic hostname
> -directive.
> -If a fallback certificate or SNI is wanted, the
> -.Sq *
> -wildcard may be used as
> +with pki entry
> .Ar pkiname .
> +The pki entry defines a keypair configuration that can be referenced
> +in listener rules and relay actions.
> .Pp
> A certificate chain may be created by appending one or many certificates,
> including a Certificate Authority certificate,
> @@ -825,10 +808,10 @@ The creation of certificates is document
> .It Ic pki Ar pkiname Cm key Ar keyfile
> Associate the key located in
> .Ar keyfile
> -with host
> +with pki entry
> .Ar pkiname .
> .It Ic pki Ar pkiname Cm dhe Ar params
> -Specify the DHE parameters to use for DHE cipher suites with host
> +Specify the DHE parameters to use for DHE cipher suites with pki entry
> .Ar pkiname .
> Valid parameter values are
> .Cm none ,
> Index: smtpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
> retrieving revision 1.661
> diff -u -p -r1.661 smtpd.h
> --- smtpd.h 19 Jan 2021 09:16:20 -0000 1.661
> +++ smtpd.h 19 Jan 2021 11:47:07 -0000
> @@ -542,6 +542,10 @@ struct listener {
> TAILQ_ENTRY(listener) entry;
>
> int local; /* there must be a better way */
> +
> + struct tls *tls;
> + struct pki **pki;
> + int pkicount;
> };
>
> struct smtpd {
> @@ -1176,6 +1180,7 @@ struct dispatcher_remote {
>
> char *source;
>
> + struct tls_config *tls_config;
> char *ca;
> char *pki;
>
> @@ -1690,6 +1695,7 @@ const char *rule_to_text(struct rule *);
> const char *sockaddr_to_text(const struct sockaddr *);
> const char *mailaddr_to_text(const struct mailaddr *);
> const char *expandnode_to_text(struct expandnode *);
> +const char *tls_to_text(struct tls *);
>
>
> /* util.c */
> Index: ssl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/ssl.c,v
> retrieving revision 1.93
> diff -u -p -r1.93 ssl.c
> --- ssl.c 5 Jun 2019 06:40:13 -0000 1.93
> +++ ssl.c 19 Jan 2021 08:41:42 -0000
> @@ -450,3 +450,59 @@ ssl_ctx_fake_private_key(SSL_CTX *ctx, c
>
> return (ret);
> }
> +
> +static void
> +hash_x509(X509 *cert, char *hash, size_t hashlen)
> +{
> + static const char hex[] = "0123456789abcdef";
> + size_t off;
> + char digest[EVP_MAX_MD_SIZE];
> + int dlen, i;
> +
> + if (X509_pubkey_digest(cert, EVP_sha256(), digest, &dlen) != 1)
> + fatalx("%s: X509_pubkey_digest failed", __func__);
> +
> + if (hashlen < 2 * dlen + sizeof("SHA256:"))
> + fatalx("%s: hash buffer to small", __func__);
> +
> + off = strlcpy(hash, "SHA256:", hashlen);
> +
> + for (i = 0; i < dlen; i++) {
> + hash[off++] = hex[(digest[i] >> 4) & 0x0f];
> + hash[off++] = hex[digest[i] & 0x0f];
> + }
> + hash[off] = 0;
> +}
> +
> +char *
> +ssl_pubkey_hash(const char *buf, off_t len)
> +{
> +#define TLS_CERT_HASH_SIZE 128
> + BIO *in;
> + X509 *x509 = NULL;
> + char *hash = NULL;
> +
> + if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
> + log_warnx("%s: BIO_new_mem_buf failed", __func__);
> + return NULL;
> + }
> +
> + if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) {
> + log_warnx("%s: PEM_read_bio_X509 failed", __func__);
> + goto fail;
> + }
> +
> + if ((hash = malloc(TLS_CERT_HASH_SIZE)) == NULL) {
> + log_warn("%s: malloc", __func__);
> + goto fail;
> + }
> + hash_x509(x509, hash, TLS_CERT_HASH_SIZE);
> +
> +fail:
> + BIO_free(in);
> +
> + if (x509)
> + X509_free(x509);
> +
> + return hash;
> +}
> Index: ssl.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/ssl.h,v
> retrieving revision 1.21
> diff -u -p -r1.21 ssl.h
> --- ssl.h 18 Sep 2019 11:26:30 -0000 1.21
> +++ ssl.h 19 Jan 2021 09:06:14 -0000
> @@ -15,6 +15,8 @@
> * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> */
>
> +#include <openssl/ssl.h>
> +
> #define SSL_CIPHERS "HIGH:!aNULL:!MD5"
> #define SSL_SESSION_TIMEOUT 300
>
> @@ -62,6 +64,7 @@ int ssl_load_pkey(const void *, size_t,
> X509 **, EVP_PKEY **);
> int ssl_ctx_fake_private_key(SSL_CTX *, const void *, size_t,
> char *, off_t, X509 **, EVP_PKEY **);
> +char *ssl_pubkey_hash(const char *, off_t);
>
> /* ssl_privsep.c */
> int ssl_by_mem_ctrl(X509_LOOKUP *, int, const char *, long, char
> **);
> Index: to.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/to.c,v
> retrieving revision 1.45
> diff -u -p -r1.45 to.c
> --- to.c 19 Jan 2021 09:16:20 -0000 1.45
> +++ to.c 19 Jan 2021 11:47:07 -0000
> @@ -43,6 +43,9 @@
> #include <stdlib.h>
> #include <string.h>
> #include <time.h>
> +#if IO_TLS
> +#include <tls.h>
> +#endif
> #include <unistd.h>
>
> #include "smtpd.h"
> @@ -795,3 +798,18 @@ alias_is_error(struct expandnode *alias,
> alias->type = EXPAND_ERROR;
> return 1;
> }
> +
> +#if IO_TLS
> +const char *
> +tls_to_text(struct tls *tls)
> +{
> + static char buf[256];
> +
> + (void)snprintf(buf, sizeof buf, "%s:%s:%d",
> + tls_conn_version(tls),
> + tls_conn_cipher(tls),
> + tls_conn_cipher_strength(tls));
> +
> + return (buf);
> +}
> +#endif
> Index: smtp/Makefile
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtp/Makefile,v
> retrieving revision 1.3
> diff -u -p -r1.3 Makefile
> --- smtp/Makefile 18 Sep 2019 11:26:30 -0000 1.3
> +++ smtp/Makefile 19 Jan 2021 09:08:22 -0000
> @@ -17,7 +17,7 @@ SRCS+= ssl_verify.c
>
> CPPFLAGS+= -DIO_TLS
>
> -LDADD+= -levent -lutil -lssl -lcrypto -lm -lz
> -DPADD+= ${LIBEVENT} ${LIBUTIL} ${LIBSSL} ${LIBCRYPTO} ${LIBM} ${LIBZ}
> +LDADD+= -levent -lutil -ltls -lssl -lcrypto -lm -lz
> +DPADD+= ${LIBEVENT} ${LIBUTIL} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO} ${LIBM}
> ${LIBZ}
>
> .include <bsd.prog.mk>
> Index: smtpd/Makefile
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd/Makefile,v
> retrieving revision 1.110
> diff -u -p -r1.110 Makefile
> --- smtpd/Makefile 31 Dec 2020 08:27:15 -0000 1.110
> +++ smtpd/Makefile 19 Jan 2021 08:36:15 -0000
> @@ -82,8 +82,8 @@ SRCS+= stat_ramstat.c
> MAN= sendmail.8 smtpd.8 smtpd.conf.5 table.5
> BINDIR= /usr/sbin
>
> -LDADD+= -levent -lutil -lssl -lcrypto -lm -lz
> -DPADD+= ${LIBEVENT} ${LIBUTIL} ${LIBSSL} ${LIBCRYPTO} ${LIBM}
> ${LIBZ}
> +LDADD+= -levent -lutil -ltls -lssl -lcrypto -lm -lz
> +DPADD+= ${LIBEVENT} ${LIBUTIL} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO}
> ${LIBM} ${LIBZ}
>
> CFLAGS+= -fstack-protector-all
> CFLAGS+= -I${.CURDIR}/..