Просмотр исходного кода

Work around broken elliptic-curve cipher suites

Unfortunately the implementation of elliptic-curve ciphers that has
been introduced in R16B01 is incomplete.  Depending on the particular
client, this can cause the TLS handshake to break during key agreement.
As it turns out that most popular browsers (e.g. Firefox, Chromium,
and Safari) are affected by this bug, we provide this workaround.

This workaround makes sure that only cipher suite implementations that
are not known to be broken are supported by default.
Klaus Trainer 11 лет назад
Родитель
Сommit
c0c09a1311
1 измененных файлов с 19 добавлено и 1 удалено
  1. 19 1
      src/ranch_ssl.erl

+ 19 - 1
src/ranch_ssl.erl

@@ -136,10 +136,11 @@ listen(Opts) ->
 	true = lists:keymember(cert, 1, Opts)
 		orelse lists:keymember(certfile, 1, Opts),
 	Opts2 = ranch:set_option_default(Opts, backlog, 1024),
+	Opts3 = ranch:set_option_default(Opts2, ciphers, unbroken_cipher_suites()),
 	%% We set the port to 0 because it is given in the Opts directly.
 	%% The port in the options takes precedence over the one in the
 	%% first argument.
-	ssl:listen(0, ranch:filter_options(Opts2,
+	ssl:listen(0, ranch:filter_options(Opts3,
 		[backlog, cacertfile, cacerts, cert, certfile, ciphers,
 			fail_if_no_peer_cert, ip, key, keyfile, next_protocols_advertised,
 			nodelay, password, port, raw, reuse_session, reuse_sessions,
@@ -269,3 +270,20 @@ ssl_accept(Socket, Timeout) ->
 		{error, Reason} ->
 			{error, {ssl_accept, Reason}}
 	end.
+
+%% Unfortunately the implementation of elliptic-curve ciphers that has
+%% been introduced in R16B01 is incomplete.  Depending on the particular
+%% client, this can cause the TLS handshake to break during key
+%% agreement.  Depending on the ssl application version, this function
+%% returns a list of all cipher suites that are supported by default,
+%% minus the elliptic-curve ones.
+-spec unbroken_cipher_suites() -> [ssl:erl_cipher_suite()].
+unbroken_cipher_suites() ->
+	case proplists:get_value(ssl_app, ssl:versions()) of
+		"5.3" ->
+			lists:filter(fun(Suite) ->
+				string:left(atom_to_list(element(1, Suite)), 4) =/= "ecdh"
+			end, ssl:cipher_suites());
+		_ ->
+			ssl:cipher_suites()
+	end.