OpenSSL option compress allows to disable compression

This commit is contained in:
Gerhard Rieger 2011-11-26 14:27:02 +01:00
parent 9e0c4e1df5
commit 7e3386f228
10 changed files with 244 additions and 8 deletions

View file

@ -93,6 +93,10 @@ new features:
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 1.7.1.3:
security:

View file

@ -10,7 +10,7 @@ def(Filan)(0)(bf(Filan))
def(procan)(0)(bf(procan))
def(Procan)(0)(bf(Procan))
manpage(socat)(1)(Jan 2010)()()
manpage(socat)(1)(Oct 2010)()()
whenhtml(
label(CONTENTS)
@ -2665,6 +2665,13 @@ label(OPTION_OPENSSL_FIPS)dit(bf(tt(fips)))
This mode might require that the involved certificates are generated with a
FIPS enabled version of openssl. Setting or clearing this option on one
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()
startdit()enddit()nl()

View file

@ -1,5 +1,5 @@
# source: xio.help
# Copyright Gerhard Rieger 2001-2007
# Copyright Gerhard Rieger 2001-2010
Operating systems:
@ -4610,6 +4610,23 @@ FIPS enabled version of openssl. Setting or clearing this option on one
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

View file

@ -1,5 +1,5 @@
/* source: sslcls.c */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2010 */
/* 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
@ -315,4 +315,42 @@ int sycFIPS_mode_set(int onoff) {
}
#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 */

View file

@ -1,5 +1,5 @@
/* source: sslcls.h */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2010 */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sslcls_h_included
@ -49,6 +49,12 @@ BIO *sycBIO_new_file(const char *filename, const char *mode);
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 */
#else /* !WITH_SYCLS */
@ -92,6 +98,10 @@ int sycFIPS_mode_set(int onoff);
#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 */
#define sycFIPS_mode_set(o) FIPS_mode_set(o)

59
test.sh
View file

@ -476,6 +476,9 @@ filloptionvalues() {
case "$OPTS" in
*,egd,*) OPTS=$(echo "$OPTS" |sed "s/,egd,/,egd=/tmp/hugo,/g");;
esac
case "$OPTS" in
*,compress,*) OPTS=$(echo "$OPTS" |sed "s/,compress,/,compress=none,/g");;
esac
# PROXY
case "$OPTS" in
*,proxyauth,*) OPTS=$(echo "$OPTS" |sed "s/,proxyauth,/,proxyauth=user:pass,/g");;
@ -3981,6 +3984,62 @@ PORT=$((PORT+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
case "$TESTS" in
*%functions%*|*%socks%*|*%socks4%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)

View file

@ -104,6 +104,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_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 };
#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
const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
#endif
@ -134,6 +137,24 @@ int xio_reset_fips_mode(void) {
#define xio_reset_fips_mode() 0
#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 */
static int
xioopen_openssl_connect(int argc,
@ -304,7 +325,7 @@ static int
break;
} 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 */
return STAT_OK;
@ -501,8 +522,7 @@ static int
return result;
}
Notice1("SSL connection using %s",
SSL_get_cipher(xfd->para.openssl.ssl));
openssl_conn_loginfo(xfd->para.openssl.ssl);
break;
} /* drop out on success */
@ -606,6 +626,59 @@ int _xioopen_openssl_listen(struct single *xfd,
#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
_xioopen_openssl_prepare(struct opt *opts,
struct single *xfd,/* a xio file descriptor
@ -625,6 +698,9 @@ int
char *opt_cafile = NULL; /* certificate authority file */
char *opt_capath = NULL; /* certificate authority directory */
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 */
unsigned long err;
int result;
@ -642,6 +718,9 @@ int
retropt_string(opts, OPT_OPENSSL_DHPARAM, &opt_dhparam);
retropt_string(opts, OPT_OPENSSL_EGD, &opt_egd);
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 (opt_fips) {
@ -783,6 +862,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 (sycSSL_CTX_load_verify_locations(*ctx, opt_cafile, opt_capath) != 1) {
int result;

View file

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

View file

@ -293,6 +293,9 @@ const struct optname optionnames[] = {
#if WITH_EXT2 && defined(EXT2_COMPR_FL)
IF_ANY ("compr", &opt_ext2_compr)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
IF_OPENSSL("compress", &opt_openssl_compress)
#endif
#ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */
IF_TCP ("conn-abort-threshold", &opt_tcp_conn_abort_threshold)
#endif
@ -1085,6 +1088,9 @@ const struct optname optionnames[] = {
IF_OPENSSL("openssl-capath", &opt_openssl_capath)
IF_OPENSSL("openssl-certificate", &opt_openssl_certificate)
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-egd", &opt_openssl_egd)
#if WITH_FIPS

View file

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