Added TLS methods support

This commit is contained in:
Gerhard Rieger 2015-04-02 16:25:51 +02:00
parent 066dac0812
commit 6a79aa6529
8 changed files with 253 additions and 42 deletions

View file

@ -202,6 +202,8 @@ corrections:
files that failed to compile due to missing IPPROTO_TCP. files that failed to compile due to missing IPPROTO_TCP.
Thanks to Thierry Fournier for report and patch. Thanks to Thierry Fournier for report and patch.
Fixed a few minor bugs with OpenSSL in configure and with messages
porting: porting:
Red Hat issue 1020203: configure checks fail with some compilers. Red Hat issue 1020203: configure checks fail with some compilers.
Use case: clang Use case: clang
@ -306,6 +308,8 @@ new features:
SOCAT_OPENSSL_X509V3_SUBJECTALTNAME_DNS SOCAT_OPENSSL_X509V3_SUBJECTALTNAME_DNS
Tests: ENV_OPENSSL_{CLIENT,SERVER}_X509_* Tests: ENV_OPENSSL_{CLIENT,SERVER}_X509_*
Added support for methods TLSv1, TLSv1.1, TLSv1.2, and DTLS1
Tests: OPENSSL_METHOD_*
docu docu
minor corrections in docu (thanks to Paggas) minor corrections in docu (thanks to Paggas)

View file

@ -394,15 +394,38 @@
/* Define if you have the unsetenv function. not on HP-UX */ /* Define if you have the unsetenv function. not on HP-UX */
#undef HAVE_UNSETENV #undef HAVE_UNSETENV
/* Define if you have the SSLv2_client_method function. not in new openssl */ /* Define if you have the SSLv2 client and server method functions. not in new openssl */
#undef HAVE_SSLv2_client_method #undef HAVE_SSLv2_client_method
/* Define if you have the SSLv2_server_method function. not in new openssl */
#undef HAVE_SSLv2_server_method #undef HAVE_SSLv2_server_method
/* Define if you have the HAVE_SSL_CTX_set_default_verify_paths function */ /* Define if you have the HAVE_SSL_CTX_set_default_verify_paths function */
#undef HAVE_SSL_CTX_set_default_verify_paths #undef HAVE_SSL_CTX_set_default_verify_paths
/* Define if you have the SSLv3 client and server method functions. not in new openssl */
#undef HAVE_SSLv3_client_method
#undef HAVE_SSLv3_server_method
/* Define if you have the SSLv3 client and server method functions with rollback to v2 */
#undef HAVE_SSLv23_client_method
#undef HAVE_SSLv23_server_method
/* Define if you have the TLSv1.0 client and server method functions */
#undef HAVE_TLSv1_client_method
#undef HAVE_TLSv1_server_method
/* Define if you have the TLSv1.1 client and server method functions */
#undef HAVE_TLSv1_1_client_method
#undef HAVE_TLSv1_1_server_method
/* Define if you have the TLSv1.2 client and server method functions */
#undef HAVE_TLSv1_2_client_method
#undef HAVE_TLSv1_2_server_method
/* Define if you have the DTLSv1 client and server method functions */
#undef HAVE_DTLSv1_client_method
#undef HAVE_DTLSv1_server_method
/* Define if you have the flock function */ /* Define if you have the flock function */
#undef HAVE_FLOCK #undef HAVE_FLOCK

View file

@ -1350,11 +1350,25 @@ dnl Search for unsetenv()
AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV)) AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV))
dnl Search for SSLv2_client_method, SSLv2_server_method dnl Search for SSLv2_client_method, SSLv2_server_method
AC_CHECK_FUNC(SSLv3_client_method, AC_DEFINE(HAVE_SSLv3_client_method), AC_CHECK_LIB(crypt, SSLv3_client_method, [LIBS=-lcrypt $LIBS])) AC_CHECK_FUNC(SSLv2_client_method, AC_DEFINE(HAVE_SSLv2_client_method), AC_CHECK_LIB(crypt, SSLv2_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv2_server_method, AC_DEFINE(HAVE_SSLv2_server_method), AC_CHECK_LIB(crypt, SSLv2_server_method, [LIBS=-lcrypt $LIBS])) AC_CHECK_FUNC(SSLv2_server_method, AC_DEFINE(HAVE_SSLv2_server_method), AC_CHECK_LIB(crypt, SSLv2_server_method, [LIBS=-lcrypt $LIBS]))
dnl dnl
AC_CHECK_FUNC(SSL_CTX_set_default_verify_paths, AC_DEFINE(HAVE_SSL_CTX_set_default_verify_paths)) AC_CHECK_FUNC(SSL_CTX_set_default_verify_paths, AC_DEFINE(HAVE_SSL_CTX_set_default_verify_paths))
AC_CHECK_FUNC(SSLv3_client_method, AC_DEFINE(HAVE_SSLv3_client_method), AC_CHECK_LIB(crypt, SSLv3_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv3_server_method, AC_DEFINE(HAVE_SSLv3_server_method), AC_CHECK_LIB(crypt, SSLv3_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv23_client_method, AC_DEFINE(HAVE_SSLv23_client_method), AC_CHECK_LIB(crypt, SSLv23_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv23_server_method, AC_DEFINE(HAVE_SSLv23_server_method), AC_CHECK_LIB(crypt, SSLv23_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_client_method, AC_DEFINE(HAVE_TLSv1_client_method), AC_CHECK_LIB(crypt, TLSv1_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_server_method, AC_DEFINE(HAVE_TLSv1_server_method), AC_CHECK_LIB(crypt, TLSv1_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_1_client_method, AC_DEFINE(HAVE_TLSv1_1_client_method), AC_CHECK_LIB(crypt, TLSv1_1_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_1_client_method, AC_DEFINE(HAVE_TLSv1_1_client_method), AC_CHECK_LIB(crypt, TLSv1_1_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_1_server_method, AC_DEFINE(HAVE_TLSv1_1_server_method), AC_CHECK_LIB(crypt, TLSv1_1_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_2_client_method, AC_DEFINE(HAVE_TLSv1_2_client_method), AC_CHECK_LIB(crypt, TLSv1_2_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_2_server_method, AC_DEFINE(HAVE_TLSv1_2_server_method), AC_CHECK_LIB(crypt, TLSv1_2_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(DTLSv1_client_method, AC_DEFINE(HAVE_DTLSv1_client_method), AC_CHECK_LIB(crypt, DTLSv1_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(DTLSv1_server_method, AC_DEFINE(HAVE_DTLSv1_server_method), AC_CHECK_LIB(crypt, DTLSv1_server_method, [LIBS=-lcrypt $LIBS]))
dnl Run time checks dnl Run time checks

View file

@ -2704,11 +2704,14 @@ label(OPTION_OPENSSL_METHOD)dit(bf(tt(method=<ssl-method>)))
Sets the protocol version to be used. Valid strings (not case sensitive) Sets the protocol version to be used. Valid strings (not case sensitive)
are: are:
startdit() startdit()
dit(tt(SSLv2)) Select SSL protocol version 2. dit(tt(SSL2)) Select SSL protocol version 2.
dit(tt(SSLv3)) Select SSL protocol version 3. dit(tt(SSL3)) Select SSL protocol version 3.
dit(tt(SSLv23)) Select SSL protocol version 2 or 3. This is the default when dit(tt(SSL23)) Select the best available SSL or TLS protocol. This is the default when
this option is not provided. this option is not provided.
dit(tt(TLSv1)) Select TLS protocol version 1. dit(tt(TLS1)) Select TLS protocol version 1.
dit(tt(TLS1.1)) Select TLS protocol version 1.1.
dit(tt(TLS1.2)) Select TLS protocol version 1.2.
dit(tt(DTLS1)) Select DTLS protocol version 1.
enddit() enddit()
label(OPTION_OPENSSL_VERIFY)dit(bf(tt(verify=<bool>))) label(OPTION_OPENSSL_VERIFY)dit(bf(tt(verify=<bool>)))
Controls check of the peer's certificate. Default is 1 (true). Disabling Controls check of the peer's certificate. Default is 1 (true). Disabling

View file

@ -102,6 +102,62 @@ const SSL_METHOD *sycTLSv1_server_method(void) {
Debug1("TLSv1_server_method() -> %p", result); Debug1("TLSv1_server_method() -> %p", result);
return result; return result;
} }
#if HAVE_TLSv1_1_client_method
const SSL_METHOD *sycTLSv1_1_client_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_1_client_method()");
result = TLSv1_1_client_method();
Debug1("TLSv1_1_client_method() -> %p", result);
return result;
}
#endif
#if HAVE_TLSv1_1_server_method
const SSL_METHOD *sycTLSv1_1_server_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_1_server_method()");
result = TLSv1_1_server_method();
Debug1("TLSv1_1_server_method() -> %p", result);
return result;
}
#endif
#if HAVE_TLSv1_2_client_method
const SSL_METHOD *sycTLSv1_2_client_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_2_client_method()");
result = TLSv1_2_client_method();
Debug1("TLSv1_2_client_method() -> %p", result);
return result;
}
#endif
#if HAVE_TLSv1_2_server_method
const SSL_METHOD *sycTLSv1_2_server_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_2_server_method()");
result = TLSv1_2_server_method();
Debug1("TLSv1_2_server_method() -> %p", result);
return result;
}
#endif
const SSL_METHOD *sycDTLSv1_client_method(void) {
const SSL_METHOD *result;
Debug("DTLSv1_client_method()");
result = DTLSv1_client_method();
Debug1("DTLSv1_client_method() -> %p", result);
return result;
}
const SSL_METHOD *sycDTLSv1_server_method(void) {
const SSL_METHOD *result;
Debug("DTLSv1_server_method()");
result = DTLSv1_server_method();
Debug1("DTLSv1_server_method() -> %p", result);
return result;
}
SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method) { SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method) {
SSL_CTX *result; SSL_CTX *result;

View file

@ -18,6 +18,12 @@ const SSL_METHOD *sycSSLv23_client_method(void);
const SSL_METHOD *sycSSLv23_server_method(void); const SSL_METHOD *sycSSLv23_server_method(void);
const SSL_METHOD *sycTLSv1_client_method(void); const SSL_METHOD *sycTLSv1_client_method(void);
const SSL_METHOD *sycTLSv1_server_method(void); const SSL_METHOD *sycTLSv1_server_method(void);
const SSL_METHOD *sycTLSv1_1_client_method(void);
const SSL_METHOD *sycTLSv1_1_server_method(void);
const SSL_METHOD *sycTLSv1_2_client_method(void);
const SSL_METHOD *sycTLSv1_2_server_method(void);
const SSL_METHOD *sycDTLSv1_client_method(void);
const SSL_METHOD *sycDTLSv1_server_method(void);
SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method); SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method);
SSL *sycSSL_new(SSL_CTX *ctx); SSL *sycSSL_new(SSL_CTX *ctx);
int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,

49
test.sh
View file

@ -11843,7 +11843,7 @@ N=$((N+1))
# Linux) with "Invalid argument". # Linux) with "Invalid argument".
NAME=OPENSSL_CONNECT_BIND NAME=OPENSSL_CONNECT_BIND
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%ssl%*|*%openssl%*|*%$NAME%*) *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%openssl%*|*%$NAME%*)
TEST="$NAME: test OPENSSL-CONNECT with bind option" TEST="$NAME: test OPENSSL-CONNECT with bind option"
# have a simple SSL server that just echoes data. # have a simple SSL server that just echoes data.
# connect with socat using OPENSSL-CONNECT with bind, send data and check if the # connect with socat using OPENSSL-CONNECT with bind, send data and check if the
@ -12490,6 +12490,53 @@ PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
# test if the various SSL methods can be used with OpenSSL
for method in SSL3 SSL23 TLS1 TLS1.1 TLS1.2 DTLS1; do
NAME=OPENSSL_METHOD_$method
case "$TESTS" in
*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%openssl%*|*%$NAME%*)
TEST="$NAME: test OpenSSL method $method"
# Start a socat process listening with OpenSSL and echoing data,
# using the selected method
# Start a second socat process connecting to the listener using
# the same method, send some data and catch the reply.
# If the reply is identical to the sent data the test succeeded.
if ! eval $NUMCOND; then :; else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,reuseaddr,method=$method,cipher=aNULL,verify=0 PIPE"
CMD1="$SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,method=$method,cipher=aNULL,verify=0"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
pid0=$!
waittcp4port $PORT 1
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
rc1=$?
kill $pid0 2>/dev/null; wait
if echo "$da" |diff - "${tf}1"; then
$PRINTF "$OK\n"
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$CMD0 &"
echo "$CMD1"
cat "${te}0"
cat "${te}1"
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
fi
fi # NUMCOND
;;
esac
PORT=$((PORT+1))
N=$((N+1))
done
############################################################################### ###############################################################################
# here come tests that might affect your systems integrity. Put normal tests # here come tests that might affect your systems integrity. Put normal tests
# before this paragraph. # before this paragraph.

View file

@ -850,7 +850,7 @@ int
SSL_CTX **ctx) SSL_CTX **ctx)
{ {
bool opt_fips = false; bool opt_fips = false;
const SSL_METHOD *method; const SSL_METHOD *method = NULL;
char *me_str = NULL; /* method string */ char *me_str = NULL; /* method string */
char *ci_str = "HIGH:-NULL:-PSK:-aNULL"; /* cipher string */ char *ci_str = "HIGH:-NULL:-PSK:-aNULL"; /* cipher string */
char *opt_key = NULL; /* file name of client private key */ char *opt_key = NULL; /* file name of client private key */
@ -905,54 +905,108 @@ int
/*! actions_to_seed_PRNG();*/ /*! actions_to_seed_PRNG();*/
if (!server) { if (!server) {
if (me_str != 0) { if (me_str != NULL) {
if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) { if (false) {
; /* for canonical reasons */
#if HAVE_SSLv2_client_method #if HAVE_SSLv2_client_method
} else if (!strcasecmp(me_str, "SSL2")) {
method = sycSSLv2_client_method(); method = sycSSLv2_client_method();
#else
Error1("OpenSSL method \"%s\" not provided by library", me_str);
method = sycSSLv23_server_method();
#endif #endif
} else #if HAVE_SSLv3_client_method
if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) { } else if (!strcasecmp(me_str, "SSL3")) {
method = sycSSLv3_client_method(); method = sycSSLv3_client_method();
} else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") || #endif
!strcasecmp(me_str, "SSL")) { #if HAVE_SSLv23_client_method
} else if (!strcasecmp(me_str, "SSL23")) {
method = sycSSLv23_client_method(); method = sycSSLv23_client_method();
} else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") || #endif
!strcasecmp(me_str, "TLS")) { #if HAVE_TLSv1_client_method
} else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
method = sycTLSv1_client_method(); method = sycTLSv1_client_method();
} else { #endif
Error1("openssl-method=\"%s\": unknown method", me_str); #if HAVE_TLSv1_1_client_method
method = sycSSLv23_client_method(); } else if (!strcasecmp(me_str, "TLS1.1")) {
method = sycTLSv1_1_client_method();
#endif
#if HAVE_TLSv1_2_client_method
} else if (!strcasecmp(me_str, "TLS1.2")) {
method = sycTLSv1_2_client_method();
#endif
#if HAVE_DTLSv1_client_method
} else if (!strcasecmp(me_str, "DTLS") || !strcasecmp(me_str, "DTLS1")) {
method = sycDTLSv1_client_method();
#endif
} else {
Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
} }
} else { } else {
#if HAVE_TLSv1_2_client_method
method = sycTLSv1_2_client_method();
#elif HAVE_TLSv1_1_client_method
method = sycTLSv1_1_client_method();
#elif HAVE_TLSv1_client_method
method = sycTLSv1_client_method();
#elif HAVE_SSLv3_client_method
method = sycSSLv3_client_method();
#elif HAVE_SSLv23_client_method
method = sycSSLv23_client_method(); method = sycSSLv23_client_method();
#elif HAVE_SSLv2_client_method
method = sycSSLv2_client_method();
#else
# error "OpenSSL does not seem to provide client methods"
#endif
} }
} else /* server */ { } else /* server */ {
if (me_str != 0) { if (me_str != NULL) {
if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) { if (false) {
; /* for canonical reasons */
#if HAVE_SSLv2_server_method #if HAVE_SSLv2_server_method
method = sycSSLv2_server_method(); } else if (!strcasecmp(me_str, "SSL2")) {
#else method = sycSSLv2_server_method();
Error1("OpenSSL method \"%s\" not provided by library", me_str); #endif
#if HAVE_SSLv3_server_method
} else if (!strcasecmp(me_str, "SSL3")) {
method = sycSSLv3_server_method();
#endif
#if HAVE_SSLv23_server_method
} else if (!strcasecmp(me_str, "SSL23")) {
method = sycSSLv23_server_method(); method = sycSSLv23_server_method();
#endif #endif
} else #if HAVE_TLSv1_server_method
if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) { } else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
method = sycSSLv3_server_method();
} else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
!strcasecmp(me_str, "SSL")) {
method = sycSSLv23_server_method();
} else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
!strcasecmp(me_str, "TLS")) {
method = sycTLSv1_server_method(); method = sycTLSv1_server_method();
#endif
#if HAVE_TLSv1_1_server_method
} else if (!strcasecmp(me_str, "TLS1.1")) {
method = sycTLSv1_1_server_method();
#endif
#if HAVE_TLSv1_2_server_method
} else if (!strcasecmp(me_str, "TLS1.2")) {
method = sycTLSv1_2_server_method();
#endif
#if HAVE_DTLSv1_server_method
} else if (!strcasecmp(me_str, "DTLS") || !strcasecmp(me_str, "DTLS1")) {
method = sycDTLSv1_server_method();
#endif
} else { } else {
Error1("openssl-method=\"%s\": unknown method", me_str); Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
method = sycSSLv23_server_method();
} }
} else { } else {
#if HAVE_TLSv1_2_server_method
method = sycTLSv1_2_server_method();
#elif HAVE_TLSv1_1_server_method
method = sycTLSv1_1_server_method();
#elif HAVE_TLSv1_server_method
method = sycTLSv1_1_method();
#elif HAVE_SSLv3_server_method
method = sycSSLv3_server_method();
#elif HAVE_SSLv23_server_method
method = sycSSLv23_server_method(); method = sycSSLv23_server_method();
#elif HAVE_SSLv2_server_method
method = sycSSLv2_server_method();
#else
# error "OpenSSL does not seem to provide client methods"
#endif
} }
} }
@ -1021,7 +1075,7 @@ int
} }
Error("BN_bin2bn() failed"); Error("BN_bin2bn() failed");
} else { } else {
if (SSL_CTX_set_tmp_dh(*ctx, dh) <= 0) { if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
while (err = ERR_get_error()) { while (err = ERR_get_error()) {
Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh, Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh,
ERR_error_string(err, NULL)); ERR_error_string(err, NULL));
@ -1095,8 +1149,12 @@ int
Info1("PEM_read_bio_DHparams(%p, NULL, NULL, NULL): error", bio); Info1("PEM_read_bio_DHparams(%p, NULL, NULL, NULL): error", bio);
} else { } else {
BIO_free(bio); BIO_free(bio);
if (sycSSL_CTX_set_tmp_dh(*ctx, dh) == 0) { if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
Error2("SSL_CTX_set_tmp_dh(%p, %p): error", ctx, dh); while (err = ERR_get_error()) {
Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh,
ERR_error_string(err, NULL));
}
Error2("SSL_CTX_set_tmp_dh(%p, %p): error", *ctx, dh);
} }
} }
} }