aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh')
-rw-r--r--lib/ssh/src/Makefile44
-rw-r--r--lib/ssh/src/ssh.erl20
-rw-r--r--lib/ssh/src/ssh_auth.erl16
-rw-r--r--lib/ssh/src/ssh_channel.erl4
-rw-r--r--lib/ssh/src/ssh_connection.erl13
-rw-r--r--lib/ssh/src/ssh_connection_manager.erl7
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl36
7 files changed, 92 insertions, 48 deletions
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index 1734ae4df4..a247692d9d 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -38,15 +38,17 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
# Behaviour (api) modules are first so they are compiled when
# the compiler reaches a callback module using them.
-MODULES= \
+BEHAVIOUR_MODULES= \
ssh_sftpd_file_api \
- ssh_key_api \
+ ssh_channel \
+ ssh_key_api
+
+MODULES= \
ssh \
ssh_sup \
sshc_sup \
sshd_sup \
ssh_connection_sup \
- ssh_channel \
ssh_connection \
ssh_connection_handler \
ssh_connection_manager \
@@ -73,11 +75,14 @@ MODULES= \
PUBLIC_HRL_FILES= ssh.hrl ssh_userauth.hrl ssh_xfer.hrl
-ERL_FILES= $(MODULES:%=%.erl)
+ERL_FILES= \
+ $(MODULES:%=%.erl) \
+ $(BEHAVIOUR_MODULES:%=%.erl)
-ALL_MODULES= $(MODULES)
-TARGET_FILES= $(ALL_MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
APP_FILE= ssh.app
APPUP_FILE= ssh.appup
@@ -93,29 +98,29 @@ INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -pa$(EBIN)\
- -pz $(ERL_TOP)/lib/public_key/ebin
+EXTRA_ERLC_FLAGS = +warn_unused_vars
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
+ -pz $(EBIN) \
+ -pz $(ERL_TOP)/lib/public_key/ebin \
+ $(EXTRA_ERLC_FLAGS)
+
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-debug: ERLC_FLAGS += -Ddebug
+debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
- rm -f $(TARGET_FILES)
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
rm -f errs core *~
-$(TARGET_FILES): ssh.hrl
-
-# $(EBIN)/ssh_sftpd_file.$(EMULATOR): ERLC_FLAGS += -pa$(EBIN)
-# $(EBIN)/ssh_sftpd_file.$(EMULATOR): $(EBIN)/ssh_sftpd_file_api.$(EMULATOR)
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
@@ -130,7 +135,8 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/src
$(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
$(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) $(APP_TARGET) \
+ $(APPUP_TARGET) $(RELSYSDIR)/ebin
$(INSTALL_DIR) $(RELSYSDIR)/include
$(INSTALL_DATA) $(PUBLIC_HRL_FILES) $(RELSYSDIR)/include
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 39c7fe329e..f4a40c81a4 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -346,8 +346,9 @@ handle_option([{role, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{compression, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
-handle_option([{allow_user_interaction, _} = Opt | Rest], SocketOptions, SshOptions) ->
- handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+%%Backwards compatibility
+handle_option([{allow_user_interaction, Value} | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option({user_interaction, Value}) | SshOptions]);
handle_option([{infofun, _} = Opt | Rest],SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{connectfun, _} = Opt | Rest], SocketOptions, SshOptions) ->
@@ -366,6 +367,8 @@ handle_option([{ssh_cli, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
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([Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions).
@@ -401,8 +404,9 @@ handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) ->
Opt;
handle_ssh_option({compression, Value} = Opt) when is_atom(Value) ->
Opt;
-handle_ssh_option({allow_user_interaction, Value} = Opt) when Value == true;
- Value == false ->
+handle_ssh_option({exec, {Module, Function, _}} = Opt) when is_atom(Module),
+ is_atom(Function) ->
+
Opt;
handle_ssh_option({infofun, Value} = Opt) when is_function(Value) ->
Opt;
@@ -412,11 +416,12 @@ handle_ssh_option({disconnectfun , Value} = Opt) when is_function(Value) ->
Opt;
handle_ssh_option({failfun, Value} = Opt) when is_function(Value) ->
Opt;
-handle_ssh_option({ip_v6_disabled, Value} = Opt) when is_function(Value) ->
+handle_ssh_option({ip_v6_disabled, Value} = Opt) when Value == true;
+ Value == false ->
Opt;
handle_ssh_option({transport, {Protocol, Cb, ClosTag}} = Opt) when is_atom(Protocol),
- is_atom(Cb),
- is_atom(ClosTag) ->
+ is_atom(Cb),
+ is_atom(ClosTag) ->
Opt;
handle_ssh_option({subsystems, Value} = Opt) when is_list(Value) ->
Opt;
@@ -495,4 +500,3 @@ verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signatur
Error ->
Error
end.
-
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 1a4517c689..aa452a8e09 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -71,7 +71,7 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb,
ssh_bits:install_messages(userauth_passwd_messages()),
Password = case proplists:get_value(password, Opts) of
undefined ->
- user_interaction(Opts, IoCb);
+ user_interaction(IoCb);
PW ->
PW
end,
@@ -89,13 +89,10 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb,
Ssh)
end.
-user_interaction(Opts, IoCb) ->
- case proplists:get_value(allow_user_interaction, Opts, true) of
- true ->
- IoCb:read_password("ssh password: ");
- false ->
- not_ok
- end.
+user_interaction(ssh_no_io) ->
+ not_ok;
+user_interaction(IoCb) ->
+ IoCb:read_password("ssh password: ").
%% See RFC 4256 for info on keyboard-interactive
@@ -124,8 +121,7 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) ->
FirstAlg = algorithm(proplists:get_value(public_key_alg, Opts,
?PREFERRED_PK_ALG)),
SecondAlg = other_alg(FirstAlg),
- AllowUserInt = proplists:get_value(allow_user_interaction, Opts,
- true),
+ AllowUserInt = proplists:get_value(user_interaction, Opts, true),
Prefs = method_preference(FirstAlg, SecondAlg, AllowUserInt),
ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User,
userauth_preference = Prefs,
diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl
index 7b600ed8b2..1938858420 100644
--- a/lib/ssh/src/ssh_channel.erl
+++ b/lib/ssh/src/ssh_channel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-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
@@ -215,7 +215,7 @@ handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
close_sent = false} = State) ->
%% To be on the safe side, i.e. the manager has already been terminated.
(catch ssh_connection:close(ConnectionManager, ChannelId)),
- {stop, normal, State};
+ {stop, normal, State#state{close_sent = true}};
handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
channel_cb = Module,
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 46f0c7e688..c46f799b6d 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -720,12 +720,17 @@ handle_msg(#ssh_msg_channel_request{request_type = "env"},
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = _Other,
- want_reply = WantReply}, Connection,
+ want_reply = WantReply}, #connection{channel_cache = Cache} = Connection,
ConnectionPid, _) ->
if WantReply == true ->
- FailMsg = channel_failure_msg(ChannelId),
- {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
- Connection};
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{remote_id = RemoteId} ->
+ FailMsg = channel_failure_msg(RemoteId),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
+ Connection};
+ undefined -> %% Chanel has been closed
+ {noreply, Connection}
+ end;
true ->
{noreply, Connection}
end;
diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl
index e993f597a5..a0ea04a2c2 100644
--- a/lib/ssh/src/ssh_connection_manager.erl
+++ b/lib/ssh/src/ssh_connection_manager.erl
@@ -267,7 +267,7 @@ handle_call({ssh_msg, Pid, Msg}, From,
disconnect_fun(Reason, SSHOpts),
{stop, {shutdown, normal}, State#state{connection_state = Connection}}
catch
- _:Reason ->
+ _:Error ->
{disconnect, Reason, {{replies, Replies}, Connection}} =
ssh_connection:handle_msg(
#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
@@ -277,7 +277,7 @@ handle_call({ssh_msg, Pid, Msg}, From,
lists:foreach(fun send_msg/1, Replies),
SSHOpts = proplists:get_value(ssh_opts, Opts),
disconnect_fun(Reason, SSHOpts),
- {stop, {shutdown, Reason}, State#state{connection_state = Connection}}
+ {stop, {shutdown, Error}, State#state{connection_state = Connection}}
end;
handle_call({global_request, Pid, _, _, _} = Request, From,
@@ -384,9 +384,10 @@ handle_call({close, ChannelId}, _,
#state{connection = Pid, connection_state =
#connection{channel_cache = Cache}} = State) ->
case ssh_channel:cache_lookup(Cache, ChannelId) of
- #channel{remote_id = Id} ->
+ #channel{remote_id = Id} = Channel ->
send_msg({connection_reply, Pid,
ssh_connection:channel_close_msg(Id)}),
+ ssh_channel:cache_update(Cache, Channel#channel{sent_close = true}),
{reply, ok, State};
undefined ->
{reply, ok, State}
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index d66214d415..c5019425cd 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -183,7 +183,29 @@ app_test(doc) ->
app_test(Config) when is_list(Config) ->
?t:app_test(ssh),
ok.
+%%--------------------------------------------------------------------
+misc_ssh_options(doc) ->
+ ["Test that we can set some misc options not tested elsewhere, "
+ "some options not yet present are not decided if we should support or "
+ "if they need thier own test case."];
+misc_ssh_options(suite) ->
+ [];
+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}],
+
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+
+ basic_test([{client_opts, CMiscOpt0 ++ ClientOpts}, {server_opts, SMiscOpt0 ++ ServerOpts}]),
+ basic_test([{client_opts, CMiscOpt1 ++ ClientOpts}, {server_opts, SMiscOpt1 ++ ServerOpts}]).
+%%--------------------------------------------------------------------
exec(doc) ->
["Test api function ssh_connection:exec"];
@@ -500,13 +522,14 @@ internal_error(Config) when is_list(Config) ->
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}]),
{error,"Internal error"} =
ssh:connect(Host, Port, [{silently_accept_hosts, true},
{user_dir, UserDir},
- {user_interaction, false}]).
+ {user_interaction, false}]),
+ ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
close(doc) ->
@@ -539,3 +562,12 @@ close(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
+
+basic_test(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon(ServerOpts),
+ {ok, CM} = ssh:connect(Host, Port, ClientOpts),
+ ok = ssh:close(CM),
+ ssh:stop_daemon(Pid).