diff options
Diffstat (limited to 'lib/ssh')
| -rw-r--r-- | lib/ssh/doc/src/Makefile | 2 | ||||
| -rw-r--r-- | lib/ssh/doc/src/notes.xml | 72 | ||||
| -rw-r--r-- | lib/ssh/doc/src/ssh.xml | 14 | ||||
| -rw-r--r-- | lib/ssh/examples/Makefile | 2 | ||||
| -rw-r--r-- | lib/ssh/src/ssh.appup.src | 24 | ||||
| -rw-r--r-- | lib/ssh/src/ssh.erl | 35 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_connection.erl | 33 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_connection_sup.erl | 10 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_file.erl | 11 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_sftpd_file_api.erl | 62 | ||||
| -rw-r--r-- | lib/ssh/test/ssh.spec.vxworks | 3 | ||||
| -rw-r--r-- | lib/ssh/test/ssh_basic_SUITE.erl | 40 | ||||
| -rw-r--r-- | lib/ssh/vsn.mk | 2 |
13 files changed, 206 insertions, 104 deletions
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile index 38782a3b00..da99c4ea0f 100644 --- a/lib/ssh/doc/src/Makefile +++ b/lib/ssh/doc/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2011. All Rights Reserved. +# Copyright Ericsson AB 2004-2012. 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 diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index a85cada732..36010da07a 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2011</year> + <year>2004</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -29,6 +29,76 @@ <file>notes.xml</file> </header> +<section><title>Ssh 2.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Ssh now only sends one channel close message under all + circumstances, before it would sometimes incorrectly send + two.</p> + <p> + Own Id: OTP-10060</p> + </item> + <item> + <p> + The options check mistreated the ip_v6_disable-option, + and did not handle some, at the moment, undocumented + options correctly.</p> + <p> + Own Id: OTP-10061</p> + </item> + <item> + <p> + The channel id in a channel failure message, sent to the + peer, is now in all cases the remote channel id</p> + <p> + Own Id: OTP-10062</p> + </item> + <item> + <p> + Improved handling of multiple closes to avoid occasional + crashes when a channel is closed more than once.</p> + <p> + Own Id: OTP-10112</p> + </item> + <item> + <p> + Fix lib/src/test/ssh_basic_SUITE.erl to fix IPv6 option + typos</p> + <p> + Fixed incorrect option "ipv6_disable" to "ipv6_disabled" + as documented in the ssh manual.</p> + <p> + Own Id: OTP-10219</p> + </item> + <item> + <p> + SSH: Make "auth_methods" server option re-usable</p> + <p> + The 'auth_methods' option is used by the server side of + the SSH code to tell a connecting SSH client about the + authentication methods that are supported by the server. + The code still extracts and handles the 'auth_methods' + option from Opts in appropriate places, but the Opts + checking code in ssh.erl didn't allow that option to be + specified.</p> + <p> + Own Id: OTP-10224</p> + </item> + <item> + <p> + Use the correct channel id when adjusting the channel + window</p> + <p> + Own Id: OTP-10232</p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 2.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index e30c6f1ccc..b84b3a3dcb 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -259,11 +259,17 @@ that identifies the host for ssh. The default is <c><![CDATA[/etc/ssh]]></c>, note that SSH normally requires the host files there to be readable only by - root.</p> + root.</p> + </item> + <tag><c><![CDATA[{auth_methods, string()}]]></c></tag> + <item> + <p>Comma separated string that determines which authentication methodes that the server + should support and in what order they will be tried. Defaults to + <c><![CDATA["publickey,keyboard_interactive,password"]]></c></p> </item> - <tag><c><![CDATA[{user_passwords, [{string() = User, string() = Password}]}]]></c></tag> - <item> - <p>Provide passwords for password authentication.They will + <tag><c><![CDATA[{user_passwords, [{string() = User, string() = Password}]}]]></c></tag> + <item> + <p>Provide passwords for password authentication.They will be used when someone tries to connect to the server and public key user authentication fails. The option provides a list of valid user names and the corresponding password. diff --git a/lib/ssh/examples/Makefile b/lib/ssh/examples/Makefile index 84c7edac8c..de019f75b5 100644 --- a/lib/ssh/examples/Makefile +++ b/lib/ssh/examples/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2005-2010. All Rights Reserved. +# Copyright Ericsson AB 2005-2012. 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 diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src index 0542054596..d08dbafc32 100644 --- a/lib/ssh/src/ssh.appup.src +++ b/lib/ssh/src/ssh.appup.src @@ -18,12 +18,26 @@ %% {"%VSN%", - [ - {<<"2\\.*">>, [{restart_application, ssh}]}, - {<<"1\\.*">>, [{restart_application, ssh}]} + [ + {<<"2.1">>, [{load_module, ssh_sftpd_file_api, soft_purge, soft_purge, []}, + {load_module, ssh_connection, soft_purge, soft_purge, []}, + {load_module, ssh_connection_manager, soft_purge, soft_purge, []}, + {load_module, ssh_auth, soft_purge, soft_purge, []}, + {load_module, ssh_channel, soft_purge, soft_purge, []}, + {load_module, ssh_file, soft_purge, soft_purge, []}]}, + {load_module, ssh, soft_purge, soft_purge, []}]}, + {<<"2.0\\.*">>, [{restart_application, ssh}]}, + {<<"1\\.*">>, [{restart_application, ssh}]} ], [ - {<<"2\\.*">>, [{restart_application, ssh}]}, - {<<"1\\.*">>, [{restart_application, ssh}]} + {<<"2.1">>,[{load_module, ssh_sftpd_file_api, soft_purge, soft_purge, []}, + {load_module, ssh_connection, soft_purge, soft_purge, []}, + {load_module, ssh_connection_manager, soft_purge, soft_purge, []}, + {load_module, ssh_auth, soft_purge, soft_purge, []}, + {load_module, ssh_channel, soft_purge, soft_purge, []}, + {load_module, ssh_file, soft_purge, soft_purge, []}]}, + {load_module, ssh, soft_purge, soft_purge, []}]}, + {<<"2.0\\.*">>, [{restart_application, ssh}]}, + {<<"1\\.*">>, [{restart_application, ssh}]} ] }. diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index f4a40c81a4..3395f73884 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -91,10 +91,8 @@ do_connect(Host, Port, SocketOptions, SshOptions, Timeout, DisableIpv6) -> {ok, ConnectionSup} -> {ok, Manager} = ssh_connection_sup:connection_manager(ConnectionSup), - MRef = erlang:monitor(process, Manager), receive {Manager, is_connected} -> - do_demonitor(MRef, Manager), {ok, Manager}; %% When the connection fails %% ssh_connection_sup:connection_manager @@ -102,30 +100,13 @@ do_connect(Host, Port, SocketOptions, SshOptions, Timeout, DisableIpv6) -> %% could allready have terminated, so we will not %% match the Manager in this case {_, not_connected, {error, econnrefused}} when DisableIpv6 == false -> - do_demonitor(MRef, Manager), do_connect(Host, Port, proplists:delete(inet6, SocketOptions), SshOptions, Timeout, true); {_, not_connected, {error, Reason}} -> - do_demonitor(MRef, Manager), {error, Reason}; {_, not_connected, Other} -> - do_demonitor(MRef, Manager), - {error, Other}; - {'DOWN', MRef, _, Manager, Reason} when is_pid(Manager) -> - error_logger:warning_report([{ssh, connect}, - {diagnose, - "Connection was closed before properly set up."}, - {host, Host}, - {port, Port}, - {reason, Reason}]), - receive %% Clear EXIT message from queue - {'EXIT', Manager, _What} -> - {error, channel_closed} - after 0 -> - {error, channel_closed} - end + {error, Other} after Timeout -> - do_demonitor(MRef, Manager), ssh_connection_manager:stop(Manager), {error, timeout} end @@ -134,16 +115,6 @@ do_connect(Host, Port, SocketOptions, SshOptions, Timeout, DisableIpv6) -> {error, ssh_not_started} end. -do_demonitor(MRef, Manager) -> - erlang:demonitor(MRef), - receive - {'DOWN', MRef, _, Manager, _} -> - ok - after 0 -> - ok - end. - - %%-------------------------------------------------------------------- %% Function: close(ConnectionRef) -> ok %% @@ -369,6 +340,8 @@ handle_option([{shell, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{exec, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{auth_methods, _} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions). @@ -408,6 +381,8 @@ handle_ssh_option({exec, {Module, Function, _}} = Opt) when is_atom(Module), is_atom(Function) -> Opt; +handle_ssh_option({auth_methods, Value} = Opt) when is_list(Value) -> + Opt; handle_ssh_option({infofun, Value} = Opt) when is_function(Value) -> Opt; handle_ssh_option({connectfun, Value} = Opt) when is_function(Value) -> diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl index c46f799b6d..e3b8ebfb79 100644 --- a/lib/ssh/src/ssh_connection.erl +++ b/lib/ssh/src/ssh_connection.erl @@ -436,32 +436,32 @@ handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId, #connection{channel_cache = Cache} = Connection, ConnectionPid, _) -> - #channel{send_window_size = Size} = + #channel{send_window_size = Size, remote_id = RemoteId} = Channel0 = ssh_channel:cache_lookup(Cache, ChannelId), - + {SendList, Channel} = %% TODO: Datatype 0 ? update_send_window(Channel0#channel{send_window_size = Size + Add}, - 0, <<>>, Connection), + 0, undefined, Connection), Replies = lists:map(fun({Type, Data}) -> {connection_reply, ConnectionPid, - channel_data_msg(ChannelId, Type, Data)} + channel_data_msg(RemoteId, Type, Data)} end, SendList), FlowCtrlMsgs = flow_control(Channel, Cache), {{replies, Replies ++ FlowCtrlMsgs}, Connection}; handle_msg(#ssh_msg_channel_open{channel_type = "session" = Type, - sender_channel = ChannelId, + sender_channel = RemoteId, initial_window_size = WindowSz, maximum_packet_size = PacketSz}, Connection0, ConnectionPid, server) -> - try setup_session(Connection0, ConnectionPid, ChannelId, + try setup_session(Connection0, ConnectionPid, RemoteId, Type, WindowSz, PacketSz) of Result -> Result catch _:_ -> - FailMsg = channel_open_failure_msg(ChannelId, + FailMsg = channel_open_failure_msg(RemoteId, ?SSH_OPEN_CONNECT_FAILED, "Connection refused", "en"), {{replies, [{connection_reply, ConnectionPid, FailMsg}]}, @@ -532,9 +532,9 @@ handle_msg(#ssh_msg_channel_open{channel_type = "forwarded-tcpip", {{replies, [{connection_reply, ConnectionPid, FailMsg}]}, Connection}; -handle_msg(#ssh_msg_channel_open{sender_channel = ChannelId}, Connection, +handle_msg(#ssh_msg_channel_open{sender_channel = RemoteId}, Connection, ConnectionPid, _) -> - FailMsg = channel_open_failure_msg(ChannelId, + FailMsg = channel_open_failure_msg(RemoteId, ?SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "Not allowed", "en"), {{replies, [{connection_reply, ConnectionPid, FailMsg}]}, Connection}; @@ -1073,14 +1073,15 @@ request_reply_or_data(#channel{local_id = ChannelId, user = ChannelPid}, false -> {{channel_data, ChannelPid, Reply}, Connection} end. +update_send_window(Channel, _, undefined, + #connection{channel_cache = Cache}) -> + do_update_send_window(Channel, Channel#channel.send_buf, Cache); + +update_send_window(Channel, DataType, Data, + #connection{channel_cache = Cache}) -> + do_update_send_window(Channel, Channel#channel.send_buf ++ [{DataType, Data}], Cache). -update_send_window(Channel0, DataType, Data, - #connection{channel_cache = Cache}) -> - Buf0 = if Data == <<>> -> - Channel0#channel.send_buf; - true -> - Channel0#channel.send_buf ++ [{DataType, Data}] - end, +do_update_send_window(Channel0, Buf0, Cache) -> {Buf1, NewSz, Buf2} = get_window(Buf0, Channel0#channel.send_packet_size, Channel0#channel.send_window_size), diff --git a/lib/ssh/src/ssh_connection_sup.erl b/lib/ssh/src/ssh_connection_sup.erl index e3544af1c6..b620056310 100644 --- a/lib/ssh/src/ssh_connection_sup.erl +++ b/lib/ssh/src/ssh_connection_sup.erl @@ -48,8 +48,12 @@ start_manager_child(Sup, Args) -> supervisor:start_child(Sup, Spec). connection_manager(SupPid) -> - Children = supervisor:which_children(SupPid), - {ok, ssh_connection_manager(Children)}. + try supervisor:which_children(SupPid) of + Children -> + {ok, ssh_connection_manager(Children)} + catch exit:{noproc,_} -> + {ok, undefined} + end. %%%========================================================================= %%% Supervisor callback @@ -107,6 +111,8 @@ handler_spec([Role, Socket, Opts]) -> Type = worker, {Name, StartFunc, Restart, Shutdown, Type, Modules}. +ssh_connection_manager([]) -> + undefined; ssh_connection_manager([{_, Child, _, [ssh_connection_manager]} | _]) -> Child; ssh_connection_manager([_ | Rest]) -> diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index d05fa8e09a..a6b82a7a13 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -232,7 +232,7 @@ lookup_host_key_fd(Fd, Host, KeyType) -> eof -> {error, not_found}; Line -> - case public_key:ssh_decode(Line, known_hosts) of + case ssh_decode_line(Line, known_hosts) of [{Key, Attributes}] -> handle_host(Fd, Host, proplists:get_value(hostnames, Attributes), Key, KeyType); [] -> @@ -240,6 +240,13 @@ lookup_host_key_fd(Fd, Host, KeyType) -> end end. +ssh_decode_line(Line, Type) -> + try + public_key:ssh_decode(Line, Type) + catch _:_ -> + [] + end. + handle_host(Fd, Host, HostList, Key, KeyType) -> Host1 = host_name(Host), case lists:member(Host1, HostList) and key_match(Key, KeyType) of @@ -285,7 +292,7 @@ lookup_user_key_fd(Fd, Key) -> eof -> {error, not_found}; Line -> - case public_key:ssh_decode(Line, auth_keys) of + case ssh_decode_line(Line, auth_keys) of [{AuthKey, _}] -> case is_auth_key(Key, AuthKey) of true -> diff --git a/lib/ssh/src/ssh_sftpd_file_api.erl b/lib/ssh/src/ssh_sftpd_file_api.erl index 38371f809d..83d90907f5 100644 --- a/lib/ssh/src/ssh_sftpd_file_api.erl +++ b/lib/ssh/src/ssh_sftpd_file_api.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. 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 @@ -22,40 +22,40 @@ -module(ssh_sftpd_file_api). %% To be further specified later --callback close(IoDevice::term(), State::term()) -> - ok | {error, Reason::term()}. --callback delete(Path::term(), State::term()) -> - ok | {error, Reason::term()}. --callback del_dir(Path::term(), State::term()) -> - ok | {error, Reason::term()}. +-callback close(file:io_device(), State::term()) -> + {ok, State::term()} | {{error, Reason::term()}, State::term()}. +-callback delete(file:name(), State::term()) -> + {ok, State::term()} | {{error, Reason::term()}, State::term()}. +-callback del_dir(file:name(), State::term()) -> + {ok, State::term()} | {{error, Reason::term()}, State::term()}. -callback get_cwd(State::term()) -> - {ok, Dir::term()} | {error, Reason::term()}. --callback is_dir(AbsPath::term(), State::term()) -> - boolean(). --callback list_dir(AbsPath::term(), State::term()) -> - {ok, Filenames::term()} | {error, Reason::term()}. + {{ok, Dir::term()}, State::term()} | {{error, Reason::term()}, State::term()}. +-callback is_dir(file:name(), State::term()) -> + {boolean(), State::term()}. +-callback list_dir(file:name(), State::term()) -> + {{ok, Filenames::term()}, State::term()} | {{error, Reason::term()}, State::term()}. -callback make_dir(Dir::term(), State::term()) -> - ok | {error, Reason::term()}. + {{ok, State::term()},State::term()} | {{error, Reason::term()}, State::term()}. -callback make_symlink(Path2::term(), Path::term(), State::term()) -> - ok | {error, Reason::term()}. + {ok, State::term()} | {{error, Reason::term()}, State::term()}. -callback open(Path::term(), Flags::term(), State::term()) -> - {ok, IoDevice::term()} | {error, Reason::term()}. --callback position(IoDevice::term(), Offs::term(), State::term()) -> - {ok, NewPosition::term()} | {error, Reason::term()}. --callback read(IoDevice::term(), Len::term(), State::term()) -> - {ok, Data::term()} | eof | {error, Reason::term()}. --callback read_link(Path::term(), State::term()) -> - {ok, FileName::term()} | {error, Reason::term()}. --callback read_link_info(Path::term(), State::term()) -> - {ok, FileInfo::term()} | {error, Reason::term()}. --callback read_file_info(Path::term(), State::term()) -> - {ok, FileInfo::term()} | {error, Reason::term()}. --callback rename(Path::term(), Path2::term(), State::term()) -> - ok | {error, Reason::term()}. --callback write(IoDevice::term(), Data::term(), State::term()) -> - ok | {error, Reason::term()}. --callback write_file_info(Path::term(),Info::term(), State::term()) -> - ok | {error, Reason::term()}. + {{ok, IoDevice::term()}, State::term()} | {{error, Reason::term()}, State::term()}. +-callback position(file:io_device(), Offs::term(), State::term()) -> + {{ok, NewPosition::term()}, State::term()} | {{error, Reason::term()}, State::term()}. +-callback read(file:io_device(), Len::term(), State::term()) -> + {{ok, Data::term()},State::term()} | {eof, State::term()} | {{error, Reason::term()}, State::term()}. +-callback read_link(file:name(), State::term()) -> + {{ok, FileName::term()}, State::term()} | {{error, Reason::term()}, State::term()}. +-callback read_link_info(file:name(), State::term()) -> + {{ok, FileInfo::term()}, State::term()} | {{error, Reason::term()}, State::term()}. +-callback read_file_info(file:name(), State::term()) -> + {{ok, FileInfo::term()}, State::term()} | {{error, Reason::term()},State::term()}. +-callback rename(file:name(), file:name(), State::term()) -> + {ok, State::term()} | {{error, Reason::term()}, State::term()}. +-callback write(file:io_device(), Data::term(), State::term()) -> + {ok, State::term()} | {{error, Reason::term()}, State::term()}. +-callback write_file_info(file:name(),Info::term(), State::term()) -> + {ok, State::term()} | {{error, Reason::term()}, State::term()}. diff --git a/lib/ssh/test/ssh.spec.vxworks b/lib/ssh/test/ssh.spec.vxworks deleted file mode 100644 index 81f665283c..0000000000 --- a/lib/ssh/test/ssh.spec.vxworks +++ /dev/null @@ -1,3 +0,0 @@ -{topcase, {dir, "../ssh_test"}}. -{require_nodenames, 1}. -%{skip, {M, F, "Not yet implemented"}}. diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index c5019425cd..c224e5b800 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -110,12 +110,13 @@ all() -> {group, rsa_pass_key}, {group, internal_error}, daemon_already_started, - server_password_option, server_userpassword_option, + server_password_option, + server_userpassword_option, close]. groups() -> - [{dsa_key, [], [exec, exec_compressed, shell, known_hosts]}, - {rsa_key, [], [exec, exec_compressed, shell, known_hosts]}, + [{dsa_key, [], [send, exec, exec_compressed, shell, known_hosts]}, + {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts]}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, {internal_error, [], [internal_error]} @@ -194,10 +195,10 @@ misc_ssh_options(Config) when is_list(Config) -> SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), - CMiscOpt0 = [{connecect_timeout, 1000}, {ip_v6_disable, false}, {user_dir, UserDir}], - CMiscOpt1 = [{connecect_timeout, infinity}, {ip_v6_disable, true}, {user_dir, UserDir}], - SMiscOpt0 = [{ip_v6_disable, false}, {user_dir, UserDir}, {system_dir, SystemDir}], - SMiscOpt1 = [{ip_v6_disable, true}, {user_dir, UserDir}, {system_dir, SystemDir}], + CMiscOpt0 = [{connecect_timeout, 1000}, {ip_v6_disabled, false}, {user_dir, UserDir}], + CMiscOpt1 = [{connecect_timeout, infinity}, {ip_v6_disabled, true}, {user_dir, UserDir}], + SMiscOpt0 = [{ip_v6_disabled, false}, {user_dir, UserDir}, {system_dir, SystemDir}], + SMiscOpt1 = [{ip_v6_disabled, true}, {user_dir, UserDir}, {system_dir, SystemDir}], ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -532,6 +533,31 @@ internal_error(Config) when is_list(Config) -> ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- +send(doc) -> + ["Test ssh_connection:send/3"]; + +send(suite) -> + []; + +send(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}]), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + ok = ssh_connection:send(ConnectionRef, ChannelId, <<"Data">>), + ok = ssh_connection:send(ConnectionRef, ChannelId, << >>), + ssh:stop_daemon(Pid). + + +%%-------------------------------------------------------------------- close(doc) -> ["Simulate that we try to close an already closed connection"]; diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index bff73a1b40..defa47f824 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 2.1 +SSH_VSN = 2.1.1 APP_VSN = "ssh-$(SSH_VSN)" |
