From f076c92e44be05d17f3de1a9c5e77cc2ac1e4e45 Mon Sep 17 00:00:00 2001 From: Oleg Moskalenko Date: Sun, 14 Dec 2014 21:41:24 -0800 Subject: [PATCH] Imported Upstream version 4.3.2.1 --- ChangeLog | 8 ++ INSTALL | 87 +++++++++--- README.turnserver | 26 +++- STATUS | 4 + TODO | 8 +- configure | 48 ------- examples/etc/turnserver.conf | 9 +- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 23 ++- man/man1/turnutils.1 | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/common/apputils.c | 41 ++++-- src/apps/common/apputils.h | 67 ++++++++- src/apps/common/hiredis_libevent2.c | 2 +- src/apps/relay/dtls_listener.c | 82 +++++++++-- src/apps/relay/mainrelay.c | 189 +++++++++++++++++++------ src/apps/relay/mainrelay.h | 9 +- src/apps/relay/netengine.c | 54 ++++--- src/apps/relay/ns_ioalib_engine_impl.c | 63 +++++---- src/apps/relay/ns_ioalib_impl.h | 28 ++-- src/apps/uclient/mainuclient.c | 11 +- src/apps/uclient/startuclient.c | 13 +- src/ns_turn_defs.h | 4 +- 24 files changed, 553 insertions(+), 233 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0bd06874..b3ca86d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +12/13/2014 Oleg Moskalenko +Version 4.3.2.1 'Tolomei': + - Redis read message queue bug fixed; + - STUN/TURN ALPN supported (when compiled with OpenSSL 1.0.2+ ); + - DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ ); + - Auto optimal ECDH parameters (when compiled with OpenSSL 1.0.2+ ); + - TLS/DTLS code cleaning. + 11/29/2014 Oleg Moskalenko Version 4.3.1.3 'Tolomei': - Reliability fixes (Issue 141 from rfc5766-turn-server). diff --git a/INSTALL b/INSTALL index 5b9d0d08..6b6cdc23 100644 --- a/INSTALL +++ b/INSTALL @@ -150,7 +150,49 @@ NOTE: On most modern systems, the build will produce dynamically linked executables. If you want statically linked executables, you have to modify, accordingly, the Makefile.in template file. -IV. INSTALL +IV. OPENSSL + +If you are using the OpenSSL that is coming with your system, and you are +OK with it, then you do not have to read this chapter. If your system has +an outdated OpenSSL version, or if you need some very fresh OpenSSL features +that are not present in the current usual stable version, then you may have +to compile (and run) your TURN server with a different OpenSSL version. + +For example, if you need ALPN feature, or DTLS1.2, and your system comes with +OpenSSL 1.0.1, you will not be able to use those features unless you install +OpenSSL 1.0.2 and compile and run the TURN server with the newer version. + +The problem is, it is usually not safe to replace the system's OpenSSL with +a different version. Some systems are "bound" to its "native" OpenSSL +installations, and their behavior may become unpredictable with the newer +versions. + +So you want to preserve your system's OpenSSL but you want to compile and to +run the TURN server with newer OpenSSL version. There are different ways to +do that. We are suggesting the following: + + 1) Download the OpenSSL version from openssl.org. + 2) Let's assume that we want to install the "custom" OpenSSL into /opt. + Configure and build OpenSSL as: + $ ./config --prefix=/opt + $ make + $ make install + Those commands will install OpenSSL into /opt, with static libraries (no + dynamic libraries). + 3) Build the TURN server: + $ ./configure --prefix=/opt + $ make + Those commands will build the TURN server binaries, statically linked + against the newer OpenSSL. + 4) Then you can run the TURN server without setting the dynamic + libraries paths - because it has been linked statically against the newer + OpenSSL libraries. + +One potential problem is that libevent2 is using the OpenSSL, too. So, ideally, +to be 100% safe of all potential discrepancies in the runtime, we'd suggesting +rebuilding libevent2 with the newer OpenSSL, too. + +V. INSTALL This step is optional. You can run the turnserver from the original build directory, successfully, without installing the TURN server into your system. @@ -206,7 +248,7 @@ but if you have some libraries in different non-default directories then you will have to add them manually to the search path, or you will have to adjust LD_LIBRARY_PATH. -V. PLATFORMS +VI. PLATFORMS The TURN Server is using generic *NIX system APIs and is supposed to be usable on wide range of *NIX systems. @@ -244,7 +286,7 @@ The code is compatible with C++ compiler, and a C++ compiler $ CC=g++ ./configure $ make -VII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED +VIII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED In addition to common *NIX OS services and libraries, to compile this code, OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5 @@ -443,7 +485,7 @@ that will set the installation prefix to /usr (without "--prefix=/usr" by default it would be installed to /usr/local). This is necessary if you want to overwrite your existing older OpenSSL installation. -VIII. BUILDING WITH NON-DEFAULT PREFIX DIRECTORY +IX. BUILDING WITH NON-DEFAULT PREFIX DIRECTORY Say, you have an older system with old openssl and old libevent library and you do not want to change that, but you still want @@ -482,7 +524,7 @@ by using $ ldconfig -m (BSD) $ crle -u -l (Solaris) -IX. TEST SCRIPTS +X. TEST SCRIPTS First of all, you can use the test vectors from RFC 5769 to double-check that the STUN/TURN message encoding algorithms work properly. Run the utility: @@ -564,15 +606,16 @@ and the peer. Check the README.* files and the comments in the scripts relay.sh and secure_relay.sh as a guidance how to run the TURN server. -X. OS X compilation notes +XI. OS X compilation notes OS X usually has an older version of openssl supplied, with some Apple additions. The the "native" openssl will work, within its limitations, but the best option is to install a good fresh openssl development library, from http://www.openssl.org. You will have -to handle the dynamic linking of the generated binaries. +to handle the dynamic linking of the generated binaries, or use the +static linking (see the section OPENSSL). -XI. MS Windows and Cygwin support +XII. MS Windows and Cygwin support Currently, this project cannot be compiled under MS Windows. @@ -585,7 +628,7 @@ libevent2 runtime and libevent-devel packages. "Manual" libevent2 compilation and installation in Cygwin is not recommended and does not garantee a good outcome. -XII. CLIENT API LIBRARY. +XIII. CLIENT API LIBRARY. The compilation process will create lib/ sub-directory with libturnclient.a library. The header files for this library are located in include/turn/client/ @@ -594,7 +637,7 @@ TurnMsgLib.h header. An example of C++ code can be found in stunclient.c file. This file is compiled as a C++ program if C++ compiler is used, and as a C program if C compiler is used. -XIII. DOCS +XIV. DOCS After installation, the man page turnserver(1) must be available. The man page is located in man/man1 subdirectory. If you want to see the man page without @@ -606,7 +649,7 @@ HTML-formatted client library functions reference is located in docs/html subdirectory of the original archive tree. After the installation, it will be placed in PREFIX/share/doc/turnserver/html. -XIV. SQLite setup +XV. SQLite setup The site http://www.sqlite.org site has excellent extensive documentation. @@ -778,7 +821,7 @@ Fill in users, for example: $ bin/turnadmin -A -b "/var/db/turndb" -u gorst -p hero $ bin/turnadmin -A -b "/var/db/turndb" -u ninefingers -p youhavetoberealistic -XV. PostgreSQL setup +XVI. PostgreSQL setup The site http://www.postgresql.org site has excellent extensive documentation. For a quick-start guide, you can take a look into this page: @@ -902,7 +945,7 @@ Fill in users, for example: $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -p hero $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -p youhavetoberealistic -XVI. MySQL (MariaDB) setup +XVII. MySQL (MariaDB) setup The MySQL setup is similar to PostgreSQL (same idea), and is well documented on their site http://www.mysql.org. The TURN Server database schema is the @@ -985,7 +1028,7 @@ ca, capath, cert, key, cipher (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the command options description). -XVII. MongoDB setup +XVIII. MongoDB setup The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/. @@ -1017,7 +1060,7 @@ explanations for the Postgres, for example. See the file testmongosetup.sh for the database structure examples. -XVIII. Redis setup +XIX. Redis setup The Redis setup is well documented on their site http://redis.io. The TURN Server Redis database schema description can be found @@ -1088,20 +1131,20 @@ Redis TURN admin commands: See the file testredisdbsetup.sh for the data structure examples. -XIX. Performance tuning +XX. Performance tuning This topic is covered in the wiki page: http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance -XX. TURN Server setup +XXI. TURN Server setup Read the project wiki pages: http://code.google.com/p/coturn/w/list Also, check the project from page links to the TURN/WebRTC configuration examples. It may give you an idea how it can be done. -XXI. Management interface +XXII. Management interface You have a telnet interface (enabled by default) to access the turnserver process, to view its state, to gather some statistical information, and to make some changes @@ -1117,3 +1160,11 @@ or ::1). The CLI may have a password configured, but that password is transferred over the network unencrypted, too. So sticking to the local system CLI access, and accessing the turnserver system terminal with ssh only, would be a wise decision. + +XXIII. ALPN support. + +Starting with version 4.3.2.1, the TURN server supports the ALPN STUN +specifications (http://tools.ietf.org/html/draft-ietf-tram-alpn-08). +If the ALPN functionality is needed, then OpenSSL version 1.0.2 or +newer has to be used. See OPENSSL section for the OpenSSL upgrade hints. + \ No newline at end of file diff --git a/README.turnserver b/README.turnserver index 31c2b5de..79de0d56 100644 --- a/README.turnserver +++ b/README.turnserver @@ -195,11 +195,11 @@ Flags: --no-sslv3 Do not allow SSLv3 protocol. ---no-tlsv1 Do not allow TLSv1 protocol. +--no-tlsv1 Do not allow TLSv1/DTLSv1 protocol. --no-tlsv1_1 Do not allow TLSv1.1 protocol. ---no-tlsv1_2 Do not allow TLSv1.2 protocol. +--no-tlsv1_2 Do not allow TLSv1.2/DTLSv1.2 protocol. --no-udp Do not start UDP client listeners. @@ -444,8 +444,11 @@ Options with required values: Forces TURN server to verify the client SSL certificates. By default, no CA is set and no client certificate check is performed. ---ec-curve-name Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). - The default value is prime256v1. +--ec-curve-name Curve name for EC ciphers, if supported by OpenSSL + library (TLS and DTLS). The default value is prime256v1, + if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+, + an optimal curve will be automatically calculated, if not defined + by this option. --dh-file Use custom DH TLS key, stored in PEM format in the file. Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file. @@ -775,7 +778,18 @@ it will set the users for you (see the turnadmin manuals). If you are using SQLi turnserver or turnadmin will initialize the empty database, for you, when started. The TURN server installation process creates an empty initialized SQLite database in the default location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system). - + +================================= + +ALPN + +The server supports ALPNs "stun.turn" and "stun.nat-discovery", when +compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS +ClientHello message that contains one or both of those ALPNs, then the +server chooses the first stun.* label and sends it back (in the ServerHello) +in the ALPN extention field. If no stun.* label is found, then the server +does not include the ALPN information into the ServerHello. + ================================= LIBRARIES @@ -786,7 +800,7 @@ The C++ wrapper for the messaging functionality is located in TurnMsgLib.h heade An example of C++ code can be found in stunclient.c file. ================================= - + DOCS After installation, run the command: diff --git a/STATUS b/STATUS index d908316a..d137195a 100644 --- a/STATUS +++ b/STATUS @@ -108,6 +108,10 @@ compatibility. 46) Third-party security mechanism (through oAuth) implemented. 47) SQLite support added as default database. + +48) DTLS1.2 supported. + +49) ALPN stun.turn and stun.nat-discovery supported. Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/TODO b/TODO index 92375d2a..49ef28c2 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,7 @@ ================================================================== -Nope +1) EC curve new features in OpenSSL 1.0.2 ================================================================== @@ -57,11 +57,7 @@ Nope 1) For extra difficult NAT/FWs, consider implementing Websockets. -2) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). - -3) Redirect draft. - -4) DTLS 1.2 (when available). +2) Redirect draft. ================================================================== diff --git a/configure b/configure index 23d95c5a..4cd9b101 100755 --- a/configure +++ b/configure @@ -7,8 +7,6 @@ cleanup() { rm -rf ${TMPCPROGB} rm -rf ${TH_TMPCPROGC} rm -rf ${TH_TMPCPROGB} - rm -rf ${DTLS_TMPCPROGC} - rm -rf ${DTLS_TMPCPROGB} rm -rf ${GCM_TMPCPROGC} rm -rf ${GCM_TMPCPROGB} rm -rf ${PQ_TMPCPROGC} @@ -239,21 +237,6 @@ pthread_testbarriers() { fi } -dtls_testlib() { - - if [ -z "${TURN_NO_DTLS}" ] ; then - ${CC} ${DTLS_TMPCPROGC} -o ${DTLS_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null - ER=$? - if [ ${ER} -eq 0 ] ; then - return 1 - else - return 0 - fi - else - return 0 - fi -} - gcm_testlib() { if [ -z "${TURN_NO_GCM}" ] ; then @@ -686,19 +669,6 @@ int main(int argc, char** argv) { ! -DTLS_TMPCPROG=__test__ccomp__dtls__$$ -DTLS_TMPCPROGC=${TMPDIR}/${DTLS_TMPCPROG}.c -DTLS_TMPCPROGB=${TMPDIR}/${DTLS_TMPCPROG} - -cat > ${DTLS_TMPCPROGC} < -#include -#include -int main(int argc, char** argv) { - return (((int)(BIO_CTRL_DGRAM_QUERY_MTU)) + argc + (int)(argv[argc][0]) + DTLSv1_listen(NULL,NULL)); -} -! - GCM_TMPCPROG=__test__ccomp__gcm__$$ GCM_TMPCPROGC=${TMPDIR}/${GCM_TMPCPROG}.c GCM_TMPCPROGB=${TMPDIR}/${GCM_TMPCPROG} @@ -961,24 +931,6 @@ else exit fi -########################### -# Can we use DTLS ? -########################### - -if [ -z ${TURN_NO_DTLS} ] ; then - -dtls_testlib -ER=$? -if [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "WARNING: Cannot find DTLS support." - ${ECHO_CMD} "Turning DTLS off." - TURN_NO_DTLS="-DTURN_NO_DTLS" -fi - -else - TURN_NO_DTLS="-DTURN_NO_DTLS" -fi - ########################### # Can we use GCM cipher ? ########################### diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 5d35de87..6e3c2f95 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -418,8 +418,11 @@ # Example: #CA-file=/etc/ssh/id_rsa.cert -# Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). -# The default value is prime256v1. +# Curve name for EC ciphers, if supported by OpenSSL +# library (TLS and DTLS). The default value is prime256v1, +# if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+, +# an optimal curve will be automatically calculated, if not defined +# by this option. # #ec-curve-name=prime256v1 @@ -620,7 +623,7 @@ # #ne=[1|2|3] -# Do not allow an SSL/TLS version of protocol +# Do not allow an SSL/TLS/DTLS version of protocol # #no-sslv2 #no-sslv3 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index d460331c..36e92cfb 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 December 2014" "" "" +.TH TURN 1 "13 December 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index b12d631a..e60e14d8 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 December 2014" "" "" +.TH TURN 1 "13 December 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -291,7 +291,7 @@ Do not allow SSLv3 protocol. .TP .B \fB\-\-no\-tlsv1\fP -Do not allow TLSv1 protocol. +Do not allow TLSv1/DTLSv1 protocol. .TP .B \fB\-\-no\-tlsv1_1\fP @@ -299,7 +299,7 @@ Do not allow TLSv1.1 protocol. .TP .B \fB\-\-no\-tlsv1_2\fP -Do not allow TLSv1.2 protocol. +Do not allow TLSv1.2/DTLSv1.2 protocol. .TP .B \fB\-\-no\-udp\fP @@ -649,8 +649,11 @@ By default, no CA is set and no client certificate check is performed. .TP .B \fB\-\-ec\-curve\-name\fP -Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). -The default value is prime256v1. +Curve name for EC ciphers, if supported by OpenSSL +library (TLS and DTLS). The default value is prime256v1, +if pre\-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+, +an optimal curve will be automatically calculated, if not defined +by this option. .TP .B \fB\-\-dh\-file\fP @@ -1032,6 +1035,16 @@ TURN server installation process creates an empty initialized SQLite database in location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system). .PP ================================= +.SH ALPN + +The server supports ALPNs "stun.turn" and "stun.nat\-discovery", when +compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS +ClientHello message that contains one or both of those ALPNs, then the +server chooses the first stun.* label and sends it back (in the ServerHello) +in the ALPN extention field. If no stun.* label is found, then the server +does not include the ALPN information into the ServerHello. +.PP +================================= .SH LIBRARIES In the lib/ sub\-directory the build process will create TURN client messaging library. diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index ecd87d77..b75d33d3 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 December 2014" "" "" +.TH TURN 1 "13 December 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index e4c19573..67acef40 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.1.3 +TURNVERSION=4.3.2.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 6b76d9e6..462bad42 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.1.3 +Version: 4.3.2.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sat Dec 13 2014 Oleg Moskalenko + - Sync to 4.3.2.1 * Sat Nov 29 2014 Oleg Moskalenko - Sync to 4.3.1.3 * Mon Nov 23 2014 Oleg Moskalenko diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index e76e3910..6d89d926 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -349,7 +349,7 @@ int set_socket_df(evutil_socket_t fd, int family, int value) static int get_mtu_from_ssl(SSL* ssl) { int ret = SOSO_MTU; -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED if(ssl) ret = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); #else @@ -395,7 +395,7 @@ int decrease_mtu(SSL* ssl, int mtu, int verbose) if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "1. mtu to use: %d\n", mtu); -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED SSL_set_mtu(ssl,mtu); BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, mtu, NULL); #endif @@ -416,7 +416,7 @@ int set_mtu_df(SSL* ssl, evutil_socket_t fd, int family, int mtu, int df_value, set_query_mtu(ssl); if(verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"3. mtu to use: %d\n",mtu); -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED SSL_set_mtu(ssl,mtu); @@ -847,23 +847,31 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul return "TLSv1.0"; } else if(method == TLSv1_client_method()) { return "TLSv1.0"; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED } else if(method == TLSv1_1_server_method()) { return "TLSv1.1"; } else if(method == TLSv1_1_client_method()) { return "TLSv1.1"; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED } else if(method == TLSv1_2_server_method()) { return "TLSv1.2"; } else if(method == TLSv1_2_client_method()) { return "TLSv1.2"; #endif #endif -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED + } else if(method == DTLSv1_server_method()) { - return "DTLSv1.0"; + return "DTLSv1.0"; } else if(method == DTLSv1_client_method()) { return "DTLSv1.0"; + +#if DTLSv1_2_SUPPORTED + } else if(method == DTLSv1_2_server_method()) { + return "DTLSv1.2"; + } else if(method == DTLSv1_2_client_method()) { + return "DTLSv1.2"; +#endif #endif } else { if(mdefault) @@ -872,20 +880,23 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul } } } - } const char* turn_get_ssl_method(SSL *ssl, const char* mdefault) { - if(!ssl) - return mdefault; - else { + const char* ret = "unknown"; + if(!ssl) { + ret = mdefault; + } else { const SSL_METHOD *method = SSL_get_ssl_method(ssl); - if(!method) - return mdefault; - else - return turn_get_method(method, mdefault); + if(!method) { + ret = mdefault; + } else { + ret = turn_get_method(method, mdefault); + } } + + return ret; } //////////// EVENT BASE /////////////// diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index 0868d6e9..adb38b69 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -53,15 +53,78 @@ extern "C" { extern int IS_TURN_SERVER; +/* ALPN */ + +#define OPENSSL_FIRST_ALPN_VERSION (0x10002003L) + +#define STUN_ALPN "stun.nat-discovery" +#define TURN_ALPN "stun.turn" +#define HTTP_ALPN "http/1.1" + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#define ALPN_SUPPORTED 1 +#else +#define ALPN_SUPPORTED 0 +#endif + +/* TLS */ + +#if defined(TURN_NO_TLS) + + #define TLS_SUPPORTED 0 + #define TLSv1_1_SUPPORTED 0 + #define TLSv1_2_SUPPORTED 0 + +#else + + #define TLS_SUPPORTED 1 + + #if defined(SSL_OP_NO_TLSv1_1) + #define TLSv1_1_SUPPORTED 1 + #else + #define TLSv1_1_SUPPORTED 0 + #endif + + #if defined(SSL_OP_NO_TLSv1_2) + #define TLSv1_2_SUPPORTED 1 + #else + #define TLSv1_2_SUPPORTED 0 + #endif + +#endif + +#if defined(TURN_NO_DTLS) || !defined(DTLS_CTRL_LISTEN) + + #define DTLS_SUPPORTED 0 + #define DTLSv1_2_SUPPORTED 0 + +#else + + #define DTLS_SUPPORTED 1 + +#if defined(SSL_OP_NO_DTLSv1_2) + #define DTLSv1_2_SUPPORTED 1 + #else + #define DTLSv1_2_SUPPORTED 0 + #endif + +#endif + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#define SSL_SESSION_ECDH_AUTO_SUPPORTED 1 +#else +#define SSL_SESSION_ECDH_AUTO_SUPPORTED 0 +#endif + /////////// SSL ////////////////////////// enum _TURN_TLS_TYPE { TURN_TLS_NO=0, TURN_TLS_SSL23, TURN_TLS_v1_0, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED TURN_TLS_v1_1, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED TURN_TLS_v1_2, #endif #endif diff --git a/src/apps/common/hiredis_libevent2.c b/src/apps/common/hiredis_libevent2.c index 24ca2fa0..c27fba35 100644 --- a/src/apps/common/hiredis_libevent2.c +++ b/src/apps/common/hiredis_libevent2.c @@ -267,7 +267,7 @@ redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int /* Initialize and install read/write events */ e->rev = event_new(e->base,e->context->c.fd, - EV_READ,redisLibeventReadEvent, + EV_READ|EV_PERSIST,redisLibeventReadEvent, e); e->wev = event_new(e->base,e->context->c.fd, diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index f6847ec3..f4428411 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -58,7 +58,12 @@ struct dtls_listener_relay_server_info { ioa_engine_handle e; turn_turnserver *ts; int verbose; +#if DTLS_SUPPORTED SSL_CTX *dtls_ctx; +#if DTLSv1_2_SUPPORTED + SSL_CTX *dtls_ctx_v1_2; +#endif +#endif struct event *udp_listen_ev; ioa_socket_handle udp_listen_s; ur_addr_map *children_ss; /* map of socket children on remote addr */ @@ -79,27 +84,28 @@ int is_dtls_handshake_message(const unsigned char* buf, int len); int is_dtls_data_message(const unsigned char* buf, int len); int is_dtls_alert_message(const unsigned char* buf, int len); int is_dtls_cipher_change_message(const unsigned char* buf, int len); +int get_dtls_version(const unsigned char* buf, int len); int is_dtls_message(const unsigned char* buf, int len); int is_dtls_handshake_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x16 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x16 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_data_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x17 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x17 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_alert_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x15 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x15 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_cipher_change_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x14 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x14 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_message(const unsigned char* buf, int len) { - if(buf && (len>3) && (buf[1])==0xfe && (buf[2]==0xff)) { + if(buf && (len>3) && (buf[1])==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))) { switch (buf[0]) { case 0x14: case 0x15: @@ -113,9 +119,16 @@ int is_dtls_message(const unsigned char* buf, int len) { return 0; } +/* 0 - 1.0, 1 - 1.2 */ +int get_dtls_version(const unsigned char* buf, int len) { + if(buf && (len>3) && (buf[2] == 0xfd)) + return 1; + return 0; +} + ///////////// utils ///////////////////// -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED static void calculate_cookie(SSL* ssl, unsigned char *cookie_secret, unsigned int cookie_length) { long rv=(long)ssl; @@ -266,7 +279,18 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); - connecting_ssl = SSL_NEW(server->dtls_ctx); +#if DTLSv1_2_SUPPORTED + if(get_dtls_version(ioa_network_buffer_data(nbh), + (int)ioa_network_buffer_get_size(nbh)) == 1) { + connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); + } else { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#else + { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#endif SSL_set_accept_state(connecting_ssl); @@ -404,7 +428,7 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, chs = NULL; -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message(ioa_network_buffer_data(sm->m.sm.nd.nbh), (int)ioa_network_buffer_get_size(sm->m.sm.nd.nbh))) { @@ -513,7 +537,7 @@ static int create_new_connected_udp_socket( ret->current_tos = s->current_tos; ret->default_tos = s->default_tos; -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message( ioa_network_buffer_data(server->sm.m.sm.nd.nbh), @@ -536,7 +560,18 @@ static int create_new_connected_udp_socket( timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); - connecting_ssl = SSL_NEW(server->dtls_ctx); +#if DTLSv1_2_SUPPORTED + if(get_dtls_version(ioa_network_buffer_data(server->sm.m.sm.nd.nbh), + (int)ioa_network_buffer_get_size(server->sm.m.sm.nd.nbh)) == 1) { + connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); + } else { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#else + { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#endif SSL_set_accept_state(connecting_ssl); @@ -566,7 +601,6 @@ static int create_new_connected_udp_socket( server->sm.m.sm.nd.nbh = NULL; ret->st = DTLS_SOCKET; - STRCPY(ret->orig_ctx_type,"DTLSv1.0"); } #endif @@ -864,7 +898,14 @@ static int init_server(dtls_listener_relay_server_type* server, if(!server) return -1; +#if DTLS_SUPPORTED server->dtls_ctx = e->dtls_ctx; + +#if DTLSv1_2_SUPPORTED + server->dtls_ctx_v1_2 = e->dtls_ctx_v1_2; +#endif +#endif + server->ts = ts; server->connect_cb = send_socket; @@ -881,6 +922,7 @@ static int init_server(dtls_listener_relay_server_type* server, server->e = e; +#if DTLS_SUPPORTED if(server->dtls_ctx) { #if defined(REQUEST_CLIENT_CERT) @@ -890,12 +932,26 @@ static int init_server(dtls_listener_relay_server_type* server, SSL_CTX_set_read_ahead(server->dtls_ctx, 1); -#if !defined(TURN_NO_DTLS) SSL_CTX_set_cookie_generate_cb(server->dtls_ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx, verify_cookie); -#endif } +#if DTLSv1_2_SUPPORTED + if(server->dtls_ctx_v1_2) { + + #if defined(REQUEST_CLIENT_CERT) + /* If client has to authenticate, then */ + SSL_CTX_set_verify(server->dtls_ctx_v1_2, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback); + #endif + + SSL_CTX_set_read_ahead(server->dtls_ctx_v1_2, 1); + + SSL_CTX_set_cookie_generate_cb(server->dtls_ctx_v1_2, generate_cookie); + SSL_CTX_set_cookie_verify_cb(server->dtls_ctx_v1_2, verify_cookie); + } +#endif +#endif + return create_server_socket(server, report_creation); } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 5abf1bd8..61768132 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -65,28 +65,30 @@ static int anon_credentials = 0; #define DEFAULT_GENERAL_RELAY_SERVERS_NUMBER (1) turn_params_t turn_params = { - NULL, NULL, - -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED NULL, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED NULL, #endif #endif - +#if DTLS_SUPPORTED +NULL, +#endif +#if DTLSv1_2_SUPPORTED NULL, +#endif -DH_1066, "", DEFAULT_EC_CURVE_NAME, "", +DH_1066, "", "", "", "turn_server_cert.pem","turn_server_pkey.pem", "", "", 0,0,0,0,0, -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED 1, #else 0, #endif -#if defined(TURN_NO_DTLS) +#if !DTLS_SUPPORTED 1, #else 0, @@ -507,17 +509,20 @@ static char Usage[] = "Usage: turnserver [options]\n" " --CA-file CA file in OpenSSL format.\n" " Forces TURN server to verify the client SSL certificates.\n" " By default, no CA is set and no client certificate check is performed.\n" -" --ec-curve-name Curve name for EC ciphers, if supported by OpenSSL library\n" -" (TLS and DTLS). The default value is prime256v1.\n" +" --ec-curve-name Curve name for EC ciphers, if supported by OpenSSL\n" +" library (TLS and DTLS). The default value is prime256v1,\n" +" if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+,\n" +" an optimal curve will be automatically calculated, if not defined\n" +" by this option.\n" " --dh566 Use 566 bits predefined DH TLS key. Default size of the predefined key is 1066.\n" " --dh2066 Use 2066 bits predefined DH TLS key. Default size of the predefined key is 1066.\n" " --dh-file Use custom DH TLS key, stored in PEM format in the file.\n" " Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file.\n" " --no-sslv2 Do not allow SSLv2 protocol.\n" " --no-sslv3 Do not allow SSLv3 protocol.\n" -" --no-tlsv1 Do not allow TLSv1 protocol.\n" +" --no-tlsv1 Do not allow TLSv1/DTLSv1 protocol.\n" " --no-tlsv1_1 Do not allow TLSv1.1 protocol.\n" -" --no-tlsv1_2 Do not allow TLSv1.2 protocol.\n" +" --no-tlsv1_2 Do not allow TLSv1.2/DTLSv1.2 protocol.\n" " --no-udp Do not start UDP client listeners.\n" " --no-tcp Do not start TCP client listeners.\n" " --no-tls Do not start TLS client listeners.\n" @@ -1219,14 +1224,14 @@ static void set_option(int c, char *value) turn_params.no_tcp_relay = get_bool_value(value); break; case NO_TLS_OPT: -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED turn_params.no_tls = 1; #else turn_params.no_tls = get_bool_value(value); #endif break; case NO_DTLS_OPT: -#if !defined(TURN_NO_DTLS) +#if DTLS_SUPPORTED turn_params.no_dtls = get_bool_value(value); #else turn_params.no_dtls = 1; @@ -1610,13 +1615,13 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n\n==== Show him the instruments, Practical Frost: ====\n\n"); -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS is not supported\n"); #else TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS supported\n"); #endif -#if defined(TURN_NO_DTLS) +#if !DTLS_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS is not supported\n"); #else TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS supported\n"); @@ -1658,17 +1663,7 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MongoDB is not supported\n"); #endif -#if defined(OPENSSL_THREADS) - //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL multithreading supported\n"); -#else - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "OpenSSL multithreading is not supported (?!)\n"); -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version 0x%llx: fresh enough\n",(unsigned long long)OPENSSL_VERSION_NUMBER); -#else - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version 0x%llx version: antique\n",(unsigned long long)OPENSSL_VERSION_NUMBER); -#endif + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version: %s\n",OPENSSL_VERSION_TEXT); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default Net Engine version: %d (%s)\n\n=====================================================\n\n", (int)turn_params.net_engine_version, turn_params.net_engine_version_txt[(int)turn_params.net_engine_version]); @@ -1796,11 +1791,11 @@ int main(int argc, char **argv) optind = 0; -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED turn_params.no_tls = 1; #endif -#if defined(TURN_NO_DTLS) +#if !DTLS_SUPPORTED turn_params.no_dtls = 1; #endif @@ -2339,8 +2334,59 @@ static int pem_password_func(char *buf, int size, int rwflag, void *password) return (strlen(buf)); } +#if ALPN_SUPPORTED + +static int ServerALPNCallback(SSL *s, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg) { + + UNUSED_ARG(s); + UNUSED_ARG(arg); + + unsigned char sa_len = (unsigned char)strlen(STUN_ALPN); + unsigned char ta_len = (unsigned char)strlen(TURN_ALPN); + unsigned char ha_len = (unsigned char)strlen(HTTP_ALPN); + + int found_http = 0; + + const unsigned char *ptr = in; + while(ptr < (in+inlen)) { + unsigned char current_len = *ptr; + if(ptr+1+current_len > in+inlen) + break; + if((!turn_params.no_stun) && (current_len == sa_len) && (memcmp(ptr+1,STUN_ALPN,sa_len)==0)) { + *out = ptr+1; + *outlen = sa_len; + return SSL_TLSEXT_ERR_OK; + } + if((!turn_params.stun_only) && (current_len == ta_len) && (memcmp(ptr+1,TURN_ALPN,ta_len)==0)) { + *out = ptr+1; + *outlen = ta_len; + return SSL_TLSEXT_ERR_OK; + } + if((current_len == ha_len) && (memcmp(ptr+1,HTTP_ALPN,ha_len)==0)) { + found_http = 1; + } + ptr += 1 + current_len; + } + + if(found_http) + return SSL_TLSEXT_ERR_NOACK; + + return SSL_TLSEXT_ERR_NOACK; //??? +} + +#endif + static void set_ctx(SSL_CTX* ctx, const char *protocol) { +#if ALPN_SUPPORTED + SSL_CTX_set_alpn_select_cb(ctx, ServerALPNCallback, NULL); +#endif + SSL_CTX_set_default_passwd_cb_userdata(ctx, turn_params.tls_password); SSL_CTX_set_default_passwd_cb(ctx, pem_password_func); @@ -2391,23 +2437,47 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) #if !defined(OPENSSL_NO_EC) && defined(OPENSSL_EC_NAMED_CURVE) { //Elliptic curve algorithms: - int nid = NID_X9_62_prime256v1; + int nid = 0; + int set_auto_curve = 0; - if (turn_params.ec_curve_name[0]) { - nid = OBJ_sn2nid(turn_params.ec_curve_name); - if (nid == 0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"unknown curve name (%s), using NID_X9_62_prime256v1\n",turn_params.ec_curve_name); - nid = NID_X9_62_prime256v1; - } + const char* curve_name = turn_params.ec_curve_name; + + if (!(curve_name[0])) { +#if !SSL_SESSION_ECDH_AUTO_SUPPORTED + curve_name = DEFAULT_EC_CURVE_NAME; +#endif + set_auto_curve = 1; } - EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); - if (!ecdh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + if(curve_name[0]) { + { + nid = OBJ_sn2nid(curve_name); + if (nid == 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"unknown curve name: %s\n",curve_name); + curve_name = DEFAULT_EC_CURVE_NAME; + nid = OBJ_sn2nid(curve_name); + set_auto_curve = 1; + } + } + + { + EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: allocate EC suite\n",__FUNCTION__); - } else { - SSL_CTX_set_tmp_ecdh(ctx, ecdh); - EC_KEY_free(ecdh); + set_auto_curve = 1; + } else { + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + } + } + } + + if(set_auto_curve) { +#if SSL_SESSION_ECDH_AUTO_SUPPORTED + SSL_CTX_set_ecdh_auto(ctx,1); +#endif + set_auto_curve = 0; } } #endif @@ -2437,6 +2507,14 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) dh = get_dh1066(); } + /* + if(!dh) { + dh = DH_new(); + DH_generate_parameters_ex(dh, 32, DH_GENERATOR_2, 0); + DH_generate_key(dh); + } + */ + if(!dh) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__); } else { @@ -2464,11 +2542,22 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if(turn_params.no_tlsv1_1) op |= SSL_OP_NO_TLSv1_1; #endif + #if defined(SSL_OP_NO_TLSv1_2) if(turn_params.no_tlsv1_2) op |= SSL_OP_NO_TLSv1_2; #endif +#if defined(SSL_OP_NO_DTLSv1) && DTLS_SUPPORTED + if(turn_params.no_tlsv1) + op |= SSL_OP_NO_DTLSv1; +#endif + +#if defined(SSL_OP_NO_DTLSv1_2) && DTLSv1_2_SUPPORTED + if(turn_params.no_tlsv1_2) + op |= SSL_OP_NO_DTLSv1_2; +#endif + #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) op |= SSL_OP_CIPHER_SERVER_PREFERENCE; #endif @@ -2491,7 +2580,7 @@ static void openssl_setup(void) SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED if(!turn_params.no_tls) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "WARNING: TLS is not supported\n"); turn_params.no_tls = 1; @@ -2521,12 +2610,12 @@ static void openssl_setup(void) turn_params.tls_ctx_v1_0 = SSL_CTX_new(TLSv1_server_method()); set_ctx(turn_params.tls_ctx_v1_0,"TLS1.0"); } -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED if(!turn_params.no_tlsv1_1) { turn_params.tls_ctx_v1_1 = SSL_CTX_new(TLSv1_1_server_method()); set_ctx(turn_params.tls_ctx_v1_1,"TLS1.1"); } -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED if(!turn_params.no_tlsv1_2) { turn_params.tls_ctx_v1_2 = SSL_CTX_new(TLSv1_2_server_method()); set_ctx(turn_params.tls_ctx_v1_2,"TLS1.2"); @@ -2537,7 +2626,7 @@ static void openssl_setup(void) } if(!turn_params.no_dtls) { -#if defined(TURN_NO_DTLS) +#if !DTLS_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: DTLS is not supported.\n"); #else if(OPENSSL_VERSION_NUMBER < 0x10000000L) { @@ -2546,7 +2635,15 @@ static void openssl_setup(void) turn_params.dtls_ctx = SSL_CTX_new(DTLSv1_server_method()); set_ctx(turn_params.dtls_ctx,"DTLS"); SSL_CTX_set_read_ahead(turn_params.dtls_ctx, 1); + +#if DTLSv1_2_SUPPORTED + turn_params.dtls_ctx_v1_2 = SSL_CTX_new(DTLSv1_2_server_method()); + set_ctx(turn_params.dtls_ctx_v1_2,"DTLS1,2"); + SSL_CTX_set_read_ahead(turn_params.dtls_ctx_v1_2, 1); +#endif + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS cipher suite: %s\n",turn_params.cipher_list); + #endif } } diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 0b684c95..b1e7ea42 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -180,14 +180,19 @@ typedef struct _turn_params_ { SSL_CTX *tls_ctx_v1_0; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED SSL_CTX *tls_ctx_v1_1; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED SSL_CTX *tls_ctx_v1_2; #endif #endif +#if DTLS_SUPPORTED SSL_CTX *dtls_ctx; +#if DTLSv1_2_SUPPORTED + SSL_CTX *dtls_ctx_v1_2; +#endif +#endif DH_KEY_SIZE dh_key_size; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 86ae4471..081cd77b 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -940,14 +940,20 @@ static ioa_engine_handle create_new_listener_engine(void) ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) - turn_params.tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) - turn_params.tls_ctx_v1_2, + set_ssl_ctx(e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 +#if TLSv1_1_SUPPORTED + ,turn_params.tls_ctx_v1_1 +#if TLSv1_2_SUPPORTED + ,turn_params.tls_ctx_v1_2 #endif #endif - turn_params.dtls_ctx); +#if DTLS_SUPPORTED + ,turn_params.dtls_ctx +#endif +#if DTLSv1_2_SUPPORTED + ,turn_params.dtls_ctx_v1_2 +#endif + ); ioa_engine_set_rtcp_map(e, turn_params.listener.rtcpmap); return e; } @@ -990,14 +996,20 @@ static void setup_listener(void) if(!turn_params.listener.ioa_eng) exit(-1); - set_ssl_ctx(turn_params.listener.ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) - turn_params.tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) - turn_params.tls_ctx_v1_2, + set_ssl_ctx(turn_params.listener.ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 +#if TLSv1_1_SUPPORTED + ,turn_params.tls_ctx_v1_1 +#if TLSv1_2_SUPPORTED + ,turn_params.tls_ctx_v1_2 +#endif +#endif +#if DTLS_SUPPORTED + ,turn_params.dtls_ctx #endif +#if DTLSv1_2_SUPPORTED + ,turn_params.dtls_ctx_v1_2 #endif - turn_params.dtls_ctx); + ); turn_params.listener.rtcpmap = rtcp_map_create(turn_params.listener.ioa_eng); @@ -1558,14 +1570,20 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) - turn_params.tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) - turn_params.tls_ctx_v1_2, + set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 +#if TLSv1_1_SUPPORTED + ,turn_params.tls_ctx_v1_1 +#if TLSv1_2_SUPPORTED + ,turn_params.tls_ctx_v1_2 +#endif #endif +#if DTLS_SUPPORTED + ,turn_params.dtls_ctx #endif - turn_params.dtls_ctx); +#if DTLSv1_2_SUPPORTED + ,turn_params.dtls_ctx_v1_2 +#endif + ); ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 8990a000..f8c71bcc 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -38,7 +38,7 @@ #include "ns_ioalib_impl.h" -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED #include #endif @@ -433,24 +433,35 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) - SSL_CTX *tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) - SSL_CTX *tls_ctx_v1_2, + SSL_CTX *tls_ctx_v1_0 +#if TLSv1_1_SUPPORTED + ,SSL_CTX *tls_ctx_v1_1 +#if TLSv1_2_SUPPORTED + ,SSL_CTX *tls_ctx_v1_2 #endif #endif - SSL_CTX *dtls_ctx) +#if DTLS_SUPPORTED + ,SSL_CTX *dtls_ctx +#endif +#if DTLSv1_2_SUPPORTED + ,SSL_CTX *dtls_ctx_v1_2 +#endif +) { e->tls_ctx_ssl23 = tls_ctx_ssl23; e->tls_ctx_v1_0 = tls_ctx_v1_0; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED e->tls_ctx_v1_1 = tls_ctx_v1_1; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED e->tls_ctx_v1_2 = tls_ctx_v1_2; #endif #endif +#if DTLS_SUPPORTED e->dtls_ctx = dtls_ctx; +#endif +#if DTLSv1_2_SUPPORTED + e->dtls_ctx_v1_2 = dtls_ctx_v1_2; +#endif } void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap) @@ -1554,8 +1565,6 @@ ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_han if(ret) { set_socket_ssl(ret,ssl); - if(st == DTLS_SOCKET) - STRCPY(ret->orig_ctx_type,"DTLSv1.0"); } return ret; @@ -1754,8 +1763,6 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) addr_cpy(&(ret->local_addr),&(s->local_addr)); ret->connected = s->connected; addr_cpy(&(ret->remote_addr),&(s->remote_addr)); - - STRCPY(ret->orig_ctx_type, s->orig_ctx_type); delete_socket_from_map(s); delete_socket_from_parent(s); @@ -2239,7 +2246,8 @@ int udp_recvfrom(evutil_socket_t fd, ioa_addr* orig_addr, const ioa_addr *like_a return len; } -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED + static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd) { TURN_TLS_TYPE ret = TURN_TLS_NO; @@ -2318,7 +2326,7 @@ static int socket_input_worker(ioa_socket_handle s) } if(s->st == TLS_SOCKET) { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if(!ctx || SSL_get_shutdown(ctx)) { s->tobeclosed = 1; @@ -2337,7 +2345,7 @@ static int socket_input_worker(ioa_socket_handle s) if(s->st == TENTATIVE_TCP_SOCKET) { EVENT_DEL(s->read_event); -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED TURN_TLS_TYPE tls_type = check_tentative_tls(s->fd); if(tls_type) { s->st = TLS_SOCKET; @@ -2348,32 +2356,28 @@ static int socket_input_worker(ioa_socket_handle s) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d: bev already exist\n", __FUNCTION__,(long)s, s->st, s->sat); } switch(tls_type) { -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED case TURN_TLS_v1_2: if(s->e->tls_ctx_v1_2) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_2)); - STRCPY(s->orig_ctx_type,"TLSv1.2"); } break; #endif -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED case TURN_TLS_v1_1: if(s->e->tls_ctx_v1_1) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_1)); - STRCPY(s->orig_ctx_type,"TLSv1.1"); } break; #endif case TURN_TLS_v1_0: if(s->e->tls_ctx_v1_0) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_0)); - STRCPY(s->orig_ctx_type,"TLSv1.0"); } break; default: if(s->e->tls_ctx_ssl23) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_ssl23)); - STRCPY(s->orig_ctx_type,"SSLv23"); } else { s->tobeclosed = 1; return 0; @@ -2392,7 +2396,7 @@ static int socket_input_worker(ioa_socket_handle s) bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */ } } else -#endif //TURN_NO_TLS +#endif //TLS_SUPPORTED { s->st = TCP_SOCKET; if(s->bev) { @@ -2444,7 +2448,7 @@ static int socket_input_worker(ioa_socket_handle s) s->broken = 1; log_socket_event(s, "socket read failed, to be closed",1); } else if(s->st == TLS_SOCKET) { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if(!ctx || SSL_get_shutdown(ctx)) { ret = -1; @@ -3084,7 +3088,7 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, if (s->connected && s->bev) { if (s->st == TLS_SOCKET) { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if (!ctx || SSL_get_shutdown(ctx)) { s->tobeclosed = 1; @@ -3241,11 +3245,10 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in return -1; } } else { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED if(!(s->ssl)) { //??? how we can get to this point ??? set_socket_ssl(s,SSL_NEW(e->tls_ctx_ssl23)); - STRCPY(s->orig_ctx_type,"SSLv23"); s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, s->ssl, @@ -3460,7 +3463,7 @@ const char* get_ioa_socket_cipher(ioa_socket_handle s) const char* get_ioa_socket_ssl_method(ioa_socket_handle s) { if(s && s->ssl) { - return turn_get_ssl_method(s->ssl, s->orig_ctx_type); + return turn_get_ssl_method(s->ssl, "UNKNOWN"); } return "no SSL"; } @@ -3478,8 +3481,8 @@ void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) ioa_engine_handle e = turn_server_get_engine(server); if(e && e->verbose && ss->client_socket) { if(ss->client_socket->ssl) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s (%s)\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_socket->ssl), - turn_get_ssl_method(ss->client_socket->ssl, ss->client_socket->orig_ctx_type),ss->client_socket->orig_ctx_type); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_socket->ssl), + turn_get_ssl_method(ss->client_socket->ssl, "UNKNOWN")); } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime); } diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 998860a7..27390dc1 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -143,13 +143,18 @@ struct _ioa_engine stun_buffer_list bufs; SSL_CTX *tls_ctx_ssl23; SSL_CTX *tls_ctx_v1_0; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED SSL_CTX *tls_ctx_v1_1; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED SSL_CTX *tls_ctx_v1_2; #endif #endif +#if DTLS_SUPPORTED SSL_CTX *dtls_ctx; +#endif +#if DTLSv1_2_SUPPORTED + SSL_CTX *dtls_ctx_v1_2; +#endif turn_time_t jiffie; /* bandwidth check interval */ ioa_timer_handle timer_ev; s08bits cmsg[TURN_CMSG_SZ+1]; @@ -180,7 +185,6 @@ struct _ioa_socket SSL* ssl; u32bits ssl_renegs; int in_write; - char orig_ctx_type[16]; int bound; int local_addr_known; ioa_addr local_addr; @@ -251,14 +255,20 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) - SSL_CTX *tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) - SSL_CTX *tls_ctx_v1_2, + SSL_CTX *tls_ctx_v1_0 +#if TLSv1_1_SUPPORTED + ,SSL_CTX *tls_ctx_v1_1 +#if TLSv1_2_SUPPORTED + ,SSL_CTX *tls_ctx_v1_2 +#endif +#endif +#if DTLS_SUPPORTED + ,SSL_CTX *dtls_ctx #endif +#if DTLSv1_2_SUPPORTED + ,SSL_CTX *dtls_ctx_v1_2 #endif - SSL_CTX *dtls_ctx); +); void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index ca7201ba..7adc7983 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -517,18 +517,18 @@ int main(int argc, char **argv) root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; #endif #endif } else { -#if defined(TURN_NO_DTLS) +#if !DTLS_SUPPORTED fprintf(stderr,"ERROR: DTLS is not supported.\n"); exit(-1); #else @@ -538,6 +538,11 @@ int main(int argc, char **argv) root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; +#if DTLSv1_2_SUPPORTED + root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_2_client_method()); + SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); + root_tls_ctx_num++; +#endif #endif } diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 6c0d366d..38ab87b5 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -50,6 +50,11 @@ static uint64_t current_reservation_token = 0; static int allocate_rtcp = 0; static const int never_allocate_rtcp = 0; +#if ALPN_SUPPORTED +static const unsigned char kALPNProtos[] = "\x08http/1.1\x09stun.turn\x12stun.nat-discovery"; +static const size_t kALPNProtosLen = sizeof(kALPNProtos) - 1; +#endif + ///////////////////////////////////////// int rare_event(void) @@ -79,15 +84,21 @@ static int get_allocate_address_family(ioa_addr *relay_addr) { static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again, int connect_cycle) { + int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num); + SSL *ssl; ssl = SSL_NEW(root_tls_ctx[ctxtype]); +#if ALPN_SUPPORTED + SSL_set_alpn_protos(ssl, kALPNProtos, kALPNProtosLen); +#endif + if(use_tcp) { SSL_set_fd(ssl, fd); } else { -#if defined(TURN_NO_DTLS) +#if !DTLS_SUPPORTED UNUSED_ARG(remote_addr); fprintf(stderr,"ERROR: DTLS is not supported.\n"); exit(-1); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index bb136d3f..6443a109 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.1.3" +#define TURN_SERVER_VERSION "4.3.2.1" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" @@ -60,8 +60,6 @@ extern "C" { #endif -/////////////////////////////////////////// - /* NS types: */ #define s08bits char