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 Test: PROXY_HTTPVERSION
Feature inspired by Robin Palotai. 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: Corrections:
When a sub process (EXEC, SYSTEM) terminated with exit code other than 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/ 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 */ /* Define if you have the OpenSSL SSL_set_tlsext_host_name define/function */
#undef HAVE_SSL_set_tlsext_host_name #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 */ /* Define if you have the flock function */
#undef HAVE_FLOCK #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(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_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_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(SSL_library_init, AC_DEFINE(HAVE_SSL_library_init))
AC_CHECK_FUNC(ERR_error_string, AC_DEFINE(HAVE_ERR_error_string)) 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 On some systems, openssl requires an explicit source of random data. Specify
the socket name where an entropy gathering daemon like egd provides random the socket name where an entropy gathering daemon like egd provides random
data, e.g. /dev/egd-pool. 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))) label(OPTION_OPENSSL_PSEUDO)dit(bf(tt(pseudo)))
On systems where openssl cannot find an entropy source and where no entropy On systems where openssl cannot find an entropy source and where no entropy
gathering daemon can be utilized, this option activates a mechanism for 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; 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 sycSSL_set_cipher_list(SSL *ssl, const char *str) {
int result; int result;
Debug2("SSL_set_cipher_list(%p, \"%s\")", ssl, str); 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 (*verify_callback)(int, X509_STORE_CTX *));
int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh); int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh);
int sycSSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); 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); int sycSSL_set_cipher_list(SSL *ssl, const char *str);
long sycSSL_get_verify_result(SSL *ssl); long sycSSL_get_verify_result(SSL *ssl);
int sycSSL_set_fd(SSL *ssl, int fd); 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_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_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) #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_set_cipher_list(s,t) SSL_set_cipher_list(s,t)
#define sycSSL_get_verify_result(s) SSL_get_verify_result(s) #define sycSSL_get_verify_result(s) SSL_get_verify_result(s)
#define sycSSL_set_fd(s,f) SSL_set_fd(s,f) #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_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_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 }; 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 }; 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) #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 }; 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 }; const struct optdesc opt_openssl_snihost = { "openssl-snihost", "snihost", OPT_OPENSSL_SNIHOST, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
#endif #endif
/* If FIPS is compiled in, we need to track if the user asked for FIPS mode. /* 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 * On forks, the FIPS mode must be reset by a disable, then enable since
* FIPS tracks the process ID that initializes things. * 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) { static void openssl_conn_loginfo(SSL *ssl) {
const char *string; const char *string;
SSL_SESSION *session;
string = SSL_get_cipher_version(ssl); string = SSL_get_cipher_version(ssl);
Notice1("SSL proto version used: %s", string); Notice1("SSL proto version used: %s", string);
@ -187,6 +193,31 @@ static void openssl_conn_loginfo(SSL *ssl) {
Notice1("SSL connection expansion \"%s\"", Notice1("SSL connection expansion \"%s\"",
expansion?sycSSL_COMP_get_name(expansion):"none"); 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 #endif
} }
@ -1405,6 +1436,60 @@ cont_out:
NULL); 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; 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_cafile;
extern const struct optdesc opt_openssl_capath; extern const struct optdesc opt_openssl_capath;
extern const struct optdesc opt_openssl_egd; 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; extern const struct optdesc opt_openssl_pseudo;
#if OPENSSL_VERSION_NUMBER >= 0x00908000L #if OPENSSL_VERSION_NUMBER >= 0x00908000L
extern const struct optdesc opt_openssl_compress; 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) IF_OPENSSL("max-version", &opt_openssl_max_proto_version)
#endif #endif
IF_LISTEN ("maxchildren", &opt_max_children) 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 #ifdef TCP_MAXSEG
IF_TCP ("maxseg", &opt_tcp_maxseg) IF_TCP ("maxseg", &opt_tcp_maxseg)
IF_TCP ("maxseg-late", &opt_tcp_maxseg_late) IF_TCP ("maxseg-late", &opt_tcp_maxseg_late)
#endif #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 #ifdef TCP_MD5SUM
IF_TCP ("md5sig", &opt_tcp_md5sig) IF_TCP ("md5sig", &opt_tcp_md5sig)
#endif #endif
@ -1190,6 +1196,12 @@ const struct optname optionnames[] = {
#if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version) #if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version)
IF_OPENSSL("openssl-max-proto-version", &opt_openssl_max_proto_version) IF_OPENSSL("openssl-max-proto-version", &opt_openssl_max_proto_version)
#endif #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 WITH_OPENSSL_METHOD
IF_OPENSSL("openssl-method", &opt_openssl_method) IF_OPENSSL("openssl-method", &opt_openssl_method)
#endif #endif

View file

@ -506,6 +506,12 @@ enum e_optcode {
OPT_OPENSSL_EGD, OPT_OPENSSL_EGD,
OPT_OPENSSL_FIPS, OPT_OPENSSL_FIPS,
OPT_OPENSSL_KEY, 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_MAX_PROTO_VERSION,
OPT_OPENSSL_METHOD, OPT_OPENSSL_METHOD,
OPT_OPENSSL_MIN_PROTO_VERSION, OPT_OPENSSL_MIN_PROTO_VERSION,