From 20363d9af0f0f9446d3a1dfb099f4aa1898dc231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20H=C3=A4ssler?= Date: Mon, 14 Oct 2013 20:42:58 +0200 Subject: Fix ssh doc typos ssh_rsa changed to 'ssh-rsa' and missing space added. --- lib/ssh/doc/src/ssh.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 141d3df38e..fb58a4b014 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -141,7 +141,7 @@

Sets the preferred public key algorithm to use for user authentication. If the the preferred algorithm fails for some reason, the other algorithm is tried. The default is - to try first.

+ to try first.

@@ -248,7 +248,7 @@ requested by the client. Default is to use the erlang shell: - Provides your own cli implementation, i.e. a channel callback -- cgit v1.2.3 From d54e4318a77c7a42a7b8952780b33987775c7608 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 25 Sep 2013 14:56:19 +0200 Subject: ssh: Add function ssh:peername/1 with test OTP-11345, sto575, tsk374 --- lib/ssh/doc/src/ssh.xml | 14 ++++++++++++++ lib/ssh/src/ssh.erl | 12 ++++++++++++ lib/ssh/test/ssh_basic_SUITE.erl | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index fb58a4b014..ddfb50ebd2 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -333,6 +333,20 @@ + + peername(ConnectionRef) -> {ok, {Address,Port}} | {error,Error} + + + ConnectionRef = ssh_connection_ref() + Address = ip_address() + Port = integer() + + +

Returns the address and port for the other end of a connection. +

+
+
+ shell(Host) -> shell(Host, Option) -> diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 7d5478c3f6..718321ef21 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -28,6 +28,7 @@ -export([start/0, start/1, stop/0, connect/3, connect/4, close/1, connection_info/2, channel_info/3, daemon/1, daemon/2, daemon/3, + peername/1, stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2, shell/1, shell/2, shell/3]). @@ -244,6 +245,17 @@ shell(Host, Port, Options) -> Error end. +%%-------------------------------------------------------------------- +%% Function: peername(ConnectionRef) -> {ok, {Host,Port}} +%% | {error,Error} +%% +%% Description: Returns the peer address of the connection +%%-------------------------------------------------------------------- +peername(ConnectionRef) -> + [{peer, {_Name,{IP,Port}}}] = + ssh_connection_manager:connection_info(ConnectionRef, [peer]), + {ok, {IP,Port}}. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 0aa60624bf..e13610bc2a 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -22,6 +22,7 @@ -module(ssh_basic_SUITE). -include_lib("common_test/include/ct.hrl"). +-include_lib("kernel/include/inet.hrl"). %% Note: This directive should only be used in test suites. -compile(export_all). @@ -48,7 +49,7 @@ all() -> close]. groups() -> - [{dsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]}, + [{dsa_key, [], [send, peername, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]}, {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, @@ -472,6 +473,37 @@ send(Config) when is_list(Config) -> ssh:stop_daemon(Pid). +%%-------------------------------------------------------------------- +peername() -> + [{doc, "Test ssh:peername/1"}]. +peername(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,{IP,Port}} = ssh:peername(ConnectionRef), + host_equal(Host,IP), + ssh:stop_daemon(Pid). + + +host_equal(Name, IP) when is_list(Name), is_tuple(IP) -> + Family = if size(IP)==4 -> inet; + size(IP)==8 -> inet6 + end, + {ok,#hostent{h_addr_list=IPs}} = inet:gethostbyname(Name,Family), + lists:any(fun(X) -> X==IP end, IPs); +host_equal(IP, Name) when is_list(Name), is_tuple(IP) -> + host_equal(Name, IP); +host_equal(X,Y) -> X==Y. + + %%-------------------------------------------------------------------- close() -> [{doc, "Simulate that we try to close an already closed connection"}]. -- cgit v1.2.3 From f5495aa1560daf65c063a8d5b99a5ea17520ea92 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 30 Sep 2013 16:35:09 +0200 Subject: ssh: Add ssh:sockname/1 incl doc and tests OTP-11345, sto575, tsk374 --- lib/ssh/doc/src/ssh.xml | 14 +++++++ lib/ssh/src/ssh.erl | 12 ++++++ lib/ssh/src/ssh_connection_handler.erl | 29 +++++++------- lib/ssh/test/Makefile | 5 ++- lib/ssh/test/ssh_basic_SUITE.erl | 55 +++++++++++++++++--------- lib/ssh/test/ssh_peername_sockname_server.erl | 56 +++++++++++++++++++++++++++ 6 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 lib/ssh/test/ssh_peername_sockname_server.erl (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index ddfb50ebd2..896b98edc2 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -366,6 +366,20 @@ + + sockname(ConnectionRef) -> {ok, {Address,Port}} | {error,Error} + + + ConnectionRef = ssh_connection_ref() + Address = ip_address() + Port = integer() + + +

Returns the local address and port number for a connection. +

+
+
+ start() -> start(Type) -> ok | {error, Reason} diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 718321ef21..80d20abbbd 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -29,6 +29,7 @@ channel_info/3, daemon/1, daemon/2, daemon/3, peername/1, + sockname/1, stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2, shell/1, shell/2, shell/3]). @@ -256,6 +257,17 @@ peername(ConnectionRef) -> ssh_connection_manager:connection_info(ConnectionRef, [peer]), {ok, {IP,Port}}. +%%-------------------------------------------------------------------- +%% Function: sockname(ConnectionRef) -> {ok, {Host,Port}} +%% | {error,Error} +%% +%% Description: Returns the local address of the connection +%%-------------------------------------------------------------------- +sockname(ConnectionRef) -> + [{sockname, Result}] = + ssh_connection_manager:connection_info(ConnectionRef, [sockname]), + Result. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 9de4dd5967..c3e8a3c742 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -46,7 +46,7 @@ handle_sync_event/4, handle_info/3, terminate/3, code_change/4]). %% spawn export --export([ssh_info_handler/3]). +-export([ssh_info_handler/4]). -record(state, { transport_protocol, % ex: tcp @@ -533,7 +533,7 @@ handle_event(renegotiate, StateName, State) -> {next_state, StateName, State}; handle_event({info, From, Options}, StateName, #state{ssh_params = Ssh} = State) -> - spawn(?MODULE, ssh_info_handler, [Options, Ssh, From]), + spawn(?MODULE, ssh_info_handler, [Options, Ssh, State, From]), {next_state, StateName, State}; handle_event(data_size, connected, #state{ssh_params = Ssh0} = State) -> {ok, [{send_oct,Sent}]} = inet:getstat(State#state.socket, [send_oct]), @@ -1022,26 +1022,29 @@ retry_fun(User, Reason, Opts) -> catch Fun(User, Reason) end. -ssh_info_handler(Options, Ssh, From) -> - Info = ssh_info(Options, Ssh, []), +ssh_info_handler(Options, Ssh, State, From) -> + Info = ssh_info(Options, Ssh, State, []), ssh_connection_manager:send_msg({channel_requst_reply, From, Info}). -ssh_info([], _, Acc) -> +ssh_info([], _, _, Acc) -> Acc; ssh_info([client_version | Rest], #ssh{c_vsn = IntVsn, - c_version = StringVsn} = SshParams, Acc) -> - ssh_info(Rest, SshParams, [{client_version, {IntVsn, StringVsn}} | Acc]); + c_version = StringVsn} = SshParams, State, Acc) -> + ssh_info(Rest, SshParams, State, [{client_version, {IntVsn, StringVsn}} | Acc]); ssh_info([server_version | Rest], #ssh{s_vsn = IntVsn, - s_version = StringVsn} = SshParams, Acc) -> - ssh_info(Rest, SshParams, [{server_version, {IntVsn, StringVsn}} | Acc]); + s_version = StringVsn} = SshParams, State, Acc) -> + ssh_info(Rest, SshParams, State, [{server_version, {IntVsn, StringVsn}} | Acc]); -ssh_info([peer | Rest], #ssh{peer = Peer} = SshParams, Acc) -> - ssh_info(Rest, SshParams, [{peer, Peer} | Acc]); +ssh_info([peer | Rest], #ssh{peer = Peer} = SshParams, State, Acc) -> + ssh_info(Rest, SshParams, State, [{peer, Peer} | Acc]); -ssh_info([ _ | Rest], SshParams, Acc) -> - ssh_info(Rest, SshParams, Acc). +ssh_info([sockname | Rest], SshParams, #state{socket=Socket}=State, Acc) -> + ssh_info(Rest, SshParams, State, [{sockname,inet:sockname(Socket)}|Acc]); + +ssh_info([ _ | Rest], SshParams, State, Acc) -> + ssh_info(Rest, SshParams, State, Acc). log_error(Reason) -> Report = io_lib:format("Erlang ssh connection handler failed with reason: " diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index f5db31baee..13caafc055 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2012. All Rights Reserved. +# Copyright Ericsson AB 2004-2013. 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 @@ -38,7 +38,8 @@ MODULES= \ ssh_sftpd_SUITE \ ssh_sftpd_erlclient_SUITE \ ssh_connection_SUITE \ - ssh_echo_server + ssh_echo_server \ + ssh_peername_sockname_server HRL_FILES_NEEDED_IN_TEST= \ $(ERL_TOP)/lib/ssh/src/ssh.hrl \ diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index e13610bc2a..e8f1d5213c 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -49,7 +49,9 @@ all() -> close]. groups() -> - [{dsa_key, [], [send, peername, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]}, + [{dsa_key, [], [send, + peername_sockname, + exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]}, {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, @@ -474,35 +476,50 @@ send(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -peername() -> - [{doc, "Test ssh:peername/1"}]. -peername(Config) when is_list(Config) -> +peername_sockname() -> + [{doc, "Test ssh:peername/1 and ssh:sockname/1"}]. +peername_sockname(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}, + {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {user_dir, UserDir}, - {failfun, fun ssh_test_lib:failfun/2}]), + {subsystems, [{"peername_sockname", + {ssh_peername_sockname_server, []}} + ]} + ]), ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, {user_dir, UserDir}, {user_interaction, false}]), - {ok,{IP,Port}} = ssh:peername(ConnectionRef), - host_equal(Host,IP), - ssh:stop_daemon(Pid). - + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:subsystem(ConnectionRef, ChannelId, "peername_sockname", infinity), + {ok,{HostPeerClient,PortPeerClient}} = ssh:peername(ConnectionRef), + {ok,{HostSockClient,PortSockClient}} = ssh:sockname(ConnectionRef), + receive + {ssh_cm, ConnectionRef, {data, ChannelId, _, Response}} -> + {PeerNameSrv,SockNameSrv} = binary_to_term(Response), + {ok,{HostPeerSrv,PortPeerSrv}} = PeerNameSrv, + {ok,{HostSockSrv,PortSockSrv}} = SockNameSrv, + host_equal(HostPeerSrv, HostSockClient), + PortPeerSrv = PortSockClient, + host_equal(HostSockSrv, HostPeerClient), + PortSockSrv = PortPeerClient, + host_equal(HostSockSrv, Host), + PortSockSrv = Port + after 10000 -> + throw(timeout) + end. -host_equal(Name, IP) when is_list(Name), is_tuple(IP) -> - Family = if size(IP)==4 -> inet; - size(IP)==8 -> inet6 - end, - {ok,#hostent{h_addr_list=IPs}} = inet:gethostbyname(Name,Family), - lists:any(fun(X) -> X==IP end, IPs); -host_equal(IP, Name) when is_list(Name), is_tuple(IP) -> - host_equal(Name, IP); -host_equal(X,Y) -> X==Y. +host_equal(H1, H2) -> + not ordsets:is_disjoint(ips(H1), ips(H2)). +ips(IP) when is_tuple(IP) -> ordsets:from_list([IP]); +ips(Name) when is_list(Name) -> + {ok,#hostent{h_addr_list=IPs4}} = inet:gethostbyname(Name,inet), + {ok,#hostent{h_addr_list=IPs6}} = inet:gethostbyname(Name,inet6), + ordsets:from_list(IPs4++IPs6). %%-------------------------------------------------------------------- close() -> diff --git a/lib/ssh/test/ssh_peername_sockname_server.erl b/lib/ssh/test/ssh_peername_sockname_server.erl new file mode 100644 index 0000000000..7664f3ee25 --- /dev/null +++ b/lib/ssh/test/ssh_peername_sockname_server.erl @@ -0,0 +1,56 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2013. 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% +%% + +%% + +-module(ssh_peername_sockname_server). + +%% The purpose of this module is to perform tests on the server side of an +%% ssh connection. + + +-behaviour(ssh_daemon_channel). +-record(state, {}). + +-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]). + +init([]) -> + {ok, #state{}}. + +handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) -> + ssh_connection:send(ConnectionManager, ChannelId, + term_to_binary( + {catch ssh:peername(ConnectionManager), + catch ssh:sockname(ConnectionManager) + }) + ), + {ok, State}. + +handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, _Error, _}}, + State) -> + {stop, ChannelId, State}; + +handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, _Status}}, State) -> + {stop, ChannelId, State}; + +handle_ssh_msg({ssh_cm, _CM, _}, State) -> + {ok, State}. + +terminate(_Reason, _State) -> + ok. -- cgit v1.2.3 From d27003ba5c5ce962df439a99076a85607b82d746 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 5 Sep 2013 17:43:05 -0500 Subject: fix private_key type documentation in ssh_server_key_api --- lib/ssh/doc/src/ssh_server_key_api.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh_server_key_api.xml b/lib/ssh/doc/src/ssh_server_key_api.xml index c4562e1211..51e1fc1f2e 100644 --- a/lib/ssh/doc/src/ssh_server_key_api.xml +++ b/lib/ssh/doc/src/ssh_server_key_api.xml @@ -29,7 +29,7 @@ -behaviour(ssh_server_key_api). -

Behaviour describing the API for an SSH server's public key handling.By implementing the callbacks defined +

Behaviour describing the API for an SSH server's public key handling. By implementing the callbacks defined in this behavior it is possible to customize the SSH server's public key handling. By default the SSH application implements this behavior with help of the standard openssh files, see ssh(6).

@@ -44,9 +44,9 @@

boolean() = true | false

string() = [byte()]

-

public_key() = #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()

-

private_key() = #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()

-

public_key_algorithm() = 'ssh-rsa'| 'ssh-dss' | atom()

+

public_key() = #'RSAPublicKey'{} | {integer(), #'Dss-Parms'{}} | term()

+

private_key() = #'RSAPrivateKey'{} | #'DSAPrivateKey'{} | term()

+

public_key_algorithm() = 'ssh-rsa' | 'ssh-dss' | atom()

@@ -56,7 +56,7 @@ Fetches the hosts private key Algorithm = public_key_algorithm() - Host key algorithm. Should support 'ssh-rsa'| 'ssh-dss' but additional algorithms + Host key algorithm. Should support 'ssh-rsa' | 'ssh-dss' but additional algorithms can be handled. DaemonOptions = proplists:proplist() Options provided to ssh:daemon/[2,3] -- cgit v1.2.3