diff options
Diffstat (limited to 'lib/ssh/src')
-rw-r--r-- | lib/ssh/src/ssh.appup.src | 16 | ||||
-rw-r--r-- | lib/ssh/src/ssh.erl | 18 | ||||
-rw-r--r-- | lib/ssh/src/ssh_acceptor_sup.erl | 13 | ||||
-rw-r--r-- | lib/ssh/src/ssh_connect.hrl | 3 | ||||
-rw-r--r-- | lib/ssh/src/ssh_connection_handler.erl | 86 | ||||
-rw-r--r-- | lib/ssh/src/ssh_system_sup.erl | 8 | ||||
-rw-r--r-- | lib/ssh/src/ssh_transport.erl | 27 |
7 files changed, 107 insertions, 64 deletions
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src index 8269f89e40..1917c95f5a 100644 --- a/lib/ssh/src/ssh.appup.src +++ b/lib/ssh/src/ssh.appup.src @@ -19,25 +19,9 @@ {"%VSN%", [ - {"3.0.2", [{load_module, ssh_message, soft_purge, soft_purge, []}, - {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, - {load_module, ssh_io, soft_purge, soft_purge, []}]}, - {"3.0.1", [{load_module, ssh, soft_purge, soft_purge, []}, - {load_module, ssh_acceptor, soft_purge, soft_purge, []}, - {load_module, ssh_message, soft_purge, soft_purge, []}, - {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, - {load_module, ssh_io, soft_purge, soft_purge, []}]}, {<<".*">>, [{restart_application, ssh}]} ], [ - {"3.0.2", [{load_module, ssh_message, soft_purge, soft_purge, []}, - {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, - {load_module, ssh_io, soft_purge, soft_purge, []}]}, - {"3.0.1", [{load_module, ssh, soft_purge, soft_purge, []}, - {load_module, ssh_acceptor, soft_purge, soft_purge, []}, - {load_module, ssh_message, soft_purge, soft_purge, []}, - {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, - {load_module, ssh_io, soft_purge, soft_purge, []}]}, {<<".*">>, [{restart_application, ssh}]} ] }. diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 8a8d4bb89e..de047d3c83 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -234,22 +234,26 @@ do_start_daemon(Host, Port, Options, SocketOptions) -> {port, Port}, {role, server}, {socket_opts, SocketOptions}, {ssh_opts, Options}]) of - {ok, SysSup} -> - {ok, SysSup}; {error, {already_started, _}} -> {error, eaddrinuse}; - {error, R} -> - {error, R} + Result = {Code, _} when (Code == ok) or (Code == error) -> + Result catch exit:{noproc, _} -> {error, ssh_not_started} end; Sup -> - case ssh_system_sup:restart_acceptor(Host, Port) of + AccPid = ssh_system_sup:acceptor_supervisor(Sup), + case ssh_acceptor_sup:start_child(AccPid, [{address, Host}, + {port, Port}, {role, server}, + {socket_opts, SocketOptions}, + {ssh_opts, Options}]) of + {error, {already_started, _}} -> + {error, eaddrinuse}; {ok, _} -> {ok, Sup}; - _ -> - {error, eaddrinuse} + Other -> + Other end end. diff --git a/lib/ssh/src/ssh_acceptor_sup.erl b/lib/ssh/src/ssh_acceptor_sup.erl index 2be729d305..46fdef07d0 100644 --- a/lib/ssh/src/ssh_acceptor_sup.erl +++ b/lib/ssh/src/ssh_acceptor_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. 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 @@ -26,7 +26,7 @@ -module(ssh_acceptor_sup). -behaviour(supervisor). --export([start_link/1, start_child/2, stop_child/2]). +-export([start_link/1, start_child/2, stop_child/3]). %% Supervisor callback -export([init/1]). @@ -45,18 +45,17 @@ start_child(AccSup, ServerOpts) -> {error, already_present} -> Address = proplists:get_value(address, ServerOpts), Port = proplists:get_value(port, ServerOpts), - Name = id(Address, Port), - supervisor:delete_child(?MODULE, Name), + stop_child(AccSup, Address, Port), supervisor:start_child(AccSup, Spec); Reply -> Reply end. -stop_child(Address, Port) -> +stop_child(AccSup, Address, Port) -> Name = id(Address, Port), - case supervisor:terminate_child(?MODULE, Name) of + case supervisor:terminate_child(AccSup, Name) of ok -> - supervisor:delete_child(?MODULE, Name); + supervisor:delete_child(AccSup, Name); Error -> Error end. diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl index 8421b07167..9307dbbad0 100644 --- a/lib/ssh/src/ssh_connect.hrl +++ b/lib/ssh/src/ssh_connect.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. 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 @@ -26,6 +26,7 @@ -define(DEFAULT_PACKET_SIZE, 32768). -define(DEFAULT_WINDOW_SIZE, 2*?DEFAULT_PACKET_SIZE). -define(DEFAULT_TIMEOUT, 5000). +-define(MAX_PROTO_VERSION, 255). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 86804c4436..4fbc5d0ae2 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. 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 @@ -48,7 +48,7 @@ userauth/2, connected/2]). -export([init/1, handle_event/3, - handle_sync_event/4, handle_info/3, terminate/3, code_change/4]). + handle_sync_event/4, handle_info/3, terminate/3, format_status/2, code_change/4]). -record(state, { role, @@ -71,7 +71,8 @@ connection_queue, address, port, - opts + opts, + recbuf }). -type state_name() :: hello | kexinit | key_exchange | new_keys | userauth | connection. @@ -103,12 +104,22 @@ start_connection(client = Role, Socket, Options, Timeout) -> end; start_connection(server = Role, Socket, Options, Timeout) -> + SSH_Opts = proplists:get_value(ssh_opts, Options, []), try - case proplists:get_value(parallel_login, Options, false) of + case proplists:get_value(parallel_login, SSH_Opts, false) of true -> - spawn(fun() -> start_server_connection(Role, Socket, Options, Timeout) end); + HandshakerPid = + spawn_link(fun() -> + receive + {do_handshake, Pid} -> + handshake(Pid, erlang:monitor(process,Pid), Timeout) + end + end), + ChildPid = start_the_connection_child(HandshakerPid, Role, Socket, Options), + HandshakerPid ! {do_handshake, ChildPid}; false -> - start_server_connection(Role, Socket, Options, Timeout) + ChildPid = start_the_connection_child(self(), Role, Socket, Options), + handshake(ChildPid, erlang:monitor(process,ChildPid), Timeout) end catch exit:{noproc, _} -> @@ -117,16 +128,14 @@ start_connection(server = Role, Socket, Options, Timeout) -> {error, Error} end. - -start_server_connection(server = Role, Socket, Options, Timeout) -> +start_the_connection_child(UserPid, Role, Socket, Options) -> Sups = proplists:get_value(supervisors, Options), ConnectionSup = proplists:get_value(connection_sup, Sups), - Opts = [{supervisors, Sups}, {user_pid, self()} | proplists:get_value(ssh_opts, Options, [])], + Opts = [{supervisors, Sups}, {user_pid, UserPid} | proplists:get_value(ssh_opts, Options, [])], {ok, Pid} = ssh_connection_sup:start_child(ConnectionSup, [Role, Socket, Opts]), {_, Callback, _} = proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}), socket_control(Socket, Pid, Callback), - Ref = erlang:monitor(process, Pid), - handshake(Pid, Ref, Timeout). + Pid. start_link(Role, Socket, Options) -> @@ -293,28 +302,39 @@ info(ConnectionHandler, ChannelProcess) -> hello(socket_control, #state{socket = Socket, ssh_params = Ssh} = State) -> VsnMsg = ssh_transport:hello_version_msg(string_version(Ssh)), send_msg(VsnMsg, State), - inet:setopts(Socket, [{packet, line}, {active, once}]), - {next_state, hello, State}; + {ok, [{recbuf, Size}]} = inet:getopts(Socket, [recbuf]), + inet:setopts(Socket, [{packet, line}, {active, once}, {recbuf, ?MAX_PROTO_VERSION}]), + {next_state, hello, State#state{recbuf = Size}}; -hello({info_line, _Line},#state{socket = Socket} = State) -> +hello({info_line, _Line},#state{role = client, socket = Socket} = State) -> + %% The server may send info lines before the version_exchange inet:setopts(Socket, [{active, once}]), {next_state, hello, State}; +hello({info_line, _Line},#state{role = server} = State) -> + DisconnectMsg = + #ssh_msg_disconnect{code = + ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Did not receive expected protocol version exchange", + language = "en"}, + handle_disconnect(DisconnectMsg, State); + hello({version_exchange, Version}, #state{ssh_params = Ssh0, - socket = Socket} = State) -> + socket = Socket, + recbuf = Size} = State) -> {NumVsn, StrVsn} = ssh_transport:handle_hello_version(Version), case handle_version(NumVsn, StrVsn, Ssh0) of {ok, Ssh1} -> - inet:setopts(Socket, [{packet,0}, {mode,binary}, {active, once}]), + inet:setopts(Socket, [{packet,0}, {mode,binary}, {active, once}, {recbuf, Size}]), {KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(Ssh1), send_msg(SshPacket, State), {next_state, kexinit, next_packet(State#state{ssh_params = Ssh, key_exchange_init_msg = KeyInitMsg})}; not_supported -> - DisconnectMsg = + DisconnectMsg = #ssh_msg_disconnect{code = - ?SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, + ?SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, description = "Protocol version " ++ StrVsn ++ " not supported", language = "en"}, @@ -951,6 +971,36 @@ terminate_subsytem(#connection{system_supervisor = SysSup, terminate_subsytem(_) -> ok. +format_status(normal, [_, State]) -> + [{data, [{"StateData", State}]}]; +format_status(terminate, [_, State]) -> + SshParams0 = (State#state.ssh_params), + SshParams = SshParams0#ssh{c_keyinit = "***", + s_keyinit = "***", + send_mac_key = "***", + send_mac_size = "***", + recv_mac_key = "***", + recv_mac_size = "***", + encrypt_keys = "***", + encrypt_ctx = "***", + decrypt_keys = "***", + decrypt_ctx = "***", + compress_ctx = "***", + decompress_ctx = "***", + shared_secret = "***", + exchanged_hash = "***", + session_id = "***", + keyex_key = "***", + keyex_info = "***", + available_host_keys = "***"}, + [{data, [{"StateData", State#state{decoded_data_buffer = "***", + encoded_data_buffer = "***", + key_exchange_init_msg = "***", + opts = "***", + recbuf = "***", + ssh_params = SshParams + }}]}]. + %%-------------------------------------------------------------------- -spec code_change(OldVsn::term(), state_name(), Oldstate::term(), Extra::term()) -> {ok, state_name(), #state{}}. diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl index 848133f838..660fe8bb65 100644 --- a/lib/ssh/src/ssh_system_sup.erl +++ b/lib/ssh/src/ssh_system_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. 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 @@ -173,8 +173,8 @@ ssh_acceptor_sup([_ | Rest]) -> ssh_acceptor_sup(Rest). stop_acceptor(Sup) -> - [Name] = - [SupName || {SupName, _, _, [ssh_acceptor_sup]} <- + [{Name, AcceptorSup}] = + [{SupName, ASup} || {SupName, ASup, _, [ssh_acceptor_sup]} <- supervisor:which_children(Sup)], - supervisor:terminate_child(Sup, Name). + supervisor:terminate_child(AcceptorSup, Name). diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index ea05c849b7..76fa776113 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -82,16 +82,21 @@ format_version({Major,Minor}) -> integer_to_list(Minor) ++ "-Erlang". handle_hello_version(Version) -> - StrVersion = trim_tail(Version), - case string:tokens(Version, "-") of - [_, "2.0" | _] -> - {{2,0}, StrVersion}; - [_, "1.99" | _] -> - {{2,0}, StrVersion}; - [_, "1.3" | _] -> - {{1,3}, StrVersion}; - [_, "1.5" | _] -> - {{1,5}, StrVersion} + try + StrVersion = trim_tail(Version), + case string:tokens(Version, "-") of + [_, "2.0" | _] -> + {{2,0}, StrVersion}; + [_, "1.99" | _] -> + {{2,0}, StrVersion}; + [_, "1.3" | _] -> + {{1,3}, StrVersion}; + [_, "1.5" | _] -> + {{1,5}, StrVersion} + end + catch + error:_ -> + {undefined, "unknown version"} end. key_exchange_init_msg(Ssh0) -> |