1
0
mirror of https://github.com/moparisthebest/socat synced 2024-12-21 14:38:48 -05:00

Added TLS methods support

This commit is contained in:
Gerhard Rieger 2015-01-23 18:38:06 +01:00
parent 899bc6845d
commit d430147bc6
8 changed files with 251 additions and 41 deletions

View File

@ -44,6 +44,9 @@ new features:
SOCAT_OPENSSL_X509V3_SUBJECTALTNAME_DNS
Tests: ENV_OPENSSL_{CLIENT,SERVER}_X509_*
Added support for methods TLSv1, TLSv1.1, TLSv1.2, and DTLS1
Tests: OPENSSL_METHOD_*
corrections:
Bind with ABSTRACT commands used non-abstract namespace (Linux).
Test: ABSTRACT_BIND
@ -67,6 +70,8 @@ corrections:
files that failed to compile due to missing IPPROTO_TCP.
Thanks to Thierry Fournier for report and patch.
fixed a few minor bugs with OpenSSL in configure and with messages
porting:
Socat included <sys/poll.h> instead of POSIX <poll.h>
Thanks to John Spencer for reporting this issue.

View File

@ -394,15 +394,37 @@
/* Define if you have the unsetenv function. not on HP-UX */
#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
/* Define if you have the SSLv2_server_method function. not in new openssl */
#undef HAVE_SSLv2_server_method
/* Define if you have the HAVE_SSL_CTX_set_default_verify_paths function */
#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 */
#undef HAVE_FLOCK

View File

@ -1334,11 +1334,24 @@ dnl Search for unsetenv()
AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV))
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]))
dnl
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_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

View File

@ -2635,11 +2635,14 @@ label(OPTION_OPENSSL_METHOD)dit(bf(tt(method=<ssl-method>)))
Sets the protocol version to be used. Valid strings (not case sensitive)
are:
startdit()
dit(tt(SSLv2)) Select SSL protocol version 2.
dit(tt(SSLv3)) Select SSL protocol version 3.
dit(tt(SSLv23)) Select SSL protocol version 2 or 3. This is the default when
dit(tt(SSL2)) Select SSL protocol version 2.
dit(tt(SSL3)) Select SSL protocol version 3.
dit(tt(SSL23)) Select the best available SSL or TLS protocol. This is the default when
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()
label(OPTION_OPENSSL_VERIFY)dit(bf(tt(verify=<bool>)))
Controls check of the peer's certificate. Default is 1 (true). Disabling

View File

@ -103,6 +103,62 @@ const SSL_METHOD *sycTLSv1_server_method(void) {
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 *result;
Debug1("SSL_CTX_new(%p)", method);

View File

@ -1,5 +1,5 @@
/* source: sslcls.h */
/* Copyright Gerhard Rieger 2001-2011 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sslcls_h_included
@ -18,6 +18,12 @@ const SSL_METHOD *sycSSLv23_client_method(void);
const SSL_METHOD *sycSSLv23_server_method(void);
const SSL_METHOD *sycTLSv1_client_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 *sycSSL_new(SSL_CTX *ctx);
int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,

50
test.sh
View File

@ -11455,7 +11455,7 @@ N=$((N+1))
# Linux) with "Invalid argument".
NAME=OPENSSL_CONNECT_BIND
case "$TESTS" in
*%$N%*|*%functions%*|*%openssl%*|*%bugs%*|*%socket%*|*%ssl%*|*%$NAME%*)
*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%openssl%*|*%$NAME%*)
TEST="$NAME: test OPENSSL-CONNECT with bind option"
# have a simple SSL server that just echoes data.
# connect with socat using OPENSSL-CONNECT with bind, send data and check if the
@ -12004,7 +12004,7 @@ unix-recvfrom . . unixport . -e FILE:/dev/null
"
# bug fix: SYSTEM address child process shutted down parents sockets including
# bug fix: SYSTEM address child process shut down parents sockets including
# SSL connection under some circumstances.
NAME=SYSTEM_SHUTDOWN
case "$TESTS" in
@ -12102,6 +12102,52 @@ esac
PORT=$((PORT+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
##################################################################################
#=================================================================================

View File

@ -715,7 +715,7 @@ int
SSL_CTX **ctx)
{
bool opt_fips = false;
const SSL_METHOD *method;
const SSL_METHOD *method = NULL;
char *me_str = NULL; /* method string */
char *ci_str = "HIGH:-NULL:-PSK:-aNULL"; /* cipher string */
char *opt_key = NULL; /* file name of client private key */
@ -771,54 +771,109 @@ int
/*! actions_to_seed_PRNG();*/
if (!server) {
if (me_str != 0) {
if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
if (me_str != NULL) {
if (false) {
; /* for canonical reasons */
#if HAVE_SSLv2_client_method
} else if (!strcasecmp(me_str, "SSL2")) {
method = sycSSLv2_client_method();
#else
Error1("OpenSSL method \"%s\" not provided by library", me_str);
method = sycSSLv23_server_method();
#endif
} else
if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
#if HAVE_SSLv3_client_method
} else if (!strcasecmp(me_str, "SSL3")) {
method = sycSSLv3_client_method();
} else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
!strcasecmp(me_str, "SSL")) {
#endif
#if HAVE_SSLv23_client_method
} else if (!strcasecmp(me_str, "SSL23")) {
method = sycSSLv23_client_method();
} else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
!strcasecmp(me_str, "TLS")) {
#endif
#if HAVE_TLSv1_client_method
} else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
method = sycTLSv1_client_method();
#endif
#if HAVE_TLSv1_1_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\": unknown method", me_str);
method = sycSSLv23_client_method();
Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
}
} 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();
#elif HAVE_SSLv2_client_method
method = sycSSLv2_client_method();
#else
# error "OpenSSL does not seem to provide client methods"
#endif
}
} else /* server */ {
if (me_str != 0) {
if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
if (false) {
; /* for canonical reasons */
#if HAVE_SSLv2_server_method
} else if (!strcasecmp(me_str, "SSL2")) {
method = sycSSLv2_server_method();
#else
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();
#endif
} else
if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
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")) {
#if HAVE_TLSv1_server_method
} else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
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 {
Error1("openssl-method=\"%s\": unknown method", me_str);
method = sycSSLv23_server_method();
Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
}
} 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();
#elif HAVE_SSLv2_server_method
method = sycSSLv2_server_method();
#else
# error "OpenSSL does not seem to provide client methods"
#endif
}
}
@ -887,7 +942,7 @@ int
}
Error("BN_bin2bn() failed");
} else {
if (SSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
while (err = ERR_get_error()) {
Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh,
ERR_error_string(err, NULL));
@ -961,8 +1016,12 @@ int
Info1("PEM_read_bio_DHparams(%p, NULL, NULL, NULL): error", bio);
} else {
BIO_free(bio);
if (sycSSL_CTX_set_tmp_dh(*ctx, dh) == 0) {
Error2("SSL_CTX_set_tmp_dh(%p, %p): error", ctx, dh);
if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
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);
}
}
}