diff options
Diffstat (limited to 'lib/ssl')
-rw-r--r-- | lib/ssl/doc/src/notes.xml | 29 | ||||
-rw-r--r-- | lib/ssl/src/ssl.erl | 19 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 48 | ||||
-rw-r--r-- | lib/ssl/src/tls_connection.erl | 45 | ||||
-rw-r--r-- | lib/ssl/src/tls_sender.erl | 36 | ||||
-rw-r--r-- | lib/ssl/test/ssl_alpn_handshake_SUITE.erl | 23 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 42 | ||||
-rw-r--r-- | lib/ssl/test/ssl_certificate_verify_SUITE.erl | 54 | ||||
-rw-r--r-- | lib/ssl/test/ssl_packet_SUITE.erl | 52 | ||||
-rw-r--r-- | lib/ssl/test/ssl_test_lib.erl | 38 | ||||
-rw-r--r-- | lib/ssl/vsn.mk | 2 |
11 files changed, 271 insertions, 117 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 5a2e394c72..673431ed0a 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,35 @@ </header> <p>This document describes the changes made to the SSL application.</p> +<section><title>SSL 9.0.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Correct alert handling with new TLS sender process, from + ssl-9.0.2. CLOSE ALERTS could under some circumstances be + encoded using an incorrect cipher state. This would cause + the peer to regard them as unknown messages.</p> + <p> + Own Id: OTP-15337 Aux Id: ERL-738 </p> + </item> + <item> + <p> + Correct handling of socket packet option with new TLS + sender process, from ssl-9.0.2. When changing the socket + option {packet, 1|2|3|4} with ssl:setopts/2 the option + must internally be propagated to the sender process as + well as the reader process as this particular option also + affects the data to be sent.</p> + <p> + Own Id: OTP-15348 Aux Id: ERL-747 </p> + </item> + </list> + </section> + +</section> + <section><title>SSL 9.0.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 4cf56035ba..03a1e40bfc 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -604,6 +604,25 @@ getopts(#sslsocket{}, OptionTags) -> %% %% Description: Sets options %%-------------------------------------------------------------------- +setopts(#sslsocket{pid = [Pid, Sender]}, Options0) when is_pid(Pid), is_list(Options0) -> + try proplists:expand([{binary, [{mode, binary}]}, + {list, [{mode, list}]}], Options0) of + Options -> + case proplists:get_value(packet, Options, undefined) of + undefined -> + ssl_connection:set_opts(Pid, Options); + PacketOpt -> + case tls_sender:setopts(Sender, [{packet, PacketOpt}]) of + ok -> + ssl_connection:set_opts(Pid, Options); + Error -> + Error + end + end + catch + _:_ -> + {error, {options, {not_a_proplist, Options0}}} + end; setopts(#sslsocket{pid = [Pid|_]}, Options0) when is_pid(Pid), is_list(Options0) -> try proplists:expand([{binary, [{mode, binary}]}, {list, [{mode, list}]}], Options0) of diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 5ea1924d40..9f876add6c 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -334,17 +334,12 @@ prf(ConnectionPid, Secret, Label, Seed, WantedLength) -> %%==================================================================== %% Alert and close handling %%==================================================================== -handle_own_alert(Alert, Version, StateName, +handle_own_alert(Alert, _, StateName, #state{role = Role, - transport_cb = Transport, - socket = Socket, protocol_cb = Connection, - connection_states = ConnectionStates, ssl_options = SslOpts} = State) -> try %% Try to tell the other side - {BinMsg, _} = - Connection:encode_alert(Alert, Version, ConnectionStates), - Connection:send(Transport, Socket, BinMsg) + send_alert(Alert, StateName, State) catch _:_ -> %% Can crash if we are in a uninitialized state ignore end, @@ -1160,24 +1155,20 @@ handle_call({close, {Pid, Timeout}}, From, StateName, State0, Connection) when i %% we must recive the close alert from the peer before releasing the %% transport socket. {next_state, downgrade, State#state{terminated = true}, [{timeout, Timeout, downgrade}]}; -handle_call({close, _} = Close, From, StateName, State, Connection) -> +handle_call({close, _} = Close, From, StateName, State, _Connection) -> %% Run terminate before returning so that the reuseaddr %% inet-option works properly - Result = Connection:terminate(Close, StateName, State#state{terminated = true}), + Result = terminate(Close, StateName, State), stop_and_reply( {shutdown, normal}, - {reply, From, Result}, State); -handle_call({shutdown, How0}, From, _, + {reply, From, Result}, State#state{terminated = true}); +handle_call({shutdown, How0}, From, StateName, #state{transport_cb = Transport, - negotiated_version = Version, - connection_states = ConnectionStates, - socket = Socket} = State, Connection) -> + socket = Socket} = State, _) -> case How0 of How when How == write; How == both -> - Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), - {BinMsg, _} = - Connection:encode_alert(Alert, Version, ConnectionStates), - Connection:send(Transport, Socket, BinMsg); + send_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), + StateName, State); _ -> ok end, @@ -1343,14 +1334,20 @@ terminate({shutdown, own_alert}, _StateName, #state{ _ -> Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, undefined, undefined) end; +terminate(downgrade = Reason, connection, #state{protocol_cb = Connection, + transport_cb = Transport, socket = Socket + } = State) -> + handle_trusted_certs_db(State), + Connection:close(Reason, Socket, Transport, undefined, undefined); terminate(Reason, connection, #state{protocol_cb = Connection, - connection_states = ConnectionStates, - ssl_options = #ssl_options{padding_check = Check}, - transport_cb = Transport, socket = Socket - } = State) -> + connection_states = ConnectionStates, + ssl_options = #ssl_options{padding_check = Check}, + transport_cb = Transport, socket = Socket + } = State) -> handle_trusted_certs_db(State), Alert = terminate_alert(Reason), - ok = Connection:send_alert_in_connection(Alert, State), + %% Send the termination ALERT if possible + catch (ok = Connection:send_alert_in_connection(Alert, State)), Connection:close(Reason, Socket, Transport, ConnectionStates, Check); terminate(Reason, _StateName, #state{transport_cb = Transport, protocol_cb = Connection, socket = Socket @@ -1387,6 +1384,11 @@ format_status(terminate, [_, StateName, State]) -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- +send_alert(Alert, connection, #state{protocol_cb = Connection} = State) -> + Connection:send_alert_in_connection(Alert, State); +send_alert(Alert, _, #state{protocol_cb = Connection} = State) -> + Connection:send_alert(Alert, State). + connection_info(#state{sni_hostname = SNIHostname, session = #session{session_id = SessionId, cipher_suite = CipherSuite, ecc = ECCCurve}, diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 2fde17a0fd..adb4f6d9ea 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -56,7 +56,9 @@ empty_connection_state/2]). %% Alert and close handling --export([send_alert/2, send_alert_in_connection/2, encode_alert/3, close/5, protocol_name/0]). +-export([send_alert/2, send_alert_in_connection/2, + send_sync_alert/2, + encode_alert/3, close/5, protocol_name/0]). %% Data handling -export([encode_data/3, passive_receive/2, next_record_if_active/1, @@ -346,16 +348,34 @@ encode_alert(#alert{} = Alert, Version, ConnectionStates) -> send_alert(Alert, #state{negotiated_version = Version, socket = Socket, - protocol_cb = Connection, transport_cb = Transport, connection_states = ConnectionStates0} = StateData0) -> {BinMsg, ConnectionStates} = - Connection:encode_alert(Alert, Version, ConnectionStates0), - Connection:send(Transport, Socket, BinMsg), + encode_alert(Alert, Version, ConnectionStates0), + send(Transport, Socket, BinMsg), StateData0#state{connection_states = ConnectionStates}. -send_alert_in_connection(Alert, #state{protocol_specific = #{sender := Sender}}) -> +%% If an ALERT sent in the connection state, should cause the TLS +%% connection to end, we need to synchronize with the tls_sender +%% process so that the ALERT if possible (that is the tls_sender process is +%% not blocked) is sent before the connection process terminates and +%% thereby closes the transport socket. +send_alert_in_connection(#alert{level = ?FATAL} = Alert, State) -> + send_sync_alert(Alert, State); +send_alert_in_connection(#alert{description = ?CLOSE_NOTIFY} = Alert, State) -> + send_sync_alert(Alert, State); +send_alert_in_connection(Alert, + #state{protocol_specific = #{sender := Sender}}) -> tls_sender:send_alert(Sender, Alert). +send_sync_alert(Alert, #state{protocol_specific = #{sender := Sender}}= State) -> + tls_sender:send_and_ack_alert(Sender, Alert), + receive + {Sender, ack_alert} -> + ok + after ?DEFAULT_TIMEOUT -> + %% Sender is blocked terminate anyway + throw({stop, {shutdown, own_alert}, State}) + end. %% User closes or recursive call! close({close, Timeout}, Socket, Transport = gen_tcp, _,_) -> @@ -505,7 +525,9 @@ hello(internal, #client_hello{client_version = ClientVersion} = Hello, case tls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of #alert{} = Alert -> - ssl_connection:handle_own_alert(Alert, ClientVersion, hello, State); + ssl_connection:handle_own_alert(Alert, ClientVersion, hello, + State#state{negotiated_version + = ClientVersion}); {Version, {Type, Session}, ConnectionStates, Protocol0, ServerHelloExt, HashSign} -> Protocol = case Protocol0 of @@ -528,7 +550,8 @@ hello(internal, #server_hello{} = Hello, ssl_options = SslOptions} = State) -> case tls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of #alert{} = Alert -> - ssl_connection:handle_own_alert(Alert, ReqVersion, hello, State); + ssl_connection:handle_own_alert(Alert, ReqVersion, hello, + State#state{negotiated_version = ReqVersion}); {Version, NewId, ConnectionStates, ProtoExt, Protocol} -> ssl_connection:handle_session(Hello, Version, NewId, ConnectionStates, ProtoExt, Protocol, State) @@ -636,8 +659,8 @@ callback_mode() -> state_functions. terminate(Reason, StateName, State) -> - ensure_sender_terminate(Reason, State), - catch ssl_connection:terminate(Reason, StateName, State). + catch ssl_connection:terminate(Reason, StateName, State), + ensure_sender_terminate(Reason, State). format_status(Type, Data) -> ssl_connection:format_status(Type, Data). @@ -788,8 +811,8 @@ handle_info({CloseTag, Socket}, StateName, %% and then receive the final message. next_event(StateName, no_record, State) end; -handle_info({'EXIT', Pid, Reason}, _, - #state{protocol_specific = Pid} = State) -> +handle_info({'EXIT', Sender, Reason}, _, + #state{protocol_specific = #{sender := Sender}} = State) -> {stop, {shutdown, sender_died, Reason}, State}; handle_info(Msg, StateName, State) -> ssl_connection:StateName(info, Msg, State, ?MODULE). diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl index db67d7ddff..f5379f60e3 100644 --- a/lib/ssl/src/tls_sender.erl +++ b/lib/ssl/src/tls_sender.erl @@ -28,7 +28,8 @@ -include("ssl_api.hrl"). %% API --export([start/0, start/1, initialize/2, send_data/2, send_alert/2, renegotiate/1, +-export([start/0, start/1, initialize/2, send_data/2, send_alert/2, + send_and_ack_alert/2, renegotiate/1, setopts/2, update_connection_state/3, dist_tls_socket/1, dist_handshake_complete/3]). %% gen_statem callbacks @@ -80,7 +81,7 @@ initialize(Pid, InitMsg) -> gen_statem:call(Pid, {self(), InitMsg}). %%-------------------------------------------------------------------- --spec send_data(pid(), iodata()) -> ok. +-spec send_data(pid(), iodata()) -> ok | {error, term()}. %% Description: Send application data %%-------------------------------------------------------------------- send_data(Pid, AppData) -> @@ -89,13 +90,27 @@ send_data(Pid, AppData) -> %%-------------------------------------------------------------------- -spec send_alert(pid(), #alert{}) -> _. -%% Description: TLS connection process wants to end an Alert +%% Description: TLS connection process wants to send an Alert %% in the connection state. %%-------------------------------------------------------------------- send_alert(Pid, Alert) -> gen_statem:cast(Pid, Alert). %%-------------------------------------------------------------------- +-spec send_and_ack_alert(pid(), #alert{}) -> ok. +%% Description: TLS connection process wants to send an Alert +%% in the connection state and recive an ack. +%%-------------------------------------------------------------------- +send_and_ack_alert(Pid, Alert) -> + gen_statem:cast(Pid, {ack_alert, Alert}). +%%-------------------------------------------------------------------- +-spec setopts(pid(), [{packet, integer() | atom()}]) -> ok | {error, term()}. +%% Description: Send application data +%%-------------------------------------------------------------------- +setopts(Pid, Opts) -> + call(Pid, {set_opts, Opts}). + +%%-------------------------------------------------------------------- -spec renegotiate(pid()) -> {ok, WriteState::map()} | {error, closed}. %% Description: So TLS connection process can synchronize the %% encryption state to be used when handshaking. @@ -192,6 +207,8 @@ connection({call, From}, {application_data, AppData}, Data -> send_application_data(Data, From, ?FUNCTION_NAME, StateData) end; +connection({call, From}, {set_opts, _} = Call, StateData) -> + handle_call(From, Call, ?FUNCTION_NAME, StateData); connection({call, From}, dist_get_tls_socket, #data{protocol_cb = Connection, transport_cb = Transport, @@ -207,6 +224,10 @@ connection({call, From}, {dist_handshake_complete, _Node, DHandle}, #data{connec process_flag(priority, normal), Events = dist_data_events(DHandle, []), {next_state, ?FUNCTION_NAME, StateData#data{dist_handle = DHandle}, [{reply, From, ok} | Events]}; +connection(cast, {ack_alert, #alert{} = Alert}, #data{connection_pid = Pid} =StateData0) -> + StateData = send_tls_alert(Alert, StateData0), + Pid ! {self(), ack_alert}, + {next_state, ?FUNCTION_NAME, StateData}; connection(cast, #alert{} = Alert, StateData0) -> StateData = send_tls_alert(Alert, StateData0), {next_state, ?FUNCTION_NAME, StateData}; @@ -241,6 +262,8 @@ connection(info, Msg, StateData) -> StateData :: term()) -> gen_statem:event_handler_result(atom()). %%-------------------------------------------------------------------- +handshake({call, From}, {set_opts, _} = Call, StateData) -> + handle_call(From, Call, ?FUNCTION_NAME, StateData); handshake({call, _}, _, _) -> {keep_state_and_data, [postpone]}; handshake(cast, {new_write, WritesState, Version}, @@ -285,6 +308,9 @@ code_change(_OldVsn, State, Data, _Extra) -> %%%=================================================================== %%% Internal functions %%%=================================================================== +handle_call(From, {set_opts, Opts}, StateName, #data{socket_options = SockOpts} = StateData) -> + {next_state, StateName, StateData#data{socket_options = set_opts(SockOpts, Opts)}, [{reply, From, ok}]}. + handle_info({'DOWN', Monitor, _, _, Reason}, _, #data{connection_monitor = Monitor, dist_handle = Handle} = StateData) when Handle =/= undefined-> @@ -351,6 +377,10 @@ encode_size_packet(Bin, Size, Max) -> false -> <<Len:Size, Bin/binary>> end. + +set_opts(SocketOptions, [{packet, N}]) -> + SocketOptions#socket_options{packet = N}. + time_to_renegotiate(_Data, #{current_write := #{sequence_number := Num}}, RenegotiateAt) -> diff --git a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl index 27062d4801..04c4b257d9 100644 --- a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl @@ -155,7 +155,7 @@ empty_client(Config) when is_list(Config) -> run_failing_handshake(Config, [{alpn_advertised_protocols, []}], [{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}], - {connect_failed,{tls_alert,"no application protocol"}}). + {error,{tls_alert,"no application protocol"}}). %-------------------------------------------------------------------------------- @@ -163,7 +163,7 @@ empty_server(Config) when is_list(Config) -> run_failing_handshake(Config, [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}], [{alpn_preferred_protocols, []}], - {connect_failed,{tls_alert,"no application protocol"}}). + {error,{tls_alert,"no application protocol"}}). %-------------------------------------------------------------------------------- @@ -171,7 +171,7 @@ empty_client_empty_server(Config) when is_list(Config) -> run_failing_handshake(Config, [{alpn_advertised_protocols, []}], [{alpn_preferred_protocols, []}], - {connect_failed,{tls_alert,"no application protocol"}}). + {error,{tls_alert,"no application protocol"}}). %-------------------------------------------------------------------------------- @@ -179,7 +179,7 @@ no_matching_protocol(Config) when is_list(Config) -> run_failing_handshake(Config, [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}], [{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}], - {connect_failed,{tls_alert,"no application protocol"}}). + {error,{tls_alert,"no application protocol"}}). %-------------------------------------------------------------------------------- @@ -342,18 +342,19 @@ run_failing_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedResult) ServerOpts = ServerExtraOpts ++ ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, {from, self()}, {mfa, {?MODULE, placeholder, []}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - ExpectedResult - = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, placeholder, []}}, - {options, ClientOpts}]). + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, placeholder, []}}, + {options, ClientOpts}]), + ssl_test_lib:check_result(Server, ExpectedResult, + Client, ExpectedResult). run_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) -> Data = "hello world", diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index cae491b882..4585ea7306 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -1183,16 +1183,16 @@ fallback(Config) when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), - Client = - ssl_test_lib:start_client_error([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {from, self()}, {options, - [{fallback, true}, - {versions, ['tlsv1']} - | ClientOpts]}]), + Client = + ssl_test_lib:start_client_error([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {from, self()}, {options, + [{fallback, true}, + {versions, ['tlsv1']} + | ClientOpts]}]), - ssl_test_lib:check_result(Server, {error,{tls_alert,"inappropriate fallback"}}, - Client, {error,{tls_alert,"inappropriate fallback"}}). + ssl_test_lib:check_result(Server, {error,{tls_alert,"inappropriate fallback"}}, + Client, {error,{tls_alert,"inappropriate fallback"}}). %%-------------------------------------------------------------------- cipher_format() -> @@ -2645,14 +2645,14 @@ default_reject_anonymous(Config) when is_list(Config) -> {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, - [{ciphers,[CipherSuite]} | - ClientOpts]}]), + {host, Hostname}, + {from, self()}, + {options, + [{ciphers,[CipherSuite]} | + ClientOpts]}]), ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}}, - Client, {error, {tls_alert, "insufficient security"}}). + Client, {error, {tls_alert, "insufficient security"}}). %%-------------------------------------------------------------------- ciphers_ecdsa_signed_certs() -> @@ -3605,14 +3605,14 @@ no_common_signature_algs(Config) when is_list(Config) -> | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{signature_algs, [{sha384, rsa}]} - | ClientOpts]}]), + {host, Hostname}, + {from, self()}, + {options, [{signature_algs, [{sha384, rsa}]} + | ClientOpts]}]), ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}}, - Client, {error, {tls_alert, "insufficient security"}}). - + Client, {error, {tls_alert, "insufficient security"}}). + %%-------------------------------------------------------------------- tls_dont_crash_on_handshake_garbage() -> diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl index b387feb97a..588ca153a9 100644 --- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl +++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl @@ -620,8 +620,8 @@ cert_expired(Config) when is_list(Config) -> {from, self()}, {options, [{verify, verify_peer}, {active, Active} | ClientOpts]}]), - tcp_delivery_workaround(Server, {error, {tls_alert, "certificate expired"}}, - Client, {error, {tls_alert, "certificate expired"}}). + ssl_test_lib:check_result(Server, {error, {tls_alert, "certificate expired"}}, + Client, {error, {tls_alert, "certificate expired"}}). two_digits_str(N) when N < 10 -> lists:flatten(io_lib:format("0~p", [N])); @@ -729,8 +729,8 @@ critical_extension_verify_server(Config) when is_list(Config) -> %% This certificate has a critical extension that we don't %% understand. Therefore, verification should fail. - tcp_delivery_workaround(Server, {error, {tls_alert, "unsupported certificate"}}, - Client, {error, {tls_alert, "unsupported certificate"}}), + ssl_test_lib:check_result(Server, {error, {tls_alert, "unsupported certificate"}}, + Client, {error, {tls_alert, "unsupported certificate"}}), ssl_test_lib:close(Server). %%-------------------------------------------------------------------- @@ -909,8 +909,8 @@ invalid_signature_server(Config) when is_list(Config) -> {from, self()}, {options, [{verify, verify_peer} | ClientOpts]}]), - tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}}, - Client, {error, {tls_alert, "unknown ca"}}). + ssl_test_lib:check_result(Server, {error, {tls_alert, "unknown ca"}}, + Client, {error, {tls_alert, "unknown ca"}}). %%-------------------------------------------------------------------- @@ -946,8 +946,8 @@ invalid_signature_client(Config) when is_list(Config) -> {from, self()}, {options, NewClientOpts}]), - tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}}, - Client, {error, {tls_alert, "unknown ca"}}). + ssl_test_lib:check_result(Server, {error, {tls_alert, "unknown ca"}}, + Client, {error, {tls_alert, "unknown ca"}}). %%-------------------------------------------------------------------- @@ -1236,41 +1236,3 @@ incomplete_chain(Config) when is_list(Config) -> %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- -tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) -> - receive - {Server, ServerMsg} -> - client_msg(Client, ClientMsg); - {Client, ClientMsg} -> - server_msg(Server, ServerMsg); - {Client, {error,closed}} -> - server_msg(Server, ServerMsg); - {Server, {error,closed}} -> - client_msg(Client, ClientMsg) - end. - -client_msg(Client, ClientMsg) -> - receive - {Client, ClientMsg} -> - ok; - {Client, {error,closed}} -> - ct:log("client got close"), - ok; - {Client, {error, Reason}} -> - ct:log("client got econnaborted: ~p", [Reason]), - ok; - Unexpected -> - ct:fail(Unexpected) - end. -server_msg(Server, ServerMsg) -> - receive - {Server, ServerMsg} -> - ok; - {Server, {error,closed}} -> - ct:log("server got close"), - ok; - {Server, {error, Reason}} -> - ct:log("server got econnaborted: ~p", [Reason]), - ok; - Unexpected -> - ct:fail(Unexpected) - end. diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index 3261244ace..ebf8ddbfac 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -141,6 +141,7 @@ socket_active_packet_tests() -> packet_4_active_some_big, packet_wait_active, packet_size_active, + packet_switch, %% inet header option should be deprecated! header_decode_one_byte_active, header_decode_two_bytes_active, @@ -702,6 +703,34 @@ packet_size_passive(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +packet_switch() -> + [{doc,"Test packet option {packet, 2} followd by {packet, 4}"}]. + +packet_switch(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, send_switch_packet ,["Hello World", 4]}}, + {options, [{nodelay, true},{packet, 2} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, recv_switch_packet, ["Hello World", 4]}}, + {options, [{nodelay, true}, {packet, 2} | + ClientOpts]}]), + + ssl_test_lib:check_result(Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + %%-------------------------------------------------------------------- packet_cdr_decode() -> [{doc,"Test setting the packet option {packet, cdr}, {mode, binary}"}]. @@ -2286,3 +2315,26 @@ client_reject_packet_opt(Config, PacketOpt) -> ClientOpts]}]), ssl_test_lib:check_result(Client, {error, {options, {not_supported, PacketOpt}}}). + + +send_switch_packet(SslSocket, Data, NextPacket) -> + ssl:send(SslSocket, Data), + receive + {ssl, SslSocket, "Hello World"} -> + ssl:setopts(SslSocket, [{packet, NextPacket}]), + ssl:send(SslSocket, Data), + receive + {ssl, SslSocket, "Hello World"} -> + ok + end + end. +recv_switch_packet(SslSocket, Data, NextPacket) -> + receive + {ssl, SslSocket, "Hello World"} -> + ssl:send(SslSocket, Data), + ssl:setopts(SslSocket, [{packet, NextPacket}]), + receive + {ssl, SslSocket, "Hello World"} -> + ssl:send(SslSocket, Data) + end + end. diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index f3235f5614..39a5bcaad6 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1003,7 +1003,6 @@ ecc_test_error(COpts, SOpts, CECCOpts, SECCOpts, Config) -> Error = {error, {tls_alert, "insufficient security"}}, check_result(Server, Error, Client, Error). - start_client(openssl, Port, ClientOpts, Config) -> Cert = proplists:get_value(certfile, ClientOpts), Key = proplists:get_value(keyfile, ClientOpts), @@ -2061,3 +2060,40 @@ hardcode_dsa_key(3) -> y = 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358, x = 1457508827177594730669011716588605181448418352823}. +tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) -> + receive + {Server, ServerMsg} -> + client_msg(Client, ClientMsg); + {Client, ClientMsg} -> + server_msg(Server, ServerMsg); + {Client, {error,closed}} -> + server_msg(Server, ServerMsg); + {Server, {error,closed}} -> + client_msg(Client, ClientMsg) + end. +client_msg(Client, ClientMsg) -> + receive + {Client, ClientMsg} -> + ok; + {Client, {error,closed}} -> + ct:log("client got close"), + ok; + {Client, {error, Reason}} -> + ct:log("client got econnaborted: ~p", [Reason]), + ok; + Unexpected -> + ct:fail(Unexpected) + end. +server_msg(Server, ServerMsg) -> + receive + {Server, ServerMsg} -> + ok; + {Server, {error,closed}} -> + ct:log("server got close"), + ok; + {Server, {error, Reason}} -> + ct:log("server got econnaborted: ~p", [Reason]), + ok; + Unexpected -> + ct:fail(Unexpected) + end. diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 741bdb6df0..b184c83f99 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.0.2 +SSL_VSN = 9.0.3 |