mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 06:05:37 +00:00
postfix-3.4-20181118
This commit is contained in:
committed by
Viktor Dukhovni
parent
5690047582
commit
2cda534f4b
2
postfix/.indent.pro
vendored
2
postfix/.indent.pro
vendored
@@ -336,7 +336,6 @@
|
||||
-TSTATE
|
||||
-TSTRING_LIST
|
||||
-TSTRING_TABLE
|
||||
-TSUMMARY_CLASS
|
||||
-TSYS_EXITS_DETAIL
|
||||
-TTLSMGR_SCACHE
|
||||
-TTLSP_STATE
|
||||
@@ -356,6 +355,7 @@
|
||||
-TTLS_SESS_STATE
|
||||
-TTLS_TICKET_KEY
|
||||
-TTLS_TLSA
|
||||
-TTLS_USAGE
|
||||
-TTLS_VINFO
|
||||
-TTLScontext_t
|
||||
-TTOK822
|
||||
|
@@ -23770,9 +23770,7 @@ Apologies for any names omitted.
|
||||
postmap/postmap.c.
|
||||
|
||||
Cleanup: don't use ssize_t for boolean result. File:
|
||||
global/smtp_stream.c. Memory leak: the Berkeley DB client
|
||||
leaked a small amount of memory asfter failing to open a
|
||||
table. File: util/dict_db.c.
|
||||
global/smtp_stream.c.
|
||||
|
||||
Cleanup: memory leak caused by missing dbenv->close() call
|
||||
after failing to open a Berkeley DB table. File: util/dict_db.c.
|
||||
@@ -23794,3 +23792,26 @@ Apologies for any names omitted.
|
||||
tls/tls_proxy_context_print.c, tls/tls_proxy_context_scan.c,
|
||||
tls/tls_client.c, tls/tls_server.c, smtpd/smtpd.c,
|
||||
posttls-finger/posttls-finger.c.
|
||||
|
||||
Cleanup: vstream_memopen() flags handling. File:
|
||||
util/vstream.c.
|
||||
|
||||
Cleanup: the SMTP client now uses 'attr_print_plain'
|
||||
serialization and 'attr_scan_plain' deserialization for
|
||||
connection cache lookup keys, which now contain a serialized
|
||||
version of the TLS context. File: smtp/smtp_session.c.
|
||||
|
||||
20181117
|
||||
|
||||
The Postfix SMTP client now logs whether an SMTP-over-TLS
|
||||
connection is newly established ("TLS connection established")
|
||||
or whether the connection is reused ("TLS connection reused").
|
||||
Files: smtp/smtp.h, smtp/smtp_proto.c, smtp/smtp_session.c.
|
||||
|
||||
20181118
|
||||
|
||||
Cleanup, no behavior change: updated comments concerning
|
||||
connection reuse, and updated some identifiers to reflect
|
||||
current reality. Files: smtp_reuse.c, smtp_key.c, smtp_proto.c,
|
||||
smtp_tls_policy.c, smtp.h, smtp_connect.c.
|
||||
|
||||
|
@@ -12,7 +12,6 @@ GGeenneerraall ccoonnffiigguurraattiioonn
|
||||
* TLS_README: TLS Encryption and authentication
|
||||
* FORWARD_SECRECY_README: TLS Forward Secrecy
|
||||
* IPV6_README: IP Version 6 Support
|
||||
* IPV6_README: IP Version 6 Support
|
||||
* SMTPUTF8_README: SMTPUTF8 Support
|
||||
* COMPATIBILITY_README: Backwards-Compatibility Safety Net
|
||||
* INSTALL: Installation from source code
|
||||
|
@@ -323,7 +323,7 @@ verification status.
|
||||
(No client certificate requested)
|
||||
|
||||
TLS 1.3 examples. Some of the new attributes may not appear when not
|
||||
applicable or not available in an older versions of the OpenSSL library.
|
||||
applicable or not available in older versions of the OpenSSL library.
|
||||
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256
|
||||
|
@@ -434,7 +434,7 @@ Received: from host.example.com (host.example.com [192.168.0.2])
|
||||
</blockquote>
|
||||
|
||||
<p> TLS 1.3 examples. Some of the new attributes may not appear when not
|
||||
applicable or not available in an older versions of the OpenSSL library. </p>
|
||||
applicable or not available in older versions of the OpenSSL library. </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
|
@@ -46,8 +46,6 @@ configuration examples </a>
|
||||
|
||||
<li> <a href="IPV6_README.html"> IP Version 6 Support </a>
|
||||
|
||||
<li> <a href="IPV6_README.html"> IP Version 6 Support </a>
|
||||
|
||||
<li> <a href="SMTPUTF8_README.html"> SMTPUTF8 Support </a>
|
||||
|
||||
<li> <a href="COMPATIBILITY_README.html"> Backwards-Compatibility Safety Net</a>
|
||||
|
@@ -434,7 +434,7 @@ Received: from host.example.com (host.example.com [192.168.0.2])
|
||||
</blockquote>
|
||||
|
||||
<p> TLS 1.3 examples. Some of the new attributes may not appear when not
|
||||
applicable or not available in an older versions of the OpenSSL library. </p>
|
||||
applicable or not available in older versions of the OpenSSL library. </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
|
@@ -20,7 +20,7 @@
|
||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||
* patchlevel; they change the release date only.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20181117"
|
||||
#define MAIL_RELEASE_DATE "20181118"
|
||||
#define MAIL_VERSION_NUMBER "3.4"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@@ -192,17 +192,25 @@ typedef struct SMTP_STATE {
|
||||
} SMTP_STATE;
|
||||
|
||||
/*
|
||||
* TODO: use the new SMTP_ITER name space.
|
||||
* Primitives to enable/disable/test connection caching and reuse based on
|
||||
* the delivery request next-hop destination (i.e. not smtp_fallback_relay).
|
||||
*
|
||||
* Connection cache lookup by the request next-hop destination allows a reuse
|
||||
* request to skip over bad hosts, and may result in a connection to a
|
||||
* fall-back relay. Once we have found a 'good' host for a request next-hop,
|
||||
* clear the request next-hop destination, to avoid caching less-preferred
|
||||
* connections under that same request next-hop.
|
||||
*/
|
||||
#define SET_NEXTHOP_STATE(state, nexthop) { \
|
||||
#define SET_SCACHE_REQUEST_NEXTHOP(state, nexthop) do { \
|
||||
vstring_strcpy((state)->iterator->request_nexthop, nexthop); \
|
||||
}
|
||||
} while (0)
|
||||
|
||||
#define FREE_NEXTHOP_STATE(state) { \
|
||||
#define CLEAR_SCACHE_REQUEST_NEXTHOP(state) do { \
|
||||
STR((state)->iterator->request_nexthop)[0] = 0; \
|
||||
}
|
||||
} while (0)
|
||||
|
||||
#define HAVE_NEXTHOP_STATE(state) (STR((state)->iterator->request_nexthop)[0] != 0)
|
||||
#define HAVE_SCACHE_REQUEST_NEXTHOP(state) \
|
||||
(STR((state)->iterator->request_nexthop)[0] != 0)
|
||||
|
||||
|
||||
/*
|
||||
@@ -229,6 +237,7 @@ typedef struct SMTP_STATE {
|
||||
#define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19) /* CVE-2009-3555 */
|
||||
#define SMTP_FEATURE_XFORWARD_IDENT (1<<20)
|
||||
#define SMTP_FEATURE_SMTPUTF8 (1<<21) /* RFC 6531 */
|
||||
#define SMTP_FEATURE_FROM_PROXY (1<<22) /* proxied connection */
|
||||
|
||||
/*
|
||||
* Features that passivate under the endpoint.
|
||||
@@ -617,7 +626,7 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
|
||||
#define SMTP_KEY_FLAG_SERVICE (1<<0) /* service name */
|
||||
#define SMTP_KEY_FLAG_SENDER (1<<1) /* sender address */
|
||||
#define SMTP_KEY_FLAG_REQ_NEXTHOP (1<<2) /* request nexthop */
|
||||
#define SMTP_KEY_FLAG_NEXTHOP (1<<3) /* current nexthop */
|
||||
#define SMTP_KEY_FLAG_CUR_NEXTHOP (1<<3) /* current nexthop */
|
||||
#define SMTP_KEY_FLAG_HOSTNAME (1<<4) /* remote host name */
|
||||
#define SMTP_KEY_FLAG_ADDR (1<<5) /* remote address */
|
||||
#define SMTP_KEY_FLAG_PORT (1<<6) /* remote port */
|
||||
@@ -626,7 +635,7 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
|
||||
#define SMTP_KEY_MASK_ALL \
|
||||
(SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \
|
||||
SMTP_KEY_FLAG_REQ_NEXTHOP | \
|
||||
SMTP_KEY_FLAG_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \
|
||||
SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \
|
||||
SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL)
|
||||
|
||||
/*
|
||||
@@ -640,14 +649,14 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
|
||||
((var_smtp_sender_auth && *var_smtp_sasl_passwd) ? \
|
||||
SMTP_KEY_FLAG_SENDER : 0)
|
||||
|
||||
#define COND_SASL_SMTP_KEY_FLAG_NEXTHOP \
|
||||
(*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_NEXTHOP : 0)
|
||||
#define COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \
|
||||
(*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0)
|
||||
|
||||
#ifdef USE_TLS
|
||||
#define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \
|
||||
(TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_NEXTHOP : 0)
|
||||
#define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \
|
||||
(TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0)
|
||||
#else
|
||||
#define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \
|
||||
#define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \
|
||||
(0)
|
||||
#endif
|
||||
|
||||
@@ -655,10 +664,13 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
|
||||
(*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_HOSTNAME : 0)
|
||||
|
||||
/*
|
||||
* Connection-cache destination lookup key. The SENDER attribute is a proxy
|
||||
* for sender-dependent SASL credentials (or absence thereof), and prevents
|
||||
* false connection sharing when different SASL credentials may be required
|
||||
* for different deliveries to the same domain and port. The SERVICE
|
||||
* Connection-cache destination lookup key, based on the delivery request
|
||||
* nexthop. The SENDER attribute is a proxy for sender-dependent SASL
|
||||
* credentials (or absence thereof), and prevents false connection sharing
|
||||
* when different SASL credentials may be required for different deliveries
|
||||
* to the same domain and port. Likewise, the delivery request nexthop
|
||||
* (REQ_NEXTHOP) prevents false sharing of TLS identities (the destination
|
||||
* key links only to appropriate endpoint lookup keys). The SERVICE
|
||||
* attribute is a proxy for all request-independent configuration details.
|
||||
*/
|
||||
#define SMTP_KEY_MASK_SCACHE_DEST_LABEL \
|
||||
@@ -666,15 +678,18 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
|
||||
| SMTP_KEY_FLAG_REQ_NEXTHOP)
|
||||
|
||||
/*
|
||||
* Connection-cache endpoint lookup key. The SENDER, NEXTHOP, and HOSTNAME
|
||||
* attributes are proxies for SASL credentials (or absence thereof), and
|
||||
* prevent false connection sharing when different SASL credentials may be
|
||||
* required for different deliveries to the same IP address and port.
|
||||
* Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME,
|
||||
* PORT and TLS_LEVEL attributes are proxies for SASL credentials and TLS
|
||||
* authentication (or absence thereof), and prevent false connection sharing
|
||||
* when different SASL credentials or TLS identities may be required for
|
||||
* different deliveries to the same IP address and port. The SERVICE
|
||||
* attribute is a proxy for all request-independent configuration details.
|
||||
*/
|
||||
#define SMTP_KEY_MASK_SCACHE_ENDP_LABEL \
|
||||
(SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \
|
||||
| COND_SASL_SMTP_KEY_FLAG_NEXTHOP | COND_SASL_SMTP_KEY_FLAG_HOSTNAME \
|
||||
| COND_TLS_SMTP_KEY_FLAG_NEXTHOP | SMTP_KEY_FLAG_ADDR | \
|
||||
| COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \
|
||||
| COND_SASL_SMTP_KEY_FLAG_HOSTNAME \
|
||||
| COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_ADDR | \
|
||||
SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL)
|
||||
|
||||
/*
|
||||
@@ -703,11 +718,6 @@ extern int smtp_mode;
|
||||
/* 111 8th Avenue
|
||||
/* New York, NY 10011, USA
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/* Google, Inc.
|
||||
/* 111 8th Avenue
|
||||
/* New York, NY 10011, USA
|
||||
/*
|
||||
/* TLS support originally by:
|
||||
/* Lutz Jaenicke
|
||||
/* BTU Cottbus
|
||||
|
@@ -417,13 +417,13 @@ static void smtp_cleanup_session(SMTP_STATE *state)
|
||||
state->session = 0;
|
||||
|
||||
/*
|
||||
* If this session was good, reset the logical next-hop state, so that we
|
||||
* won't cache connections to alternate servers under the logical
|
||||
* next-hop destination. Otherwise we could end up skipping over the
|
||||
* available and more preferred servers.
|
||||
* If this session was good, reset the logical next-hop destination, so
|
||||
* that we won't cache connections to less-preferred servers under the
|
||||
* logical next-hop destination. Otherwise we could end up skipping over
|
||||
* the available and more-preferred servers.
|
||||
*/
|
||||
if (HAVE_NEXTHOP_STATE(state) && !throttled)
|
||||
FREE_NEXTHOP_STATE(state);
|
||||
if (HAVE_SCACHE_REQUEST_NEXTHOP(state) && !throttled)
|
||||
CLEAR_SCACHE_REQUEST_NEXTHOP(state);
|
||||
|
||||
/*
|
||||
* Clean up the lists with todo and dropped recipients.
|
||||
@@ -678,7 +678,7 @@ static int smtp_reuse_session(SMTP_STATE *state, DNS_RR **addr_list,
|
||||
#endif
|
||||
SMTP_ITER_SAVE_DEST(state->iterator);
|
||||
if (*addr_list && SMTP_RCPT_LEFT(state) > 0
|
||||
&& HAVE_NEXTHOP_STATE(state)
|
||||
&& HAVE_SCACHE_REQUEST_NEXTHOP(state)
|
||||
&& (session = smtp_reuse_nexthop(state, SMTP_KEY_MASK_SCACHE_DEST_LABEL)) != 0) {
|
||||
session_count = 1;
|
||||
smtp_update_addr_list(addr_list, STR(iter->addr), session_count);
|
||||
@@ -899,7 +899,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
|
||||
if (addr_list && (state->misc_flags & SMTP_MISC_FLAG_FIRST_NEXTHOP)) {
|
||||
smtp_cache_policy(state, domain);
|
||||
if (state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE_MASK)
|
||||
SET_NEXTHOP_STATE(state, dest);
|
||||
SET_SCACHE_REQUEST_NEXTHOP(state, dest);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1124,8 +1124,8 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
|
||||
/*
|
||||
* Cleanup.
|
||||
*/
|
||||
if (HAVE_NEXTHOP_STATE(state))
|
||||
FREE_NEXTHOP_STATE(state);
|
||||
if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
|
||||
CLEAR_SCACHE_REQUEST_NEXTHOP(state);
|
||||
argv_free(sites);
|
||||
}
|
||||
|
||||
|
@@ -53,7 +53,7 @@
|
||||
/* .IP SMTP_KEY_FLAG_REQ_NEXTHOP
|
||||
/* The request nexthop destination. This is a proxy for
|
||||
/* destination-dependent, but host-independent context.
|
||||
/* .IP SMTP_KEY_FLAG_NEXTHOP
|
||||
/* .IP SMTP_KEY_FLAG_CUR_NEXTHOP
|
||||
/* The current iterator's nexthop destination (request nexthop
|
||||
/* or fallback nexthop, including optional [] and :port). This
|
||||
/* is the form that users specify in a SASL or TLS lookup
|
||||
@@ -183,7 +183,7 @@ char *smtp_key_prefix(VSTRING *buffer, const char *delim_na,
|
||||
*/
|
||||
if (flags & SMTP_KEY_FLAG_REQ_NEXTHOP)
|
||||
smtp_key_append_str(buffer, STR(iter->request_nexthop), delim_na);
|
||||
if (flags & SMTP_KEY_FLAG_NEXTHOP)
|
||||
if (flags & SMTP_KEY_FLAG_CUR_NEXTHOP)
|
||||
smtp_key_append_str(buffer, STR(iter->dest), delim_na);
|
||||
|
||||
/*
|
||||
|
@@ -899,7 +899,7 @@ static int smtp_start_tls(SMTP_STATE *state)
|
||||
*/
|
||||
serverid = vstring_alloc(10);
|
||||
smtp_key_prefix(serverid, "&", state->iterator, SMTP_KEY_FLAG_SERVICE
|
||||
| SMTP_KEY_FLAG_NEXTHOP /* With port */
|
||||
| SMTP_KEY_FLAG_CUR_NEXTHOP /* With port */
|
||||
| SMTP_KEY_FLAG_HOSTNAME
|
||||
| SMTP_KEY_FLAG_ADDR);
|
||||
|
||||
@@ -1018,6 +1018,11 @@ static int smtp_start_tls(SMTP_STATE *state)
|
||||
* context attributes.
|
||||
*/
|
||||
session->tls_context = tls_proxy_context_receive(session->stream);
|
||||
if (session->tls_context) {
|
||||
session->features |= SMTP_FEATURE_FROM_PROXY;
|
||||
tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW,
|
||||
session->tls_context);
|
||||
}
|
||||
}
|
||||
} else { /* state->tls->conn_reuse */
|
||||
|
||||
|
@@ -23,27 +23,26 @@
|
||||
/* This module implements the SMTP client specific interface to
|
||||
/* the generic session cache infrastructure.
|
||||
/*
|
||||
/* A cached connection is closed when the TLS policy requires
|
||||
/* that TLS is enabled.
|
||||
/* The caller needs to include additional state in _key_flags
|
||||
/* to avoid false sharing of SASL-authenticated or TLS-authenticated
|
||||
/* sessions.
|
||||
/*
|
||||
/* smtp_save_session() stores the current session under the
|
||||
/* next-hop logical destination (if available) and under the
|
||||
/* remote server address. The SMTP_SESSION object is destroyed.
|
||||
/* delivery request next-hop logical destination (if applicable)
|
||||
/* and under the remote server address. The SMTP_SESSION object
|
||||
/* is destroyed.
|
||||
/*
|
||||
/* smtp_reuse_nexthop() looks up a cached session by its logical
|
||||
/* destination, and verifies that the session is still alive.
|
||||
/* The restored session information includes the "best MX" bit
|
||||
/* and overrides the iterator dest, host and addr fields.
|
||||
/* The result is null in case of failure.
|
||||
/* smtp_reuse_nexthop() looks up a cached session by its
|
||||
/* delivery request next-hop destination, and verifies that
|
||||
/* the session is still alive. The restored session information
|
||||
/* includes the "best MX" bit and overrides the iterator dest,
|
||||
/* host and addr fields. The result is null in case of failure.
|
||||
/*
|
||||
/* smtp_reuse_addr() looks up a cached session by its server
|
||||
/* address, and verifies that the session is still alive.
|
||||
/* The restored session information does not include the "best
|
||||
/* MX" bit, and does not override the iterator dest, host and
|
||||
/* addr fields.
|
||||
/* This function is a NOOP for TLS levels stronger than "encrypt",
|
||||
/* because stronger levels require certificate checks,
|
||||
/* The result is null in case of failure.
|
||||
/* addr fields. The result is null in case of failure.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP state
|
||||
@@ -116,10 +115,16 @@ void smtp_save_session(SMTP_STATE *state, int name_key_flags,
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Encode the next-hop logical destination, if available. Reuse storage
|
||||
* that is also used for cache lookup queries.
|
||||
* Encode the delivery request next-hop destination, if applicable. Reuse
|
||||
* storage that is also used for cache lookup queries.
|
||||
*
|
||||
* HAVE_SCACHE_REQUEST_NEXTHOP() controls whether or not to reuse or cache a
|
||||
* connection by its delivery request next-hop destination. The idea is
|
||||
* 1) to allow a reuse request to skip over bad hosts, and 2) to avoid
|
||||
* caching a less-preferred connection when a more-preferred connection
|
||||
* was possible.
|
||||
*/
|
||||
if (HAVE_NEXTHOP_STATE(state))
|
||||
if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
|
||||
smtp_key_prefix(state->dest_label, SMTP_REUSE_KEY_DELIM_NA,
|
||||
state->iterator, name_key_flags);
|
||||
|
||||
@@ -138,16 +143,18 @@ void smtp_save_session(SMTP_STATE *state, int name_key_flags,
|
||||
state->session = 0;
|
||||
|
||||
/*
|
||||
* Save the session under the next-hop name, if available.
|
||||
* Save the session under the delivery request next-hop name, if
|
||||
* applicable.
|
||||
*
|
||||
* XXX The logical to physical binding can be kept for as long as the DNS
|
||||
* allows us to (but that could result in the caching of lots of unused
|
||||
* bindings). The session should be idle for no more than 30 seconds or
|
||||
* so.
|
||||
*/
|
||||
if (HAVE_NEXTHOP_STATE(state))
|
||||
scache_save_dest(smtp_scache, var_smtp_cache_conn, STR(state->dest_label),
|
||||
STR(state->dest_prop), STR(state->endp_label));
|
||||
if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
|
||||
scache_save_dest(smtp_scache, var_smtp_cache_conn,
|
||||
STR(state->dest_label), STR(state->dest_prop),
|
||||
STR(state->endp_label));
|
||||
|
||||
/*
|
||||
* Save every good session under its physical endpoint address.
|
||||
@@ -165,15 +172,6 @@ static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd,
|
||||
SMTP_ITERATOR *iter = state->iterator;
|
||||
SMTP_SESSION *session;
|
||||
|
||||
/*
|
||||
* Obsolete.
|
||||
*/
|
||||
#ifdef notdef
|
||||
if (state->tls->level > TLS_LEV_NONE)
|
||||
msg_panic("%s: unexpected plain-text cached session to %s",
|
||||
myname, label);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Re-activate the SMTP_SESSION object.
|
||||
*/
|
||||
@@ -216,15 +214,6 @@ SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags)
|
||||
SMTP_SESSION *session;
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Obsolete: the TLS level and nexthop are part of the connection cache
|
||||
* key. TODO(tlsproxy) is the port included in the nexthop?
|
||||
*/
|
||||
#ifdef notdef
|
||||
if (state->tls->level > TLS_LEV_NONE)
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Look up the session by its logical name.
|
||||
*/
|
||||
@@ -250,18 +239,13 @@ SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags)
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Allow address-based reuse only for security levels that don't require
|
||||
* certificate checks. Not to be confused with a similar constraint in
|
||||
* the destination label smtp_key pattern, which conditionally includes
|
||||
* the nexthop to prevent the reuse of an authenticated connection to the
|
||||
* same MX hostname and the same IP address, but for a different nexthop
|
||||
* destination (just in case we start to send SNI with the nexthop, and
|
||||
* forget to update connection cache lookup key patterns).
|
||||
* Address-based reuse is safe for security levels that require TLS
|
||||
* certificate checks, as long as the current nexhop is included in the
|
||||
* cache lookup key (COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP). This is
|
||||
* sufficient to prevent the reuse of a TLS-authenticated connection to
|
||||
* the same MX hostname, IP address, and port, but for a different
|
||||
* current nexthop destination with a different TLS policy.
|
||||
*/
|
||||
#ifdef USE_TLS
|
||||
if (TLS_MUST_MATCH(state->tls->level))
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Look up the session by its IP address. This means that we have no
|
||||
|
@@ -113,11 +113,28 @@
|
||||
#include <debug_peer.h>
|
||||
#include <mail_params.h>
|
||||
|
||||
/* TLS Library. */
|
||||
|
||||
#include <tls_proxy.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "smtp.h"
|
||||
#include "smtp_sasl.h"
|
||||
|
||||
/*
|
||||
* Local, because these are meaningful only for code in this file.
|
||||
*/
|
||||
#define SESS_ATTR_DEST "destination"
|
||||
#define SESS_ATTR_HOST "host_name"
|
||||
#define SESS_ATTR_ADDR "host_addr"
|
||||
#define SESS_ATTR_DEST_FEATURES "destination_features"
|
||||
|
||||
#define SESS_ATTR_TLS_LEVEL "tls_level"
|
||||
#define SESS_ATTR_REUSE_COUNT "reuse_count"
|
||||
#define SESS_ATTR_ENDP_FEATURES "endpoint_features"
|
||||
#define SESS_ATTR_EXPIRE_TIME "expire_time"
|
||||
|
||||
/* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
|
||||
|
||||
SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, SMTP_ITERATOR *iter,
|
||||
@@ -183,7 +200,8 @@ void smtp_session_free(SMTP_SESSION *session)
|
||||
vstream_fflush(session->stream);
|
||||
}
|
||||
if (session->tls_context) {
|
||||
if (session->state->tls->conn_reuse)
|
||||
if (session->features &
|
||||
(SMTP_FEATURE_FROM_CACHE | SMTP_FEATURE_FROM_PROXY))
|
||||
tls_proxy_context_free(session->tls_context);
|
||||
else
|
||||
tls_client_stop(smtp_tls_ctx, session->stream,
|
||||
@@ -220,6 +238,7 @@ int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
|
||||
VSTRING *endp_prop)
|
||||
{
|
||||
SMTP_ITERATOR *iter = session->iterator;
|
||||
VSTREAM *mp;
|
||||
int fd;
|
||||
|
||||
/*
|
||||
@@ -228,55 +247,61 @@ int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
|
||||
* destination (this information is needed for loop handling in
|
||||
* smtp_proto()).
|
||||
*
|
||||
* XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can
|
||||
* serialize the properties with attr_print() instead of using ad-hoc,
|
||||
* non-reusable, code and hard-coded format strings.
|
||||
*
|
||||
* TODO(tlsproxy): save TLS_SESS_STATE information so that we can restore
|
||||
* TLS session properties.
|
||||
*
|
||||
* TODO: save SASL username and password information so that we can
|
||||
* correctly save a reused authenticated connection.
|
||||
*
|
||||
* Note: the TLS level field is always present.
|
||||
* These memory writes should never fail.
|
||||
*/
|
||||
vstring_sprintf(dest_prop, "%s\n%s\n%s\n%u\n%u",
|
||||
STR(iter->dest), STR(iter->host), STR(iter->addr),
|
||||
#ifdef USE_TLS
|
||||
iter->parent->tls->level,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
session->features & SMTP_FEATURE_DESTINATION_MASK);
|
||||
if ((mp = vstream_memopen(dest_prop, O_WRONLY)) == 0
|
||||
|| attr_print_plain(mp, ATTR_FLAG_NONE,
|
||||
SEND_ATTR_STR(SESS_ATTR_DEST, STR(iter->dest)),
|
||||
SEND_ATTR_STR(SESS_ATTR_HOST, STR(iter->host)),
|
||||
SEND_ATTR_STR(SESS_ATTR_ADDR, STR(iter->addr)),
|
||||
SEND_ATTR_INT(SESS_ATTR_DEST_FEATURES,
|
||||
session->features & SMTP_FEATURE_DESTINATION_MASK),
|
||||
ATTR_TYPE_END) != 0
|
||||
|| vstream_fclose(mp) != 0)
|
||||
msg_fatal("smtp_session_passivate: can't save dest properties: %m");
|
||||
|
||||
/*
|
||||
* Encode the physical endpoint properties: all the session properties
|
||||
* except for "session from cache", "best MX", or "RSET failure".
|
||||
* Plus the TLS level, reuse count, and connection expiration time.
|
||||
*
|
||||
* XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can
|
||||
* serialize the properties with attr_print() instead of using obscure
|
||||
* hard-coded format strings.
|
||||
* XXX Should also record how many non-delivering mail transactions there
|
||||
* were during this session, and perhaps other statistics, so that we
|
||||
* don't reuse a session too much.
|
||||
*
|
||||
* XXX Should also record an absolute time when a session must be closed,
|
||||
* how many non-delivering mail transactions there were during this
|
||||
* session, and perhaps other statistics, so that we don't reuse a
|
||||
* session too much.
|
||||
* TODO: passivate SASL username and password information so that we can
|
||||
* correctly save a reused authenticated connection.
|
||||
*
|
||||
* XXX Be sure to use unsigned types in the format string. Sign characters
|
||||
* would be rejected by the alldig() test on the reading end.
|
||||
* These memory writes should never fail.
|
||||
*/
|
||||
vstring_sprintf(endp_prop, "%u\n%u\n%lu",
|
||||
session->reuse_count,
|
||||
session->features & SMTP_FEATURE_ENDPOINT_MASK,
|
||||
(long) session->expire_time);
|
||||
if ((mp = vstream_memopen(endp_prop, O_WRONLY)) == 0
|
||||
|| attr_print_plain(mp, ATTR_FLAG_NONE,
|
||||
SEND_ATTR_INT(SESS_ATTR_TLS_LEVEL,
|
||||
session->state->tls->level),
|
||||
SEND_ATTR_INT(SESS_ATTR_REUSE_COUNT,
|
||||
session->reuse_count),
|
||||
SEND_ATTR_INT(SESS_ATTR_ENDP_FEATURES,
|
||||
session->features & SMTP_FEATURE_ENDPOINT_MASK),
|
||||
SEND_ATTR_LONG(SESS_ATTR_EXPIRE_TIME,
|
||||
(long) session->expire_time),
|
||||
ATTR_TYPE_END) != 0
|
||||
|
||||
/*
|
||||
* Append the passivated SASL attributes.
|
||||
* Append the passivated TLS context. These memory writes should never
|
||||
* fail.
|
||||
*/
|
||||
#ifdef notdef
|
||||
if (smtp_sasl_enable)
|
||||
smtp_sasl_passivate(endp_prop, session);
|
||||
#ifdef USE_TLS
|
||||
|| (session->tls_context
|
||||
&& attr_print_plain(mp, ATTR_FLAG_NONE,
|
||||
SEND_ATTR_FUNC(tls_proxy_context_print,
|
||||
(void *) session->tls_context),
|
||||
ATTR_TYPE_END) != 0)
|
||||
#endif
|
||||
|| vstream_fclose(mp) != 0)
|
||||
msg_fatal("smtp_session_passivate: cannot save TLS context: %m");
|
||||
|
||||
/*
|
||||
* Salvage the underlying file descriptor, and destroy the session
|
||||
@@ -297,50 +322,52 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
|
||||
VSTRING *endp_prop)
|
||||
{
|
||||
const char *myname = "smtp_session_activate";
|
||||
VSTREAM *mp;
|
||||
SMTP_SESSION *session;
|
||||
char *dest_props;
|
||||
char *endp_props;
|
||||
const char *prop;
|
||||
const char *dest;
|
||||
const char *host;
|
||||
const char *addr;
|
||||
unsigned features; /* server features */
|
||||
time_t expire_time; /* session re-use expiration time */
|
||||
unsigned reuse_count; /* # times reused */
|
||||
int endp_features; /* server features */
|
||||
int dest_features; /* server features */
|
||||
long expire_time; /* session re-use expiration time */
|
||||
int reuse_count; /* # times reused */
|
||||
TLS_SESS_STATE *tls_context = 0;
|
||||
|
||||
#ifdef USE_TLS
|
||||
SMTP_TLS_POLICY *tls = iter->parent->tls;
|
||||
|
||||
#endif
|
||||
|
||||
#define SMTP_SESSION_ACTIVATE_ERR_RETURN() do { \
|
||||
if (tls_context) \
|
||||
tls_proxy_context_free(tls_context); \
|
||||
return (0); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* XXX it would be nice to have a VSTRING to VSTREAM adapter so that we
|
||||
* can de-serialize the properties with attr_scan(), instead of using
|
||||
* ad-hoc, non-reusable code.
|
||||
*
|
||||
* XXX As a preliminary solution we use mystrtok(), but that function is not
|
||||
* suitable for zero-length fields.
|
||||
* Sanity check: if TLS is required, the cached properties must contain a
|
||||
* TLS context.
|
||||
*/
|
||||
endp_props = STR(endp_prop);
|
||||
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
|
||||
msg_warn("%s: bad cached session reuse count property", myname);
|
||||
return (0);
|
||||
}
|
||||
reuse_count = atoi(prop);
|
||||
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
|
||||
msg_warn("%s: bad cached session features property", myname);
|
||||
return (0);
|
||||
}
|
||||
features = atoi(prop);
|
||||
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
|
||||
msg_warn("%s: bad cached session expiration time property", myname);
|
||||
return (0);
|
||||
}
|
||||
#ifdef MISSING_STRTOUL
|
||||
expire_time = strtol(prop, 0, 10);
|
||||
#else
|
||||
expire_time = strtoul(prop, 0, 10);
|
||||
if ((mp = vstream_memopen(endp_prop, O_RDONLY)) == 0
|
||||
|| attr_scan_plain(mp, ATTR_FLAG_NONE,
|
||||
RECV_ATTR_INT(SESS_ATTR_TLS_LEVEL,
|
||||
&tls->level),
|
||||
RECV_ATTR_INT(SESS_ATTR_REUSE_COUNT,
|
||||
&reuse_count),
|
||||
RECV_ATTR_INT(SESS_ATTR_ENDP_FEATURES,
|
||||
&endp_features),
|
||||
RECV_ATTR_LONG(SESS_ATTR_EXPIRE_TIME,
|
||||
&expire_time),
|
||||
ATTR_TYPE_END) != 4
|
||||
#ifdef USE_TLS
|
||||
|| ((tls->level > TLS_LEV_MAY
|
||||
|| (tls->level == TLS_LEV_MAY && vstream_peek(mp) > 0))
|
||||
&& attr_scan_plain(mp, ATTR_FLAG_NONE,
|
||||
RECV_ATTR_FUNC(tls_proxy_context_scan,
|
||||
(void *) &tls_context),
|
||||
ATTR_TYPE_END) != 1)
|
||||
#endif
|
||||
|| vstream_fclose(mp) != 0) {
|
||||
msg_warn("smtp_session_activate: bad cached endp properties");
|
||||
SMTP_SESSION_ACTIVATE_ERR_RETURN();
|
||||
}
|
||||
|
||||
/*
|
||||
* Clobber the iterator's current nexthop, host and address fields with
|
||||
@@ -355,36 +382,25 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
|
||||
* correctly save a reused authenticated connection.
|
||||
*/
|
||||
if (dest_prop && VSTRING_LEN(dest_prop)) {
|
||||
dest_props = STR(dest_prop);
|
||||
if ((dest = mystrtok(&dest_props, "\n")) == 0) {
|
||||
msg_warn("%s: missing cached session destination property", myname);
|
||||
return (0);
|
||||
if ((mp = vstream_memopen(dest_prop, O_RDONLY)) == 0
|
||||
|| attr_scan_plain(mp, ATTR_FLAG_NONE,
|
||||
RECV_ATTR_STR(SESS_ATTR_DEST, iter->dest),
|
||||
RECV_ATTR_STR(SESS_ATTR_HOST, iter->host),
|
||||
RECV_ATTR_STR(SESS_ATTR_ADDR, iter->addr),
|
||||
RECV_ATTR_INT(SESS_ATTR_DEST_FEATURES,
|
||||
&dest_features),
|
||||
ATTR_TYPE_END) != 4
|
||||
|| vstream_fclose(mp) != 0) {
|
||||
msg_warn("smtp_session_passivate: bad cached dest properties");
|
||||
SMTP_SESSION_ACTIVATE_ERR_RETURN();
|
||||
}
|
||||
if ((host = mystrtok(&dest_props, "\n")) == 0) {
|
||||
msg_warn("%s: missing cached session hostname property", myname);
|
||||
return (0);
|
||||
}
|
||||
if ((addr = mystrtok(&dest_props, "\n")) == 0) {
|
||||
msg_warn("%s: missing cached session address property", myname);
|
||||
return (0);
|
||||
}
|
||||
/* Note: the TLS level field is always present. */
|
||||
if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) {
|
||||
msg_warn("%s: bad cached destination TLS level property", myname);
|
||||
return (0);
|
||||
}
|
||||
#ifdef USE_TLS
|
||||
tls->level = atoi(prop);
|
||||
if (msg_verbose)
|
||||
msg_info("%s: tls_level=%d", myname, tls->level);
|
||||
#endif
|
||||
if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) {
|
||||
msg_warn("%s: bad cached destination features property", myname);
|
||||
return (0);
|
||||
}
|
||||
features |= atoi(prop);
|
||||
SMTP_ITER_CLOBBER(iter, dest, host, addr);
|
||||
} else {
|
||||
dest_features = 0;
|
||||
}
|
||||
#ifdef USE_TLS
|
||||
if (msg_verbose)
|
||||
msg_info("%s: tls_level=%d", myname, tls->level);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allright, bundle up what we have sofar.
|
||||
@@ -393,7 +409,9 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
|
||||
|
||||
session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), iter,
|
||||
(time_t) 0, NO_FLAGS);
|
||||
session->features = (features | SMTP_FEATURE_FROM_CACHE);
|
||||
session->features =
|
||||
(endp_features | dest_features | SMTP_FEATURE_FROM_CACHE);
|
||||
session->tls_context = tls_context;
|
||||
CACHE_THIS_SESSION_UNTIL(expire_time);
|
||||
session->reuse_count = ++reuse_count;
|
||||
|
||||
@@ -401,20 +419,15 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
|
||||
msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, "
|
||||
"ttl=%ld, reuse=%d",
|
||||
myname, STR(iter->dest), STR(iter->host),
|
||||
STR(iter->addr), ntohs(iter->port), features,
|
||||
STR(iter->addr), ntohs(iter->port),
|
||||
endp_features | dest_features,
|
||||
(long) (expire_time - time((time_t *) 0)),
|
||||
reuse_count);
|
||||
|
||||
/*
|
||||
* Re-activate the SASL attributes.
|
||||
*/
|
||||
#ifdef notdef
|
||||
if (smtp_sasl_enable && smtp_sasl_activate(session, endp_props) < 0) {
|
||||
vstream_fdclose(session->stream);
|
||||
session->stream = 0;
|
||||
smtp_session_free(session);
|
||||
return (0);
|
||||
}
|
||||
#if USE_TLS
|
||||
if (tls_context)
|
||||
tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_USED,
|
||||
session->tls_context);
|
||||
#endif
|
||||
|
||||
return (session);
|
||||
|
@@ -668,7 +668,7 @@ int smtp_tls_policy_cache_query(DSN_BUF *why, SMTP_TLS_POLICY *tls,
|
||||
* values that also appear in other cache and table search keys.
|
||||
*/
|
||||
key = vstring_alloc(100);
|
||||
smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_NEXTHOP
|
||||
smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_CUR_NEXTHOP
|
||||
| SMTP_KEY_FLAG_HOSTNAME
|
||||
| SMTP_KEY_FLAG_PORT);
|
||||
ctable_newcontext(policy_cache, (void *) iter);
|
||||
|
@@ -115,12 +115,12 @@ extern const char *str_tls_level(int);
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* Backwards compatibility with OpenSSL < 1.1.1a (or some later version).
|
||||
* Backwards compatibility with OpenSSL < 1.1.1a.
|
||||
*
|
||||
* The client-only interface SSL_get_server_tmp_key() is slated to be made to
|
||||
* work on both client and server, and renamed to SSL_get_peer_tmp_key(), with
|
||||
* the original name left behind as an alias. We use the new name when
|
||||
* available.
|
||||
* In OpenSSL 1.1.1a the client-only interface SSL_get_server_tmp_key() was
|
||||
* updated to work on both the client and the server, and was renamed to
|
||||
* SSL_get_peer_tmp_key(), with the original name left behind as an alias. We
|
||||
* use the new name when available.
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1010101fUL
|
||||
#undef SSL_get_signature_nid
|
||||
@@ -159,9 +159,13 @@ extern const char *str_tls_level(int);
|
||||
/*
|
||||
* TLS role, presently for logging.
|
||||
*/
|
||||
typedef enum { TLS_ROLE_CLIENT, TLS_ROLE_SERVER, } TLS_ROLE;
|
||||
typedef enum {
|
||||
TLS_ROLE_CLIENT, TLS_ROLE_SERVER,
|
||||
} TLS_ROLE;
|
||||
|
||||
typedef enum { TLS_USAGE_NEW, TLS_USAGE_USED, } TLS_USAGE;
|
||||
typedef enum {
|
||||
TLS_USAGE_NEW, TLS_USAGE_USED,
|
||||
} TLS_USAGE;
|
||||
|
||||
/*
|
||||
* Names of valid tlsmgr(8) session caches.
|
||||
|
@@ -1191,6 +1191,9 @@ TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext,
|
||||
&& !TLS_NEVER_SECURED(props->tls_level))
|
||||
TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
|
||||
|
||||
/*
|
||||
* With the handshake done, extract TLS 1.3 signature metadata.
|
||||
*/
|
||||
tls_get_signature_params(TLScontext);
|
||||
|
||||
if (TLScontext->log_mask & TLS_LOG_SUMMARY)
|
||||
|
@@ -14,6 +14,12 @@
|
||||
/* TLS_USAGE usage;
|
||||
/* TLS_SESS_STATE *TLScontext;
|
||||
/*
|
||||
/* const char *tls_compile_version(void)
|
||||
/*
|
||||
/* const char *tls_run_version(void)
|
||||
/*
|
||||
/* const char **tls_pkey_algorithms(void)
|
||||
/*
|
||||
/* .SH Internal functions
|
||||
/* .nf
|
||||
/* .na
|
||||
@@ -103,12 +109,6 @@
|
||||
/*
|
||||
/* int tls_validate_digest(dgst)
|
||||
/* const char *dgst;
|
||||
/*
|
||||
/* const char *tls_compile_version(void)
|
||||
/*
|
||||
/* const char *tls_run_version(void)
|
||||
/*
|
||||
/* const char **tls_pkey_algorithms(void)
|
||||
/* DESCRIPTION
|
||||
/* This module implements public and internal routines that
|
||||
/* support the TLS client and server.
|
||||
@@ -118,6 +118,16 @@
|
||||
/* connections, or TLS_ROLE_SERVER for incoming server connections,
|
||||
/* and the "usage" must be TLS_USAGE_NEW or TLS_USAGE_USED.
|
||||
/*
|
||||
/* tls_compile_version() returns a text string description of
|
||||
/* the compile-time TLS library.
|
||||
/*
|
||||
/* tls_run_version() is just tls_compile_version() but with the runtime
|
||||
/* version instead of the compile-time version.
|
||||
/*
|
||||
/* tls_pkey_algorithms() returns a pointer to null-terminated
|
||||
/* array of string constants with the names of the supported
|
||||
/* public-key algorithms.
|
||||
/*
|
||||
/* tls_alloc_app_context() creates an application context that
|
||||
/* holds the SSL context for the application and related cached state.
|
||||
/*
|
||||
@@ -190,16 +200,6 @@
|
||||
/*
|
||||
/* tls_validate_digest() returns non-zero if the named digest
|
||||
/* is usable and zero otherwise.
|
||||
/*
|
||||
/* tls_compile_version() returns a text string description of
|
||||
/* the compile-time TLS library.
|
||||
/*
|
||||
/* tls_run_version() is just tls_compile_version() but with the runtime
|
||||
/* version instead of the compile-time version.
|
||||
/*
|
||||
/* tls_pkey_algorithms() returns a pointer to null-terminated
|
||||
/* array of string constants with the names of the supported
|
||||
/* public-key algorithms.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@@ -1714,7 +1714,7 @@ VSTREAM *vstream_memreopen(VSTREAM *stream, VSTRING *string, int flags)
|
||||
stream->write_fn = 0;
|
||||
stream->vstring = string;
|
||||
memcpy(&stream->buf, &stream->vstring->vbuf, sizeof(stream->buf));
|
||||
stream->buf.flags |= (flags | VSTREAM_FLAG_MEMORY);
|
||||
stream->buf.flags |= VSTREAM_FLAG_MEMORY;
|
||||
switch (VSTREAM_ACC_MASK(flags)) {
|
||||
case O_RDONLY:
|
||||
stream->buf.flags |= VSTREAM_FLAG_READ;
|
||||
|
Reference in New Issue
Block a user