Browse Source

Use a single SSL context object (#989)

openssl allows multiple TLS version support through a single SSL_CTX
object.

This PR replaces 4 per-version SSL_CTX objects with a single object
(DTLS is not yet changed).
SSL context initialization code for openssl with modern API (>=1.1.0)
uses `TLS_server_method` and `SSL_CTX_set_min_proto_version` instead of
enabling specific TLS version. Byproduct of this is TLSv1_3 support when
used with openssl-1.1.1 and above

TLS 1.2 and TLS 1.3 cannot be disabled (as before)

Test plan:
- run_tests.sh script now runs turnserver with SSL certificate (which
enables TLS support)
- run_tests.sh now has one more basic test that uses TLS protocol

Co-authored-by: Pavel Punsky <[email protected]>
Pavel Punsky 3 years ago
parent
commit
4bab2adba4

+ 6 - 3
README.turnserver

@@ -204,11 +204,14 @@ Flags:
 
 --dh1066		Use 1066 bits predefined DH TLS key. Default size of the key is 2066.
 
---no-tlsv1		Do not allow TLSv1/DTLSv1 protocol.
+--no-tlsv1		Set TLSv1_1/DTLSv1.2 as a minimum supported protocol version.
+				With openssl-1.0.2 and below, do not allow TLSv1.2/DTLSv1.2 protocols.
 
---no-tlsv1_1		Do not allow TLSv1.1 protocol.
+--no-tlsv1_1		Set TLSv1_2/DTLSv1.2 as a minimum supported protocol version.
+					With openssl-1.0.2 and below, do not allow TLSv1.1 protocol.
 
---no-tlsv1_2		Do not allow TLSv1.2/DTLSv1.2 protocol.
+--no-tlsv1_2		Set TLSv1_3/DTLSv1.2 as a minimum supported protocol version.
+					With openssl-1.0.2 and below, do not allow TLSv1.2/DTLSv1.2 protocols.
 
 --no-udp		Do not start UDP client listeners.
 

+ 10 - 1
examples/run_tests.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 echo 'Running turnserver'
-../bin/turnserver --use-auth-secret  --static-auth-secret=secret --realm=north.gov --allow-loopback-peers --no-cli > /dev/null &
+../bin/turnserver --use-auth-secret  --static-auth-secret=secret --realm=north.gov --allow-loopback-peers --no-cli --cert ../examples/ca/turn_server_cert.pem --pkey ../examples/ca/turn_server_pkey.pem > /dev/null &
 echo 'Running peer client'
 ../bin/turnutils_peer -L 127.0.0.1 -L ::1 -L 0.0.0.0 > /dev/null &
 
@@ -16,6 +16,15 @@ else
 	exit $?
 fi
 
+echo 'Running turn client TLS'
+../bin/turnutils_uclient -t -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
+if [ $? -eq 0 ]; then
+    echo OK
+else
+    echo FAIL
+	exit $?
+fi
+
 echo 'Running turn client UDP'
 ../bin/turnutils_uclient -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1  | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
 if [ $? -eq 0 ]; then

+ 26 - 27
src/apps/relay/mainrelay.c

@@ -83,13 +83,7 @@ char HTTP_ALPN[128] = "http/1.1";
 #define DEFAULT_GENERAL_RELAY_SERVERS_NUMBER (1)
 
 turn_params_t turn_params = {
-NULL, NULL,
-#if TLSv1_1_SUPPORTED
-	NULL,
-#if TLSv1_2_SUPPORTED
 	NULL,
-#endif
-#endif
 #if DTLS_SUPPORTED
 NULL,
 #endif
@@ -603,9 +597,12 @@ static char Usage[] = "Usage: turnserver [options]\n"
 " --dh1066					Use 1066 bits predefined DH TLS key. Default size of the predefined key is 2066.\n"
 " --dh-file	<dh-file-name>			Use custom DH TLS key, stored in PEM format in the file.\n"
 "						Flags --dh566 and --dh1066 are ignored when the DH key is taken from a file.\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/DTLSv1.2 protocol.\n"
+" --no-tlsv1					Set TLSv1_1/DTLSv1.2 as a minimum supported protocol version.\n"
+"								With openssl-1.0.2 and below, do not allow TLSv1/DTLSv1 protocols.\n"
+" --no-tlsv1_1					Set TLSv1_2/DTLSv1.2 as a minimum supported protocol version.\n"
+"								With openssl-1.0.2 and below, do not allow TLSv1.1 protocol.\n"
+" --no-tlsv1_2					Set TLSv1_3/DTLSv1.2 as a minimum supported protocol version.\n"
+"								With openssl-1.0.2 and below, do not allow TLSv1.2/DTLSv1.2 protocols.\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"
@@ -3152,23 +3149,10 @@ static void set_ctx(SSL_CTX** out, const char *protocol, const SSL_METHOD* metho
 		op |= SSL_OP_NO_SSLv2;
 #endif
 
-#if defined(SSL_OP_NO_SSLv2)
+#if defined(SSL_OP_NO_SSLv3)
 			op |= SSL_OP_NO_SSLv3;
 #endif
 
-		if(turn_params.no_tlsv1)
-			op |= SSL_OP_NO_TLSv1;
-
-#if defined(SSL_OP_NO_TLSv1_1)
-		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;
@@ -3240,20 +3224,35 @@ static void openssl_load_certificates(void)
 {
 	pthread_mutex_lock(&turn_params.tls_mutex);
 	if(!turn_params.no_tls) {
-		set_ctx(&turn_params.tls_ctx_ssl23,"SSL23",SSLv23_server_method()); /*compatibility mode */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+        set_ctx(&turn_params.tls_ctx,"TLS", TLSv1_2_server_method()); /*openssl-1.0.2 version specific API */
 		if(!turn_params.no_tlsv1) {
-			set_ctx(&turn_params.tls_ctx_v1_0,"TLS1.0",TLSv1_server_method());
+			SSL_CTX_set_options(turn_params.tls_ctx, SSL_OP_NO_TLSv1);
 		}
 #if TLSv1_1_SUPPORTED
 		if(!turn_params.no_tlsv1_1) {
-			set_ctx(&turn_params.tls_ctx_v1_1,"TLS1.1",TLSv1_1_server_method());
+			SSL_CTX_set_options(turn_params.tls_ctx, SSL_OP_NO_TLSv1_1);
 		}
 #if TLSv1_2_SUPPORTED
 		if(!turn_params.no_tlsv1_2) {
-			set_ctx(&turn_params.tls_ctx_v1_2,"TLS1.2",TLSv1_2_server_method());
+			SSL_CTX_set_options(turn_params.tls_ctx, SSL_OP_NO_TLSv1_2);
 		}
 #endif
 #endif
+#else // OPENSSL_VERSION_NUMBER < 0x10100000L
+        set_ctx(&turn_params.tls_ctx,"TLS", TLS_server_method());
+        if(!turn_params.no_tlsv1) {
+            SSL_CTX_set_min_proto_version(turn_params.tls_ctx, TLS1_1_VERSION);
+        }
+        if(!turn_params.no_tlsv1_1) {
+            SSL_CTX_set_min_proto_version(turn_params.tls_ctx, TLS1_2_VERSION);
+        }
+#if TLSv1_3_SUPPORTED
+        if(!turn_params.no_tlsv1_2) {
+            SSL_CTX_set_min_proto_version(turn_params.tls_ctx, TLS1_3_VERSION);
+        }
+#endif
+#endif // OPENSSL_VERSION_NUMBER < 0x10100000L
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS cipher suite: %s\n",turn_params.cipher_list);
 	}
 

+ 1 - 10
src/apps/relay/mainrelay.h

@@ -176,16 +176,7 @@ typedef struct _turn_params_ {
 
 //////////////// OpenSSL group //////////////////////
 
-  SSL_CTX *tls_ctx_ssl23;
-  
-  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 *tls_ctx;
   
 #if DTLS_SUPPORTED
   SSL_CTX *dtls_ctx;

+ 1 - 8
src/apps/relay/netengine.c

@@ -333,14 +333,7 @@ static void update_ssl_ctx(evutil_socket_t sock, short events, update_ssl_ctx_cb
 
 	/* No mutex with "e" as these are only used in the same event loop */
 	pthread_mutex_lock(&turn_params.tls_mutex);
-	replace_one_ssl_ctx(&e->tls_ctx_ssl23, params->tls_ctx_ssl23);
-	replace_one_ssl_ctx(&e->tls_ctx_v1_0, params->tls_ctx_v1_0);
-#if TLSv1_1_SUPPORTED
-	replace_one_ssl_ctx(&e->tls_ctx_v1_1, params->tls_ctx_v1_1);
-#if TLSv1_2_SUPPORTED
-	replace_one_ssl_ctx(&e->tls_ctx_v1_2, params->tls_ctx_v1_2);
-#endif
-#endif
+	replace_one_ssl_ctx(&e->tls_ctx, params->tls_ctx);
 #if DTLS_SUPPORTED
 	replace_one_ssl_ctx(&e->dtls_ctx, params->dtls_ctx);
 #endif

+ 9 - 57
src/apps/relay/ns_ioalib_engine_impl.c

@@ -2425,34 +2425,11 @@ static int socket_input_worker(ioa_socket_handle s)
 			if(s->bev) {
 				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 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));
-				}
-				break;
-#endif
-#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));
-				}
-				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));
-				}
-				break;
-			default:
-				if(s->e->tls_ctx_ssl23) {
-					set_socket_ssl(s,SSL_new(s->e->tls_ctx_ssl23));
-				} else {
-					s->tobeclosed = 1;
-					return 0;
-				}
-			};
+
+			if(s->e->tls_ctx) {
+				set_socket_ssl(s,SSL_new(s->e->tls_ctx));
+			}
+
 			if(s->ssl) {
 				s->bev = bufferevent_openssl_socket_new(s->e->event_base,
 								s->fd,
@@ -2491,34 +2468,9 @@ static int socket_input_worker(ioa_socket_handle s)
 			if(s->bev) {
 				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 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));
-				}
-				break;
-#endif
-#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));
-				}
-				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));
-				}
-				break;
-			default:
-				if(s->e->tls_ctx_ssl23) {
-					set_socket_ssl(s,SSL_new(s->e->tls_ctx_ssl23));
-				} else {
-					s->tobeclosed = 1;
-					return 0;
-				}
-			};
+			if(s->e->tls_ctx) {
+				set_socket_ssl(s,SSL_new(s->e->tls_ctx));
+			}
 			if(s->ssl) {
 				s->bev = bufferevent_openssl_socket_new(s->e->event_base,
 								s->fd,
@@ -3520,7 +3472,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
 #if TLS_SUPPORTED
 						if(!(s->ssl)) {
 							//??? how we can get to this point ???
-							set_socket_ssl(s,SSL_new(e->tls_ctx_ssl23));
+							set_socket_ssl(s,SSL_new(e->tls_ctx));
 							s->bev = bufferevent_openssl_socket_new(s->e->event_base,
 											s->fd,
 											s->ssl,

+ 1 - 8
src/apps/relay/ns_ioalib_impl.h

@@ -141,14 +141,7 @@ struct _ioa_engine
   turnipports* tp;
   rtcp_map *map_rtcp;
   stun_buffer_list bufs;
-  SSL_CTX *tls_ctx_ssl23;
-  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 *tls_ctx;
 #if DTLS_SUPPORTED
   SSL_CTX *dtls_ctx;
 #endif