Skip to content

Commit f65d56b

Browse files
committed
ssl: Preserve inet option order in emulated_options
The emulated_options/3 function in tls_socket and dtls_socket used a prepend accumulator pattern without reversing the result, causing inet options to be reversed when passed to gen_tcp:connect/gen_udp:open. This broke the inet_backend option which must be the first option in the list according to gen_tcp and gen_udp documentation. Fix by reversing the Inet accumulator before returning. For dtls_socket, also change the initial Inet accumulator from internal_inet_values() to [] since those values are already appended in the connect and listen call sites. Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
1 parent c77b8b0 commit f65d56b

4 files changed

Lines changed: 39 additions & 4 deletions

File tree

lib/ssl/src/dtls_socket.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ emulated_options() ->
233233
[mode, active, packet, packet_size].
234234

235235
emulated_options(Opts) ->
236-
emulated_options(Opts, internal_inet_values(), default_inet_values()).
236+
emulated_options(Opts, [], default_inet_values()).
237237

238238
internal_inet_values() ->
239239
[{active, false}, {mode,binary}].
@@ -280,7 +280,7 @@ emulated_options([{packet_size, _} = Opt | _], _, _) ->
280280
emulated_options([Opt|Opts], Inet, Emulated) ->
281281
emulated_options(Opts, [Opt|Inet], Emulated);
282282
emulated_options([], Inet,Emulated) ->
283-
{Inet, Emulated}.
283+
{lists:reverse(Inet), Emulated}.
284284

285285
validate_inet_option(mode, Value)
286286
when Value =/= list, Value =/= binary ->

lib/ssl/src/tls_socket.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ emulated_options([{low_watermark, Value} = Opt | Opts], Inet, Emulated) ->
561561
emulated_options([Opt|Opts], Inet, Emulated) ->
562562
emulated_options(Opts, [Opt|Inet], Emulated);
563563
emulated_options([], Inet,Emulated) ->
564-
{Inet, Emulated}.
564+
{lists:reverse(Inet), Emulated}.
565565

566566
validate_inet_option(mode, Value)
567567
when Value =/= list, Value =/= binary ->

lib/ssl/test/ssl_api_SUITE.erl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
select_best_cert/1,
6262
select_sha1_cert/0,
6363
select_sha1_cert/1,
64+
inet_backend_option_order/0,
65+
inet_backend_option_order/1,
6466
root_any_sign/0,
6567
root_any_sign/1,
6668
connection_information/0,
@@ -302,6 +304,7 @@ gen_api_tests() ->
302304
peercert,
303305
peercert_with_client_cert,
304306
select_sha1_cert,
307+
inet_backend_option_order,
305308
connection_information,
306309
secret_connection_info,
307310
keylog_connection_info,
@@ -646,6 +649,30 @@ root_any_sign(Config) when is_list(Config) ->
646649
ssl_test_lib:basic_alert(CFail, [{verify, verify_peer}, {signature_algs, SigAlgs} | SFail],
647650
Config, unsupported_certificate).
648651

652+
%%--------------------------------------------------------------------
653+
inet_backend_option_order() ->
654+
[{doc,"Test that inet_backend option is preserved as first option "
655+
"when passed to gen_tcp:connect"}].
656+
inet_backend_option_order(Config) when is_list(Config) ->
657+
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
658+
ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
659+
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
660+
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
661+
{from, self()},
662+
{mfa, {ssl_test_lib, send_recv_result_active, []}},
663+
{options, [{inet_backend, socket} | ServerOpts]}]),
664+
Port = ssl_test_lib:inet_port(Server),
665+
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
666+
{host, Hostname},
667+
{from, self()},
668+
{mfa, {ssl_test_lib, send_recv_result_active, []}},
669+
{options, [{inet_backend, socket} | ClientOpts]}]),
670+
671+
ssl_test_lib:check_result(Server, ok, Client, ok),
672+
673+
ssl_test_lib:close(Server),
674+
ssl_test_lib:close(Client).
675+
649676
%%--------------------------------------------------------------------
650677
connection_information() ->
651678
[{doc,"Test the API function ssl:connection_information/1"}].

lib/ssl/test/ssl_test_lib.erl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1472,7 +1472,15 @@ patch_dtls_options(Options0) ->
14721472
case proplists:get_value(protocol, Options0) of
14731473
dtls ->
14741474
case proplists:get_value(recbuf, Options0, undefined) of
1475-
undefined -> [{recbuf, ?DTLS_RECBUF}|Options0];
1475+
undefined ->
1476+
%% inet_backend must be the first option in the list
1477+
%% for gen_tcp/gen_udp, so insert recbuf after it
1478+
case Options0 of
1479+
[{inet_backend, _} = InetBackend | Rest] ->
1480+
[InetBackend, {recbuf, ?DTLS_RECBUF} | Rest];
1481+
_ ->
1482+
[{recbuf, ?DTLS_RECBUF} | Options0]
1483+
end;
14761484
_ -> Options0
14771485
end;
14781486
_ -> Options0

0 commit comments

Comments
 (0)