OpenSSL option compress allows to disable compression

This commit is contained in:
Gerhard Rieger 2012-11-16 21:10:44 +01:00
parent dbb6ea3a52
commit 800fd903b1
10 changed files with 243 additions and 7 deletions

View file

@ -135,6 +135,10 @@ new features:
Till Maas added support for tun/tap addresses without IP address Till Maas added support for tun/tap addresses without IP address
added an option openssl-compress that allows to disable the compression
feature of newer OpenSSL versions. Thanks to Michael Hanselmann for
providing this contribution (sponsored by Google Inc.)
####################### V 2.0.0-b7: ####################### V 2.0.0-b7:
security: security:

View file

@ -10,7 +10,7 @@ def(Filan)(0)(bf(Filan))
def(procan)(0)(bf(procan)) def(procan)(0)(bf(procan))
def(Procan)(0)(bf(Procan)) def(Procan)(0)(bf(Procan))
manpage(socat)(1)(Apr 2012)()() manpage(socat)(1)(Nov 2012)()()
whenhtml( whenhtml(
label(CONTENTS) label(CONTENTS)
@ -2737,6 +2737,13 @@ label(OPTION_OPENSSL_FIPS)dit(bf(tt(fips)))
This mode might require that the involved certificates are generated with a This mode might require that the involved certificates are generated with a
FIPS enabled version of openssl. Setting or clearing this option on one FIPS enabled version of openssl. Setting or clearing this option on one
socat() address affects all OpenSSL addresses of this process. socat() address affects all OpenSSL addresses of this process.
label(OPTION_OPENSSL_COMPRESS)dit(bf(tt(compress)))
Enable or disable the use of compression for a connection. Setting this to
"none" disables compression, setting it to "auto" lets OpenSSL choose the best
available algorithm supported by both parties. The default is to not touch any
compression-related settings.
NOTE: Requires OpenSSL 0.9.8 or higher and disabling compression with
OpenSSL 0.9.8 affects all new connections in the process.
enddit() enddit()
startdit()enddit()nl() startdit()enddit()nl()

View file

@ -4609,6 +4609,23 @@ This mode might require that the involved certificates are generated with a
FIPS enabled version of openssl. Setting or clearing this option on one FIPS enabled version of openssl. Setting or clearing this option on one
socat address affects all OpenSSL addresses of this process. socat address affects all OpenSSL addresses of this process.
Option: openssl-compress
Aliases: compress
Type: STRING
Option group: OPENSSL
Phase: SPEC
Platforms: (depends on openssl installation)
Enable or disable the use of compression for a connection. Setting this to
"none" disables compression, setting it to "auto" lets OpenSSL choose the best
available algorithm supported by both parties. The default is to not touch any
compression-related settings.
NOTE: Requires OpenSSL 0.9.8 or higher.
NOTE: Disabling compression with OpenSSL 0.9.8 affects all new connections in
the same process.
=============================================================================== ===============================================================================
Application specific address options Application specific address options

View file

@ -1,5 +1,5 @@
/* source: sslcls.c */ /* source: sslcls.c */
/* Copyright Gerhard Rieger 2001-2007 */ /* Copyright Gerhard Rieger 2001-2012 */
/* Published under the GNU General Public License V.2, see file COPYING */ /* Published under the GNU General Public License V.2, see file COPYING */
/* explicit system call and C library trace function, for those who miss strace /* explicit system call and C library trace function, for those who miss strace
@ -331,4 +331,42 @@ int sycFIPS_mode_set(int onoff) {
} }
#endif /* WITH_FIPS */ #endif /* WITH_FIPS */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
const COMP_METHOD *sycSSL_get_current_compression(SSL *ssl) {
const COMP_METHOD *result;
Debug1("SSL_get_current_compression(%p)", ssl);
result = SSL_get_current_compression(ssl);
if (result) {
Debug1("SSL_get_current_compression() -> %p", result);
} else {
Debug("SSL_get_current_compression() -> NULL");
}
return result;
}
const COMP_METHOD *sycSSL_get_current_expansion(SSL *ssl) {
const COMP_METHOD *result;
Debug1("SSL_get_current_expansion(%p)", ssl);
result = SSL_get_current_expansion(ssl);
if (result) {
Debug1("SSL_get_current_expansion() -> %p", result);
} else {
Debug("SSL_get_current_expansion() -> NULL");
}
return result;
}
const char *sycSSL_COMP_get_name(const COMP_METHOD *comp) {
const char *result;
Debug1("SSL_COMP_get_name(%p)", comp);
result = SSL_COMP_get_name(comp);
if (result) {
Debug1("SSL_COMP_get_name() -> \"%s\"", result);
} else {
Debug("SSL_COMP_get_name() -> NULL");
}
return result;
}
#endif
#endif /* WITH_SYCLS && WITH_OPENSSL */ #endif /* WITH_SYCLS && WITH_OPENSSL */

View file

@ -1,5 +1,5 @@
/* source: sslcls.h */ /* source: sslcls.h */
/* Copyright Gerhard Rieger 2001-2007 */ /* Copyright Gerhard Rieger 2001-2012 */
/* Published under the GNU General Public License V.2, see file COPYING */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sslcls_h_included #ifndef __sslcls_h_included
@ -51,6 +51,12 @@ BIO *sycBIO_new_file(const char *filename, const char *mode);
int sycFIPS_mode_set(int onoff); int sycFIPS_mode_set(int onoff);
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
const COMP_METHOD *sycSSL_get_current_compression(SSL *ssl);
const COMP_METHOD *sycSSL_get_current_expansion(SSL *ssl);
const char *sycSSL_COMP_get_name(const COMP_METHOD *comp);
#endif
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
#else /* !WITH_SYCLS */ #else /* !WITH_SYCLS */
@ -96,6 +102,10 @@ int sycFIPS_mode_set(int onoff);
#define sycBIO_new_file(f,m) BIO_new_file(f,m) #define sycBIO_new_file(f,m) BIO_new_file(f,m)
#define sycSSL_get_current_compression(s) SSL_get_current_compression(s)
#define sycSSL_get_current_expansion(s) SSL_get_current_expansion(s)
#define sycSSL_COMP_get_name(c) SSL_COMP_get_name(c)
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
#define sycFIPS_mode_set(o) FIPS_mode_set(o) #define sycFIPS_mode_set(o) FIPS_mode_set(o)

59
test.sh
View file

@ -491,6 +491,9 @@ filloptionvalues() {
case "$OPTS" in case "$OPTS" in
*,egd,*) OPTS=$(echo "$OPTS" |sed "s/,egd,/,egd=/tmp/hugo,/g");; *,egd,*) OPTS=$(echo "$OPTS" |sed "s/,egd,/,egd=/tmp/hugo,/g");;
esac esac
case "$OPTS" in
*,compress,*) OPTS=$(echo "$OPTS" |sed "s/,compress,/,compress=none,/g");;
esac
# PROXY # PROXY
case "$OPTS" in case "$OPTS" in
*,proxyauth,*) OPTS=$(echo "$OPTS" |sed "s/,proxyauth,/,proxyauth=user:pass,/g");; *,proxyauth,*) OPTS=$(echo "$OPTS" |sed "s/,proxyauth,/,proxyauth=user:pass,/g");;
@ -4139,6 +4142,62 @@ PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
NAME=OPENSSL_COMPRESS
case "$TESTS" in
*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
TEST="$NAME: OpenSSL compression"
if ! eval $NUMCOND; then :;
elif ! testaddrs openssl >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
elif ! testoptions openssl-compress >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL compression option not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
gentestcert testsrv
printf "test $F_n $TEST... " $N
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
success=yes
for srccompr in '' compress=auto compress=none; do
for dstcompr in '' compress=auto compress=none; do
CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0,$dstcompr pipe"
CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD,$srccompr"
eval "$CMD2 2>\"${te}1\" &"
pid=$! # background process id
waittcp4port $PORT
echo "$da" | $CMD >$tf 2>"${te}2"
kill $pid 2>/dev/null
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
success=
break
fi
done
done
if test -z "$success"; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD2 &"
echo "$CMD"
cat "${te}1"
cat "${te}2"
cat "$tdiff"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
numOK=$((numOK+1))
fi
fi ;; # NUMCOND, feats
esac
PORT=$((PORT+1))
N=$((N+1))
NAME=SOCKS4CONNECT_TCP4 NAME=SOCKS4CONNECT_TCP4
case "$TESTS" in case "$TESTS" in
*%functions%*|*%chain%*|*%socks%*|*%socks4%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) *%functions%*|*%chain%*|*%socks%*|*%socks4%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)

View file

@ -177,6 +177,9 @@ const struct optdesc opt_openssl_cafile = { "openssl-cafile", "cafile",
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 };
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
const struct optdesc opt_openssl_compress = { "openssl-compress", "compress", OPT_OPENSSL_COMPRESS, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
#endif
#if WITH_FIPS #if WITH_FIPS
const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
#endif #endif
@ -207,6 +210,24 @@ int xio_reset_fips_mode(void) {
#define xio_reset_fips_mode() 0 #define xio_reset_fips_mode() 0
#endif #endif
static void openssl_conn_loginfo(SSL *ssl) {
Notice1("SSL connection using %s", SSL_get_cipher(ssl));
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
{
const COMP_METHOD *comp, *expansion;
comp = sycSSL_get_current_compression(ssl);
expansion = sycSSL_get_current_expansion(ssl);
Notice1("SSL connection compression \"%s\"",
comp?sycSSL_COMP_get_name(comp):"none");
Notice1("SSL connection expansion \"%s\"",
expansion?sycSSL_COMP_get_name(expansion):"none");
}
#endif
}
/* the open function for OpenSSL client */ /* the open function for OpenSSL client */
static int static int
xioopen_openssl_connect(int argc, xioopen_openssl_connect(int argc,
@ -415,7 +436,7 @@ static int
break; break;
} while (true); /* drop out on success */ } while (true); /* drop out on success */
Notice1("SSL connection using %s", SSL_get_cipher(xfd->para.openssl.ssl)); openssl_conn_loginfo(xfd->para.openssl.ssl);
/* fill in the fd structure */ /* fill in the fd structure */
return STAT_OK; return STAT_OK;
@ -634,8 +655,7 @@ static int
return result; return result;
} }
Notice1("SSL connection using %s", openssl_conn_loginfo(xfd->para.openssl.ssl);
SSL_get_cipher(xfd->para.openssl.ssl));
break; break;
} /* drop out on success */ } /* drop out on success */
@ -738,6 +758,59 @@ int _xioopen_openssl_listen(struct single *xfd,
#endif /* WITH_LISTEN */ #endif /* WITH_LISTEN */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
/* In OpenSSL 0.9.7 compression methods could be added using
* SSL_COMP_add_compression_method(3), but the implemntation is not compatible
* with the standard (RFC3749).
*/
static int openssl_setup_compression(SSL_CTX *ctx, char *method)
{
STACK_OF(SSL_COMP)* comp_methods;
assert(method);
/* Getting the stack of compression methods has the intended side-effect of
* initializing the SSL library's compression part.
*/
comp_methods = SSL_COMP_get_compression_methods();
if (!comp_methods) {
Info("OpenSSL built without compression support");
return STAT_OK;
}
if (strcasecmp(method, "auto") == 0) {
Info("Using default OpenSSL compression");
return STAT_OK;
}
if (strcasecmp(method, "none") == 0) {
/* Disable compression */
#ifdef SSL_OP_NO_COMPRESSION
Info("Disabling OpenSSL compression");
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
#else
/* SSL_OP_NO_COMPRESSION was only introduced in OpenSSL 0.9.9 (released
* as 1.0.0). Removing all compression methods is a work-around for
* earlier versions of OpenSSL, but it affects all SSL connections.
*/
Info("Disabling OpenSSL compression globally");
sk_SSL_COMP_zero(comp_methods);
#endif
return STAT_OK;
}
/* zlib compression in OpenSSL before version 0.9.8e-beta1 uses the libc's
* default malloc/free instead of the ones passed to OpenSSL. Should socat
* ever use custom malloc/free functions for OpenSSL, this must be taken
* into consideration. See OpenSSL bug #1468.
*/
Error1("openssl-compress=\"%s\": unknown compression method", method);
return STAT_NORETRY;
}
#endif
int int
_xioopen_openssl_prepare(struct opt *opts, _xioopen_openssl_prepare(struct opt *opts,
struct single *xfd,/* a xio file descriptor struct single *xfd,/* a xio file descriptor
@ -757,6 +830,9 @@ int
char *opt_cafile = NULL; /* certificate authority file */ char *opt_cafile = NULL; /* certificate authority file */
char *opt_capath = NULL; /* certificate authority directory */ char *opt_capath = NULL; /* certificate authority directory */
char *opt_egd = NULL; /* entropy gathering daemon socket path */ char *opt_egd = NULL; /* entropy gathering daemon socket path */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
char *opt_compress = NULL; /* compression method */
#endif
bool opt_pseudo = false; /* use pseudo entropy if nothing else */ bool opt_pseudo = false; /* use pseudo entropy if nothing else */
unsigned long err; unsigned long err;
int result; int result;
@ -773,6 +849,9 @@ int
retropt_string(opts, OPT_OPENSSL_DHPARAM, &opt_dhparam); retropt_string(opts, OPT_OPENSSL_DHPARAM, &opt_dhparam);
retropt_string(opts, OPT_OPENSSL_EGD, &opt_egd); retropt_string(opts, OPT_OPENSSL_EGD, &opt_egd);
retropt_bool(opts,OPT_OPENSSL_PSEUDO, &opt_pseudo); retropt_bool(opts,OPT_OPENSSL_PSEUDO, &opt_pseudo);
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
retropt_string(opts, OPT_OPENSSL_COMPRESS, &opt_compress);
#endif
#if WITH_FIPS #if WITH_FIPS
if (opt_fips) { if (opt_fips) {
@ -914,6 +993,16 @@ int
} }
} }
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
if (opt_compress) {
int result;
result = openssl_setup_compression(*ctx, opt_compress);
if (result != STAT_OK) {
return result;
}
}
#endif
if (opt_cafile != NULL || opt_capath != NULL) { if (opt_cafile != NULL || opt_capath != NULL) {
if (sycSSL_CTX_load_verify_locations(*ctx, opt_cafile, opt_capath) != 1) { if (sycSSL_CTX_load_verify_locations(*ctx, opt_cafile, opt_capath) != 1) {
int result; int result;

View file

@ -1,5 +1,5 @@
/* source: xio-openssl.h */ /* source: xio-openssl.h */
/* Copyright Gerhard Rieger 2002-2007 */ /* Copyright Gerhard Rieger 2002-2012 */
/* Published under the GNU General Public License V.2, see file COPYING */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_openssl_included #ifndef __xio_openssl_included
@ -23,6 +23,9 @@ 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;
extern const struct optdesc opt_openssl_pseudo; extern const struct optdesc opt_openssl_pseudo;
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
extern const struct optdesc opt_openssl_compress;
#endif
#if WITH_FIPS #if WITH_FIPS
extern const struct optdesc opt_openssl_fips; extern const struct optdesc opt_openssl_fips;
#endif #endif

View file

@ -300,6 +300,9 @@ const struct optname optionnames[] = {
#if WITH_EXT2 && defined(EXT2_COMPR_FL) #if WITH_EXT2 && defined(EXT2_COMPR_FL)
IF_ANY ("compr", &opt_ext2_compr) IF_ANY ("compr", &opt_ext2_compr)
#endif #endif
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
IF_OPENSSL("compress", &opt_openssl_compress)
#endif
#ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */ #ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */
IF_TCP ("conn-abort-threshold", &opt_tcp_conn_abort_threshold) IF_TCP ("conn-abort-threshold", &opt_tcp_conn_abort_threshold)
#endif #endif
@ -1049,6 +1052,9 @@ const struct optname optionnames[] = {
IF_OPENSSL("openssl-capath", &opt_openssl_capath) IF_OPENSSL("openssl-capath", &opt_openssl_capath)
IF_OPENSSL("openssl-certificate", &opt_openssl_certificate) IF_OPENSSL("openssl-certificate", &opt_openssl_certificate)
IF_OPENSSL("openssl-cipherlist", &opt_openssl_cipherlist) IF_OPENSSL("openssl-cipherlist", &opt_openssl_cipherlist)
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
IF_OPENSSL("openssl-compress", &opt_openssl_compress)
#endif
IF_OPENSSL("openssl-dhparam", &opt_openssl_dhparam) IF_OPENSSL("openssl-dhparam", &opt_openssl_dhparam)
IF_OPENSSL("openssl-egd", &opt_openssl_egd) IF_OPENSSL("openssl-egd", &opt_openssl_egd)
#if WITH_FIPS #if WITH_FIPS

View file

@ -477,6 +477,9 @@ enum e_optcode {
OPT_OPENSSL_CAPATH, OPT_OPENSSL_CAPATH,
OPT_OPENSSL_CERTIFICATE, OPT_OPENSSL_CERTIFICATE,
OPT_OPENSSL_CIPHERLIST, OPT_OPENSSL_CIPHERLIST,
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
OPT_OPENSSL_COMPRESS,
#endif
OPT_OPENSSL_DHPARAM, OPT_OPENSSL_DHPARAM,
OPT_OPENSSL_EGD, OPT_OPENSSL_EGD,
OPT_OPENSSL_FIPS, OPT_OPENSSL_FIPS,