From f29538e8002cf0e37fa4f988fbf5484c46513bf4 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Wed, 17 Feb 2010 15:49:22 +0000 Subject: OTP-8459 Do a controlled shutdown if a non ssl packet arrives as the first packet. --- lib/ssl/src/ssl_connection.erl | 14 ++++---- lib/ssl/test/ssl_basic_SUITE.erl | 43 ++++++++++++++++++++++-- lib/ssl/test/ssl_packet_SUITE.erl | 69 ++++++++++++++++++++++++++++++++++++++- lib/ssl/test/ssl_test_lib.erl | 56 ++++++++++++++++--------------- 4 files changed, 147 insertions(+), 35 deletions(-) (limited to 'lib/ssl') diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index bbffa1e564..eaa022ed29 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1429,12 +1429,10 @@ encode_handshake(HandshakeRec, SigAlg, Version, ConnectionStates0, Hashes0) -> encode_packet(Data, #socket_options{packet=Packet}) -> case Packet of - 0 -> Data; 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1); 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1); 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1); - _ -> - throw({error, {badarg, {eoptions, {packet, Packet}}}}) + _ -> Data end. encode_size_packet(Bin, Size, Max) -> @@ -1732,9 +1730,13 @@ handle_own_alert(Alert, Version, StateName, role = Role, connection_states = ConnectionStates, log_alert = Log}) -> - {BinMsg, _} = - encode_alert(Alert, Version, ConnectionStates), - Transport:send(Socket, BinMsg), + try + {BinMsg, _} = + encode_alert(Alert, Version, ConnectionStates), + Transport:send(Socket, BinMsg) + catch _:_ -> %% Can crash if we are in a uninitialized state + ignore + end, log_alert(Log, StateName, Alert), alert_user(User, Alert, Role). diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 22a0fb1ee1..3d9cec43dd 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -150,8 +150,8 @@ all(doc) -> all(suite) -> [app, connection_info, controlling_process, controller_dies, peercert, connect_dist, - peername, sockname, socket_options, versions, cipher_suites, upgrade, - upgrade_with_timeout, + peername, sockname, socket_options, versions, cipher_suites, + upgrade, upgrade_with_timeout, tcp_connect, ipv6, ekeyfile, ecertfile, ecacertfile, eoptions, shutdown, shutdown_write, shutdown_both, shutdown_error, ciphers, send_close, @@ -754,6 +754,45 @@ upgrade_with_timeout(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +tcp_connect(doc) -> + ["Test what happens when a tcp tries to connect, i,e. a bad (ssl) packet is sent first"]; + +tcp_connect(suite) -> + []; + +tcp_connect(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + TcpOpts = [binary, {reuseaddr, true}], + + Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {timeout, 5000}, + {mfa, {?MODULE, should_close, []}}, + {tcp_options, TcpOpts}, + {ssl_options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]), + test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]), + gen_tcp:send(Socket, ""), + + ssl_test_lib:check_result(Server, {error,esslerrssl}, tcp_closed, Socket), + + ssl_test_lib:close(Server). + + +should_close(Socket) -> + receive + {ssl, Socket, closed} -> + server_closed; + Other -> + exit({?LINE, Other}) + end. + %%-------------------------------------------------------------------- ipv6(doc) -> ["Test ipv6."]; diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index 3f8a560be9..f031552457 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -143,7 +143,8 @@ all(suite) -> packet_send_to_large, packet_wait_passive, packet_wait_active, packet_baddata_passive, packet_baddata_active, - packet_size_passive, packet_size_active + packet_size_passive, packet_size_active, + packet_erl_decode ]. %% Test cases starts here. @@ -1400,6 +1401,72 @@ packet_size_passive(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +packet_erl_decode(doc) -> + ["Test that packets of sent to erlang:decode_packet works, i.e. currently" + "asn1 | cdr | sunrm | fcgi | tpkt | line | http | http_bin" + ]; +packet_erl_decode(suite) -> + []; + +packet_erl_decode(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + %% A valid cdr packet + Data = <<71,73,79,80,1,2,2,1,0,0,0,41,0,0,0,0,0,0,0,0,0,0,0,1,78, + 69,79,0,0,0,0,2,0,10,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,4,49>>, + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_packet_decode ,[Data]}}, + {options, [{active, true}, binary, {packet, cdr}|ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_packet_decode, [Data]}}, + {options, [{active, true}, binary | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +server_packet_decode(Socket, CDR) -> + receive + {ssl, Socket, CDR} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + ok = ssl:send(Socket, CDR), + receive + {ssl, Socket, CDR} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + ok = ssl:send(Socket, CDR), + ok. + +client_packet_decode(Socket, CDR) -> + <> = CDR, + ok = ssl:send(Socket, P1), + ok = ssl:send(Socket, P2), + receive + {ssl, Socket, CDR} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + ssl:setopts(Socket, [{packet, cdr}]), + ok = ssl:send(Socket, CDR), + receive + {ssl, Socket, CDR} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + ok. + + %%-------------------------------------------------------------------- %% Internal functions diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 7ed19b3a05..2df2e70679 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -278,10 +278,10 @@ run_upgrade_server(Opts) -> TcpOptions = proplists:get_value(tcp_options, Opts), SslOptions = proplists:get_value(ssl_options, Opts), Pid = proplists:get_value(from, Opts), - + test_server:format("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]), {ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]), - + case Port of 0 -> {ok, {_, NewPort}} = inet:sockname(ListenSocket), @@ -292,25 +292,29 @@ run_upgrade_server(Opts) -> test_server:format("gen_tcp:accept(~p)~n", [ListenSocket]), {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, [ListenSocket]), - - {ok, SslAcceptSocket} = case TimeOut of - infinity -> - test_server:format("ssl:ssl_accept(~p, ~p)~n", - [AcceptSocket, SslOptions]), - rpc:call(Node, ssl, ssl_accept, - [AcceptSocket, SslOptions]); - _ -> - test_server:format("ssl:ssl_accept(~p, ~p, ~p)~n", - [AcceptSocket, SslOptions, TimeOut]), - rpc:call(Node, ssl, ssl_accept, - [AcceptSocket, SslOptions, TimeOut]) - end, - {Module, Function, Args} = proplists:get_value(mfa, Opts), - Msg = rpc:call(Node, Module, Function, [SslAcceptSocket | Args]), - Pid ! {self(), Msg}, - receive - close -> - ok = rpc:call(Node, ssl, close, [SslAcceptSocket]) + + try + {ok, SslAcceptSocket} = case TimeOut of + infinity -> + test_server:format("ssl:ssl_accept(~p, ~p)~n", + [AcceptSocket, SslOptions]), + rpc:call(Node, ssl, ssl_accept, + [AcceptSocket, SslOptions]); + _ -> + test_server:format("ssl:ssl_accept(~p, ~p, ~p)~n", + [AcceptSocket, SslOptions, TimeOut]), + rpc:call(Node, ssl, ssl_accept, + [AcceptSocket, SslOptions, TimeOut]) + end, + {Module, Function, Args} = proplists:get_value(mfa, Opts), + Msg = rpc:call(Node, Module, Function, [SslAcceptSocket | Args]), + Pid ! {self(), Msg}, + receive + close -> + ok = rpc:call(Node, ssl, close, [SslAcceptSocket]) + end + catch error:{badmatch, Error} -> + Pid ! {self(), Error} end. start_upgrade_client(Args) -> -- cgit v1.2.3