-TEC_KEY
-TEDIT_FILE
-TEVENT_MASK
+-TEVP_CIPHER_CTX
+-TEVP_MAC_CTX
+-TEVP_MD
-TEVP_MD_CTX
-TEVP_PKEY
-TEXPAND_ATTR
-THBC_TEST_CONTEXT
-THEADER_OPTS
-THEADER_TOKEN
+-THMAC_CTX
-THOST
-THTABLE
-THTABLE_INFO
-TLDAP
-TLDAP_CONN
-TLDAPMessage
+-TLDAPURLDesc
-TLIB_DP
-TLIB_FN
-TLMTP_ATTR
-TNAME_CODE
-TNAME_MASK
-TNBBIO
+-TNVTABLE_INFO
-Toff_t
-TOPTIONS
-TPCF_DBMS_INFO
-TSCAN_INFO
-TSCAN_OBJ
-TSENDER_LOGIN_MATCH
+-TSERVER_AC
-TSESSION
-Tsfsistat
-TSHARED_PATH
backwards-compatible default value.
Minor text and code cleanups. File: postlog/postlog.c.
+
+20210925
+
+ Prevent sharing of xxx_tls_session_cache_database instances
+ between different Postfix instances when a database is
+ not multi-writer safe. Like postscreen(8) and verify(8),
+ open such a database with a permanent lock, and raise
+ a fatal error when that database is already opened as
+ xxx_tls_session_cache_database. File: src/tls/tls_scache.c.
+
+ Bugfix (bug introduced: Postfix 2.10): postconf -x produced
+ incorrect output, because different functions were implicitly
+ sharing a buffer for intermediate results. Reported by raf, root
+ cause analysis by Viktor Dukhovni, and Wietse eliminated the
+ underlying anti-pattern. Files: postconf/postconf_builtin.c,
+ postconf/postconf_dbms.c, postconf/postconf_lookup.c,
+ postconf/postconf_main.c, postconf/postconf_master.c.
+
+ Documentation: missing lmtp_tls_wrappermode parameter
+ documentation. Viktor Dukhovni. Files: mantools/postlink,
+ proto/postconf.proto.
+
+20210926
+
+ OpenSSL 3.0.0 feature and bitrot updates. Viktor Dukhovni.
+ Files: proto/FORWARD_SECRECY_README.html, proto/postconf.proto,
+ tls/tls_client.c, tls/tls_dh.c, tls/tls.h, tls/tls_misc.c,
+ tls/tls_server.c/^+
+
+ Cleanup: don't hyperlink text that is already hyperlinked.
+ File: mantools/postlink.
patched Exim SMTP clients that require a >= 2048-bit length for the non-export
prime.
-Execute as root (prime group generation can take a few seconds to a few
-minutes):
+With Postfix >= 3.7 built against OpenSSL version is 3.0.0 or later, when the
+value of smtpd_tls_dh1024_param_file is either empty or "a\bau\but\bto\bo", the EDH
+parameter selection is delegated to the OpenSSL library, which selects
+appropriate parameters based on the TLS handshake. This choice is likely to be
+the most interoperable with SMTP clients using various TLS libraries, and
+custom local parameters are no longer recommended when using Postfix >= 3.7
+built against OpenSSL 3.0.0. Just leave smtpd_tls_dh1024_param_file at its
+default value (both in main.cf(5) and any master.cf(5) overrides, and let
+OpenSSL do the work.
+
+Otherwise, execute as root (prime group generation can take a few seconds to a
+few minutes):
# cd /etc/postfix
# umask 022
# chmod 644 dh512.pem dh1024.pem dh2048.pem
The Postfix SMTP server EDH parameter files are not secret, after all these
-parameters are sent to all remote SMTP clients in the clear. Mode 0644 is fine.
+parameters are sent to all remote SMTP clients in the clear. Mode 0644 is
+appropriate.
You can improve security against pre-computation attacks further by
regenerating the Postfix SMTP server EDH parameters periodically (an hourly or
the software under the license of their choice. Those who are more
comfortable with the IPL can continue with that license.
-Major changes with snapshot 20210814-nonprod
-============================================
+Major changes with snapshot 20210815
+====================================
Updated defense against remote clients or servers that 'trickle'
SMTP or LMTP traffc. The new {smtpd,smtp,lmtp}_per_request_deadline
compatibility with Debian-patched Exim SMTP clients that require a
≥ 2048-bit length for the non-export prime. </p>
-<p> Execute as root (prime group generation can take a
+<p> With Postfix ≥ 3.7 built against OpenSSL version is 3.0.0 or later, when
+the value of <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> is either empty or "<b>auto</b>", the
+EDH parameter selection is delegated to the OpenSSL library, which selects
+appropriate parameters based on the TLS handshake. This choice is likely to be
+the most interoperable with SMTP clients using various TLS libraries, and
+custom local parameters are no longer recommended when using Postfix ≥ 3.7
+built against OpenSSL 3.0.0. Just leave <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> at its
+default value (both in <a href="postconf.5.html">main.cf</a>(5) and any <a href="master.5.html">master.cf</a>(5) overrides, and let
+OpenSSL do the work. </p>
+
+<p> Otherwise, execute as root (prime group generation can take a
few seconds to a few minutes): </p>
<blockquote>
<p> The Postfix SMTP server EDH parameter files are not secret,
after all these parameters are sent to all remote SMTP clients in
-the clear. Mode 0644 is fine. </p>
+the clear. Mode 0644 is appropriate. </p>
<p> You can improve security against pre-computation attacks further
by regenerating the Postfix SMTP server EDH parameters periodically
<p> This feature is available in Postfix 2.3 and later. </p>
+</DD>
+
+<DT><b><a name="lmtp_tls_wrappermode">lmtp_tls_wrappermode</a>
+(default: no)</b></DT><DD>
+
+<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_wrappermode">smtp_tls_wrappermode</a> configuration
+parameter. See there for details. </p>
+
+<p> This feature is available in Postfix 3.0 and later. </p>
+
+
</DD>
<DT><b><a name="lmtp_use_tls">lmtp_use_tls</a>
to hosts resolved via "native" lookups. </p>
<p> As mentioned above, Postfix is not a validating <a
-href="<a href="https://tools.ietf.org/html/rfc4035#section-4.9">https://tools.ietf.org/html/rfc4035#section-4.9</a>">stub
+href="https://tools.ietf.org/html/rfc4035#section-4.9">stub
resolver</a>; it relies on the system's configured DNSSEC-validating
<a href="https://tools.ietf.org/html/rfc4035#section-3.2">recursive
nameserver</a> to perform all DNSSEC validation. Since this
<p> Pattern matching of domain names is controlled by the presence
or absence of "<a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a>" in the
-<a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> parameter value (postfix 3.0 and
+<a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> parameter value (Postfix 3.0 and
later). </p>
<p>
<p> File with DH parameters that the Postfix SMTP server should
use with non-export EDH ciphers. </p>
+<p> With Postfix ≥ 3.7, built with OpenSSL version is 3.0.0 or later, if the
+parameter value is either empty or "<b>auto</b>", then the DH parameter
+selection is delegated to the OpenSSL library, which selects appropriate
+parameters based on the TLS handshake. This choice is likely to be the most
+interoperable with SMTP clients using various TLS libraries, and custom local
+parameters are no longer recommended when using Postfix ≥ 3.7 built against
+OpenSSL 3.0.0. </p>
+
<p> The best-practice choice of parameters uses a 2048-bit prime. This is fine,
despite the historical "1024" in the parameter name. Do not be tempted to use
much larger values, performance degrades quickly, and you may also cease to
"=<number>" suffix. For example, "sha512" may instead be specified
as "sha512=2" and "sha256" may instead be specified as "sha256=1".
The optional number must match the <a
-href="<a href="https://www.iana.org/assignments/dane-parameters/dane-parameters.xhtml#matching-types">https://www.iana.org/assignments/dane-parameters/dane-parameters.xhtml#matching-types</a>"
+href="https://www.iana.org/assignments/dane-parameters/dane-parameters.xhtml#matching-types"
>IANA</a> assigned TLSA matching type number the algorithm in question.
Postfix will check this constraint for the algorithms it knows about.
Additional matching type algorithms registered with IANA can be added
small subset of clients. </p>
<p> The default "strong" curve is rated in NSA <a
-href="<a href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/</a>">Suite
+href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite
B</a> for information classified up to SECRET. </p>
<p> Note: elliptic curve names are poorly standardized; different
of <a href="http://tools.ietf.org/html/rfc4492">RFC 4492</a>. You should not generally change this setting. </p>
<p> This default "ultra" curve is rated in NSA <a
-href="<a href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/</a>">Suite
+href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite
B</a> for information classified up to TOP SECRET. </p>
<p> If you want to take maximal advantage of ciphers that offer <a
configuration parameter. See there for details.
.PP
This feature is available in Postfix 2.3 and later.
+.SH lmtp_tls_wrappermode (default: no)
+The LMTP\-specific version of the smtp_tls_wrappermode configuration
+parameter. See there for details.
+.PP
+This feature is available in Postfix 3.0 and later.
.SH lmtp_use_tls (default: no)
The LMTP\-specific version of the smtp_use_tls configuration
parameter. See there for details.
.PP
Pattern matching of domain names is controlled by the presence
or absence of "smtpd_client_event_limit_exceptions" in the
-parent_domain_matches_subdomains parameter value (postfix 3.0 and
+parent_domain_matches_subdomains parameter value (Postfix 3.0 and
later).
.PP
This feature is available in Postfix 2.2 and later.
File with DH parameters that the Postfix SMTP server should
use with non\-export EDH ciphers.
.PP
+With Postfix >= 3.7, built with OpenSSL version is 3.0.0 or later, if the
+parameter value is either empty or "\fBauto\fR", then the DH parameter
+selection is delegated to the OpenSSL library, which selects appropriate
+parameters based on the TLS handshake. This choice is likely to be the most
+interoperable with SMTP clients using various TLS libraries, and custom local
+parameters are no longer recommended when using Postfix >= 3.7 built against
+OpenSSL 3.0.0.
+.PP
The best\-practice choice of parameters uses a 2048\-bit prime. This is fine,
despite the historical "1024" in the parameter name. Do not be tempted to use
much larger values, performance degrades quickly, and you may also cease to
s;\blmtp_tls_loglevel\b;<a href="postconf.5.html#lmtp_tls_loglevel">$&</a>;g;
s;\blmtp_tls_session_cache_database\b;<a href="postconf.5.html#lmtp_tls_session_cache_database">$&</a>;g;
s;\blmtp_tls_session_cache_timeout\b;<a href="postconf.5.html#lmtp_tls_session_cache_timeout">$&</a>;g;
+ s;\blmtp_tls_wrappermode\b;<a href="postconf.5.html#lmtp_tls_wrappermode">$&</a>;g;
s;\blmtp_generic_maps\b;<a href="postconf.5.html#lmtp_generic_maps">$&</a>;g;
s;\blmtp_pix_workaround_threshold_time\b;<a href="postconf.5.html#lmtp_pix_workaround_threshold_time">$&</a>;g;
s;\blmtp_pix_workaround_delay_time\b;<a href="postconf.5.html#lmtp_pix_workaround_delay_time">$&</a>;g;
# Hyperlink URLs and RFC documents
- s/(https?:\/\/[^ ,"\(\)]*[^ ,"\(\):;!?.])/<a href="$1">$1<\/a>/;
+ if (!/href=/) { s/(https?:\/\/[^ ,"\(\)]*[^ ,"\(\):;!?.])/<a href="$1">$1<\/a>/; }
s/(ftp:\/\/[^ ,"\(\)]*[^ ,"\(\):;!?.])/<a href="$1">$1<\/a>/;
s/\bRFC\s*([1-9]\d*)/<a href="http:\/\/tools.ietf.org\/html\/rfc$1">$&<\/a>/g;
compatibility with Debian-patched Exim SMTP clients that require a
≥ 2048-bit length for the non-export prime. </p>
-<p> Execute as root (prime group generation can take a
+<p> With Postfix ≥ 3.7 built against OpenSSL version is 3.0.0 or later, when
+the value of smtpd_tls_dh1024_param_file is either empty or "<b>auto</b>", the
+EDH parameter selection is delegated to the OpenSSL library, which selects
+appropriate parameters based on the TLS handshake. This choice is likely to be
+the most interoperable with SMTP clients using various TLS libraries, and
+custom local parameters are no longer recommended when using Postfix ≥ 3.7
+built against OpenSSL 3.0.0. Just leave smtpd_tls_dh1024_param_file at its
+default value (both in main.cf(5) and any master.cf(5) overrides, and let
+OpenSSL do the work. </p>
+
+<p> Otherwise, execute as root (prime group generation can take a
few seconds to a few minutes): </p>
<blockquote>
<p> The Postfix SMTP server EDH parameter files are not secret,
after all these parameters are sent to all remote SMTP clients in
-the clear. Mode 0644 is fine. </p>
+the clear. Mode 0644 is appropriate. </p>
<p> You can improve security against pre-computation attacks further
by regenerating the Postfix SMTP server EDH parameters periodically
<p> Pattern matching of domain names is controlled by the presence
or absence of "smtpd_client_event_limit_exceptions" in the
-parent_domain_matches_subdomains parameter value (postfix 3.0 and
+parent_domain_matches_subdomains parameter value (Postfix 3.0 and
later). </p>
<p>
<p> File with DH parameters that the Postfix SMTP server should
use with non-export EDH ciphers. </p>
+<p> With Postfix ≥ 3.7, built with OpenSSL version is 3.0.0 or later, if the
+parameter value is either empty or "<b>auto</b>", then the DH parameter
+selection is delegated to the OpenSSL library, which selects appropriate
+parameters based on the TLS handshake. This choice is likely to be the most
+interoperable with SMTP clients using various TLS libraries, and custom local
+parameters are no longer recommended when using Postfix ≥ 3.7 built against
+OpenSSL 3.0.0. </p>
+
<p> The best-practice choice of parameters uses a 2048-bit prime. This is fine,
despite the historical "1024" in the parameter name. Do not be tempted to use
much larger values, performance degrades quickly, and you may also cease to
<p> This feature is available in Postfix 3.0 and later. </p>
+%PARAM lmtp_tls_wrappermode no
+
+<p> The LMTP-specific version of the smtp_tls_wrappermode configuration
+parameter. See there for details. </p>
+
+<p> This feature is available in Postfix 3.0 and later. </p>
+
%PARAM smtp_tls_connection_reuse no
<p> Try to make multiple deliveries per TLS-encrypted connection.
#define VAR_SMTP_MIN_DATA_RATE "smtp_min_data_rate"
#define DEF_SMTP_MIN_DATA_RATE 500
-#define VAR_LMTP_MIN_DATA_RATE "smtp_min_data_rate"
+#define VAR_LMTP_MIN_DATA_RATE "lmtp_min_data_rate"
#define DEF_LMTP_MIN_DATA_RATE 500
extern int var_smtp_min_data_rate;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20210815"
+#define MAIL_RELEASE_DATE "20210926"
#define MAIL_VERSION_NUMBER "3.7"
#ifdef SNAPSHOT
static const char *pcf_mynetworks(void)
{
static const char *networks;
+ VSTRING *exp_buf;
const char *junk;
/*
if (networks)
return (networks);
+ exp_buf = vstring_alloc(100);
+
if (var_inet_interfaces == 0) {
if ((pcf_cmd_mode & PCF_SHOW_DEFS)
|| (junk = mail_conf_lookup_eval(VAR_INET_INTERFACES)) == 0)
- junk = pcf_expand_parameter_value((VSTRING *) 0, pcf_cmd_mode,
+ junk = pcf_expand_parameter_value(exp_buf, pcf_cmd_mode,
DEF_INET_INTERFACES,
(PCF_MASTER_ENT *) 0);
var_inet_interfaces = mystrdup(junk);
if (var_mynetworks_style == 0) {
if ((pcf_cmd_mode & PCF_SHOW_DEFS)
|| (junk = mail_conf_lookup_eval(VAR_MYNETWORKS_STYLE)) == 0)
- junk = pcf_expand_parameter_value((VSTRING *) 0, pcf_cmd_mode,
+ junk = pcf_expand_parameter_value(exp_buf, pcf_cmd_mode,
DEF_MYNETWORKS_STYLE,
(PCF_MASTER_ENT *) 0);
var_mynetworks_style = mystrdup(junk);
if (var_inet_protocols == 0) {
if ((pcf_cmd_mode & PCF_SHOW_DEFS)
|| (junk = mail_conf_lookup_eval(VAR_INET_PROTOCOLS)) == 0)
- junk = pcf_expand_parameter_value((VSTRING *) 0, pcf_cmd_mode,
+ junk = pcf_expand_parameter_value(exp_buf, pcf_cmd_mode,
DEF_INET_PROTOCOLS,
(PCF_MASTER_ENT *) 0);
var_inet_protocols = mystrdup(junk);
(void) inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
}
+ vstring_free(exp_buf);
return (networks = mystrdup(mynetworks()));
}
/*
/* Arguments:
/* .IP buf
-/* Null buffer pointer, or pointer to user-supplied buffer.
+/* Pointer to user-supplied buffer; must not be null.
/* .IP mode
/* Bit-wise OR of zero or one of the following (other flags
/* are ignored):
PCF_EVAL_CTX eval_ctx;
/*
- * Initialize.
+ * Sanity check.
*/
- if (buf == 0) {
- if (local_buf == 0)
- local_buf = vstring_alloc(10);
- buf = local_buf;
- }
+ if (buf == 0)
+ msg_panic("%s: null buffer pointer", myname);
/*
* Expand macros recursively.
static void pcf_print_parameter(VSTREAM *fp, int mode, const char *name,
PCF_PARAM_NODE *node)
{
+ static VSTRING *exp_buf = 0;
const char *value;
+ if (exp_buf == 0)
+ exp_buf = vstring_alloc(100);
+
/*
* Use the default or actual value.
*/
pcf_print_line(fp, mode, "%s\n", name);
} else {
if ((mode & PCF_SHOW_EVAL) != 0 && PCF_RAW_PARAMETER(node) == 0)
- value = pcf_expand_parameter_value((VSTRING *) 0, mode, value,
+ value = pcf_expand_parameter_value(exp_buf, mode, value,
(PCF_MASTER_ENT *) 0);
if ((mode & PCF_HIDE_NAME) == 0) {
pcf_print_line(fp, mode, "%s = %s\n", name, value);
static const char pcf_valid_bool_types[] = "yn-";
+static VSTRING *pcf_exp_buf;
+
#define STR(x) vstring_str(x)
/* pcf_extract_field - extract text from {}, trim leading/trailing blanks */
while (0)
#define ADD_SPACE ADD_TEXT(" ", 1)
+ if (pcf_exp_buf == 0)
+ pcf_exp_buf = vstring_alloc(100);
+
/*
* Show the standard fields at their preferred column position. Use at
* least one-space column separation.
*/
if (strcmp(arg, "-o") == 0
&& (mode & PCF_SHOW_EVAL) != 0)
- aval = pcf_expand_parameter_value((VSTRING *) 0, mode,
+ aval = pcf_expand_parameter_value(pcf_exp_buf, mode,
aval, masterp);
/*
int in_daemon_options;
int need_parens;
+ if (pcf_exp_buf == 0)
+ pcf_exp_buf = vstring_alloc(100);
+
/*
* Show the field value, or the first value in the case of a multi-column
* field.
*/
if (strcmp(arg, "-o") == 0
&& (mode & PCF_SHOW_EVAL) != 0)
- aval = pcf_expand_parameter_value((VSTRING *) 0, mode,
+ aval = pcf_expand_parameter_value(pcf_exp_buf, mode,
aval, masterp);
/*
const char *param_name,
const char *param_value)
{
+ if (pcf_exp_buf == 0)
+ pcf_exp_buf = vstring_alloc(100);
+
if (mode & PCF_HIDE_VALUE) {
pcf_print_line(fp, mode, "%s%c%s\n",
masterp->name_space, PCF_NAMESP_SEP_CH,
param_name);
} else {
if ((mode & PCF_SHOW_EVAL) != 0)
- param_value = pcf_expand_parameter_value((VSTRING *) 0, mode,
+ param_value = pcf_expand_parameter_value(pcf_exp_buf, mode,
param_value, masterp);
if ((mode & PCF_HIDE_NAME) == 0) {
pcf_print_line(fp, mode, "%s%c%s = %s\n",
#include <openssl/x509v3.h>
#include <openssl/rand.h>
#include <openssl/crypto.h> /* Legacy SSLEAY_VERSION_NUMBER */
+#include <openssl/evp.h> /* New OpenSSL 3.0 EVP_PKEY APIs */
#include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */
#include <openssl/ssl.h>
#define ssl_cipher_stack_t STACK_OF(SSL_CIPHER)
#define ssl_comp_stack_t STACK_OF(SSL_COMP)
+/*-
+ * Official way to check minimum OpenSSL API version from 3.0 onward.
+ * We simply define it false for all prior versions, where we typically also
+ * need the patch level to determine API compatibility.
+ */
+#ifndef OPENSSL_VERSION_PREREQ
+#define OPENSSL_VERSION_PREREQ(m,n) 0
+#endif
+
#if (OPENSSL_VERSION_NUMBER < 0x1010100fUL)
#error "OpenSSL releases prior to 1.1.1 are no longer supported"
#endif
#define tls_get_peer_dh_pubkey SSL_get_server_tmp_key
#else
#define tls_get_peer_dh_pubkey SSL_get_peer_tmp_key
+#endif
+
+#if OPENSSL_VERSION_PREREQ(3,0)
+#define TLS_PEEK_PEER_CERT(ssl) SSL_get0_peer_certificate(ssl)
+#define TLS_FREE_PEER_CERT(x) ((void) 0)
+#define tls_set_bio_callback BIO_set_callback_ex
+#else
+#define TLS_PEEK_PEER_CERT(ssl) SSL_get_peer_certificate(ssl)
+#define TLS_FREE_PEER_CERT(x) X509_free(x)
+#define tls_set_bio_callback BIO_set_callback
#endif
/*
* tls_dh.c
*/
extern void tls_set_dh_from_file(const char *);
-extern void tls_tmp_dh(SSL_CTX *);
+extern void tls_tmp_dh(SSL_CTX *, int);
extern void tls_auto_eecdh_curves(SSL_CTX *, const char *);
/*
extern long tls_bug_bits(void);
extern void tls_print_errors(void);
extern void tls_info_callback(const SSL *, int, int);
+
+#if OPENSSL_VERSION_PREREQ(3,0)
+extern long tls_bio_dump_cb(BIO *, int, const char *, size_t, int, long,
+ int, size_t *);
+
+#else
extern long tls_bio_dump_cb(BIO *, int, const char *, int, long, long);
+
+#endif
extern const EVP_MD *tls_validate_digest(const char *);
/*
* created for us, so we can use it for debugging purposes.
*/
if (log_mask & TLS_LOG_TLSPKTS)
- BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
+ tls_set_bio_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
/*
* If we don't trigger the handshake in the library, leave control over
/* Turn off packet dump if only dumping the handshake */
if ((TLScontext->log_mask & TLS_LOG_ALLPKTS) == 0)
- BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
+ tls_set_bio_callback(SSL_get_rbio(TLScontext->con), 0);
/*
* The caller may want to know if this session was reused or if a new
* Do peername verification if requested and extract useful information
* from the certificate for later use.
*/
- if ((peercert = SSL_get_peer_certificate(TLScontext->con)) != 0) {
+ if ((peercert = TLS_PEEK_PEER_CERT(TLScontext->con)) != 0) {
TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT;
/*
TLScontext->peer_CN, TLScontext->issuer_CN,
TLScontext->peer_cert_fprint,
TLScontext->peer_pkey_fprint);
- X509_free(peercert);
} else {
TLScontext->issuer_CN = mystrdup("");
TLScontext->peer_CN = mystrdup("");
/* SSL_CTX *ctx;
/* char *configured;
/*
-/* void tls_tmp_dh(ctx)
+/* void tls_tmp_dh(ctx, useauto)
/* SSL_CTX *ctx;
+/* int useauto;
/* DESCRIPTION
/* This module maintains parameters for Diffie-Hellman key generation.
/*
/* is as expected by the PEM_read_DHparams() routine.
/*
/* tls_auto_eecdh_curves() enables negotiation of the most preferred curve
-/* among the curves specified by the "configured" argument.
+/* among the curves specified by the "configured" argument. The useauto
+/* argument enables OpenSSL-builtin group selection in preference to our
+/* own compiled-in group. This may interoperate better with overly strict
+/* peers that accept only "standard" groups (bogus threat model).
/* DIAGNOSTICS
/* In case of error, tls_set_dh_from_file() logs a warning and
/* ignores the request.
#ifndef OPENSSL_NO_ECDH
#include <openssl/ec.h>
#endif
+#if OPENSSL_VERSION_PREREQ(3,0)
+#include <openssl/decoder.h>
+#endif
/* Application-specific. */
/*
* Compiled-in FFDHE (finite-field ephemeral Diffie-Hellman) parameters.
* Used when no parameters are explicitly loaded from a site-specific file.
+ *
+ * With OpenSSL 3.0 and later when no explicit parameter file is specified by
+ * the administrator (or the setting is "auto"), we delegate group selection
+ * to OpenSSL via SSL_CTX_set_dh_auto(3).
+ *
* Using an ASN.1 DER encoding avoids the need to explicitly manipulate the
* internal representation of DH parameter objects.
*
/*-
* Generated via:
* $ openssl dhparam -2 -outform DER 2048 2>/dev/null |
- * hexdump -ve '/1 "0x%02x, "' | fmt
+ * hexdump -ve '/1 "0x%02x, "' | fmt -73
* TODO: generate at compile-time. But that is no good for the majority of
* sites that install pre-compiled binaries, and breaks reproducible builds.
* Instead, generate at installation time and use main.cf configuration.
*/
-static unsigned char dh2048_der[] = {
- 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9e, 0x28, 0x15,
- 0xc5, 0xcc, 0x9b, 0x5a, 0xb0, 0xe9, 0xab, 0x74, 0x8b, 0x2a, 0x23, 0xce,
- 0xea, 0x87, 0xa0, 0x18, 0x09, 0xd0, 0x40, 0x2c, 0x93, 0x23, 0x5d, 0xc0,
- 0xe9, 0x78, 0x2c, 0x53, 0xd9, 0x3e, 0x21, 0x14, 0x89, 0x5c, 0x79, 0x73,
- 0x1e, 0xbd, 0x23, 0x1e, 0x18, 0x65, 0x6d, 0xd2, 0x3c, 0xeb, 0x41, 0xca,
- 0xbb, 0xa9, 0x99, 0x55, 0x84, 0xae, 0x9e, 0x70, 0x57, 0x25, 0x21, 0x42,
- 0xaa, 0xdb, 0x82, 0xc6, 0xe6, 0xf1, 0xcf, 0xb7, 0xbc, 0x2a, 0x56, 0xcc,
- 0x55, 0x1f, 0xad, 0xe9, 0x68, 0x18, 0x22, 0xfc, 0x09, 0x62, 0xc3, 0x32,
- 0x1b, 0x05, 0x1f, 0xce, 0xec, 0xe3, 0x6d, 0xb5, 0x79, 0xe0, 0x89, 0x45,
- 0xf3, 0xf3, 0x26, 0xa3, 0x81, 0xd9, 0x59, 0xee, 0xed, 0x78, 0xbe, 0x0e,
- 0xdd, 0xf7, 0xef, 0xcb, 0x81, 0x3f, 0x01, 0xb7, 0x10, 0x8f, 0x0d, 0xbe,
- 0x29, 0x21, 0x13, 0xff, 0x2a, 0x13, 0x25, 0x75, 0x99, 0xec, 0xf5, 0x2d,
- 0x49, 0x01, 0x1d, 0xa4, 0x13, 0xe8, 0x2c, 0xc8, 0x13, 0x60, 0x57, 0x98,
- 0xb1, 0x06, 0x45, 0x77, 0xa4, 0x24, 0xf9, 0x27, 0x3f, 0x08, 0xe6, 0x9b,
- 0x4b, 0x20, 0x3b, 0x43, 0x69, 0xa3, 0xcc, 0x9a, 0xc4, 0x3c, 0x1e, 0xec,
- 0xb7, 0x35, 0xe4, 0x59, 0x6b, 0x6d, 0x2a, 0xdf, 0xf7, 0x0b, 0xd4, 0x5a,
- 0x0f, 0x79, 0x80, 0xe1, 0x75, 0x4c, 0x10, 0xea, 0x26, 0xf0, 0xd5, 0xf3,
- 0xa6, 0x15, 0xa9, 0x3e, 0x3d, 0x0d, 0xb8, 0x53, 0x50, 0x49, 0x77, 0x49,
- 0x47, 0x43, 0x39, 0xee, 0xb8, 0x8a, 0xe5, 0x14, 0xc4, 0xe3, 0x10, 0xfb,
- 0xf5, 0x52, 0xef, 0xa5, 0x8f, 0xa4, 0x7e, 0x57, 0xb9, 0x5f, 0xda, 0x00,
- 0x18, 0xf0, 0x72, 0x29, 0xd4, 0xfe, 0x90, 0x5a, 0x1f, 0x1a, 0x40, 0xee,
- 0x4e, 0xfa, 0x3e, 0xf3, 0x72, 0x4b, 0xea, 0x44, 0x53, 0x43, 0x53, 0x57,
- 0x9b, 0x02, 0x01, 0x02,
+static unsigned char builtin_der[] = {
+ 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xec, 0x02, 0x7b,
+ 0x74, 0xc6, 0xd4, 0xb4, 0x89, 0x68, 0xfd, 0xbc, 0xe0, 0x82, 0xae, 0xd6,
+ 0xf1, 0x4d, 0x93, 0xaa, 0x47, 0x07, 0x84, 0x3d, 0x86, 0xf8, 0x47, 0xf7,
+ 0xdf, 0x08, 0x7b, 0xca, 0x04, 0xa4, 0x72, 0xec, 0x11, 0xe2, 0x38, 0x43,
+ 0xb7, 0x94, 0xab, 0xaf, 0xe2, 0x85, 0x59, 0x43, 0x4e, 0x71, 0x85, 0xfe,
+ 0x52, 0x0c, 0xe0, 0x1c, 0xb6, 0xc7, 0xb0, 0x1b, 0x06, 0xb3, 0x4d, 0x1b,
+ 0x4f, 0xf6, 0x4b, 0x45, 0xbd, 0x1d, 0xb8, 0xe4, 0xa4, 0x48, 0x09, 0x28,
+ 0x19, 0xd7, 0xce, 0xb1, 0xe5, 0x9a, 0xc4, 0x94, 0x55, 0xde, 0x4d, 0x86,
+ 0x0f, 0x4c, 0x5e, 0x25, 0x51, 0x6c, 0x96, 0xca, 0xfa, 0xe3, 0x01, 0x69,
+ 0x82, 0x6c, 0x8f, 0xf5, 0xe7, 0x0e, 0xb7, 0x8e, 0x52, 0xf1, 0xcf, 0x0b,
+ 0x67, 0x10, 0xd0, 0xb3, 0x77, 0x79, 0xa4, 0xc1, 0xd0, 0x0f, 0x3f, 0xf5,
+ 0x5c, 0x35, 0xf9, 0x46, 0xd2, 0xc7, 0xfb, 0x97, 0x6d, 0xd5, 0xbe, 0xe4,
+ 0x8b, 0x5a, 0xf2, 0x88, 0xfa, 0x47, 0xdc, 0xc2, 0x4a, 0x4d, 0x69, 0xd3,
+ 0x2a, 0xdf, 0x55, 0x6c, 0x5f, 0x71, 0x11, 0x1e, 0x87, 0x03, 0x68, 0xe1,
+ 0xf4, 0x21, 0x06, 0x63, 0xd9, 0x65, 0xd4, 0x0c, 0x4d, 0xa7, 0x1f, 0x15,
+ 0x53, 0x3a, 0x50, 0x1a, 0xf5, 0x9b, 0x50, 0x35, 0xe0, 0x16, 0xa1, 0xd7,
+ 0xe6, 0xbf, 0xd7, 0xd9, 0xd9, 0x53, 0xe5, 0x8b, 0xf8, 0x7b, 0x45, 0x46,
+ 0xb6, 0xac, 0x50, 0x16, 0x46, 0x42, 0xca, 0x76, 0x38, 0x4b, 0x8e, 0x83,
+ 0xc6, 0x73, 0x13, 0x9c, 0x03, 0xd1, 0x7a, 0x3d, 0x8d, 0x99, 0x34, 0x10,
+ 0x79, 0x67, 0x21, 0x23, 0xf9, 0x6f, 0x48, 0x9a, 0xa6, 0xde, 0xbf, 0x7f,
+ 0x9c, 0x16, 0x53, 0xff, 0xf7, 0x20, 0x96, 0xeb, 0x34, 0xcb, 0x5b, 0x85,
+ 0x2b, 0x7c, 0x98, 0x00, 0x23, 0x47, 0xce, 0xc2, 0x58, 0x12, 0x86, 0x2c,
+ 0x57, 0x02, 0x01, 0x02,
};
- /*
- * Cached results.
- */
-static DH *dh_2048 = 0;
+#if OPENSSL_VERSION_PREREQ(3,0)
+
+/* ------------------------------------- 3.0 API */
+
+static EVP_PKEY *dhp = 0;
+
+/* load_builtin - load compile-time FFDHE group */
+
+static void load_builtin(void)
+{
+ EVP_PKEY *tmp = 0;
+ OSSL_DECODER_CTX *d;
+ const unsigned char *endp = builtin_der;
+ size_t dlen = sizeof(builtin_der);
+
+ d = OSSL_DECODER_CTX_new_for_pkey(&tmp, "DER", NULL, "DH",
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ NULL, NULL);
+ /* Check decode succeeds and consumes all data (final dlen == 0) */
+ if (d && OSSL_DECODER_from_data(d, &endp, &dlen) && tmp && !dlen) {
+ dhp = tmp;
+ } else {
+ EVP_PKEY_free(tmp);
+ msg_warn("error loading compiled-in DH parameters");
+ tls_print_errors();
+ }
+ OSSL_DECODER_CTX_free(d);
+}
/* tls_set_dh_from_file - set Diffie-Hellman parameters from file */
void tls_set_dh_from_file(const char *path)
{
- FILE *paramfile;
+ FILE *fp;
+ EVP_PKEY *tmp = 0;
+ OSSL_DECODER_CTX *d;
/*
* This function is the first to set the DH parameters, but free any
* prior value just in case the call sequence changes some day.
*/
- if (dh_2048) {
- DH_free(dh_2048);
- dh_2048 = 0;
+ if (dhp) {
+ EVP_PKEY_free(dhp);
+ dhp = 0;
}
- if ((paramfile = fopen(path, "r")) != 0) {
- if ((dh_2048 = PEM_read_DHparams(paramfile, 0, 0, 0)) == 0) {
- msg_warn("cannot load DH parameters from file %s"
- " -- using compiled-in defaults", path);
- tls_print_errors();
- }
- (void) fclose(paramfile); /* 200411 */
- } else {
+ if (strcmp(path, "auto") == 0)
+ return;
+
+ if ((fp = fopen(path, "r")) == 0) {
msg_warn("cannot load DH parameters from file %s: %m"
" -- using compiled-in defaults", path);
+ return;
+ }
+ d = OSSL_DECODER_CTX_new_for_pkey(&tmp, "PEM", NULL, "DH",
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ NULL, NULL);
+ if (!d || !OSSL_DECODER_from_fp(d, fp) || !tmp) {
+ msg_warn("error loading compiled-in DH parameters");
+ tls_print_errors();
+ } else {
+ dhp = tmp;
}
+ OSSL_DECODER_CTX_free(d);
+ (void) fclose(fp);
}
/* tls_tmp_dh - configure FFDHE group */
-void tls_tmp_dh(SSL_CTX *ctx)
+void tls_tmp_dh(SSL_CTX *ctx, int useauto)
{
- if (dh_2048 == 0) {
- const unsigned char *endp = dh2048_der;
- DH *dh = 0;
-
- if (d2i_DHparams(&dh, &endp, sizeof(dh2048_der))
- && sizeof(dh2048_der) == endp - dh2048_der) {
- dh_2048 = dh;
- } else {
- DH_free(dh); /* Unlikely non-zero, but by
- * the book */
- msg_warn("error loading compiled-in DH parameters");
- }
+ if (!dhp && !useauto)
+ load_builtin();
+ if (!ctx)
+ return;
+ if (dhp) {
+ EVP_PKEY *tmp = EVP_PKEY_dup(dhp);
+
+ if (tmp && SSL_CTX_set0_tmp_dh_pkey(ctx, tmp) > 0)
+ return;
+ EVP_PKEY_free(tmp);
+ msg_warn("error configuring explicit DH parameters");
+ tls_print_errors();
+ } else {
+ if (SSL_CTX_set_dh_auto(ctx, 1) > 0)
+ return;
+ msg_warn("error configuring auto DH parameters");
+ tls_print_errors();
}
- if (ctx != 0 && dh_2048 != 0)
- SSL_CTX_set_tmp_dh(ctx, dh_2048);
}
+#else /* OPENSSL_VERSION_PREREQ(3,0) */
+
+/* ------------------------------------- 1.1.1 API */
+
+static DH *dhp = 0;
+
+static void load_builtin(void)
+{
+ DH *tmp = 0;
+ const unsigned char *endp = builtin_der;
+
+ if (d2i_DHparams(&tmp, &endp, sizeof(builtin_der))
+ && sizeof(builtin_der) == endp - builtin_der) {
+ dhp = tmp;
+ } else {
+ DH_free(tmp);
+ msg_warn("error loading compiled-in DH parameters");
+ tls_print_errors();
+ }
+}
+
+/* tls_set_dh_from_file - set Diffie-Hellman parameters from file */
+
+void tls_set_dh_from_file(const char *path)
+{
+ FILE *fp;
+
+ /*
+ * This function is the first to set the DH parameters, but free any
+ * prior value just in case the call sequence changes some day.
+ */
+ if (dhp) {
+ DH_free(dhp);
+ dhp = 0;
+ }
+
+ /*
+ * Forwards compatibility, support "auto" by using the builtin group when
+ * OpenSSL is < 3.0 and does not support automatic FFDHE group selection.
+ */
+ if (strcmp(path, "auto") == 0)
+ return;
+
+ if ((fp = fopen(path, "r")) == 0) {
+ msg_warn("cannot load DH parameters from file %s: %m"
+ " -- using compiled-in defaults", path);
+ return;
+ }
+ if ((dhp = PEM_read_DHparams(fp, 0, 0, 0)) == 0) {
+ msg_warn("cannot load DH parameters from file %s"
+ " -- using compiled-in defaults", path);
+ tls_print_errors();
+ }
+ (void) fclose(fp);
+}
+
+/* tls_tmp_dh - configure FFDHE group */
+
+void tls_tmp_dh(SSL_CTX *ctx, int useauto)
+{
+ if (!dhp)
+ load_builtin();
+ if (!ctx || !dhp || SSL_CTX_set_tmp_dh(ctx, dhp) > 0)
+ return;
+ msg_warn("error configuring explicit DH parameters");
+ tls_print_errors();
+}
+
+#endif /* OPENSSL_VERSION_PREREQ(3,0) */
+
+/* ------------------------------------- Common API */
+
void tls_auto_eecdh_curves(SSL_CTX *ctx, const char *configured)
{
#ifndef OPENSSL_NO_ECDH
int main(int unused_argc, char **unused_argv)
{
- tls_tmp_dh(0);
- return (dh_2048 == 0);
+ tls_tmp_dh(0, 0);
+ return (dhp == 0);
}
#endif
/* int where;
/* int ret;
/*
-/* long tls_bio_dump_cb(bio, cmd, argp, argi, argl, ret)
+/* long tls_bio_dump_cb(bio, cmd, argp, len, argi, argl, ret, processed)
/* BIO *bio;
/* int cmd;
/* const char *argp;
+/* size_t len;
/* int argi;
/* long argl; /* unused */
-/* long ret;
+/* int ret;
+/* size_t *processed;
/*
/* int tls_log_mask(log_param, log_level)
/* const char *log_param;
return (vstring_str(buf));
}
+/* ec_curve_name - copy EC key curve group name */
+
+#ifndef OPENSSL_NO_EC
+static char *ec_curve_name(EVP_PKEY *pkey)
+{
+ char *curve = 0;
+
+#if OPENSSL_VERSION_PREREQ(3,0)
+ size_t namelen;
+
+ if (EVP_PKEY_get_group_name(pkey, 0, 0, &namelen)) {
+ curve = mymalloc(++namelen);
+ if (!EVP_PKEY_get_group_name(pkey, curve, namelen, 0)) {
+ myfree(curve);
+ curve = 0;
+ }
+ }
+#else
+ EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
+ int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+ const char *tmp = EC_curve_nid2nist(nid);
+
+ if (!tmp)
+ tmp = OBJ_nid2sn(nid);
+ if (tmp)
+ curve = mystrdup(tmp);
+#endif
+ return (curve);
+}
+
+#endif
+
/* tls_get_signature_params - TLS 1.3 signature details */
void tls_get_signature_params(TLS_SESS_STATE *TLScontext)
{
const char *kex_name = 0;
- const char *kex_curve = 0;
const char *locl_sig_name = 0;
- const char *locl_sig_curve = 0;
const char *locl_sig_dgst = 0;
const char *peer_sig_name = 0;
- const char *peer_sig_curve = 0;
const char *peer_sig_dgst = 0;
+ char *kex_curve = 0;
+ char *locl_sig_curve = 0;
+ char *peer_sig_curve = 0;
int nid;
SSL *ssl = TLScontext->con;
int srvr = SSL_is_server(ssl);
X509 *peer_cert;
EVP_PKEY *peer_pkey = 0;
-#ifndef OPENSSL_NO_EC
- EC_KEY *eckey;
-
-#endif
-
#define SIG_PROP(c, s, p) (*((s) ? &c->srvr_sig_##p : &c->clnt_sig_##p))
if (SSL_version(ssl) < TLS1_3_VERSION)
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
kex_name = "ECDHE";
- eckey = EVP_PKEY_get0_EC_KEY(dh_pkey);
- nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
- kex_curve = EC_curve_nid2nist(nid);
- if (!kex_curve)
- kex_curve = OBJ_nid2sn(nid);
+ kex_curve = ec_curve_name(dh_pkey);
break;
#endif
}
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
locl_sig_name = "ECDSA";
- eckey = EVP_PKEY_get0_EC_KEY(local_pkey);
- nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
- locl_sig_curve = EC_curve_nid2nist(nid);
- if (!locl_sig_curve)
- locl_sig_curve = OBJ_nid2sn(nid);
+ locl_sig_curve = ec_curve_name(local_pkey);
break;
#endif
}
locl_sig_dgst = OBJ_nid2sn(nid);
}
/* Signature algorithms for the peer end of the connection */
- if ((peer_cert = SSL_get_peer_certificate(ssl)) != 0) {
+ if ((peer_cert = TLS_PEEK_PEER_CERT(ssl)) != 0) {
peer_pkey = X509_get0_pubkey(peer_cert);
/*
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
peer_sig_name = "ECDSA";
- eckey = EVP_PKEY_get0_EC_KEY(peer_pkey);
- nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
- peer_sig_curve = EC_curve_nid2nist(nid);
- if (!peer_sig_curve)
- peer_sig_curve = OBJ_nid2sn(nid);
+ peer_sig_curve = ec_curve_name(peer_pkey);
break;
#endif
}
if (SSL_get_peer_signature_nid(ssl, &nid) && nid != NID_undef)
peer_sig_dgst = OBJ_nid2sn(nid);
- X509_free(peer_cert);
+ TLS_FREE_PEER_CERT(peer_cert);
}
if (kex_name) {
TLScontext->kex_name = mystrdup(kex_name);
- if (kex_curve)
- TLScontext->kex_curve = mystrdup(kex_curve);
+ TLScontext->kex_curve = kex_curve;
}
if (locl_sig_name) {
SIG_PROP(TLScontext, srvr, name) = mystrdup(locl_sig_name);
- if (locl_sig_curve)
- SIG_PROP(TLScontext, srvr, curve) = mystrdup(locl_sig_curve);
+ SIG_PROP(TLScontext, srvr, curve) = locl_sig_curve;
if (locl_sig_dgst)
SIG_PROP(TLScontext, srvr, dgst) = mystrdup(locl_sig_dgst);
}
if (peer_sig_name) {
SIG_PROP(TLScontext, !srvr, name) = mystrdup(peer_sig_name);
- if (peer_sig_curve)
- SIG_PROP(TLScontext, !srvr, curve) = mystrdup(peer_sig_curve);
+ SIG_PROP(TLScontext, !srvr, curve) = peer_sig_curve;
if (peer_sig_dgst)
SIG_PROP(TLScontext, !srvr, dgst) = mystrdup(peer_sig_dgst);
}
int line;
int flags;
- while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
+#if OPENSSL_VERSION_PREREQ(3,0)
+/* XXX: We're ignoring the function name, do we want to log it? */
+#define ERRGET(fi, l, d, fl) ERR_get_error_all(fi, l, 0, d, fl)
+#else
+#define ERRGET(fi, l, d, fl) ERR_get_error_line_data(fi, l, d, fl)
+#endif
+
+ while ((err = ERRGET(&file, &line, &data, &flags)) != 0) {
ERR_error_string_n(err, buffer, sizeof(buffer));
if (flags & ERR_TXT_STRING)
msg_warn("TLS library problem: %s:%s:%d:%s:",
/* taken from OpenSSL apps/s_cb.c */
+#if !OPENSSL_VERSION_PREREQ(3,0)
long tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, int argi,
long unused_argl, long ret)
{
return (ret);
}
+#else
+long tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, size_t len,
+ int argi, long unused_argl, int ret, size_t *processed)
+{
+ size_t bytes = (ret > 0 && processed != NULL) ? *processed : len;
+
+ if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
+ if (ret > 0) {
+ msg_info("read from %08lX [%08lX] (%ld bytes => %ld (0x%lX))",
+ (unsigned long) bio, (unsigned long) argp, (long) len,
+ (long) bytes, (long) bytes);
+ tls_dump_buffer((unsigned char *) argp, (int) bytes);
+ } else {
+ msg_info("read from %08lX [%08lX] (%ld bytes => %d)",
+ (unsigned long) bio, (unsigned long) argp,
+ (long) len, ret);
+ }
+ } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
+ if (ret > 0) {
+ msg_info("write to %08lX [%08lX] (%ld bytes => %ld (0x%lX))",
+ (unsigned long) bio, (unsigned long) argp, (long) len,
+ (long) bytes, (long) bytes);
+ tls_dump_buffer((unsigned char *) argp, (int) bytes);
+ } else {
+ msg_info("write to %08lX [%08lX] (%ld bytes => %d)",
+ (unsigned long) bio, (unsigned long) argp,
+ (long) len, ret);
+ }
+ }
+ return ret;
+}
+
+#endif
+
const EVP_MD *tls_validate_digest(const char *dgst)
{
const EVP_MD *md_alg;
* Open the dictionary with O_TRUNC, so that we never have to worry about
* opening a damaged file after some process terminated abnormally.
*/
-#ifdef SINGLE_UPDATER
-#define DICT_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_OPEN_LOCK \
- | DICT_FLAG_UTF8_REQUEST)
-#else
#define DICT_FLAGS \
- (DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE \
+ (DICT_FLAG_DUP_REPLACE | DICT_FLAG_OPEN_LOCK | DICT_FLAG_SYNC_UPDATE \
| DICT_FLAG_UTF8_REQUEST)
-#endif
dict = dict_open(dbname, O_RDWR | O_CREAT | O_TRUNC, DICT_FLAGS);
#include <tls_mgr.h>
#define TLS_INTERNAL
#include <tls.h>
+#if OPENSSL_VERSION_PREREQ(3,0)
+#include <openssl/core_names.h> /* EVP_MAC parameters */
+#endif
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
#define TLS_TKT_ACCEPT 1 /* Ticket decryptable and re-usable */
#define TLS_TKT_REISSUE 2 /* Ticket decryptable, not re-usable */
+#if defined(SSL_OP_NO_TICKET) && !defined(OPENSSL_NO_TLSEXT)
+
+#if OPENSSL_VERSION_PREREQ(3,0)
+
/* ticket_cb - configure tls session ticket encrypt/decrypt context */
-#if defined(SSL_OP_NO_TICKET) && !defined(OPENSSL_NO_TLSEXT)
+static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
+ EVP_CIPHER_CTX *ctx, EVP_MAC_CTX *hctx, int create)
+{
+ OSSL_PARAM params[3];
+ static const EVP_CIPHER *ciph;
+ TLS_TICKET_KEY *key;
+ TLS_SESS_STATE *TLScontext = SSL_get_ex_data(con, TLScontext_index);
+ int timeout = ((int) SSL_CTX_get_timeout(SSL_get_SSL_CTX(con))) / 2;
+
+ if ((!ciph && (ciph = EVP_get_cipherbyname(var_tls_tkt_cipher)) == 0)
+ || (key = tls_mgr_key(create ? 0 : name, timeout)) == 0
+ || (create && RAND_bytes(iv, TLS_TICKET_IVLEN) <= 0))
+ return (create ? TLS_TKT_NOKEYS : TLS_TKT_STALE);
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ LN_sha256, 0);
+ params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (char *) key->hmac,
+ TLS_TICKET_MACLEN);
+ params[2] = OSSL_PARAM_construct_end();
+ if (!EVP_MAC_CTX_set_params(hctx, params))
+ return (create ? TLS_TKT_NOKEYS : TLS_TKT_STALE);
+
+ if (create) {
+ EVP_EncryptInit_ex(ctx, ciph, NOENGINE, key->bits, iv);
+ memcpy((void *) name, (void *) key->name, TLS_TICKET_NAMELEN);
+ if (TLScontext->log_mask & TLS_LOG_CACHE)
+ msg_info("%s: Issuing session ticket, key expiration: %ld",
+ TLScontext->namaddr, (long) key->tout);
+ } else {
+ EVP_DecryptInit_ex(ctx, ciph, NOENGINE, key->bits, iv);
+ if (TLScontext->log_mask & TLS_LOG_CACHE)
+ msg_info("%s: Decrypting session ticket, key expiration: %ld",
+ TLScontext->namaddr, (long) key->tout);
+ }
+ TLScontext->ticketed = 1;
+ return (TLS_TKT_ACCEPT);
+}
+
+#else /* OPENSSL_VERSION_PREREQ(3,0) */
+
+/* ticket_cb - configure tls session ticket encrypt/decrypt context */
static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
- EVP_CIPHER_CTX * ctx, HMAC_CTX * hctx, int create)
+ EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int create)
{
static const EVP_MD *sha256;
static const EVP_CIPHER *ciph;
return (TLS_TKT_ACCEPT);
}
-#endif
+#endif /* OPENSSL_VERSION_PREREQ(3,0) */
+
+#endif /* defined(SSL_OP_NO_TICKET) &&
+ * !defined(OPENSSL_NO_TLSEXT) */
/* tls_server_init - initialize the server-side TLS engine */
}
}
if (ticketable) {
+#if OPENSSL_VERSION_PREREQ(3,0)
+ SSL_CTX_set_tlsext_ticket_key_evp_cb(server_ctx, ticket_cb);
+#else
SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, ticket_cb);
+#endif
/*
* OpenSSL 1.1.1 introduces support for TLS 1.3, which can issue more
*/
if (*props->dh1024_param_file != 0)
tls_set_dh_from_file(props->dh1024_param_file);
- tls_tmp_dh(server_ctx);
- tls_tmp_dh(sni_ctx);
+ tls_tmp_dh(server_ctx, 1);
+ tls_tmp_dh(sni_ctx, 1);
/*
* Enable EECDH if available, errors are not fatal, we just keep going
* created for us, so we can use it for debugging purposes.
*/
if (log_mask & TLS_LOG_TLSPKTS)
- BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
+ tls_set_bio_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
/*
* If we don't trigger the handshake in the library, leave control over
/* Turn off packet dump if only dumping the handshake */
if ((TLScontext->log_mask & TLS_LOG_ALLPKTS) == 0)
- BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
+ tls_set_bio_callback(SSL_get_rbio(TLScontext->con), 0);
/*
* The caller may want to know if this session was reused or if a new
* Let's see whether a peer certificate is available and what is the
* actual information. We want to save it for later use.
*/
- peer = SSL_get_peer_certificate(TLScontext->con);
+ peer = TLS_PEEK_PEER_CERT(TLScontext->con);
if (peer != NULL) {
TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT;
if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
TLScontext->peer_cert_fprint,
TLScontext->peer_pkey_fprint);
}
- X509_free(peer);
+ TLS_FREE_PEER_CERT(peer);
/*
* Give them a clue. Problems with trust chain verification are