tags 920489 + patch thanks For convenience, I've attached the updated patch series + files which should be replaced in debian/patches.
I'll leave it up to the maintainer to decide what to do with this; uploading to experimental might be fine (considering we really should be using LibreSSL instead), although I've been rocking on with these patches for over a month now with no issues at all.
Description: Enable support for OpenSSL 1.1 Author: Sebastian Andrzej Siewior <sebast...@breakpoint.cc> Ryan Kavanagh <r...@debian.org> Linda Lapinlampi <li...@lindalap.fi> Origin: Debian Bug: https://github.com/OpenSMTPD/OpenSMTPD/issues/738 Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859544 Forwarded: https://github.com/OpenSMTPD/OpenSMTPD/pull/825 Last-Update: 2019-01-06 --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ --- a/openbsd-compat/libressl.c +++ b/openbsd-compat/libressl.c @@ -81,14 +81,14 @@ x = ca = NULL; if ((in = BIO_new_mem_buf(buf, len)) == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB); goto end; } if ((x = PEM_read_bio_X509(in, NULL, - ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata)) == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); + SSL_CTX_get_default_passwd_cb(ctx), + SSL_CTX_get_default_passwd_cb_userdata(ctx))) == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_PEM_LIB); goto end; } @@ -99,14 +99,11 @@ * the CA certificates. */ - if (ctx->extra_certs != NULL) { - sk_X509_pop_free(ctx->extra_certs, X509_free); - ctx->extra_certs = NULL; - } + SSL_CTX_clear_extra_chain_certs(ctx); while ((ca = PEM_read_bio_X509(in, NULL, - ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata)) != NULL) { + SSL_CTX_get_default_passwd_cb(ctx), + SSL_CTX_get_default_passwd_cb_userdata(ctx))) != NULL) { if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) goto end; --- a/smtpd/ca.c +++ b/smtpd/ca.c @@ -170,6 +170,190 @@ return ok; } +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) + +static int RSA_meth_get_flags(RSA_METHOD *meth) +{ + return meth->flags; +} + +static int RSA_meth_set_flags(RSA_METHOD *meth, int flags) +{ + meth->flags = flags; + return 1; +} + +static void *RSA_meth_get0_app_data(const RSA_METHOD *meth) +{ + return meth->app_data; +} + +static int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data) +{ + meth->app_data = app_data; + return 1; +} + +static int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth)) +(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_pub_enc; +} + +static int RSA_meth_set_pub_enc(RSA_METHOD *meth, + int (*pub_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)) +{ + meth->rsa_pub_enc = pub_enc; + return 1; +} + +static int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth)) +(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_pub_dec; +} + +static int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth)) +(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_priv_enc; +} + +int RSA_meth_set_priv_enc(RSA_METHOD *meth, + int (*priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding)) +{ + meth->rsa_priv_enc = priv_enc; + return 1; +} + +static int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth)) +(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_priv_dec; +} + +static int RSA_meth_set_priv_dec(RSA_METHOD *meth, + int (*priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding)) +{ + meth->rsa_priv_dec = priv_dec; + return 1; +} + +static int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth)) + (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) +{ + return meth->rsa_mod_exp; +} + +static int RSA_meth_set_mod_exp(RSA_METHOD *meth, + int (*mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)) +{ + meth->rsa_mod_exp = mod_exp; + return 1; +} + +static int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth)) +(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) +{ + return meth->bn_mod_exp; +} + +static int RSA_meth_set_bn_mod_exp(RSA_METHOD *meth, int (*bn_mod_exp) + (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *m_ctx)) +{ + meth->bn_mod_exp = bn_mod_exp; + return 1; +} + +static int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa) +{ + return meth->init; +} + +static int RSA_meth_set_init(RSA_METHOD *meth, int (*init) (RSA *rsa)) +{ + meth->init = init; + return 1; +} + +static int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa) +{ + return meth->finish; +} + +static int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa)) +{ + meth->finish = finish; + return 1; +} + +static int (*RSA_meth_get_keygen(const RSA_METHOD *meth)) + (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) +{ + return meth->rsa_keygen; +} + +static int RSA_meth_set_keygen(RSA_METHOD *meth, int (*keygen) + (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)) +{ + meth->rsa_keygen = keygen; + return 1; +} + +static int (*RSA_meth_get_verify(const RSA_METHOD *meth)) + (int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa) +{ + if (meth->flags & RSA_FLAG_SIGN_VER) + return meth->rsa_verify; + return NULL; +} + +static int (*RSA_meth_get_sign(const RSA_METHOD *meth)) + (int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa) +{ + if (meth->flags & RSA_FLAG_SIGN_VER) + return meth->rsa_sign; + return NULL; +} + +static int RSA_meth_set_pub_dec(RSA_METHOD *meth, + int (*pub_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding)) +{ + meth->rsa_pub_dec = pub_dec; + return 1; +} + +static RSA_METHOD *RSA_meth_new(const char *name, int flags) +{ + RSA_METHOD *meth = malloc(sizeof(*meth)); + + if (meth != NULL) { + memset(meth, 0, sizeof(*meth)); + meth->flags = flags; + + meth->name = strdup(name); + if (meth->name != NULL) + return meth; + + free(meth); + } + + return NULL; +} + +#endif + int ca_X509_verify(void *certificate, void *chain, const char *CAfile, const char *CRLfile, const char **errstr) @@ -201,7 +385,7 @@ *errstr = NULL; if (ret != 1) { if (xsc) - *errstr = X509_verify_cert_error_string(xsc->error); + *errstr = X509_verify_cert_error_string(X509_STORE_CTX_get_error(xsc)); else if (ERR_peek_last_error()) *errstr = ERR_error_string(ERR_peek_last_error(), NULL); } @@ -302,24 +486,9 @@ * RSA privsep engine (called from unprivileged processes) */ -const RSA_METHOD *rsa_default = NULL; +static const RSA_METHOD *rsa_default = NULL; -static RSA_METHOD rsae_method = { - "RSA privsep engine", - rsae_pub_enc, - rsae_pub_dec, - rsae_priv_enc, - rsae_priv_dec, - rsae_mod_exp, - rsae_bn_mod_exp, - rsae_init, - rsae_finish, - 0, - NULL, - NULL, - NULL, - rsae_keygen -}; +static const char *rsae_method_name = "RSA privsep engine"; static int rsae_send_imsg(int flen, const unsigned char *from, unsigned char *to, @@ -404,7 +573,7 @@ int padding) { log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); - return (rsa_default->rsa_pub_enc(flen, from, to, rsa, padding)); + return (RSA_meth_get_pub_enc(rsa_default)(flen, from, to, rsa, padding)); } static int @@ -412,7 +581,7 @@ int padding) { log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); - return (rsa_default->rsa_pub_dec(flen, from, to, rsa, padding)); + return (RSA_meth_get_pub_dec(rsa_default)(flen, from, to, rsa, padding)); } static int @@ -424,7 +593,7 @@ return (rsae_send_imsg(flen, from, to, rsa, padding, IMSG_CA_PRIVENC)); } - return (rsa_default->rsa_priv_enc(flen, from, to, rsa, padding)); + return (RSA_meth_get_priv_enc(rsa_default)(flen, from, to, rsa, padding)); } static int @@ -436,14 +605,14 @@ return (rsae_send_imsg(flen, from, to, rsa, padding, IMSG_CA_PRIVDEC)); } - return (rsa_default->rsa_priv_dec(flen, from, to, rsa, padding)); + return (RSA_meth_get_priv_dec(rsa_default)(flen, from, to, rsa, padding)); } static int rsae_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); - return (rsa_default->rsa_mod_exp(r0, I, rsa, ctx)); + return (RSA_meth_get_mod_exp(rsa_default)(r0, I, rsa, ctx)); } static int @@ -451,34 +620,36 @@ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) { log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); - return (rsa_default->bn_mod_exp(r, a, p, m, ctx, m_ctx)); + return (RSA_meth_get_bn_mod_exp(rsa_default)(r, a, p, m, ctx, m_ctx)); } static int rsae_init(RSA *rsa) { log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); - if (rsa_default->init == NULL) + if (RSA_meth_get_init(rsa_default) == NULL) return (1); - return (rsa_default->init(rsa)); + return (RSA_meth_get_init(rsa_default)(rsa)); } static int rsae_finish(RSA *rsa) { log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); - if (rsa_default->finish == NULL) + if (RSA_meth_get_finish(rsa_default) == NULL) return (1); - return (rsa_default->finish(rsa)); + return (RSA_meth_get_finish(rsa_default)(rsa)); } static int rsae_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) { log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); - return (rsa_default->rsa_keygen(rsa, bits, e, cb)); + return (RSA_meth_get_keygen(rsa_default)(rsa, bits, e, cb)); } +static RSA_METHOD *rsae_method; + void ca_engine_init(void) { @@ -490,7 +661,7 @@ errstr = "ENGINE_new"; goto fail; } - if (!ENGINE_set_name(e, rsae_method.name)) { + if (!ENGINE_set_name(e, rsae_method_name)) { errstr = "ENGINE_set_name"; goto fail; } @@ -503,25 +674,58 @@ goto fail; } + rsae_method = RSA_meth_new(rsae_method_name, 0); + if (!rsae_method) { + errstr = "RSA_meth_new"; + goto fail; + } + if ((name = ENGINE_get_name(e)) == NULL) name = "unknown RSA engine"; log_debug("debug: %s: using %s", __func__, name); - if (rsa_default->flags & RSA_FLAG_SIGN_VER) + if (RSA_meth_get_sign(rsa_default) || + RSA_meth_get_verify(rsa_default)) fatalx("unsupported RSA engine"); - if (rsa_default->rsa_mod_exp == NULL) - rsae_method.rsa_mod_exp = NULL; - if (rsa_default->bn_mod_exp == NULL) - rsae_method.bn_mod_exp = NULL; - if (rsa_default->rsa_keygen == NULL) - rsae_method.rsa_keygen = NULL; - rsae_method.flags = rsa_default->flags | - RSA_METHOD_FLAG_NO_CHECK; - rsae_method.app_data = rsa_default->app_data; + errstr = "Setting callback"; + if (!RSA_meth_set_pub_enc(rsae_method, rsae_pub_enc)) + goto fail; + if (!RSA_meth_set_pub_dec(rsae_method, rsae_pub_dec)) + goto fail; + if (!RSA_meth_set_priv_enc(rsae_method, rsae_priv_enc)) + goto fail; + if (!RSA_meth_set_priv_dec(rsae_method, rsae_priv_dec)) + goto fail; + + if (RSA_meth_get_mod_exp(rsa_default)) { + if (!RSA_meth_set_mod_exp(rsae_method, rsae_mod_exp)) + goto fail; + } + + if (RSA_meth_get_bn_mod_exp(rsa_default)) + if (!RSA_meth_set_bn_mod_exp(rsae_method, rsae_bn_mod_exp)) + goto fail; + if (!RSA_meth_set_init(rsae_method, rsae_init)) + goto fail; + if (!RSA_meth_set_finish(rsae_method, rsae_finish)) + goto fail; + + if (RSA_meth_get_keygen(rsa_default)) { + if (!RSA_meth_set_keygen(rsae_method, rsae_keygen)) + goto fail; + } + + if (!RSA_meth_set_flags(rsae_method, + RSA_meth_get_flags(rsa_default) | + RSA_METHOD_FLAG_NO_CHECK)) + goto fail; + + if (!RSA_meth_set0_app_data(rsae_method, RSA_meth_get0_app_data(rsa_default))) + goto fail; - if (!ENGINE_set_RSA(e, &rsae_method)) { + if (!ENGINE_set_RSA(e, rsae_method)) { errstr = "ENGINE_set_RSA"; goto fail; } --- a/smtpd/crypto.c +++ b/smtpd/crypto.c @@ -64,7 +64,7 @@ int crypto_encrypt_file(FILE * in, FILE * out) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; uint8_t ibuf[CRYPTO_BUFFER_SIZE]; uint8_t obuf[CRYPTO_BUFFER_SIZE]; uint8_t iv[IV_SIZE]; @@ -91,12 +91,14 @@ if ((w = fwrite(iv, 1, sizeof iv, out)) != sizeof iv) return 0; - EVP_CIPHER_CTX_init(&ctx); - EVP_EncryptInit_ex(&ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return 0; + EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); /* encrypt until end of file */ while ((r = fread(ibuf, 1, CRYPTO_BUFFER_SIZE, in)) != 0) { - if (!EVP_EncryptUpdate(&ctx, obuf, &len, ibuf, r)) + if (!EVP_EncryptUpdate(ctx, obuf, &len, ibuf, r)) goto end; if (len && (w = fwrite(obuf, len, 1, out)) != 1) goto end; @@ -105,13 +107,13 @@ goto end; /* finalize and write last chunk if any */ - if (!EVP_EncryptFinal_ex(&ctx, obuf, &len)) + if (!EVP_EncryptFinal_ex(ctx, obuf, &len)) goto end; if (len && (w = fwrite(obuf, len, 1, out)) != 1) goto end; /* get and append tag */ - EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, sizeof tag, tag); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, sizeof tag, tag); if ((w = fwrite(tag, sizeof tag, 1, out)) != 1) goto end; @@ -119,14 +121,14 @@ ret = 1; end: - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_free(ctx); return ret; } int crypto_decrypt_file(FILE * in, FILE * out) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; uint8_t ibuf[CRYPTO_BUFFER_SIZE]; uint8_t obuf[CRYPTO_BUFFER_SIZE]; uint8_t iv[IV_SIZE]; @@ -171,11 +173,13 @@ sz -= sizeof tag; - EVP_CIPHER_CTX_init(&ctx); - EVP_DecryptInit_ex(&ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return 0; + EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); /* set expected tag */ - EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, sizeof tag, tag); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, sizeof tag, tag); /* decrypt until end of ciphertext */ while (sz) { @@ -185,7 +189,7 @@ r = fread(ibuf, 1, sz, in); if (!r) break; - if (!EVP_DecryptUpdate(&ctx, obuf, &len, ibuf, r)) + if (!EVP_DecryptUpdate(ctx, obuf, &len, ibuf, r)) goto end; if (len && (w = fwrite(obuf, len, 1, out)) != 1) goto end; @@ -195,7 +199,7 @@ goto end; /* finalize, write last chunk if any and perform authentication check */ - if (!EVP_DecryptFinal_ex(&ctx, obuf, &len)) + if (!EVP_DecryptFinal_ex(ctx, obuf, &len)) goto end; if (len && (w = fwrite(obuf, len, 1, out)) != 1) goto end; @@ -204,14 +208,14 @@ ret = 1; end: - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_free(ctx); return ret; } size_t crypto_encrypt_buffer(const char *in, size_t inlen, char *out, size_t outlen) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; uint8_t iv[IV_SIZE]; uint8_t tag[GCM_TAG_SIZE]; uint8_t version = API_VERSION; @@ -239,33 +243,35 @@ memcpy(out + len, iv, sizeof iv); len += sizeof iv; - EVP_CIPHER_CTX_init(&ctx); - EVP_EncryptInit_ex(&ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return 0; + EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); /* encrypt buffer */ - if (!EVP_EncryptUpdate(&ctx, out + len, &olen, in, inlen)) + if (!EVP_EncryptUpdate(ctx, out + len, &olen, in, inlen)) goto end; len += olen; /* finalize and write last chunk if any */ - if (!EVP_EncryptFinal_ex(&ctx, out + len, &olen)) + if (!EVP_EncryptFinal_ex(ctx, out + len, &olen)) goto end; len += olen; /* get and append tag */ - EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, sizeof tag, tag); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, sizeof tag, tag); memcpy(out + len, tag, sizeof tag); ret = len + sizeof tag; end: - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_cleanup(ctx); return ret; } size_t crypto_decrypt_buffer(const char *in, size_t inlen, char *out, size_t outlen) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; uint8_t iv[IV_SIZE]; uint8_t tag[GCM_TAG_SIZE]; int olen; @@ -292,24 +298,26 @@ inlen -= sizeof iv; in += sizeof iv; - EVP_CIPHER_CTX_init(&ctx); - EVP_DecryptInit_ex(&ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return 0; + EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); /* set expected tag */ - EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, sizeof tag, tag); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, sizeof tag, tag); /* decrypt buffer */ - if (!EVP_DecryptUpdate(&ctx, out, &olen, in, inlen)) + if (!EVP_DecryptUpdate(ctx, out, &olen, in, inlen)) goto end; len += olen; /* finalize, write last chunk if any and perform authentication check */ - if (!EVP_DecryptFinal_ex(&ctx, out + len, &olen)) + if (!EVP_DecryptFinal_ex(ctx, out + len, &olen)) goto end; ret = len + olen; end: - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_cleanup(ctx); return ret; } --- a/smtpd/libressl.c +++ b/smtpd/libressl.c @@ -94,10 +94,10 @@ ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ - x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata); + x = PEM_read_bio_X509_AUX(in, NULL, SSL_CTX_get_default_passwd_cb(ctx), + SSL_CTX_get_default_passwd_cb_userdata(ctx)); if (x == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_PEM_LIB); goto end; } @@ -115,14 +115,11 @@ int r; unsigned long err; - if (ctx->extra_certs != NULL) { - sk_X509_pop_free(ctx->extra_certs, X509_free); - ctx->extra_certs = NULL; - } + SSL_CTX_clear_extra_chain_certs(ctx); while ((ca = PEM_read_bio_X509(in, NULL, - ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata)) != NULL) { + SSL_CTX_get_default_passwd_cb(ctx), + SSL_CTX_get_default_passwd_cb_userdata(ctx))) != NULL) { r = SSL_CTX_add_extra_chain_cert(ctx, ca); if (!r) { X509_free(ca); @@ -160,7 +157,7 @@ in = BIO_new_mem_buf(buf, len); if (in == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB); goto end; } --- a/smtpd/ssl.c +++ b/smtpd/ssl.c @@ -425,7 +425,7 @@ */ ret = SSL_CTX_use_PrivateKey(ctx, pkey); if (!ret) - SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_SSL_LIB); + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_SYS_LIB); if (pkeyptr != NULL) *pkeyptr = pkey; --- a/smtpd/ssl.h +++ b/smtpd/ssl.h @@ -66,3 +66,17 @@ /* ssl_privsep.c */ int ssl_by_mem_ctrl(X509_LOOKUP *, int, const char *, long, char **); int SSL_CTX_use_certificate_chain_mem(SSL_CTX *, void *, int); + +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) + +static inline pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) +{ + return ctx->default_passwd_callback; +} + +static inline void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx) +{ + return ctx->default_passwd_callback_userdata; +} + +#endif --- a/configure.ac +++ b/configure.ac @@ -1133,6 +1133,10 @@ ##gilles +AC_CHECK_DECLS([SSL_OP_NO_CLIENT_RENEGOTIATION], [], [], [ +#include <openssl/ssl.h> +]) + SMTPD_USER=_smtpd AC_ARG_WITH([user-smtpd], [ --with-user-smtpd=user Specify non-privileged user for smtpd (default=_smtpd)], @@ -1922,6 +1926,43 @@ ) #l2371 +##gilles +OPENSSL_SUPPORTS_ECDH_AUTO=no +AC_MSG_CHECKING([if programs using SSL_CTX_set_ecdh_auto will link]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ #include <openssl/ssl.h> ]], + [[ SSL_CTX_set_ecdh_auto(NULL, 1); ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_SSL_CTX_SET_ECDH_AUTO], [1], + [Define if SSL library support SSL_CTX_set_ecdh_auto]) + OPENSSL_SUPPORTS_ECDH_AUTO=yes + ], + [ + AC_MSG_RESULT([no]) + ] +) +AM_CONDITIONAL([HAVE_SSL_CTX_SET_ECDH_AUTO], [test $OPENSSL_SUPPORTS_ECDH_AUTO = yes]) +##gilles + +##gilles +OPENSSL_SUPPORTS_DH_AUTO=no +AC_MSG_CHECKING([if programs using SSL_CTX_set_dh_auto will link]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ #include <openssl/ssl.h> ]], + [[ SSL_CTX_set_dh_auto(NULL, 1); ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_SSL_CTX_SET_DH_AUTO], [1], + [Define if SSL library support SSL_CTX_set_dh_auto]) + OPENSSL_SUPPORTS_DH_AUTO=yes + ], + [ + AC_MSG_RESULT([no]) + ] +) +AM_CONDITIONAL([HAVE_SSL_CTX_SET_DH_AUTO], [test $OPENSSL_SUPPORTS_DH_AUTO = yes]) +##gilles dnl zlib is required AC_ARG_WITH([libz], --- a/mk/smtpd/Makefile.am +++ b/mk/smtpd/Makefile.am @@ -28,7 +28,7 @@ smtpd_SOURCES+= $(smtpd_srcdir)/forward.c smtpd_SOURCES+= $(smtpd_srcdir)/iobuf.c smtpd_SOURCES+= $(smtpd_srcdir)/ioev.c -#smtpd_SOURCES+= $(smtpd_srcdir)/libressl.c +smtpd_SOURCES+= $(smtpd_srcdir)/libressl.c smtpd_SOURCES+= $(smtpd_srcdir)/limit.c smtpd_SOURCES+= $(smtpd_srcdir)/lka.c smtpd_SOURCES+= $(smtpd_srcdir)/lka_session.c --- a/openbsd-compat/Makefile.am +++ b/openbsd-compat/Makefile.am @@ -1,7 +1,7 @@ noinst_LIBRARIES = libopenbsd-compat.a -#libopenbsd_compat_a_SOURCES = arc4random.c -libopenbsd_compat_a_SOURCES = base64.c +libopenbsd_compat_a_SOURCES = arc4random.c +libopenbsd_compat_a_SOURCES += base64.c libopenbsd_compat_a_SOURCES += bsd-getpeereid.c libopenbsd_compat_a_SOURCES += bsd-misc.c libopenbsd_compat_a_SOURCES += bsd-waitpid.c @@ -12,7 +12,7 @@ libopenbsd_compat_a_SOURCES += getopt.c libopenbsd_compat_a_SOURCES += imsg.c libopenbsd_compat_a_SOURCES += imsg-buffer.c -#libopenbsd_compat_a_SOURCES += libressl.c +libopenbsd_compat_a_SOURCES += libressl.c libopenbsd_compat_a_SOURCES += pidfile.c libopenbsd_compat_a_SOURCES += pw_dup.c libopenbsd_compat_a_SOURCES += reallocarray.c --- a/openbsd-compat/defines.h +++ b/openbsd-compat/defines.h @@ -503,4 +503,8 @@ #define LOG_PERROR 0 #endif +#if !HAVE_DECL_SSL_OP_NO_CLIENT_RENEGOTIATION +#define SSL_OP_NO_CLIENT_RENEGOTIATION 0 +#endif + #endif /* _DEFINES_H */
Description: Revert "GCM is available in all LibreSSL versions" (d74dbd3) GCM is not available on OpenSSL versions < 1.0.2. Restores old OpenSSL compatibility. (This patch is safe to remove on OpenSSL 1.1.1a.) Origin: other, https://github.com/OpenSMTPD/OpenSMTPD/commit/d74dbd3 Author: Linda Lapinlampi <li...@lindalap.fi> Last-Update: 2019-01-06 --- a/configure.ac +++ b/configure.ac @@ -1131,6 +1131,25 @@ #l2816 +##chl +EXPERIMENTAL_GCM_CRYPTO=no +AC_MSG_CHECKING([if programs using LibreSSL EVP_aes_256_gcm() will link]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]], + [[ EVP_aes_256_gcm(); ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_GCM_CRYPTO], [1], + [Define if you want to use GCM crypto support]) + EXPERIMENTAL_GCM_CRYPTO=yes + ], + [ + AC_MSG_RESULT([no]) + ] +) +AM_CONDITIONAL([HAVE_GCM_CRYPTO], [test $EXPERIMENTAL_GCM_CRYPTO = yes]) +##chl + ##gilles AC_CHECK_DECLS([SSL_OP_NO_CLIENT_RENEGOTIATION], [], [], [ --- a/mk/smtpctl/Makefile.am +++ b/mk/smtpctl/Makefile.am @@ -32,7 +32,9 @@ smtpctl_SOURCES+= $(smtpd_srcdir)/makemap.c endif +if HAVE_GCM_CRYPTO smtpctl_SOURCES+= $(smtpd_srcdir)/crypto.c +endif smtpctl_CFLAGS= -DNO_IO -DCONFIG_MINIMUM smtpctl_CFLAGS+= -DPATH_GZCAT=\"$(ZCAT)\" \ --- a/mk/smtpd/Makefile.am +++ b/mk/smtpd/Makefile.am @@ -65,7 +65,9 @@ smtpd_SOURCES+= $(smtpd_srcdir)/waitq.c # backends +if HAVE_GCM_CRYPTO smtpd_SOURCES+= $(smtpd_srcdir)/crypto.c +endif smtpd_SOURCES+= $(smtpd_srcdir)/compress_gzip.c if HAVE_DB_API smtpd_SOURCES+= $(smtpd_srcdir)/table_db.c --- a/smtpd/queue.c +++ b/smtpd/queue.c @@ -647,11 +647,13 @@ if (env->sc_queue_flags & QUEUE_COMPRESSION) log_info("queue: queue compression enabled"); +#ifdef HAVE_GCM_CRYPTO if (env->sc_queue_key) { if (!crypto_setup(env->sc_queue_key, strlen(env->sc_queue_key))) fatalx("crypto_setup: invalid key for queue encryption"); log_info("queue: queue encryption enabled"); } +#endif if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || --- a/smtpd/queue_backend.c +++ b/smtpd/queue_backend.c @@ -254,6 +254,7 @@ } } +#ifdef HAVE_GCM_CRYPTO if (env->sc_queue_flags & QUEUE_ENCRYPTION) { bsnprintf(tmppath, sizeof tmppath, "%s.enc", msgpath); ifp = fopen(msgpath, "r"); @@ -275,6 +276,7 @@ return (0); } } +#endif r = handler_message_commit(msgid, msgpath); profile_leave(); @@ -313,6 +315,7 @@ if (fdin == -1) return (-1); +#ifdef HAVE_GCM_CRYPTO if (env->sc_queue_flags & QUEUE_ENCRYPTION) { if ((fdout = mktmpfile()) == -1) goto err; @@ -334,6 +337,7 @@ ofp = NULL; lseek(fdin, SEEK_SET, 0); } +#endif if (env->sc_queue_flags & QUEUE_COMPRESSION) { if ((fdout = mktmpfile()) == -1) @@ -390,8 +394,10 @@ size_t evplen; size_t complen; char compbuf[sizeof(struct envelope)]; +#ifdef HAVE_GCM_CRYPTO size_t enclen; char encbuf[sizeof(struct envelope)]; +#endif evp = evpbuf; evplen = envelope_dump_buffer(ep, evpbuf, evpbufsize); @@ -406,6 +412,7 @@ evplen = complen; } +#ifdef HAVE_GCM_CRYPTO if (env->sc_queue_flags & QUEUE_ENCRYPTION) { enclen = crypto_encrypt_buffer(evp, evplen, encbuf, sizeof encbuf); if (enclen == 0) @@ -413,6 +420,7 @@ evp = encbuf; evplen = enclen; } +#endif memmove(evpbuf, evp, evplen); @@ -426,12 +434,15 @@ size_t evplen; char compbuf[sizeof(struct envelope)]; size_t complen; +#ifdef HAVE_GCM_CRYPTO char encbuf[sizeof(struct envelope)]; size_t enclen; +#endif evp = evpbuf; evplen = evpbufsize; +#ifdef HAVE_GCM_CRYPTO if (env->sc_queue_flags & QUEUE_ENCRYPTION) { enclen = crypto_decrypt_buffer(evp, evplen, encbuf, sizeof encbuf); if (enclen == 0) @@ -439,6 +450,7 @@ evp = encbuf; evplen = enclen; } +#endif if (env->sc_queue_flags & QUEUE_COMPRESSION) { complen = uncompress_chunk(evp, evplen, compbuf, sizeof compbuf); --- a/smtpd/smtpctl.c +++ b/smtpd/smtpctl.c @@ -1302,7 +1302,9 @@ display(const char *s) { FILE *fp; +#ifdef HAVE_GCM_CRYPTO char *key; +#endif int gzipped; char *gzcat_argv0 = strrchr(PATH_GZCAT, '/') + 1; @@ -1310,6 +1312,7 @@ err(1, "fopen"); if (is_encrypted_fp(fp)) { +#ifdef HAVE_GCM_CRYPTO int i; int fd; FILE *ofp = NULL; @@ -1342,6 +1345,10 @@ fclose(fp); fp = ofp; fseek(fp, 0, SEEK_SET); +#else + printf("GCM crypto not supported!\n"); + exit(1); +#endif } gzipped = is_gzip_fp(fp); --- a/smtpd/smtpd.c +++ b/smtpd/smtpd.c @@ -650,12 +650,14 @@ errx(1, "config file exceeds PATH_MAX"); if (env->sc_opts & SMTPD_OPT_NOACTION) { +#ifdef HAVE_GCM_CRYPTO if (env->sc_queue_key && crypto_setup(env->sc_queue_key, strlen(env->sc_queue_key)) == 0) { fatalx("crypto_setup:" "invalid key for queue encryption"); } +#endif load_pki_tree(); load_pki_keys(); fprintf(stderr, "configuration OK\n");
Description: Revert "SNI is available in all LibreSSL versions" (b6cfe5b) SNI is not available on OpenSSL versions < 1.1.1. Restores old OpenSSL compatibility. (This patch is safe to remove on OpenSSL 1.1.1a.) Origin: other, https://github.com/OpenSMTPD/OpenSMTPD/commit/b6cfe5b Author: Linda Lapinlampi <li...@lindalap.fi> Last-Update: 2019-01-06 --- a/configure.ac +++ b/configure.ac @@ -1151,6 +1151,25 @@ ##chl ##gilles +OPENSSL_SUPPORTS_SNI=no +AC_MSG_CHECKING([if programs using TLSEXT_NAMETYPE_host_name will link]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ #include <openssl/ssl.h> ]], + [[ SSL_CTX_set_tlsext_servername_callback(NULL, NULL); ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_TLSEXT_SERVERNAME], [1], + [Define if you want to enable TLS extension SERVERNAME]) + OPENSSL_SUPPORTS_SNI=yes + ], + [ + AC_MSG_RESULT([no]) + ] +) +AM_CONDITIONAL([HAVE_TLSEXT_SERVERNAME], [test $OPENSSL_SUPPORTS_SNI = yes]) +##gilles + +##gilles AC_CHECK_DECLS([SSL_OP_NO_CLIENT_RENEGOTIATION], [], [], [ #include <openssl/ssl.h> --- a/smtpd/smtp.c +++ b/smtpd/smtp.c @@ -324,6 +324,7 @@ static int smtp_sni_callback(SSL *ssl, int *ad, void *arg) { +#if defined(HAVE_TLSEXT_SERVERNAME) const char *sn; void *ssl_ctx; @@ -335,6 +336,10 @@ return SSL_TLSEXT_ERR_NOACK; SSL_set_SSL_CTX(ssl, ssl_ctx); return SSL_TLSEXT_ERR_OK; +#else + /* ssl_smtp_init should have ignored the callback if SNI is not supported */ + fatalx("unxepected call to smtp_sni_callback()"); +#endif /* defined(HAVE_TLSEXT_SERVERNAME) */ } static void
07_automake_missing_options.diff 10_smtpd.conf.diff 11_ssl_1.1.diff 12_revert_gcm_removal_d74dbd3.diff 13_revert_sni_removal_b6cfe5b.diff