Browse Source

Imported Upstream version 4.3.2.1

Oleg Moskalenko 11 years ago
parent
commit
f076c92e44

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+12/13/2014 Oleg Moskalenko <[email protected]>
+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 <[email protected]>
 Version 4.3.1.3 'Tolomei':
 	- Reliability fixes (Issue 141 from rfc5766-turn-server).

+ 69 - 18
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 <libdirname> (BSD) 
  $ crle -u -l <libdirname> (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.
+  

+ 20 - 6
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:

+ 4 - 0
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.

+ 2 - 6
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.
 
 ==================================================================
 

+ 0 - 48
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 <stdlib.h>
-#include <openssl/ssl.h>
-#include <openssl/bio.h>
-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 ?
 ###########################

+ 6 - 3
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

+ 1 - 1
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 

+ 18 - 5
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.

+ 1 - 1
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

+ 1 - 1
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

+ 3 - 1
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 <[email protected]>
+  - Sync to 4.3.2.1
 * Sat Nov 29 2014 Oleg Moskalenko <[email protected]>
   - Sync to 4.3.1.3
 * Mon Nov 23 2014 Oleg Moskalenko <[email protected]>

+ 26 - 15
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 ///////////////

+ 65 - 2
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

+ 1 - 1
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,

+ 69 - 13
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);
 }
 

+ 143 - 46
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		<filename>		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>		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>		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	<dh-file-name>			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
 	}
 }

+ 7 - 2
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;
   

+ 36 - 18
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);
 	}
 

+ 33 - 30
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 <event2/bufferevent_ssl.h>
 #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);
 					}

+ 19 - 9
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);
 

+ 8 - 3
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
 		}
 

+ 12 - 1
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);

+ 1 - 3
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