aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/ssl.erl39
-rw-r--r--lib/ssl/test/ssl_npn_handshake_SUITE.erl187
-rw-r--r--lib/ssl/test/ssl_npn_hello_SUITE.erl6
3 files changed, 166 insertions, 66 deletions
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index c72c4d7a93..9a562aa5a8 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -746,22 +746,39 @@ validate_option(hibernate_after, Value) when is_integer(Value), Value >= 0 ->
validate_option(erl_dist,Value) when Value == true;
Value == false ->
Value;
-validate_option(client_preferred_next_protocols, {Precedence, PreferredProtocols})
+validate_option(client_preferred_next_protocols = Opt, {Precedence, PreferredProtocols} = Value)
when is_list(PreferredProtocols) ->
- validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
- validate_npn_ordering(Precedence),
- {Precedence, PreferredProtocols, ?NO_PROTOCOL};
-validate_option(client_preferred_next_protocols, {Precedence, PreferredProtocols, Default} = Value)
+ case ssl_record:highest_protocol_version([]) of
+ {3,0} ->
+ throw({error, {eoptions, {not_supported_in_sslv3, {Opt, Value}}}});
+ _ ->
+ validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
+ validate_npn_ordering(Precedence),
+ {Precedence, PreferredProtocols, ?NO_PROTOCOL}
+ end;
+validate_option(client_preferred_next_protocols = Opt, {Precedence, PreferredProtocols, Default} = Value)
when is_list(PreferredProtocols), is_binary(Default),
byte_size(Default) > 0, byte_size(Default) < 256 ->
- validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
- validate_npn_ordering(Precedence),
- Value;
+ case ssl_record:highest_protocol_version([]) of
+ {3,0} ->
+ throw({error, {eoptions, {not_supported_in_sslv3, {Opt, Value}}}});
+ _ ->
+ validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
+ validate_npn_ordering(Precedence),
+ Value
+ end;
+
validate_option(client_preferred_next_protocols, undefined) ->
undefined;
-validate_option(next_protocols_advertised, Value) when is_list(Value) ->
- validate_binary_list(next_protocols_advertised, Value),
- Value;
+validate_option(next_protocols_advertised = Opt, Value) when is_list(Value) ->
+ case ssl_record:highest_protocol_version([]) of
+ {3,0} ->
+ throw({error, {eoptions, {not_supported_in_sslv3, {Opt, Value}}}});
+ _ ->
+ validate_binary_list(next_protocols_advertised, Value),
+ Value
+ end;
+
validate_option(next_protocols_advertised, undefined) ->
undefined;
validate_option(Opt, Value) ->
diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
index eef09f42f2..cfeb328e21 100644
--- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
@@ -26,6 +26,39 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
+all() ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}].
+
+groups() ->
+ [
+ {'tlsv1.2', [], next_protocol_tests()},
+ {'tlsv1.1', [], next_protocol_tests()},
+ {'tlsv1', [], next_protocol_tests()},
+ {'sslv3', [], next_protocol_not_supported()}
+ ].
+
+next_protocol_tests() ->
+ [validate_empty_protocols_are_not_allowed,
+ validate_empty_advertisement_list_is_allowed,
+ validate_advertisement_must_be_a_binary_list,
+ validate_client_protocols_must_be_a_tuple,
+ normal_npn_handshake_server_preference,
+ normal_npn_handshake_client_preference,
+ fallback_npn_handshake,
+ fallback_npn_handshake_server_preference,
+ client_tries_to_negotiate_but_server_does_not_support,
+ client_does_not_try_to_negotiate_but_server_supports_npn,
+ renegotiate_from_client_after_npn_handshake
+ ].
+
+next_protocol_not_supported() ->
+ [npn_not_supported_client,
+ npn_not_supported_server
+ ].
+
init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
@@ -46,23 +79,30 @@ end_per_suite(_Config) ->
application:stop(crypto).
-all() ->
- [validate_empty_protocols_are_not_allowed_test,
- validate_empty_advertisement_list_is_allowed_test,
- validate_advertisement_must_be_a_binary_list_test,
- validate_client_protocols_must_be_a_tuple_test,
- perform_normal_npn_handshake_server_preference_test,
- perform_normal_npn_handshake_client_preference_test,
- perform_fallback_npn_handshake_test,
- perform_fallback_npn_handshake_server_preference_test,
- perform_client_tries_to_negotiate_but_server_does_not_support_test,
- perform_client_does_not_try_to_negotiate_but_server_supports_npn_test,
- perform_renegotiate_from_client_after_npn_handshake].
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
-connection_info_result(Socket) ->
- ssl:connection_info(Socket).
-validate_empty_protocols_are_not_allowed_test(_Config) ->
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+
+validate_empty_protocols_are_not_allowed(Config) when is_list(Config) ->
{error, {eoptions, {next_protocols_advertised, {invalid_protocol, <<>>}}}}
= (catch ssl:listen(9443,
[{next_protocols_advertised, [<<"foo/1">>, <<"">>]}])),
@@ -73,64 +113,75 @@ validate_empty_protocols_are_not_allowed_test(_Config) ->
Option = {client_preferred_next_protocols, {invalid_protocol, <<"">>}},
{error, {eoptions, Option}} = (catch ssl:connect({127,0,0,1}, 9443, [Option], infinity)).
-validate_empty_advertisement_list_is_allowed_test(_Config) ->
+%--------------------------------------------------------------------------------
+
+validate_empty_advertisement_list_is_allowed(Config) when is_list(Config) ->
Option = {next_protocols_advertised, []},
{ok, Socket} = ssl:listen(0, [Option]),
ssl:close(Socket).
+%--------------------------------------------------------------------------------
-validate_advertisement_must_be_a_binary_list_test(_Config) ->
+validate_advertisement_must_be_a_binary_list(Config) when is_list(Config) ->
Option = {next_protocols_advertised, blah},
{error, {eoptions, Option}} = (catch ssl:listen(9443, [Option])).
+%--------------------------------------------------------------------------------
-validate_client_protocols_must_be_a_tuple_test(_Config) ->
+validate_client_protocols_must_be_a_tuple(Config) when is_list(Config) ->
Option = {client_preferred_next_protocols, [<<"foo/1">>]},
{error, {eoptions, Option}} = (catch ssl:connect({127,0,0,1}, 9443, [Option])).
+%--------------------------------------------------------------------------------
+normal_npn_handshake_server_preference(Config) when is_list(Config) ->
+ run_npn_handshake(Config,
+ [{client_preferred_next_protocols,
+ {server, [<<"http/1.0">>, <<"http/1.1">>], <<"http/1.1">>}}],
+ [{next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}],
+ {ok, <<"http/1.1">>}).
+%--------------------------------------------------------------------------------
-perform_client_does_not_try_to_negotiate_but_server_supports_npn_test(Config) ->
- run_npn_handshake_test(Config,
- [],
- [{next_protocols_advertised, [<<"spdy/1">>, <<"http/1.1">>, <<"http/1.0">>]}],
- {error, next_protocol_not_negotiated}).
+normal_npn_handshake_client_preference(Config) when is_list(Config) ->
+ run_npn_handshake(Config,
+ [{client_preferred_next_protocols,
+ {client, [<<"http/1.0">>, <<"http/1.1">>], <<"http/1.1">>}}],
+ [{next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}],
+ {ok, <<"http/1.0">>}).
-perform_client_tries_to_negotiate_but_server_does_not_support_test(Config) ->
- run_npn_handshake_test(Config,
- [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}}],
- [],
- {error, next_protocol_not_negotiated}).
+%--------------------------------------------------------------------------------
-perform_fallback_npn_handshake_test(Config) ->
- run_npn_handshake_test(Config,
- [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}}],
- [{next_protocols_advertised, [<<"spdy/1">>, <<"http/1.1">>, <<"http/1.0">>]}],
- {ok, <<"http/1.1">>}).
+fallback_npn_handshake(Config) when is_list(Config) ->
+ run_npn_handshake(Config,
+ [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}}],
+ [{next_protocols_advertised, [<<"spdy/1">>, <<"http/1.1">>, <<"http/1.0">>]}],
+ {ok, <<"http/1.1">>}).
+%--------------------------------------------------------------------------------
-perform_fallback_npn_handshake_server_preference_test(Config) ->
- run_npn_handshake_test(Config,
- [{client_preferred_next_protocols, {server, [<<"spdy/2">>], <<"http/1.1">>}}],
- [{next_protocols_advertised, [<<"spdy/1">>, <<"http/1.1">>, <<"http/1.0">>]}],
- {ok, <<"http/1.1">>}).
+fallback_npn_handshake_server_preference(Config) when is_list(Config) ->
+ run_npn_handshake(Config,
+ [{client_preferred_next_protocols, {server, [<<"spdy/2">>], <<"http/1.1">>}}],
+ [{next_protocols_advertised, [<<"spdy/1">>, <<"http/1.1">>, <<"http/1.0">>]}],
+ {ok, <<"http/1.1">>}).
+%--------------------------------------------------------------------------------
-perform_normal_npn_handshake_client_preference_test(Config) ->
- run_npn_handshake_test(Config,
- [{client_preferred_next_protocols,
- {client, [<<"http/1.0">>, <<"http/1.1">>], <<"http/1.1">>}}],
- [{next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}],
- {ok, <<"http/1.0">>}).
+client_does_not_try_to_negotiate_but_server_supports_npn(Config) when is_list(Config) ->
+ run_npn_handshake(Config,
+ [],
+ [{next_protocols_advertised, [<<"spdy/1">>, <<"http/1.1">>, <<"http/1.0">>]}],
+ {error, next_protocol_not_negotiated}).
+%--------------------------------------------------------------------------------
-perform_normal_npn_handshake_server_preference_test(Config) ->
- run_npn_handshake_test(Config,
- [{client_preferred_next_protocols,
- {server, [<<"http/1.0">>, <<"http/1.1">>], <<"http/1.1">>}}],
- [{next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}],
- {ok, <<"http/1.1">>}).
+client_tries_to_negotiate_but_server_does_not_support(Config) when is_list(Config) ->
+ run_npn_handshake(Config,
+ [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}}],
+ [],
+ {error, next_protocol_not_negotiated}).
-perform_renegotiate_from_client_after_npn_handshake(Config) ->
+%--------------------------------------------------------------------------------
+renegotiate_from_client_after_npn_handshake(Config) when is_list(Config) ->
Data = "hello world",
-
+
ClientOpts0 = ?config(client_opts, Config),
ClientOpts = [{client_preferred_next_protocols,
{client, [<<"http/1.0">>], <<"http/1.1">>}}] ++ ClientOpts0,
@@ -155,8 +206,33 @@ perform_renegotiate_from_client_after_npn_handshake(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok).
%--------------------------------------------------------------------------------
+npn_not_supported_client(Config) when is_list(Config) ->
+ ClientOpts0 = ?config(client_opts, Config),
+ PrefProtocols = {client_preferred_next_protocols,
+ {client, [<<"http/1.0">>], <<"http/1.1">>}},
+ ClientOpts = [PrefProtocols] ++ ClientOpts0,
+ {ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Client = ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, 8888}, {host, Hostname},
+ {from, self()}, {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Client, {error,
+ {eoptions,
+ {not_supported_in_sslv3, PrefProtocols}}}).
+
+%--------------------------------------------------------------------------------
+npn_not_supported_server(Config) when is_list(Config)->
+ ServerOpts0 = ?config(server_opts, Config),
+ AdvProtocols = {next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]},
+ ServerOpts = [AdvProtocols] ++ ServerOpts0,
+
+ {error, {eoptions, {not_supported_in_sslv3, AdvProtocols}}} = ssl:listen(0, ServerOpts).
-run_npn_handshake_test(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) ->
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+run_npn_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) ->
Data = "hello world",
ClientOpts0 = ?config(client_opts, Config),
@@ -179,6 +255,7 @@ run_npn_handshake_test(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtoco
ssl_test_lib:check_result(Server, ok, Client, ok).
+
assert_npn(Socket, Protocol) ->
test_server:format("Negotiated Protocol ~p, Expecting: ~p ~n",
[ssl:negotiated_next_protocol(Socket), Protocol]),
@@ -227,3 +304,7 @@ ssl_receive(Socket, Data, Buffer) ->
after 4000 ->
test_server:fail({did_not_get, Data})
end.
+
+
+connection_info_result(Socket) ->
+ ssl:connection_info(Socket).
diff --git a/lib/ssl/test/ssl_npn_hello_SUITE.erl b/lib/ssl/test/ssl_npn_hello_SUITE.erl
index 0bca8bbeb4..5102c74e87 100644
--- a/lib/ssl/test/ssl_npn_hello_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_hello_SUITE.erl
@@ -111,5 +111,7 @@ create_server_hello_with_no_advertised_protocols_test(_Config) ->
undefined = Hello#server_hello.next_protocol_negotiation.
create_server_hello_with_advertised_protocols_test(_Config) ->
- Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(), false, [<<"spdy/1">>, <<"http/1.0">>, <<"http/1.1">>]),
- #next_protocol_negotiation{extension_data = <<6, "spdy/1", 8, "http/1.0", 8, "http/1.1">>} = Hello#server_hello.next_protocol_negotiation.
+ Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(),
+ false, [<<"spdy/1">>, <<"http/1.0">>, <<"http/1.1">>]),
+ #next_protocol_negotiation{extension_data = <<6, "spdy/1", 8, "http/1.0", 8, "http/1.1">>} =
+ Hello#server_hello.next_protocol_negotiation.