New options openssl-maxfraglen, openssl-maxsendfrag

This commit is contained in:
Gerhard Rieger 2023-10-26 16:43:20 +02:00
parent 454a499401
commit 2db04378ae
10 changed files with 181 additions and 1 deletions

View file

@ -25,6 +25,13 @@ Features:
Test: PROXY_HTTPVERSION
Feature inspired by Robin Palotai.
New options openssl-maxfraglen and openssl-maxsendfrag for
functions/macros SSL_CTX_set_tlsext_max_fragment_length() and
SSL_CTX_set_max_send_fragment().
Thanks to James Tavares for his contribution.
Added Info log of resulting OpenSSL max fragment length.
Corrections:
When a sub process (EXEC, SYSTEM) terminated with exit code other than
0, its last sent data might have been lost depending on timing of read/

View file

@ -532,6 +532,12 @@
/* Define if you have the OpenSSL SSL_set_tlsext_host_name define/function */
#undef HAVE_SSL_set_tlsext_host_name
/* Define if you have the OpenSSL SSL_CTX_set_tlsext_max_fragment_length define/function */
#undef HAVE_SSL_CTX_set_tlsext_max_fragment_length
/* Define if you have the OpenSSL SSL_CTX_set_max_send_fragment define/function */
#undef HAVE_SSL_CTX_set_max_send_fragment
/* Define if you have the flock function */
#undef HAVE_FLOCK

View file

@ -1578,6 +1578,23 @@ AC_CHECK_FUNC(ASN1_STRING_get0_data, AC_DEFINE(HAVE_ASN1_STRING_get0_data), AC_C
AC_CHECK_FUNC(RAND_status, AC_DEFINE(HAVE_RAND_status))
AC_CHECK_FUNC(SSL_CTX_clear_mode, AC_DEFINE(HAVE_SSL_CTX_clear_mode))
AC_CHECK_FUNC(SSL_set_tlsext_host_name, AC_DEFINE(HAVE_SSL_set_tlsext_host_name))
AC_CHECK_FUNC(SSL_CTX_set_tlsext_max_fragment_length, AC_DEFINE(HAVE_SSL_CTX_set_tlsext_max_fragment_length))
AC_MSG_CHECKING(if SSL_CTX_set_max_send_fragment exists)
AC_CACHE_VAL(ac_cv_have_SSL_CTX_set_max_send_fragment,
[AC_TRY_COMPILE([#include <openssl/ssl.h>],[
#ifndef SSL_CTX_set_max_send_fragment
#error "SSL_CTX_set_max_send_fragment not found"
#endif
],
[ac_cv_have_SSL_CTX_set_max_send_fragment=yes],
[ac_cv_have_SSL_CTX_set_max_send_fragment=no])]
)
if test $ac_cv_have_SSL_CTX_set_max_send_fragment = yes; then
AC_DEFINE(HAVE_SSL_CTX_set_max_send_fragment)
fi
AC_MSG_RESULT($ac_cv_have_SSL_CTX_set_max_send_fragment)
AC_CHECK_FUNC(SSL_library_init, AC_DEFINE(HAVE_SSL_library_init))
AC_CHECK_FUNC(ERR_error_string, AC_DEFINE(HAVE_ERR_error_string))

View file

@ -2896,6 +2896,15 @@ label(OPTION_OPENSSL_EGD)dit(bf(tt(egd=<filename>)))
On some systems, openssl requires an explicit source of random data. Specify
the socket name where an entropy gathering daemon like egd provides random
data, e.g. /dev/egd-pool.
label(OPTION_OPENSSL_MAXFRAGLEN)dit(bf(tt(maxfraglen=<int>, openssl-maxfraglen=<int>)))
For client connections, make a Max Fragment Length Negotiation Request to the server to limit the
maximum size fragment the server will send to us. Supported lengths are: 512, 1024, 2048, or
4096. Note that this option is not applicable for link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN).
label(OPTION_OPENSSL_MAXSENDFRAG)dit(bf(tt(maxsendfrag=<int>, openssl-maxsendfrag=<int>)))
Limit the maximum size of the fragment we will send to the other side. Supported length range:
512 - 16384. Note that under link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN), the maximum fragment
size may be further limited by the client's Maximum Fragment Length Negotiation Request, if it
makes one.
label(OPTION_OPENSSL_PSEUDO)dit(bf(tt(pseudo)))
On systems where openssl cannot find an entropy source and where no entropy
gathering daemon can be utilized, this option activates a mechanism for

View file

@ -319,6 +319,26 @@ int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh) {
return result;
}
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
int sycSSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode) {
int result;
Debug2("SSL_CTX_set_tlsext_max_fragment_length(%p, %u)", ctx, mode);
result = SSL_CTX_set_tlsext_max_fragment_length(ctx, mode);
Debug1("SSL_CTX_set_tlsext_max_fragment_length() -> %d", result);
return result;
}
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
int sycSSL_CTX_set_max_send_fragment(SSL_CTX *ctx, long msf) {
int result;
Debug2("SSL_CTX_set_max_send_fragment(%p, %ld)", ctx, msf);
result = SSL_CTX_set_max_send_fragment(ctx, msf);
Debug1("SSL_CTX_set_max_send_fragment() -> %d", result);
return result;
}
#endif
int sycSSL_set_cipher_list(SSL *ssl, const char *str) {
int result;
Debug2("SSL_set_cipher_list(%p, \"%s\")", ssl, str);

View file

@ -44,6 +44,12 @@ void sycSSL_CTX_set_verify(SSL_CTX *ctx, int mode,
int (*verify_callback)(int, X509_STORE_CTX *));
int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh);
int sycSSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
int sycSSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
int sycSSL_CTX_set_max_send_fragment(SSL_CTX *ctx, long msf);
#endif
int sycSSL_set_cipher_list(SSL *ssl, const char *str);
long sycSSL_get_verify_result(SSL *ssl);
int sycSSL_set_fd(SSL *ssl, int fd);
@ -108,6 +114,12 @@ const char *sycSSL_COMP_get_name(const COMP_METHOD *comp);
#define sycSSL_CTX_set_verify(c,m,v) SSL_CTX_set_verify(c,m,v)
#define sycSSL_CTX_set_tmp_dh(c,d) SSL_CTX_set_tmp_dh(c,d)
#define sycSSL_CTX_set_cipher_list(c,s) SSL_CTX_set_cipher_list(c,s)
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
#define sycSSL_CTX_set_tlsext_max_fragment_length(c,m) SSL_CTX_set_tlsext_max_fragment_length(c, m)
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
#define sycSSL_CTX_set_max_send_fragment(c,m) SSL_CTX_set_max_send_fragment(c, m)
#endif
#define sycSSL_set_cipher_list(s,t) SSL_set_cipher_list(s,t)
#define sycSSL_get_verify_result(s) SSL_get_verify_result(s)
#define sycSSL_set_fd(s,f) SSL_set_fd(s,f)

View file

@ -125,6 +125,12 @@ const struct optdesc opt_openssl_dhparam = { "openssl-dhparam", "dh",
const struct optdesc opt_openssl_cafile = { "openssl-cafile", "cafile", OPT_OPENSSL_CAFILE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
const struct optdesc opt_openssl_capath = { "openssl-capath", "capath", OPT_OPENSSL_CAPATH, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
const struct optdesc opt_openssl_egd = { "openssl-egd", "egd", OPT_OPENSSL_EGD, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
const struct optdesc opt_openssl_maxfraglen = { "openssl-maxfraglen", "maxfraglen", OPT_OPENSSL_MAXFRAGLEN, GROUP_OPENSSL, PH_SPEC, TYPE_INT, OFUNC_SPEC };
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
const struct optdesc opt_openssl_maxsendfrag = { "openssl-maxsendfrag", "maxsendfrag", OPT_OPENSSL_MAXSENDFRAG, GROUP_OPENSSL, PH_SPEC, TYPE_INT, OFUNC_SPEC };
#endif
const struct optdesc opt_openssl_pseudo = { "openssl-pseudo", "pseudo", OPT_OPENSSL_PSEUDO, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP)
const struct optdesc opt_openssl_compress = { "openssl-compress", "compress", OPT_OPENSSL_COMPRESS, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
@ -138,7 +144,6 @@ const struct optdesc opt_openssl_no_sni = { "openssl-no-sni", "nosni",
const struct optdesc opt_openssl_snihost = { "openssl-snihost", "snihost", OPT_OPENSSL_SNIHOST, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
#endif
/* If FIPS is compiled in, we need to track if the user asked for FIPS mode.
* On forks, the FIPS mode must be reset by a disable, then enable since
* FIPS tracks the process ID that initializes things.
@ -166,6 +171,7 @@ int xio_reset_fips_mode(void) {
static void openssl_conn_loginfo(SSL *ssl) {
const char *string;
SSL_SESSION *session;
string = SSL_get_cipher_version(ssl);
Notice1("SSL proto version used: %s", string);
@ -187,6 +193,31 @@ static void openssl_conn_loginfo(SSL *ssl) {
Notice1("SSL connection expansion \"%s\"",
expansion?sycSSL_COMP_get_name(expansion):"none");
}
#endif
session = SSL_get_session(ssl);
if (session == NULL) {
Warn1("SSL_get_session(%p) failed", ssl);
return;
}
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
{
uint8_t fragcod;
int fraglen = -1;
fragcod = SSL_SESSION_get_max_fragment_length(session);
switch (fragcod) {
case TLSEXT_max_fragment_length_DISABLED: fraglen = 0; break;
case TLSEXT_max_fragment_length_512: fraglen = 512; break;
case TLSEXT_max_fragment_length_1024: fraglen = 1024; break;
case TLSEXT_max_fragment_length_2048: fraglen = 2048; break;
case TLSEXT_max_fragment_length_4096: fraglen = 4096; break;
default: Warn1("SSL_SESSION_get_max_fragment_length(): unknown code %u",
fragcod);
break;
}
if (fraglen > 0) {
Info1("OpenSSL: max fragment length is %d", fraglen);
}
}
#endif
}
@ -1405,6 +1436,60 @@ cont_out:
NULL);
}
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
{
/* set client max fragment length negotiation (512, 1024, 2048, or 4096) */
int opt_maxfraglen = -1;
retropt_int(opts, OPT_OPENSSL_MAXFRAGLEN, &opt_maxfraglen);
if (!server) {
/* on client connection, ask the server not to send us packets bigger than our inbound buffer */
uint8_t mfl_code = TLSEXT_max_fragment_length_DISABLED;
if (opt_maxfraglen == -1) {
/* max frag length is not specified, leave DISABLED */
} else if (opt_maxfraglen == 512) {
mfl_code = TLSEXT_max_fragment_length_512;
} else if (opt_maxfraglen == 1024) {
mfl_code = TLSEXT_max_fragment_length_1024;
} else if (opt_maxfraglen == 2048) {
mfl_code = TLSEXT_max_fragment_length_2048;
} else if (opt_maxfraglen == 4096) {
mfl_code = TLSEXT_max_fragment_length_4096;
} else {
Error1("openssl: maxfraglen %d is not one of 512, 1024, 2048, or 4096", opt_maxfraglen);
return STAT_NORETRY;
}
sycSSL_CTX_set_tlsext_max_fragment_length(ctx, mfl_code);
} else {
if (opt_maxfraglen != -1) {
Error("openssl: maxfraglen option not applicable to a server");
return STAT_NORETRY;
}
}
}
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
{
/* limit the maximum size of sent packets */
const int maxsendfrag_min = 512; /* per OpenSSL documentation */
int opt_maxsendfrag = SSL3_RT_MAX_PLAIN_LENGTH;
retropt_int(opts, OPT_OPENSSL_MAXSENDFRAG, &opt_maxsendfrag);
if (opt_maxsendfrag < maxsendfrag_min || opt_maxsendfrag > SSL3_RT_MAX_PLAIN_LENGTH) {
Error2("openssl: maxsendfrag %d out of range 512 - %d", maxsendfrag_min,
SSL3_RT_MAX_PLAIN_LENGTH);
return STAT_NORETRY;
}
sycSSL_CTX_set_max_send_fragment(ctx, opt_maxsendfrag);
}
#endif
return STAT_OK;
}

View file

@ -26,6 +26,12 @@ extern const struct optdesc opt_openssl_dhparam;
extern const struct optdesc opt_openssl_cafile;
extern const struct optdesc opt_openssl_capath;
extern const struct optdesc opt_openssl_egd;
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
extern const struct optdesc opt_openssl_maxfraglen;
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
extern const struct optdesc opt_openssl_maxsendfrag;
#endif
extern const struct optdesc opt_openssl_pseudo;
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
extern const struct optdesc opt_openssl_compress;

View file

@ -936,10 +936,16 @@ const struct optname optionnames[] = {
IF_OPENSSL("max-version", &opt_openssl_max_proto_version)
#endif
IF_LISTEN ("maxchildren", &opt_max_children)
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
IF_OPENSSL("maxfraglen", &opt_openssl_maxfraglen)
#endif
#ifdef TCP_MAXSEG
IF_TCP ("maxseg", &opt_tcp_maxseg)
IF_TCP ("maxseg-late", &opt_tcp_maxseg_late)
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
IF_OPENSSL("maxsendfrag", &opt_openssl_maxsendfrag)
#endif
#ifdef TCP_MD5SUM
IF_TCP ("md5sig", &opt_tcp_md5sig)
#endif
@ -1190,6 +1196,12 @@ const struct optname optionnames[] = {
#if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version)
IF_OPENSSL("openssl-max-proto-version", &opt_openssl_max_proto_version)
#endif
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
IF_OPENSSL("openssl-maxfraglen", &opt_openssl_maxfraglen)
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
IF_OPENSSL("openssl-maxsendfrag", &opt_openssl_maxsendfrag)
#endif
#if WITH_OPENSSL_METHOD
IF_OPENSSL("openssl-method", &opt_openssl_method)
#endif

View file

@ -506,6 +506,12 @@ enum e_optcode {
OPT_OPENSSL_EGD,
OPT_OPENSSL_FIPS,
OPT_OPENSSL_KEY,
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
OPT_OPENSSL_MAXFRAGLEN,
#endif
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
OPT_OPENSSL_MAXSENDFRAG,
#endif
OPT_OPENSSL_MAX_PROTO_VERSION,
OPT_OPENSSL_METHOD,
OPT_OPENSSL_MIN_PROTO_VERSION,