From d6e981e751b4565773204d7eb394ca445d63e771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 26 Nov 2010 14:55:41 +0100 Subject: Add test suite for ssh --- lib/ssh/test/Makefile | 131 +++ lib/ssh/test/ssh.spec | 6 + lib/ssh/test/ssh.spec.vxworks | 3 + lib/ssh/test/ssh_SUITE.erl | 64 ++ lib/ssh/test/ssh_basic_SUITE.erl | 395 +++++++++ lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key | 12 + .../test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub | 1 + lib/ssh/test/ssh_host_dsa_key | 12 + lib/ssh/test/ssh_host_dsa_key.pub | 1 + lib/ssh/test/ssh_sftp_SUITE.erl | 531 ++++++++++++ lib/ssh/test/ssh_sftp_SUITE_data/id_rsa | 15 + lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub | 1 + lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt | 252 ++++++ lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key | 12 + .../test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub | 1 + lib/ssh/test/ssh_sftpd_SUITE.erl | 914 +++++++++++++++++++++ lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key | 12 + .../test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub | 1 + lib/ssh/test/ssh_sftpd_SUITE_data/test.txt | 1 + lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 304 +++++++ .../ssh_host_dsa_key | 12 + .../ssh_host_dsa_key.pub | 1 + .../ssh_sftpd_file_alt.erl | 100 +++ .../test/ssh_sftpd_erlclient_SUITE_data/test.txt | 1 + lib/ssh/test/ssh_test_lib.erl | 189 +++++ lib/ssh/test/ssh_to_openssh_SUITE.erl | 463 +++++++++++ .../ssh_to_openssh_SUITE_data/ssh_host_dsa_key | 12 + .../ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub | 1 + 28 files changed, 3448 insertions(+) create mode 100644 lib/ssh/test/Makefile create mode 100644 lib/ssh/test/ssh.spec create mode 100644 lib/ssh/test/ssh.spec.vxworks create mode 100644 lib/ssh/test/ssh_SUITE.erl create mode 100644 lib/ssh/test/ssh_basic_SUITE.erl create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_sftp_SUITE.erl create mode 100644 lib/ssh/test/ssh_sftp_SUITE_data/id_rsa create mode 100644 lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub create mode 100644 lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt create mode 100644 lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_sftpd_SUITE.erl create mode 100644 lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_sftpd_SUITE_data/test.txt create mode 100644 lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl create mode 100644 lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl create mode 100644 lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt create mode 100644 lib/ssh/test/ssh_test_lib.erl create mode 100644 lib/ssh/test/ssh_to_openssh_SUITE.erl create mode 100644 lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile new file mode 100644 index 0000000000..116f894493 --- /dev/null +++ b/lib/ssh/test/Makefile @@ -0,0 +1,131 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-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% +# + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk +VSN=$(GS_VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + ssh_test_lib \ + ssh_SUITE \ + ssh_basic_SUITE \ + ssh_to_openssh_SUITE \ + ssh_sftp_SUITE \ + ssh_sftpd_SUITE \ + ssh_sftpd_erlclient_SUITE + +HRL_FILES_NEEDED_IN_TEST= \ + $(ERL_TOP)/lib/ssh/src/ssh.hrl \ + $(ERL_TOP)/lib/ssh/src/ssh_xfer.hrl + +ERL_FILES= $(MODULES:%=%.erl) + +KEY_FILES= ssh_host_dsa_key ssh_host_dsa_key.pub + +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +DATA_DIRS = $(MODULES:%=%_data) + +INCLUDES = -I$(ERL_TOP)/lib/test_server/include \ + -I$(ERL_TOP)/lib/ssh/src \ + +EMAKEFILE=Emakefile +MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile) + +ifeq ($(MAKE_EMAKE),) +BUILDTARGET = $(TARGET_FILES) +RELTEST_FILES = $(INETS_SPECS) $(SOURCE) +else +BUILDTARGET = emakebuild +RELTEST_FILES = $(EMAKEFILE) $(INETS_SPECS) $(SOURCE) +endif + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/ssh_test + +# ---------------------------------------------------- +# FLAGS +# The path to the test_server ebin dir is needed when +# running the target "targets". +# ---------------------------------------------------- +ERL_COMPILE_FLAGS += -pa ../../../internal_tools/test_server/ebin \ + $(INCLUDES) + +EBIN = . + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +tests debug opt: $(BUILDTARGET) + +targets: $(TARGET_FILES) + +.PHONY: emakebuild + +emakebuild: $(EMAKEFILE) + +$(EMAKEFILE): + $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' | grep -v Warning > $(EMAKEFILE) + $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) | grep -v Warning >> $(EMAKEFILE) + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core +docs: + +info: + @echo "TARGET_FILES = $(TARGET_FILES)" + @echo "DATA_DIRS = $(DATA_DIRS)" + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + +release_tests_spec: opt + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) + $(INSTALL_DATA) ssh.spec $(RELSYSDIR) + $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR) + @for dir in $(DATA_DIRS); do \ + if test ! -d $$dir ; then \ + echo "=== Skipping datadir $$dir" ; \ + else \ + echo "Installling $(KEY_FILES) in $$dir"; \ + $(INSTALL_DATA) $(KEY_FILES) $$dir; \ + fi ; \ + done + chmod -f -R u+w $(RELSYSDIR) + @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec new file mode 100644 index 0000000000..d99250654e --- /dev/null +++ b/lib/ssh/test/ssh.spec @@ -0,0 +1,6 @@ +{topcase, {dir, "../ssh_test"}}. +{require_nodenames, 1}. +{skip, {ssh_ssh_SUITE, ssh, "Current implementation is timingdependent and +hence will succeed/fail on a whim"}}. +{skip, {ssh_ssh_SUITE, ssh_compressed, +"Current implementation is timingdependent hence will succeed/fail on a whim"}}. diff --git a/lib/ssh/test/ssh.spec.vxworks b/lib/ssh/test/ssh.spec.vxworks new file mode 100644 index 0000000000..81f665283c --- /dev/null +++ b/lib/ssh/test/ssh.spec.vxworks @@ -0,0 +1,3 @@ +{topcase, {dir, "../ssh_test"}}. +{require_nodenames, 1}. +%{skip, {M, F, "Not yet implemented"}}. diff --git a/lib/ssh/test/ssh_SUITE.erl b/lib/ssh/test/ssh_SUITE.erl new file mode 100644 index 0000000000..dd4571febe --- /dev/null +++ b/lib/ssh/test/ssh_SUITE.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% + +%% +%%%---------------------------------------------------------------- +%%% Purpose:ssh application test suite. +%%%----------------------------------------------------------------- +-module(ssh_SUITE). +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(1)). +-define(application, ssh). + +% Test server specific exports +-export([all/1]). +-export([init_per_testcase/2, fin_per_testcase/2]). + +% Test cases must be exported. +-export([app_test/1]). +-define(cases, [app_test]). + +%% +%% all/1 +%% +all(doc) -> + []; +all(suite) -> + [?cases]. + +init_per_testcase(_Case, Config) -> + Dog=test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. +% +% Test cases starts here. +% +app_test(suite) -> + []; +app_test(doc) -> + ["Application consistency test."]; +app_test(Config) when is_list(Config) -> + ?t:app_test(?application), + ok. diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl new file mode 100644 index 0000000000..d5eb5367e6 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -0,0 +1,395 @@ +%% +%% %CopyrightBegin% +%% +%% 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% +%% + +%% + +-module(ssh_basic_SUITE). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-define(NEWLINE, <<"\r\n">>). + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initialization before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + crypto:start(), + Dir = ?config(priv_dir, Config), + ssh_test_lib:save_known_hosts(Dir), + {ok, _} = ssh_test_lib:get_id_keys(Dir), + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- +end_per_suite(Config) -> + Dir = ?config(priv_dir, Config), + crypto:stop(), + ssh_test_lib:remove_id_keys(Dir), + ssh_test_lib:restore_known_hosts(Dir), + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config) -> Config +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Initialization before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Description: Initialization before each test case +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + rename_known_hosts(backup), + ssh:start(), + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config) -> _ +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after each test case +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ssh:stop(), + rename_known_hosts(restore), + ok. + +%%-------------------------------------------------------------------- +%% Function: all(Clause) -> TestCases +%% Clause - atom() - suite | doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% Description: Returns a list of all test cases in this test suite +%%-------------------------------------------------------------------- +all(doc) -> + ["Test ssh API"]; + +all(suite) -> + [exec, exec_compressed, shell, daemon_allready_started, + server_password_option, server_userpassword_option, known_hosts]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- + +exec(doc) -> + ["Test api function ssh_connection:exec"]; + +exec(suite) -> + []; + +exec(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = ?config(data_dir, Config), + Host = ssh_test_lib:hostname(), + Port = ssh_test_lib:inet_port(), + {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + {ok, ConnectionRef} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user_interaction, false}]), + {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId0, + "1+1.", infinity), + Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"2\n">>}}, + case ssh_test_lib:receive_exec_result(Data0) of + expected -> + ok; + Other0 -> + test_server:fail(Other0) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0), + + %% Test that it is possible to start a new channel and + %% run an other exec on the same connection. + {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId1, + "2+2.", infinity), + Data1 = {ssh_cm, ConnectionRef, {data, ChannelId1, 0, <<"4\n">>}}, + case ssh_test_lib:receive_exec_result(Data1) of + expected -> + ok; + Other1 -> + test_server:fail(Other1) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +exec_compressed(doc) -> + ["Test that compression option works"]; + +exec_compressed(suite) -> + []; + +exec_compressed(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = ?config(data_dir, Config), + Host = ssh_test_lib:hostname(), + Port = ssh_test_lib:inet_port(), + {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, + {compression, zlib}, + {failfun, fun ssh_test_lib:failfun/2}]), + + {ok, ConnectionRef} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user_interaction, false}]), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "1+1.", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ok; + Other -> + test_server:fail(Other) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- + +shell(doc) -> + ["Test that ssh:shell/2 works"]; + +shell(suite) -> + []; + +shell(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = ?config(data_dir, Config), + Port = ssh_test_lib:inet_port(), + {ok, _Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + test_server:sleep(500), + + IO = ssh_test_lib:start_io_server(), + Shell = ssh_test_lib:start_shell(Port, IO), + receive + ErlShellStart -> + test_server:format("Erlang shell start: ~p~n", [ErlShellStart]) + end, + receive + ErlPrompt0 -> + test_server:format("Erlang prompt: ~p~n", [ErlPrompt0]) + end, + IO ! {input, self(), "1+1.\r\n"}, + receive + Echo0 -> + test_server:format("Echo: ~p ~n", [Echo0]) + end, + receive + ?NEWLINE -> + ok + end, + receive + Result0 = <<"2">> -> + test_server:format("Result: ~p~n", [Result0]) + end, + receive + ?NEWLINE -> + ok + end, + receive + ErlPrompt1 -> + test_server:format("Erlang prompt: ~p~n", [ErlPrompt1]) + end, + exit(Shell, kill), + %% Does not seem to work in the testserver! + %% IO ! {input, self(), "q().\r\n"}, + %% receive + %% ?NEWLINE -> + %% ok + %% end, + %% receive + %% Echo1 -> + %% test_server:format("Echo: ~p ~n", [Echo1]) + %% end, + %% receive + %% ?NEWLINE -> + %% ok + %% end, + %% receive + %% Result1 -> + %% test_server:format("Result: ~p~n", [Result1]) + %% end, + receive + {'EXIT', Shell, killed} -> + ok + end. + +%%-------------------------------------------------------------------- +daemon_allready_started(doc) -> + ["Test that get correct error message if you try to start a daemon", + "on an adress that allready runs a daemon see also seq10667" ]; + +daemon_allready_started(suite) -> + []; + +daemon_allready_started(Config) when is_list(Config) -> + SystemDir = ?config(data_dir, Config), + Port = ssh_test_lib:inet_port(), + {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + {error, eaddrinuse} = ssh:daemon(Port, [{system_dir, SystemDir}, + {failfun, + fun ssh_test_lib:failfun/2}]), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +server_password_option(doc) -> + ["validate to server that uses the 'password' option"]; +server_password_option(suite) -> + []; +server_password_option(Config) when is_list(Config) -> + UserDir = ?config(data_dir, Config), % to make sure we don't use + SysDir = ?config(data_dir, Config), % public-key-auth + Port = ssh_test_lib:inet_port(), + {ok, Pid} = + ssh:daemon(Port, [{system_dir, SysDir}, + {password, "morot"}]), + Host = ssh_test_lib:hostname(), + + {ok, ConnectionRef} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + + test_server:format("Test of wrong pasword: Error msg: ~p ~n", [Reason]), + + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- + +server_userpassword_option(doc) -> + ["validate to server that uses the 'password' option"]; +server_userpassword_option(suite) -> + []; +server_userpassword_option(Config) when is_list(Config) -> + UserDir = ?config(data_dir, Config), % to make sure we don't use + SysDir = ?config(data_dir, Config), % public-key-auth + Port = ssh_test_lib:inet_port(), + {ok, Pid} = + ssh:daemon(Port, [{system_dir, SysDir}, + {user_passwords, [{"vego", "morot"}]}]), + Host = ssh_test_lib:hostname(), + + {ok, ConnectionRef} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:close(ConnectionRef), + + {error, Reason0} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + + test_server:format("Test of user foo that does not exist. " + "Error msg: ~p ~n", [Reason0]), + + {error, Reason1} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + test_server:format("Test of wrong Pasword. " + "Error msg: ~p ~n", [Reason1]), + + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +known_hosts(doc) -> + ["check that known_hosts is updated correctly"]; +known_hosts(suite) -> + []; +known_hosts(Config) when is_list(Config) -> + SystemDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + Port = ssh_test_lib:inet_port(), + + {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + + KnownHosts = filename:join(UserDir, "known_hosts"), + file:delete(KnownHosts), + {error, enoent} = file:read_file(KnownHosts), + Host = ssh_test_lib:hostname(), + {ok, ConnectionRef} = + ssh:connect(Host, Port, [{user_dir, UserDir}, + {user_interaction, false}, + silently_accept_hosts]), + {ok, _Channel} = ssh_connection:session_channel(ConnectionRef, infinity), + ok = ssh:close(ConnectionRef), + {ok, Binary} = file:read_file(KnownHosts), + Lines = string:tokens(binary_to_list(Binary), "\n"), + [Line] = Lines, + {ok, Hostname} = inet:gethostname(), + [HostAndIp, Alg, _KeyData] = string:tokens(Line, " "), + [Hostname, _Ip] = string:tokens(HostAndIp, ","), + "ssh-" ++ _ = Alg, + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +rename_known_hosts(BR) -> + KnownHosts = ssh_file:file_name(user, "known_hosts", []), + B = KnownHosts ++ "xxx", + case BR of + backup -> + file:rename(KnownHosts, B); + restore -> + file:delete(KnownHosts), + file:rename(B, KnownHosts) + end. diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..58f0a65cba --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 +jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ +ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe +uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 +nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq +mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 +2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS +QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C +ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 ++basD1iibtNHs9Edfdkm +-----END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..d83487fc50 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_host_dsa_key b/lib/ssh/test/ssh_host_dsa_key new file mode 100644 index 0000000000..58f0a65cba --- /dev/null +++ b/lib/ssh/test/ssh_host_dsa_key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 +jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ +ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe +uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 +nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq +mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 +2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS +QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C +ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 ++basD1iibtNHs9Edfdkm +-----END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..d83487fc50 --- /dev/null +++ b/lib/ssh/test/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl new file mode 100644 index 0000000000..eb7fbd6998 --- /dev/null +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -0,0 +1,531 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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% +%% + +%% +-module(ssh_sftp_SUITE). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +-include_lib("kernel/include/file.hrl"). + +% Default timetrap timeout +-define(default_timeout, ?t:minutes(1)). + +-define(SFPD_PORT, 9999). +-define(USER, "Alladin"). +-define(PASSWD, "Sesame"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + crypto:start(), + ssh:start(), + Dir = ?config(priv_dir, Config), + ssh_test_lib:save_known_hosts(Dir), + %% More like copy_id_keys!!! + {ok, _} = ssh_test_lib:get_id_keys(Dir), + Config. +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- +end_per_suite(Config) -> + crypto:stop(), + Dir = ?config(priv_dir, Config), + ssh_test_lib:remove_id_keys(Dir), + ssh_test_lib:restore_known_hosts(Dir), + Config. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config) -> Config +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Description: Initiation before each test case +%%-------------------------------------------------------------------- +init_per_testcase(_Case, Config) -> + prep(Config), + TmpConfig0 = lists:keydelete(watchdog, 1, Config), + TmpConfig = lists:keydelete(sftp, 1, TmpConfig0), + Dog = test_server:timetrap(?default_timeout), + Dir = ?config(priv_dir, Config), + SysDir = ?config(data_dir, Config), + Host = ssh_test_lib:hostname(), + + Sftp = case (catch ssh_sftp:start_channel(Host, + [{user_dir, Dir}, + {user_interaction, false}, + {silently_accept_hosts, true}])) of + {ok, ChannelPid, Connection} -> + {ChannelPid, Connection}; + _Error -> + {ok, _Sftpd} = + ssh:daemon(?SFPD_PORT, + [{system_dir, SysDir}, + {user_passwords, + [{?USER, ?PASSWD}]}, + {failfun, + fun ssh_test_lib:failfun/2}]), + Result = (catch ssh_sftp:start_channel(Host, ?SFPD_PORT, + [{user, ?USER}, + {password, ?PASSWD}, + {user_interaction, false}, + {silently_accept_hosts, true}])), + {ok, ChannelPid, Connection} = Result, + {ChannelPid, Connection} + end, + + [{sftp, Sftp}, {watchdog, Dog} | TmpConfig]. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config) -> _ +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after each test case +%%-------------------------------------------------------------------- +end_per_testcase(_Case, Config) -> + {Sftp, Connection} = ?config(sftp, Config), + ssh_sftp:stop_channel(Sftp), + ssh:close(Connection), + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +%%-------------------------------------------------------------------- +%% Function: all(Clause) -> TestCases +%% Clause - atom() - suite | doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% Description: Returns a list of all test cases in this test suite +%%-------------------------------------------------------------------- +all(doc) -> + ["Test the sftp client"]; + +all(suite) -> + [ + open_close_file, open_close_dir, read_file, read_dir, write_file, + rename_file, mk_rm_dir, remove_file, links, retrieve_attributes, + set_attributes, async_read, async_write, position, pos_read, pos_write + ]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +open_close_file(doc) -> + ["Test API functions open/3 and close/2"]; +open_close_file(suite) -> + []; +open_close_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + + {Sftp, _} = ?config(sftp, Config), + + ok = open_close_file(Sftp, FileName, [read]), + ok = open_close_file(Sftp, FileName, [write]), + ok = open_close_file(Sftp, FileName, [write, creat]), + ok = open_close_file(Sftp, FileName, [write, trunc]), + ok = open_close_file(Sftp, FileName, [append]), + ok = open_close_file(Sftp, FileName, [read, binary]), + + ok. + +open_close_file(Server, File, Mode) -> + {ok, Handle} = ssh_sftp:open(Server, File, Mode), + ok = ssh_sftp:close(Server, Handle), + ok. + + +%%-------------------------------------------------------------------- +open_close_dir(doc) -> + ["Test API functions opendir/2 and close/2"]; +open_close_dir(suite) -> + []; +open_close_dir(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + {Sftp, _} = ?config(sftp, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + + {ok, Handle} = ssh_sftp:opendir(Sftp, PrivDir), + ok = ssh_sftp:close(Sftp, Handle), + {error, _} = ssh_sftp:opendir(Sftp, FileName), + + ok. +%%-------------------------------------------------------------------- +read_file(doc) -> + ["Test API funtion read_file/2"]; +read_file(suite) -> + []; +read_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + + {Sftp, _} = ?config(sftp, Config), + + {ok, Data} = ssh_sftp:read_file(Sftp, FileName), + + {ok, Data} = file:read_file(FileName), + + ok. +%%-------------------------------------------------------------------- +read_dir(doc) -> + ["Test API function list_dir/2"]; +read_dir(suite) -> + []; +read_dir(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + {Sftp, _} = ?config(sftp, Config), + {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), + test_server:format("sftp list dir: ~p~n", [Files]), + ok. + +%%-------------------------------------------------------------------- +write_file(doc) -> + ["Test API function write_file/2"]; +write_file(suite) -> + []; +write_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + + {Sftp, _} = ?config(sftp, Config), + + Data = list_to_binary("Hej hopp!"), + + ssh_sftp:write_file(Sftp, FileName, [Data]), + + {ok, Data} = file:read_file(FileName), + + ok. + +%%-------------------------------------------------------------------- +remove_file(doc) -> + ["Test API function delete/2"]; +remove_file(suite) -> + []; +remove_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + + {Sftp, _} = ?config(sftp, Config), + + {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), + + true = lists:member(filename:basename(FileName), Files), + + ok = ssh_sftp:delete(Sftp, FileName), + + {ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir), + + false = lists:member(filename:basename(FileName), NewFiles), + + {error, _} = ssh_sftp:delete(Sftp, FileName), + + ok. + +%%-------------------------------------------------------------------- +rename_file(doc) -> + ["Test API function rename_file/2"]; +rename_file(suite) -> + []; +rename_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + NewFileName = filename:join(PrivDir, "test.txt"), + + {Sftp, _} = ?config(sftp, Config), + + {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), + + test_server:format("FileName: ~p, Files: ~p~n", [FileName, Files]), + + true = lists:member(filename:basename(FileName), Files), + false = lists:member(filename:basename(NewFileName), Files), + + ok = ssh_sftp:rename(Sftp, FileName, NewFileName), + + {ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir), + + test_server:format("FileName: ~p, Files: ~p~n", [FileName, NewFiles]), + + false = lists:member(filename:basename(FileName), NewFiles), + true = lists:member(filename:basename(NewFileName), NewFiles), + + ok. + +%%-------------------------------------------------------------------- +mk_rm_dir(doc) -> + ["Test API functions make_dir/2, del_dir/2"]; +mk_rm_dir(suite) -> + []; +mk_rm_dir(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + {Sftp, _} = ?config(sftp, Config), + DirName = filename:join(PrivDir, "test"), + + ok = ssh_sftp:make_dir(Sftp, DirName), + ok = ssh_sftp:del_dir(Sftp, DirName), + + NewDirName = filename:join(PrivDir, "foo/bar"), + + {error, _} = ssh_sftp:make_dir(Sftp, NewDirName), + {error, _} = ssh_sftp:del_dir(Sftp, PrivDir), + + ok. + +%%-------------------------------------------------------------------- +links(doc) -> + ["Tests API function make_symlink/3"]; +links(suite) -> + []; +links(Config) when is_list(Config) -> + case test_server:os_type() of + {win32, _} -> + {skip, "Links are not fully supported by windows"}; + _ -> + {Sftp, _} = ?config(sftp, Config), + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + LinkFileName = filename:join(PrivDir, "link_test.txt"), + + ok = ssh_sftp:make_symlink(Sftp, FileName, LinkFileName), + {ok, FileName} = ssh_sftp:read_link(Sftp, LinkFileName), + ok + end. + +%%-------------------------------------------------------------------- +retrieve_attributes(doc) -> + ["Test API function read_file_info/3"]; +retrieve_attributes(suite) -> + []; +retrieve_attributes(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + {Sftp, _} = ?config(sftp, Config), + + {ok, FileInfo} = ssh_sftp:read_file_info(Sftp, FileName), + + {ok, NewFileInfo} = file:read_file_info(FileName), + + %% TODO comparison. There are some differences now is that ok? + test_server:format("SFTP: ~p FILE: ~p~n", [FileInfo, NewFileInfo]), + ok. + +%%-------------------------------------------------------------------- +set_attributes(doc) -> + ["Test API function write_file_info/3"]; +set_attributes(suite) -> + []; +set_attributes(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + {Sftp, _} = ?config(sftp, Config), + + {ok,Fd} = file:open(FileName, write), + io:put_chars(Fd,"foo"), + + ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#400}), + {error, eacces} = file:write_file(FileName, "hello again"), + ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#600}), + ok = file:write_file(FileName, "hello again"), + + ok. + +%%-------------------------------------------------------------------- + +async_read(doc) -> + ["Test API aread/3"]; +async_read(suite) -> + []; +async_read(Config) when is_list(Config) -> + {Sftp, _} = ?config(sftp, Config), + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "sftp.txt"), + {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]), + {async, Ref} = ssh_sftp:aread(Sftp, Handle, 20), + + receive + {async_reply, Ref, {ok, Data}} -> + test_server:format("Data: ~p~n", [Data]), + ok; + Msg -> + test_server:fail(Msg) + end, + ok. +%%-------------------------------------------------------------------- +async_write(doc) -> + ["Test API awrite/3"]; +async_write(suite) -> + []; +async_write(Config) when is_list(Config) -> + {Sftp, _} = ?config(sftp, Config), + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]), + Data = list_to_binary("foobar"), + {async, Ref} = ssh_sftp:awrite(Sftp, Handle, Data), + + receive + {async_reply, Ref, ok} -> + {ok, Data} = file:read_file(FileName); + Msg -> + test_server:fail(Msg) + end, + ok. + +%%-------------------------------------------------------------------- + +position(doc) -> + ["Test API functions position/3"]; +position(suite) -> + []; +position(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + {Sftp, _} = ?config(sftp, Config), + + Data = list_to_binary("1234567890"), + ssh_sftp:write_file(Sftp, FileName, [Data]), + + {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]), + + {ok, 3} = ssh_sftp:position(Sftp, Handle, {bof, 3}), + {ok, "4"} = ssh_sftp:read(Sftp, Handle, 1), + + {ok, 10} = ssh_sftp:position(Sftp, Handle, eof), + eof = ssh_sftp:read(Sftp, Handle, 1), + + {ok, 6} = ssh_sftp:position(Sftp, Handle, {bof, 6}), + {ok, "7"} = ssh_sftp:read(Sftp, Handle, 1), + + {ok, 9} = ssh_sftp:position(Sftp, Handle, {cur, 2}), + {ok, "0"} = ssh_sftp:read(Sftp, Handle, 1), + + {ok, 0} = ssh_sftp:position(Sftp, Handle, bof), + {ok, "1"} = ssh_sftp:read(Sftp, Handle, 1), + + {ok, 1} = ssh_sftp:position(Sftp, Handle, cur), + {ok, "2"} = ssh_sftp:read(Sftp, Handle, 1), + + ok. + +%%-------------------------------------------------------------------- +pos_read(doc) -> + ["Test API functions pread/3 and apread/3"]; +pos_read(suite) -> + []; +pos_read(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + {Sftp, _} = ?config(sftp, Config), + Data = list_to_binary("Hej hopp!"), + ssh_sftp:write_file(Sftp, FileName, [Data]), + + {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]), + + {async, Ref} = ssh_sftp:apread(Sftp, Handle, {bof, 5}, 4), + + NewData = "opp!", + + receive + {async_reply, Ref, {ok, NewData}} -> + ok; + Msg -> + test_server:fail(Msg) + end, + + NewData1 = "hopp", + + {ok, NewData1} = ssh_sftp:pread(Sftp, Handle, {bof, 4}, 4), + + ok. +%%-------------------------------------------------------------------- +pos_write(doc) -> + ["Test API functions pwrite/4 and apwrite/4"]; +pos_write(suite) -> + []; +pos_write(Config) when is_list(Config) -> + + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + {Sftp, _} = ?config(sftp, Config), + + {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]), + + Data = list_to_binary("Bye,"), + ssh_sftp:write_file(Sftp, FileName, [Data]), + + NewData = list_to_binary(" see you tomorrow"), + {async, Ref} = ssh_sftp:apwrite(Sftp, Handle, {bof, 4}, NewData), + receive + {async_reply, Ref, ok} -> + ok; + Msg -> + test_server:fail(Msg) + end, + + ok = ssh_sftp:pwrite(Sftp, Handle, eof, list_to_binary("!")), + + NewData1 = list_to_binary("Bye, see you tomorrow!"), + {ok, NewData1} = ssh_sftp:read_file(Sftp, FileName), + + ok. + +%% Internal functions +%%-------------------------------------------------------------------- +prep(Config) -> + PrivDir = ?config(priv_dir, Config), + TestFile = filename:join(PrivDir, "sftp.txt"), + TestFile1 = filename:join(PrivDir, "test.txt"), + TestLink = filename:join(PrivDir, "link_test.txt"), + + file:delete(TestFile), + file:delete(TestFile1), + file:delete(TestLink), + + %% Initial config + DataDir = ?config(data_dir, Config), + FileName = filename:join(DataDir, "sftp.txt"), + file:copy(FileName, TestFile), + Mode = 8#00400 bor 8#00200 bor 8#00040, % read & write owner, read group + {ok, FileInfo} = file:read_file_info(TestFile), + ok = file:write_file_info(TestFile, + FileInfo#file_info{mode = Mode}). diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa new file mode 100644 index 0000000000..7e3f885f5d --- /dev/null +++ b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQDLKYTdRnGzphcN+pF8UuI3sYB7rxZUHbOT87K3vh8XOLkDOsS3 +8VREtNS8Wb3uYXsRtyDoUvrLIDnyllOfJSDupWLr4ibckUZd/nhFAaC6WryVmH6k +GlQLLp9KU+vcn2DwYeo14gbwHYDB3pmv4CWAlnO1m/BkX4aLz1zC314OkQIBIwKB +gD/Z2UzboBPjvhpWEHeHw3CW3zzQoJ4X9pw2peH57IOkHOPCA0/A3/hWFvleCH4e +owWRU3w3ViKVGYbBh/7RJ5rllN+ENUmVn536srJTxLKUtvb5jRGj3W6EWgAGHSUB +hm83Kt9Lb5hprL7dPrNGvSseBm/LQSfBQ4vUUyiVRKGPAkEA/rPxWoLdBBP+FZtE +fGzz9izPM6Fe6o8ZGNZIlRBProOhgEvvIqdgzQWObgLVVrw+M/YApPpiYS3PEmWj +b2b+jwJBAMwyYeL6coKTl8swDu8HvLnshgUFJFTtHhOTXsKtXQNI1b24xhUrB3Sb +X8fmoByyRNRpOfvg4Jdqi3Z6KfIcsN8CQQDEfC83McBw3DkJWoVKCugVrYnmACSm +USH9N5cT6AL0VupNB2C0VTwL37cEaJXyc/V4ipLIaWHV8CNl9qKmZWVJAkEAurG4 +lQI8zyfbPW3EgsU+1d+QeZ5NGnJkpC73jWtNudwxIn0M4CdXRgpmMxwAGjyWs5No +Nr75OfsDKn5SPHIAywJAKrtONlOizgDiG3EvAXZlwFtOb+HkQ7lrFwczrQu9m7yi +brSAcnTrLKI6CrR33b/QJLvb9C/HTEZojFABGq8M7A== +-----END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub new file mode 100644 index 0000000000..77f57de4af --- /dev/null +++ b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAyymE3UZxs6YXDfqRfFLiN7GAe68WVB2zk/Oyt74fFzi5AzrEt/FURLTUvFm97mF7Ebcg6FL6yyA58pZTnyUg7qVi6+Im3JFGXf54RQGgulq8lZh+pBpUCy6fSlPr3J9g8GHqNeIG8B2Awd6Zr+AlgJZztZvwZF+Gi89cwt9eDpE= jakob@balin diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt b/lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt new file mode 100644 index 0000000000..2a878ae255 --- /dev/null +++ b/lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt @@ -0,0 +1,252 @@ +There are 5 KeySyms per KeyCode; KeyCodes range from 8 to 254. + + KeyCode Keysym (Keysym) ... + Value Value (Name) ... + + 8 + 9 + 10 + 11 0x0041 (A) + 12 0x0042 (B) + 13 0x0043 (C) + 14 0x0044 (D) + 15 0x0065 (e) 0x0045 (E) 0x20ac (EuroSign) + 16 0x0046 (F) + 17 0x0047 (G) + 18 0x0048 (H) + 19 0x0049 (I) + 20 0x004a (J) + 21 0x004b (K) + 22 0x004c (L) + 23 0x004d (M) + 24 0x004e (N) + 25 0x004f (O) + 26 0x0050 (P) + 27 0x0051 (Q) + 28 0x0052 (R) + 29 0x0053 (S) + 30 0x0054 (T) + 31 0x0055 (U) + 32 0x0056 (V) + 33 0x0057 (W) + 34 0x0058 (X) + 35 0x0059 (Y) + 36 0x005a (Z) + 37 0x0031 (1) 0x0021 (exclam) + 38 0x0032 (2) 0x0022 (quotedbl) 0x0040 (at) + 39 0x0033 (3) 0x0023 (numbersign) 0x00a3 (sterling) + 40 0x0034 (4) 0x00a4 (currency) 0x0024 (dollar) + 41 0x0035 (5) 0x0025 (percent) + 42 0x0036 (6) 0x0026 (ampersand) + 43 0x0037 (7) 0x002f (slash) 0x007b (braceleft) + 44 0x0038 (8) 0x0028 (parenleft) 0x005b (bracketleft) + 45 0x0039 (9) 0x0029 (parenright) 0x005d (bracketright) + 46 0x0030 (0) 0x003d (equal) 0x007d (braceright) + 47 0xff0d (Return) + 48 0xff1b (Escape) + 49 0xff08 (BackSpace) + 50 0xff09 (Tab) + 51 0x0020 (space) + 52 0x002b (plus) 0x003f (question) 0x005c (backslash) + 53 0x1005ff03 (SunFA_Acute) 0x1005ff00 (SunFA_Grave) + 54 0x00c5 (Aring) + 55 0x1005ff04 (SunFA_Diaeresis) 0x005e (asciicircum) 0x007e (asciitilde) + 56 + 57 0x0027 (apostrophe) 0x002a (asterisk) 0x0060 (grave) + 58 0x00d6 (Odiaeresis) + 59 0x00c4 (Adiaeresis) + 60 0x00a7 (section) 0x00bd (onehalf) + 61 0x002c (comma) 0x003b (semicolon) + 62 0x002e (period) 0x003a (colon) + 63 0x002d (minus) 0x005f (underscore) + 64 0xffe5 (Caps_Lock) + 65 0xffbe (F1) + 66 0xffbf (F2) + 67 0xffc0 (F3) + 68 0xffc1 (F4) + 69 0xffc2 (F5) + 70 0xffc3 (F6) + 71 0xffc4 (F7) + 72 0xffc5 (F8) + 73 0xffc6 (F9) + 74 0xffc7 (F10) + 75 0x1005ff10 (SunF36) + 76 0x1005ff11 (SunF37) + 77 0xffd3 (F22) 0xffd3 (F22) 0xff61 (Print) 0x1005ff60 (SunSys_Req) + 78 0xffd4 (F23) 0xffd4 (F23) 0xff14 (Scroll_Lock) + 79 0xffd2 (F21) 0xffd2 (F21) 0xff13 (Pause) 0xff6b (Break) + 80 0xff63 (Insert) + 81 0xff50 (Home) + 82 0xff55 (Prior) + 83 0xffff (Delete) + 84 0xff57 (End) + 85 0xff56 (Next) + 86 0xff53 (Right) + 87 0xff51 (Left) + 88 0xff54 (Down) + 89 0xff52 (Up) + 90 0xff7f (Num_Lock) + 91 0xffd6 (F25) 0xffd6 (F25) 0xffaf (KP_Divide) + 92 0xffd7 (F26) 0xffd7 (F26) 0xffaa (KP_Multiply) + 93 0xffd5 (F24) 0xffd5 (F24) 0xffad (KP_Subtract) + 94 0xffab (KP_Add) + 95 0xff8d (KP_Enter) + 96 0xffde (F33) 0xffde (F33) 0xffb1 (KP_1) 0xff57 (End) + 97 0xff54 (Down) 0xffdf (F34) 0xffb2 (KP_2) + 98 0xffe0 (F35) 0xffe0 (F35) 0xffb3 (KP_3) 0xff56 (Next) + 99 0xff51 (Left) 0xffdb (F30) 0xffb4 (KP_4) + 100 0xffdc (F31) 0xffdc (F31) 0xffb5 (KP_5) + 101 0xff53 (Right) 0xffdd (F32) 0xffb6 (KP_6) + 102 0xffd8 (F27) 0xffd8 (F27) 0xffb7 (KP_7) 0xff50 (Home) + 103 0xff52 (Up) 0xffd9 (F28) 0xffb8 (KP_8) + 104 0xffda (F29) 0xffda (F29) 0xffb9 (KP_9) 0xff55 (Prior) + 105 0xff9e (KP_Insert) 0xff9e (KP_Insert) 0xffb0 (KP_0) + 106 0xffff (Delete) 0xffff (Delete) 0xffac (KP_Separator) + 107 0x003c (less) 0x003e (greater) 0x007c (bar) + 108 0xff20 (Multi_key) + 109 0x1005ff76 (SunPowerSwitch) 0x1005ff7d (SunPowerSwitchShift) + 110 + 111 + 112 + 113 + 114 + 115 + 116 + 117 + 118 + 119 + 120 + 121 + 122 + 123 0xffce (F17) 0xffce (F17) 0x1005ff73 (SunOpen) + 124 0xff6a (Help) + 125 0xffca (F13) 0xffca (F13) 0x1005ff70 (SunProps) + 126 0xffcc (F15) 0xffcc (F15) 0x1005ff71 (SunFront) + 127 0xffc8 (F11) 0xffc8 (F11) 0xff69 (Cancel) + 128 0xffc9 (F12) 0xffc9 (F12) 0xff66 (Redo) + 129 0xffcb (F14) 0xffcb (F14) 0xff65 (Undo) + 130 0xffd1 (F20) 0xffd1 (F20) 0x1005ff75 (SunCut) + 131 0xffcd (F16) 0xffcd (F16) 0x1005ff72 (SunCopy) + 132 0xffcf (F18) 0xffcf (F18) 0x1005ff74 (SunPaste) + 133 0xffd0 (F19) 0xffd0 (F19) 0xff68 (Find) + 134 0x1005ff78 (SunAudioMute) 0x1005ff7a (SunVideoDegauss) + 135 0x1005ff79 (SunAudioRaiseVolume) 0x1005ff7c (SunVideoRaiseBrightness) + 136 0x1005ff77 (SunAudioLowerVolume) 0x1005ff7b (SunVideoLowerBrightness) + 137 + 138 + 139 + 140 + 141 + 142 + 143 + 144 + 145 + 146 + 147 + 148 + 149 + 150 + 151 + 152 + 153 + 154 + 155 + 156 + 157 + 158 + 159 + 160 + 161 + 162 + 163 + 164 + 165 + 166 + 167 + 168 + 169 + 170 + 171 + 172 + 173 + 174 + 175 + 176 + 177 + 178 + 179 + 180 + 181 + 182 + 183 + 184 + 185 + 186 + 187 + 188 + 189 + 190 + 191 + 192 + 193 + 194 + 195 + 196 + 197 + 198 + 199 + 200 + 201 + 202 + 203 + 204 + 205 + 206 + 207 + 208 + 209 + 210 + 211 + 212 + 213 + 214 + 215 + 216 + 217 + 218 + 219 + 220 + 221 + 222 + 223 + 224 + 225 + 226 + 227 + 228 + 229 + 230 + 231 0xffe3 (Control_L) + 232 0xffe1 (Shift_L) + 233 0xffe9 (Alt_L) + 234 0xffe7 (Meta_L) + 235 + 236 0xffe2 (Shift_R) + 237 0xff7e (Mode_switch) + 238 0xffe8 (Meta_R) + 239 + 240 + 241 + 242 + 243 + 244 + 245 + 246 + 247 + 248 + 249 + 250 + 251 + 252 + 253 + 254 diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..58f0a65cba --- /dev/null +++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 +jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ +ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe +uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 +nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq +mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 +2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS +QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C +ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 ++basD1iibtNHs9Edfdkm +-----END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..d83487fc50 --- /dev/null +++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl new file mode 100644 index 0000000000..4ce6bd45b3 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -0,0 +1,914 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-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% +%% + +%% +-module(ssh_sftpd_SUITE). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). +-include("ssh_xfer.hrl"). +-include("ssh.hrl"). + +-include_lib("kernel/include/file.hrl"). + +-define(SFPD_PORT, 9999). +-define(USER, "Alladin"). +-define(PASSWD, "Sesame"). +-define(XFER_PACKET_SIZE, 32768). +-define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE). +-define(TIMEOUT, 10000). +-define(REG_ATTERS, <<0,0,0,0,1>>). +-define(UNIX_EPOCH, 62167219200). + +-define(is_set(F, Bits), + ((F) band (Bits)) == (F)). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + ssh:stop(), + crypto:start(), + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + crypto:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config) -> Config +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Description: Initiation before each test case +%%-------------------------------------------------------------------- +init_per_testcase(TestCase, Config) -> + ssh:start(), + prep(Config), + SysDir = ?config(data_dir, Config), + {ok, Sftpd} = + ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SysDir}, + {user_passwords,[{?USER, ?PASSWD}]}]), + + Host = ssh_test_lib:hostname(), + {ok, Cm} = ssh:connect(Host, ?SFPD_PORT, + [{silently_accept_hosts, true}, + {user, ?USER}, {password, ?PASSWD}]), + {ok, Channel} = + ssh_connection:session_channel(Cm, ?XFER_WINDOW_SIZE, + ?XFER_PACKET_SIZE, ?TIMEOUT), + + success = ssh_connection:subsystem(Cm, Channel, "sftp", ?TIMEOUT), + + ProtocolVer = case atom_to_list(TestCase) of + "ver3_" ++ _ -> + 3; + _ -> + ?SSH_SFTP_PROTOCOL_VERSION + end, + + Data = <> , + + Size = 1 + size(Data), + + ssh_connection:send(Cm, Channel, << ?UINT32(Size), + ?SSH_FXP_INIT, Data/binary >>), + + {ok, <>, _} + = reply(Cm, Channel), + + test_server:format("Client: ~p Server ~p~n", [ProtocolVer, Version]), + + [{sftp, {Cm, Channel}}, {sftpd, Sftpd }| Config]. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config) -> _ +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after each test case +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, Config) -> + ssh_sftpd:stop(?config(sftpd, Config)), + {Cm, Channel} = ?config(sftp, Config), + ssh_connection:close(Cm, Channel), + ssh:close(Cm), + ssh:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Function: all(Clause) -> TestCases +%% Clause - atom() - suite | doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% Description: Returns a list of all test cases in this test suite +%%-------------------------------------------------------------------- +all(doc) -> + ["Test the sftp server"]; + +all(suite) -> + [open_close_file, open_close_dir, read_file, read_dir, write_file, + rename_file, mk_rm_dir, remove_file, real_path, retrieve_attributes, + set_attributes, links, ver3_rename_OTP_6352, seq10670, sshd_read_file]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +open_close_file(doc) -> + ["Test SSH_FXP_OPEN and SSH_FXP_CLOSE commands"]; +open_close_file(suite) -> + []; +open_close_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + {Cm, Channel} = ?config(sftp, Config), + ReqId = 0, + + {ok, <>, _} = + open_file(FileName, Cm, Channel, ReqId, + ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), + + {ok, <>, _} = close(Handle, ReqId, + Cm, Channel), + NewReqId = ReqId + 1, + {ok, <>, _} = + close(Handle, ReqId, Cm, Channel), + + NewReqId1 = NewReqId + 1, + %% {ok, <>, _} = + {ok, <>, _} = + open_file(PrivDir, Cm, Channel, NewReqId1, + ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), + + ok. + +%%-------------------------------------------------------------------- +open_close_dir(doc) -> + ["Test SSH_FXP_OPENDIR and SSH_FXP_CLOSE commands"]; +open_close_dir(suite) -> + []; +open_close_dir(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + {Cm, Channel} = ?config(sftp, Config), + FileName = filename:join(PrivDir, "test.txt"), + ReqId = 0, + + {ok, <>, _} = + open_dir(PrivDir, Cm, Channel, ReqId), + + {ok, <>, _} = close(Handle, ReqId, + Cm, Channel), + + NewReqId = 1, + case open_dir(FileName, Cm, Channel, NewReqId) of + {ok, <>, _} -> + %% Only if server is using vsn > 5. + ok; + {ok, <>, _} -> + ok + end. + +%%-------------------------------------------------------------------- +read_file(doc) -> + ["Test SSH_FXP_READ command"]; +read_file(suite) -> + []; +read_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, <>, _} = + open_file(FileName, Cm, Channel, ReqId, + ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), + + NewReqId = 1, + + {ok, <>, _} = + read_file(Handle, 100, 0, Cm, Channel, NewReqId), + + {ok, Data} = file:read_file(FileName), + + ok. +%%-------------------------------------------------------------------- +read_dir(doc) -> + ["Test SSH_FXP_READDIR command"]; +read_dir(suite) -> + []; +read_dir(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + {Cm, Channel} = ?config(sftp, Config), + ReqId = 0, + {ok, <>, _} = + open_dir(PrivDir, Cm, Channel, ReqId), + ok = read_dir(Handle, Cm, Channel, ReqId), + ok. + +%%-------------------------------------------------------------------- +write_file(doc) -> + ["Test SSH_FXP_WRITE command"]; +write_file(suite) -> + []; +write_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, <>, _} = + open_file(FileName, Cm, Channel, ReqId, + ?ACE4_WRITE_DATA bor ?ACE4_WRITE_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), + + NewReqId = 1, + Data = list_to_binary("Write file test"), + + {ok, <>, _} + = write_file(Handle, Data, 0, Cm, Channel, NewReqId), + + {ok, Data} = file:read_file(FileName), + + ok. + +%%-------------------------------------------------------------------- +remove_file(doc) -> + ["Test SSH_FXP_REMOVE command"]; +remove_file(suite) -> + []; +remove_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, <>, _} = + remove(FileName, Cm, Channel, ReqId), + + NewReqId = 1, + %% {ok, <>, _} = + + {ok, <>, _} = + remove(PrivDir, Cm, Channel, NewReqId), + + ok. + +%%-------------------------------------------------------------------- +rename_file(doc) -> + ["Test SSH_FXP_RENAME command"]; +rename_file(suite) -> + []; +rename_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + NewFileName = filename:join(PrivDir, "test1.txt"), + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, <>, _} = + rename(FileName, NewFileName, Cm, Channel, ReqId, 6, 0), + + NewReqId = ReqId + 1, + + {ok, <>, _} = + rename(NewFileName, FileName, Cm, Channel, NewReqId, 6, + ?SSH_FXP_RENAME_OVERWRITE), + + NewReqId1 = NewReqId + 1, + file:copy(FileName, NewFileName), + + %% No owerwrite + {ok, <>, _} = + rename(FileName, NewFileName, Cm, Channel, NewReqId1, 6, + ?SSH_FXP_RENAME_NATIVE), + + NewReqId2 = NewReqId1 + 1, + + {ok, <>, _} = + rename(FileName, NewFileName, Cm, Channel, NewReqId2, 6, + ?SSH_FXP_RENAME_ATOMIC), + + ok. + +%%-------------------------------------------------------------------- +mk_rm_dir(doc) -> + ["Test SSH_FXP_MKDIR and SSH_FXP_RMDIR command"]; +mk_rm_dir(suite) -> + []; +mk_rm_dir(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + {Cm, Channel} = ?config(sftp, Config), + DirName = filename:join(PrivDir, "test"), + ReqId = 0, + {ok, <>, _} = mkdir(DirName, Cm, Channel, ReqId), + + NewReqId = 1, + {ok, <>, _} = mkdir(DirName, Cm, Channel, NewReqId), + + NewReqId1 = 2, + {ok, <>, _} = rmdir(DirName, Cm, Channel, NewReqId1), + + NewReqId2 = 3, + {ok, <>, _} = rmdir(DirName, Cm, Channel, NewReqId2), + + ok. +%%-------------------------------------------------------------------- +real_path(doc) -> + ["Test SSH_FXP_REALPATH command"]; +real_path(suite) -> + []; +real_path(Config) when is_list(Config) -> + case test_server:os_type() of + {win32, _} -> + {skip, "Not a relevant test on windows"}; + _ -> + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + PrivDir = ?config(priv_dir, Config), + TestDir = filename:join(PrivDir, "ssh_test"), + ok = file:make_dir(TestDir), + + OrigPath = filename:join(TestDir, ".."), + + {ok, <>, _} + = real_path(OrigPath, Cm, Channel, ReqId), + + RealPath = filename:absname(binary_to_list(Path)), + AbsPrivDir = filename:absname(PrivDir), + + test_server:format("Path: ~p PrivDir: ~p~n", [RealPath, AbsPrivDir]), + + true = RealPath == AbsPrivDir, + + ok + end. + +%%-------------------------------------------------------------------- +links(doc) -> + []; +links(suite) -> + []; +links(Config) when is_list(Config) -> + case test_server:os_type() of + {win32, _} -> + {skip, "Links are not fully supported by windows"}; + _ -> + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + LinkFileName = filename:join(PrivDir, "link_test.txt"), + + {ok, <>, _} = + create_link(LinkFileName, FileName, Cm, Channel, ReqId), + + NewReqId = 1, + {ok, <>, _} + = read_link(LinkFileName, Cm, Channel, NewReqId), + + + true = binary_to_list(Path) == FileName, + + test_server:format("Path: ~p~n", [binary_to_list(Path)]), + ok + end. + +%%-------------------------------------------------------------------- +retrieve_attributes(doc) -> + ["Test SSH_FXP_STAT, SSH_FXP_LSTAT AND SSH_FXP_FSTAT commands"]; +retrieve_attributes(suite) -> + []; +retrieve_attributes(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, FileInfo} = file:read_file_info(FileName), + + AttrValues = + retrive_attributes(FileName, Cm, Channel, ReqId), + + Type = encode_file_type(FileInfo#file_info.type), + Size = FileInfo#file_info.size, + Owner = FileInfo#file_info.uid, + Group = FileInfo#file_info.gid, + Permissions = FileInfo#file_info.mode, + Atime = calendar:datetime_to_gregorian_seconds( + erlang:localtime_to_universaltime(FileInfo#file_info.atime)) + - ?UNIX_EPOCH, + Mtime = calendar:datetime_to_gregorian_seconds( + erlang:localtime_to_universaltime(FileInfo#file_info.mtime)) + - ?UNIX_EPOCH, + Ctime = calendar:datetime_to_gregorian_seconds( + erlang:localtime_to_universaltime(FileInfo#file_info.ctime)) + - ?UNIX_EPOCH, + + lists:foreach(fun(Value) -> + <> = Value, + true = ?is_set(?SSH_FILEXFER_ATTR_SIZE, + Flags), + true = ?is_set(?SSH_FILEXFER_ATTR_PERMISSIONS, + Flags), + true = ?is_set(?SSH_FILEXFER_ATTR_ACCESSTIME, + Flags), + true = ?is_set(?SSH_FILEXFER_ATTR_CREATETIME, + Flags), + true = ?is_set(?SSH_FILEXFER_ATTR_MODIFYTIME, + Flags), + true = ?is_set(?SSH_FILEXFER_ATTR_OWNERGROUP, + Flags), + false = ?is_set(?SSH_FILEXFER_ATTR_ACL, + Flags), + false = ?is_set(?SSH_FILEXFER_ATTR_SUBSECOND_TIMES, + Flags), + false = ?is_set(?SSH_FILEXFER_ATTR_BITS, + Flags), + false = ?is_set(?SSH_FILEXFER_ATTR_EXTENDED, + Flags), + + <> = Value, + + Owner = list_to_integer(binary_to_list(BinOwner)), + Group = list_to_integer(binary_to_list(BinGroup)) + end, AttrValues), + + ok. +%%-------------------------------------------------------------------- +set_attributes(doc) -> + ["Test SSH_FXP_SETSTAT AND SSH_FXP_FSETSTAT commands"]; +set_attributes(suite) -> + []; +set_attributes(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, FileInfo} = file:read_file_info(FileName), + + OrigPermissions = FileInfo#file_info.mode, + Permissions = 8#400, %% User read-only + + Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS, + + Atters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR), + ?uint32(Permissions)], + + {ok, <>, _} = + set_attributes_file(FileName, Atters, Cm, Channel, ReqId), + + {ok, NewFileInfo} = file:read_file_info(FileName), + NewPermissions = NewFileInfo#file_info.mode, + + %% Can not test that NewPermissions = Permissions as + %% on Unix platforms, other bits than those listed in the + %% API may be set. + test_server:format("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]), + true = OrigPermissions =/= NewPermissions, + + test_server:format("Try to open the file"), + NewReqId = 2, + {ok, <>, _} = + open_file(FileName, Cm, Channel, NewReqId, + ?ACE4_READ_DATA bor ?ACE4_WRITE_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), + + NewAtters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR), + ?uint32(OrigPermissions)], + + NewReqId1 = 3, + + test_server:format("Set original permissions on the now open file"), + + {ok, <>, _} = + set_attributes_open_file(Handle, NewAtters, Cm, Channel, NewReqId1), + + {ok, NewFileInfo1} = file:read_file_info(FileName), + OrigPermissions = NewFileInfo1#file_info.mode, + + ok. + +%%-------------------------------------------------------------------- +ver3_rename_OTP_6352(doc) -> + ["Test that ver3 rename message is handled"]; + +ver3_rename_OTP_6352(suite) -> + []; + +ver3_rename_OTP_6352(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + NewFileName = filename:join(PrivDir, "test1.txt"), + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, <>, _} = + rename(FileName, NewFileName, Cm, Channel, ReqId, 3, 0), + + ok. + +%%-------------------------------------------------------------------- +seq10670(doc) -> + ["Check that realpath works ok"]; + +seq10670(suite) -> + []; + +seq10670(Config) when is_list(Config) -> + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + case test_server:os_type() of + {win32, _} -> + {skip, "Not a relevant test on windows"}; + _ -> + {ok, <>, _} + = real_path("/..", Cm, Channel, ReqId), + + <<"/">> = Root, + + {ok, <>, _} + = real_path("/usr/bin/../..", Cm, Channel, ReqId), + + Root = Path + end. + +%% Internal functions +%%-------------------------------------------------------------------- +prep(Config) -> + PrivDir = ?config(priv_dir, Config), + TestFile = filename:join(PrivDir, "test.txt"), + TestFile1 = filename:join(PrivDir, "test1.txt"), + + file:delete(TestFile), + file:delete(TestFile1), + + %% Initial config + DataDir = ?config(data_dir, Config), + FileName = filename:join(DataDir, "test.txt"), + file:copy(FileName, TestFile), + Mode = 8#00400 bor 8#00200 bor 8#00040, % read & write owner, read group + {ok, FileInfo} = file:read_file_info(TestFile), + ok = file:write_file_info(TestFile, + FileInfo#file_info{mode = Mode}). + +reply(Cm, Channel) -> + reply(Cm, Channel,<<>>). + +reply(Cm, Channel, RBuf) -> + receive + {ssh_cm, Cm, {data, Channel, 0, Data}} -> + case <> of + <> -> + {ok, Reply, Rest}; + RBuf2 -> + reply(Cm, Channel, RBuf2) + end; + {ssh_cm, Cm, {eof, Channel}} -> + eof; + {ssh_cm, Cm, {closed, Channel}} -> + closed; + {ssh_cm, Cm, Msg} -> + test_server:fail(Msg) + end. + + +open_file(File, Cm, Channel, ReqId, Access, Flags) -> + + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(File)), + ?uint32(Access), + ?uint32(Flags), + ?REG_ATTERS]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + + +close(Handle, ReqId, Cm , Channel) -> + Data = list_to_binary([?uint32(ReqId), Handle]), + + Size = 1 + size(Data), + + ssh_connection:send(Cm, Channel, <>), + + reply(Cm, Channel). + + + +open_dir(Dir, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(Dir))]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +rename(OldName, NewName, Cm, Channel, ReqId, Version, Flags) -> + Data = + case Version of + 3 -> + list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(OldName)), + ?binary(list_to_binary(NewName))]); + _ -> + list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(OldName)), + ?binary(list_to_binary(NewName)), + ?uint32(Flags)]) + end, + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +mkdir(Dir, Cm, Channel, ReqId)-> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(Dir)), + ?REG_ATTERS]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +rmdir(Dir, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(Dir))]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + +remove(File, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(File))]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +read_dir(Handle, Cm, Channel, ReqId) -> + + Data = list_to_binary([?uint32(ReqId), Handle]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + case reply(Cm, Channel) of + {ok, <>, _} -> + test_server:format("Count: ~p Listing: ~p~n", + [Count, binary_to_list(Listing)]), + read_dir(Handle, Cm, Channel, ReqId); + {ok, <>, _} -> + ok + end. + +read_file(Handle, MaxLength, OffSet, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), Handle, + ?uint64(OffSet), + ?uint32(MaxLength)]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +write_file(Handle, FileData, OffSet, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), Handle, + ?uint64(OffSet), + ?binary(FileData)]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +real_path(OrigPath, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(OrigPath))]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + +create_link(LinkPath, Path, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(LinkPath)), + ?binary(list_to_binary(Path))]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +read_link(Link, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(Link))]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + +retrive_attributes_file(FilePath, Flags, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(FilePath)), + ?uint32(Flags)]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + +retrive_attributes_file_or_link(FilePath, Flags, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(FilePath)), + ?uint32(Flags)]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + +retrive_attributes_open_file(Handle, Flags, Cm, Channel, ReqId) -> + + Data = list_to_binary([?uint32(ReqId), + Handle, + ?uint32(Flags)]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + +retrive_attributes(FileName, Cm, Channel, ReqId) -> + + Attr = ?SSH_FILEXFER_ATTR_SIZE, + + {ok, <>, _} + = retrive_attributes_file(FileName, Attr, + Cm, Channel, ReqId), + + NewReqId = ReqId + 1, + {ok, <>, _} + = retrive_attributes_file_or_link(FileName, + Attr, Cm, Channel, NewReqId), + + NewReqId1 = NewReqId + 1, + {ok, <>, _} = + open_file(FileName, Cm, Channel, NewReqId1, + ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), + + NewReqId2 = NewReqId1 + 1, + {ok, <>, _} + = retrive_attributes_open_file(Handle, Attr, Cm, Channel, NewReqId2), + + [Value, Value1, Value2]. + +set_attributes_file(FilePath, Atters, Cm, Channel, ReqId) -> + Data = list_to_binary([?uint32(ReqId), + ?binary(list_to_binary(FilePath)), + Atters]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +set_attributes_open_file(Handle, Atters, Cm, Channel, ReqId) -> + + Data = list_to_binary([?uint32(ReqId), + Handle, + Atters]), + Size = 1 + size(Data), + ssh_connection:send(Cm, Channel, <>), + reply(Cm, Channel). + + +encode_file_type(Type) -> + case Type of + regular -> ?SSH_FILEXFER_TYPE_REGULAR; + directory -> ?SSH_FILEXFER_TYPE_DIRECTORY; + symlink -> ?SSH_FILEXFER_TYPE_SYMLINK; + special -> ?SSH_FILEXFER_TYPE_SPECIAL; + unknown -> ?SSH_FILEXFER_TYPE_UNKNOWN; + other -> ?SSH_FILEXFER_TYPE_UNKNOWN; + socket -> ?SSH_FILEXFER_TYPE_SOCKET; + char_device -> ?SSH_FILEXFER_TYPE_CHAR_DEVICE; + block_device -> ?SSH_FILEXFER_TYPE_BLOCK_DEVICE; + fifo -> ?SSH_FILEXFER_TYPE_FIFO; + undefined -> ?SSH_FILEXFER_TYPE_UNKNOWN + end. + +%%-------------------------------------------------------------------- +sshd_read_file(doc) -> + ["Test SSH_FXP_READ command, using sshd-server"]; +sshd_read_file(suite) -> + []; +sshd_read_file(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), + + {ok, <>, _} = + open_file(FileName, Cm, Channel, ReqId, + ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), + + NewReqId = 1, + + {ok, <>, _} = + read_file(Handle, 100, 0, Cm, Channel, NewReqId), + + {ok, Data} = file:read_file(FileName), + + ok. diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..58f0a65cba --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 +jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ +ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe +uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 +nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq +mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 +2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS +QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C +ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 ++basD1iibtNHs9Edfdkm +-----END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..d83487fc50 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/test.txt b/lib/ssh/test/ssh_sftpd_SUITE_data/test.txt new file mode 100644 index 0000000000..681bff80a0 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_SUITE_data/test.txt @@ -0,0 +1 @@ +Sftp test file. \ No newline at end of file diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl new file mode 100644 index 0000000000..6ae5e73dcb --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -0,0 +1,304 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-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% +%% + +%% +-module(ssh_sftpd_erlclient_SUITE). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +-include_lib("kernel/include/file.hrl"). + +-define(SSHD_PORT, 9999). +-define(USER, "Alladin"). +-define(PASSWD, "Sesame"). +-define(SSH_MAX_PACKET_SIZE, 32768). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + ssh:stop(), + crypto:start(), + DataDir = ?config(data_dir, Config), + FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"), + c:c(FileAlt), + FileName = filename:join(DataDir, "test.txt"), + {ok, FileInfo} = file:read_file_info(FileName), + ok = file:write_file_info(FileName, + FileInfo#file_info{mode = 8#400}), + + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + crypto:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config) -> Config +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Description: Initiation before each test case +%%-------------------------------------------------------------------- +init_per_testcase(TestCase, Config) -> + ssh:start(), + DataDir = ?config(data_dir, Config), + + Options = + case atom_to_list(TestCase) of + "file_cb" ++ _ -> + Spec = + ssh_sftpd:subsystem_spec([{file_handler, + ssh_sftpd_file_alt}]), + [{user_passwords,[{?USER, ?PASSWD}]}, + {system_dir, DataDir}, + {subsystems, [Spec]}]; + "root_dir" -> + Privdir = ?config(priv_dir, Config), + Root = filename:join(Privdir, root), + file:make_dir(Root), + Spec = ssh_sftpd:subsystem_spec([{root,Root}]), + [{user_passwords,[{?USER, ?PASSWD}]}, + {system_dir, DataDir}, + {subsystems, [Spec]}]; + "list_dir_limited" -> + Spec = + ssh_sftpd:subsystem_spec([{max_files,1}]), + [{user_passwords,[{?USER, ?PASSWD}]}, + {system_dir, DataDir}, + {subsystems, [Spec]}]; + + _ -> + [{user_passwords,[{?USER, ?PASSWD}]}, + {system_dir, DataDir}] + end, + + {ok, Sftpd} = ssh:daemon(any, ?SSHD_PORT, Options), + + Host = ssh_test_lib:hostname(), + {ok, ChannelPid, Connection} = + ssh_sftp:start_channel(Host, ?SSHD_PORT, + [{silently_accept_hosts, true}, + {user, ?USER}, {password, ?PASSWD}, {timeout, 30000}]), + TmpConfig = lists:keydelete(sftp, 1, Config), + NewConfig = lists:keydelete(sftpd, 1, TmpConfig), + [{sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig]. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config) -> _ +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after each test case +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, Config) -> + catch ssh_sftpd:stop(?config(sftpd, Config)), + {Sftp, Connection} = ?config(sftp, Config), + catch ssh_sftp:stop_channel(Sftp), + catch ssh:close(Connection), + ssh:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Function: all(Clause) -> TestCases +%% Clause - atom() - suite | doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% Description: Returns a list of all test cases in this test suite +%%-------------------------------------------------------------------- +all(doc) -> + ["Test ssh_sftpd"]; + +all(suite) -> + [close_file_OTP_6350, quit_OTP_6349, file_cb_OTP_6356, + root_dir, list_dir_limited]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +close_file_OTP_6350(doc) -> + ["Test that sftpd closes its fildescriptors after compleating the " + "transfer"]; + +close_file_OTP_6350(suite) -> + []; + +close_file_OTP_6350(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + FileName = filename:join(DataDir, "test.txt"), + + {Sftp, _} = ?config(sftp, Config), + + NumOfPorts = length(erlang:ports()), + + test_server:format("Number of open ports: ~p~n", [NumOfPorts]), + + {ok, <<_/binary>>} = ssh_sftp:read_file(Sftp, FileName), + + NumOfPorts = length(erlang:ports()), + + test_server:format("Number of open ports: ~p~n", + [length(erlang:ports())]), + + ok. + +%%-------------------------------------------------------------------- + +quit_OTP_6349(doc) -> + [" When the sftp client ends the session the " + "server will now behave correctly and not leave the " + "client hanging."]; + +quit_OTP_6349(suite) -> + []; + +quit_OTP_6349(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + FileName = filename:join(DataDir, "test.txt"), + + {Sftp, _} = ?config(sftp, Config), + + {ok, <<_/binary>>} = ssh_sftp:read_file(Sftp, FileName), + + ok = ssh_sftp:stop_channel(Sftp), + + Host = ssh_test_lib:hostname(), + + timer:sleep(5000), + {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, ?SSHD_PORT, + [{silently_accept_hosts, true}, + {user, ?USER}, {password, ?PASSWD}]), + + {ok, <<_/binary>>} = ssh_sftp:read_file(NewSftp, FileName), + + ok = ssh_sftp:stop_channel(NewSftp), + ok. + +%%-------------------------------------------------------------------- + +file_cb_OTP_6356(doc) -> + ["Test that it is possible to change the callback module for" + " the sftpds filehandling."]; + +file_cb_OTP_6356(suite) -> + []; + +file_cb_OTP_6356(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(DataDir, "test.txt"), + + register(sftpd_file_alt_tester, self()), + + {Sftp, _} = ?config(sftp, Config), + + {ok, Bin} = ssh_sftp:read_file(Sftp, FileName), + alt_file_handler_check(alt_open), + alt_file_handler_check(alt_read_file_info), + alt_file_handler_check(alt_position), + alt_file_handler_check(alt_read), + alt_file_handler_check(alt_position), + alt_file_handler_check(alt_read), + alt_file_handler_check(alt_close), + + + NewFileName = filename:join(PrivDir, "test.txt"), + ok = ssh_sftp:write_file(Sftp, NewFileName, Bin), + alt_file_handler_check(alt_open), + alt_file_handler_check(alt_read_file_info), + alt_file_handler_check(alt_position), + alt_file_handler_check(alt_write), + alt_file_handler_check(alt_close), + + ReFileName = filename:join(PrivDir, "test1.txt"), + ok = ssh_sftp:rename(Sftp, NewFileName, ReFileName), + alt_file_handler_check(alt_rename), + + ok = ssh_sftp:delete(Sftp, ReFileName), + alt_file_handler_check(alt_delete), + + NewDir = filename:join(PrivDir, "testdir"), + ok = ssh_sftp:make_dir(Sftp, NewDir), + alt_file_handler_check(alt_make_dir), + + ok = ssh_sftp:del_dir(Sftp, NewDir), + alt_file_handler_check(alt_read_link_info), + alt_file_handler_check(alt_write_file_info), + alt_file_handler_check(alt_del_dir), + ok. + +root_dir(doc) -> + [""]; +root_dir(suite) -> + []; +root_dir(Config) when is_list(Config) -> + {Sftp, _} = ?config(sftp, Config), + FileName = "test.txt", + Bin = <<"Test file for root dir option">>, + ok = ssh_sftp:write_file(Sftp, FileName, Bin), + {ok, Bin} = ssh_sftp:read_file(Sftp, FileName), + {ok, Listing} = + ssh_sftp:list_dir(Sftp, "."), + test_server:format("Listing: ~p~n", [Listing]), + ok. + +list_dir_limited(doc) -> + [""]; +list_dir_limited(suite) -> + []; +list_dir_limited(Config) when is_list(Config) -> + {Sftp, _} = ?config(sftp, Config), + {ok, Listing} = + ssh_sftp:list_dir(Sftp, "."), + test_server:format("Listing: ~p~n", [Listing]), + ok. + +alt_file_handler_check(Msg) -> + receive + Msg -> + ok; + Other -> + test_server:fail({Msg, Other}) + after 10000 -> + test_server:fail("Not alt file handler") + end. diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..58f0a65cba --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 +jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ +ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe +uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 +nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq +mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 +2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS +QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C +ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 ++basD1iibtNHs9Edfdkm +-----END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..d83487fc50 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl new file mode 100644 index 0000000000..9e119c4929 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl @@ -0,0 +1,100 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-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% +%% + +%% + +%%% Description: Dummy Callback module for ssh_sftpd to test +%%% the possibility to switch file handling implementation. + +-module(ssh_sftpd_file_alt). + +-behaviour(ssh_sftpd_file_api). + +%% API +-export([close/2, delete/2, del_dir/2, get_cwd/1, is_dir/2, list_dir/2, + make_dir/2, make_symlink/3, open/3, position/3, read/3, + read_file_info/2, read_link/2, read_link_info/2, rename/3, + write/3, write_file_info/3]). + +close(IoDevice, State) -> + sftpd_file_alt_tester ! alt_close, + {file:close(IoDevice), State}. + +delete(Path, State) -> + sftpd_file_alt_tester ! alt_delete, + {file:delete(Path), State}. + +del_dir(Path, State) -> + sftpd_file_alt_tester ! alt_del_dir, + {file:del_dir(Path), State}. + +get_cwd(State) -> + {file:get_cwd(), State}. + +is_dir(AbsPath, State) -> + sftpd_file_alt_tester ! alt_is_dir, + {filelib:is_dir(AbsPath), State}. + +list_dir(AbsPath, State) -> + sftpd_file_alt_tester ! alt_list_dir, + {file:list_dir(AbsPath), State}. + +make_dir(Dir, State) -> + sftpd_file_alt_tester ! alt_make_dir, + {file:make_dir(Dir), State}. + +make_symlink(Path2, Path, State) -> + sftpd_file_alt_tester ! alt_make_symlink, + {file:make_symlink(Path2, Path), State}. + +open(Path, Flags, State) -> + sftpd_file_alt_tester ! alt_open, + {file:open(Path, Flags), State}. + +position(IoDevice, Offs, State) -> + sftpd_file_alt_tester ! alt_position, + {file:position(IoDevice, Offs), State}. + +read(IoDevice, Len, State) -> + sftpd_file_alt_tester ! alt_read, + {file:read(IoDevice, Len), State}. + +read_link(Path, State) -> + sftpd_file_alt_tester ! alt_read_link, + {file:read_link(Path), State}. + +read_link_info(Path, State) -> + sftpd_file_alt_tester ! alt_read_link_info, + {file:read_link_info(Path), State}. + +read_file_info(Path, State) -> + sftpd_file_alt_tester ! alt_read_file_info, + {file:read_file_info(Path), State}. + +rename(Path, Path2, State) -> + sftpd_file_alt_tester ! alt_rename, + {file:rename(Path, Path2), State}. + +write(IoDevice, Data, State) -> + sftpd_file_alt_tester ! alt_write, + {file:write(IoDevice, Data), State}. + +write_file_info(Path,Info, State) -> + sftpd_file_alt_tester ! alt_write_file_info, + {file:write_file_info(Path, Info), State}. diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt new file mode 100644 index 0000000000..681bff80a0 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt @@ -0,0 +1 @@ +Sftp test file. \ No newline at end of file diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl new file mode 100644 index 0000000000..2eb19cec22 --- /dev/null +++ b/lib/ssh/test/ssh_test_lib.erl @@ -0,0 +1,189 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% + +%% +%%---------------------------------------------------------------------- +-module(ssh_test_lib). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +start_shell(Port, IOServer) -> + spawn_link(?MODULE, init_shell, [Port, IOServer]). + +init_shell(Port, IOServer) -> + Host = ssh_test_lib:hostname(), + UserDir = ssh_test_lib:get_user_dir(), + Options = [{user_interaction, false}, {silently_accept_hosts, + true}] ++ UserDir, + group_leader(IOServer, self()), + loop_shell(Host, Port, Options). + +loop_shell(Host, Port, Options) -> + ssh:shell(Host, Port, Options). + +start_io_server() -> + spawn_link(?MODULE, init_io_server, [self()]). + +init_io_server(TestCase) -> + process_flag(trap_exit, true), + loop_io_server(TestCase, []). + +loop_io_server(TestCase, Buff0) -> + receive + {input, TestCase, Line} -> + %io:format("~p~n",[{input, TestCase, Line}]), + loop_io_server(TestCase, Buff0 ++ [Line]); + {io_request, From, ReplyAs, Request} -> + %io:format("request -> ~p~n",[Request]), + {ok, Reply, Buff} = io_request(Request, TestCase, From, + ReplyAs, Buff0), + %io:format("reply -> ~p~n",[Reply]), + io_reply(From, ReplyAs, Reply), + loop_io_server(TestCase, Buff); + {'EXIT',_, _} -> + erlang:display('EXIT'), + ok + end. + +io_request({put_chars, Chars}, TestCase, _, _, Buff) -> + reply(TestCase, Chars), + {ok, ok, Buff}; +io_request({put_chars, Enc, Chars}, TestCase, _, _, Buff) -> + reply(TestCase, unicode:characters_to_binary(Chars,Enc,latin1)), + {ok, ok, Buff}; + +io_request({get_line, _} = Request, _, From, ReplyAs, [] = Buff) -> + erlang:send_after(1000, self(), {io_request, From, ReplyAs, Request}), + {ok, [], Buff}; +io_request({get_line, _Enc, _Prompt} = Request, _, From, ReplyAs, [] = Buff) -> + erlang:send_after(1000, self(), {io_request, From, ReplyAs, Request}), + {ok, [], Buff}; + +io_request({get_line, _Enc,_}, _, _, _, [Line | Buff]) -> + {ok, Line, Buff}. + +io_reply(_, _, []) -> + ok; +io_reply(From, ReplyAs, Reply) -> + From ! {io_reply, ReplyAs, Reply}. + +reply(_, []) -> + ok; +reply(TestCase, Result) -> + TestCase ! Result. + +receive_exec_result(Msg) -> + test_server:format("Expect data! ~p", [Msg]), + receive + Msg -> + test_server:format("1: Collected data ~p", [Msg]), + expected; + Other -> + {unexpected_msg, Other} + end. +receive_exec_end(ConnectionRef, ChannelId) -> + Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}}, + ExitStatus = {ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}}, + Closed = {ssh_cm, ConnectionRef,{closed, ChannelId}}, + case receive_exec_result(ExitStatus) of + {unexpected_msg, Eof} -> %% Open ssh seems to not allways send these messages + %% in the same order! + test_server:format("2: Collected data ~p", [Eof]), + case receive_exec_result(ExitStatus) of + expected -> + expected = receive_exec_result(Closed); + {unexpected_msg, Closed} -> + test_server:format("3: Collected data ~p", [Closed]) + end; + expected -> + test_server:format("4: Collected data ~p", [ExitStatus]), + expected = receive_exec_result(Eof), + expected = receive_exec_result(Closed); + Other -> + test_server:fail({unexpected_msg, Other}) + end. + +receive_exec_result(Data, ConnectionRef, ChannelId) -> + Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}}, + Closed = {ssh_cm, ConnectionRef,{closed, ChannelId}}, + expected = ssh_test_lib:receive_exec_result(Data), + expected = ssh_test_lib:receive_exec_result(Eof), + expected = ssh_test_lib:receive_exec_result(Closed). + + +inet_port()-> + {ok, Socket} = gen_tcp:listen(0, [{reuseaddr, true}]), + {ok, Port} = inet:port(Socket), + gen_tcp:close(Socket), + Port. + + +%% copy private keys to given dir from ~/.ssh +get_id_keys(DstDir) -> + SrcDir = filename:join(os:getenv("HOME"), ".ssh"), + RsaOk = copyfile(SrcDir, DstDir, "id_rsa"), + DsaOk = copyfile(SrcDir, DstDir, "id_dsa"), + case {RsaOk, DsaOk} of + {{ok, _}, {ok, _}} -> {ok, both}; + {{ok, _}, _} -> {ok, rsa}; + {_, {ok, _}} -> {ok, dsa}; + {Error, _} -> Error + end. + +remove_id_keys(Dir) -> + file:delete(filename:join(Dir, "id_rsa")), + file:delete(filename:join(Dir, "id_dsa")). + +copyfile(SrcDir, DstDir, Fn) -> + file:copy(filename:join(SrcDir, Fn), + filename:join(DstDir, Fn)). + +failfun(_User, {authmethod,none}) -> + ok; +failfun(User, Reason) -> + error_logger:format("~p failed XXX to login: ~p~n", [User, Reason]). + +hostname() -> + {ok,Host} = inet:gethostname(), + Host. + +save_known_hosts(PrivDir) -> + Src = ssh_file:file_name(user, "known_hosts", []), + Dst = filename:join(PrivDir, "kh_save"), + Ok = file:copy(Src, Dst), + io:format("save ~p -> ~p : ~p", [Src, Dst, Ok]). + +restore_known_hosts(_PrivDir) -> + %% Race condition. + ok. +%% Src = filename:join(PrivDir, "kh_save"), +%% Dst = ssh_file:file_name(user, "known_hosts", []), +%% D1 = file:delete(Dst), +%% C = file:copy(Src, Dst), +%% D2 = file:delete(Src), +%% io:format("restore ~p -> ~p : ~p ~p ~p\n", [Src, Dst, D1, C, D2]). + +get_user_dir() -> + case os:type() of + {win32, _} -> + [{user_dir, filename:join([os:getenv("HOME"), ".ssh"])}]; + _ -> + [] + end. diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl new file mode 100644 index 0000000000..1b7a9b23ed --- /dev/null +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -0,0 +1,463 @@ +%% +%% %CopyrightBegin% +%% +%% 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% +%% + +%% +-module(ssh_to_openssh_SUITE). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-define(TIMEOUT, 50000). +-define(SSH_DEFAULT_PORT, 22). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initialization before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + crypto:start(), + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + crypto:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config) -> Config +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Initialization before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Description: Initialization before each test case +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + ssh:start(), + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config) -> _ +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after each test case +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ssh:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Function: all(Clause) -> TestCases +%% Clause - atom() - suite | doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% Description: Returns a list of all test cases in this test suite +%%-------------------------------------------------------------------- +all(doc) -> + ["Test ssh API"]; + +all(suite) -> + case os:find_executable("ssh") of + false -> + {skip, "openSSH not installed on host"}; + _ -> + [erlang_shell_client_openssh_server, + erlang_client_openssh_server_exec, + erlang_client_openssh_server_exec_compressed, + erlang_server_openssh_client_exec, + erlang_server_openssh_client_exec_compressed, + erlang_client_openssh_server_setenv, + erlang_client_openssh_server_publickey_rsa, + erlang_client_openssh_server_publickey_dsa, + erlang_server_openssh_client_pulic_key_dsa, + erlang_client_openssh_server_password] + end. + +%% TEST cases starts here. +%%-------------------------------------------------------------------- +erlang_shell_client_openssh_server(doc) -> + ["Test that ssh:shell/2 works"]; + +erlang_shell_client_openssh_server(suite) -> + []; + +erlang_shell_client_openssh_server(Config) when is_list(Config) -> + process_flag(trap_exit, true), + IO = ssh_test_lib:start_io_server(), + Shell = ssh_test_lib:start_shell(?SSH_DEFAULT_PORT, IO), + IO ! {input, self(), "echo Hej\n"}, + receive_hej(), + IO ! {input, self(), "exit\n"}, + receive + <<"logout">> -> + receive + <<"Connection closed">> -> + ok + end; + Other0 -> + test_server:fail({unexpected_msg, Other0}) + end, + receive + {'EXIT', Shell, normal} -> + ok; + Other1 -> + test_server:fail({unexpected_msg, Other1}) + end. + +%-------------------------------------------------------------------- +erlang_client_openssh_server_exec(doc) -> + ["Test api function ssh_connection:exec"]; + +erlang_client_openssh_server_exec(suite) -> + []; + +erlang_client_openssh_server_exec(Config) when is_list(Config) -> + Host = ssh_test_lib:hostname(), + {ok, ConnectionRef} = + ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}]), + {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId0, + "echo testing", infinity), + Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"testing\n">>}}, + case ssh_test_lib:receive_exec_result(Data0) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0); + {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} + = ExitStatus0} -> + test_server:format("0: Collected data ~p", [ExitStatus0]), + ssh_test_lib:receive_exec_result(Data0, + ConnectionRef, ChannelId0); + Other0 -> + test_server:fail(Other0) + end, + + {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId1, + "echo testing1", infinity), + Data1 = {ssh_cm, ConnectionRef, {data, ChannelId1, 0, <<"testing1\n">>}}, + case ssh_test_lib:receive_exec_result(Data1) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1); + {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId1, 0}} + = ExitStatus1} -> + test_server:format("0: Collected data ~p", [ExitStatus1]), + ssh_test_lib:receive_exec_result(Data1, + ConnectionRef, ChannelId1); + Other1 -> + test_server:fail(Other1) + end. + +%%-------------------------------------------------------------------- +erlang_client_openssh_server_exec_compressed(doc) -> + ["Test that compression option works"]; + +erlang_client_openssh_server_exec_compressed(suite) -> + []; + +erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) -> + Host = ssh_test_lib:hostname(), + {ok, ConnectionRef} = + ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}, + {compression, zlib}]), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "echo testing", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); + {unexpected_msg,{ssh_cm, ConnectionRef, + {exit_status, ChannelId, 0}} = ExitStatus} -> + test_server:format("0: Collected data ~p", [ExitStatus]), + ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId); + Other -> + test_server:fail(Other) + end. + +%%-------------------------------------------------------------------- +erlang_server_openssh_client_exec(doc) -> + ["Test that exec command works."]; + +erlang_server_openssh_client_exec(suite) -> + []; + +erlang_server_openssh_client_exec(Config) when is_list(Config) -> + SytemDir = ?config(data_dir, Config), + Host = ssh_test_lib:hostname(), + Port = ssh_test_lib:inet_port(), + + {ok, Pid} = ssh:daemon(Port, [{system_dir, SytemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + + + test_server:sleep(500), + + Cmd = "ssh -p " ++ integer_to_list(Port) ++ + " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.", + SshPort = open_port({spawn, Cmd}, [binary]), + + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + test_server:fail("Did not receive answer") + + end, + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +erlang_server_openssh_client_exec_compressed(doc) -> + ["Test that exec command works."]; + +erlang_server_openssh_client_exec_compressed(suite) -> + []; + +erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) -> + SytemDir = ?config(data_dir, Config), + Host = ssh_test_lib:hostname(), + Port = ssh_test_lib:inet_port(), + {ok, Pid} = ssh:daemon(Port, [{system_dir, SytemDir}, + {compression, zlib}, + {failfun, fun ssh_test_lib:failfun/2}]), + + test_server:sleep(500), + + Cmd = "ssh -p " ++ integer_to_list(Port) ++ + " -o StrictHostKeyChecking=no -C "++ Host ++ " 1+1.", + SshPort = open_port({spawn, Cmd}, [binary]), + + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + test_server:fail("Did not receive answer") + + end, + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +erlang_client_openssh_server_setenv(doc) -> + ["Test api function ssh_connection:setenv"]; + +erlang_client_openssh_server_setenv(suite) -> + []; + +erlang_client_openssh_server_setenv(Config) when is_list(Config) -> + Host = ssh_test_lib:hostname(), + {ok, ConnectionRef} = + ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}]), + {ok, ChannelId} = + ssh_connection:session_channel(ConnectionRef, infinity), + Env = case ssh_connection:setenv(ConnectionRef, ChannelId, + "ENV_TEST", "testing_setenv", + infinity) of + success -> + <<"tesing_setenv\n">>; + failure -> + <<"\n">> + end, + success = ssh_connection:exec(ConnectionRef, ChannelId, + "echo $ENV_TEST", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, Env}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); + {unexpected_msg,{ssh_cm, ConnectionRef, + {data,0,1, UnxpectedData}}} -> + %% Some os may return things as + %% ENV_TEST: Undefined variable.\n" + test_server:format("UnxpectedData: ~p", [UnxpectedData]), + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); + {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}} + = ExitStatus} -> + test_server:format("0: Collected data ~p", [ExitStatus]), + ssh_test_lib:receive_exec_result(Data, + ConnectionRef, ChannelId); + Other -> + test_server:fail(Other) + end. + +%%-------------------------------------------------------------------- + +%% setenv not meaningfull on erlang ssh daemon! + +%%-------------------------------------------------------------------- +erlang_client_openssh_server_publickey_rsa(doc) -> + ["Validate using rsa publickey."]; +erlang_client_openssh_server_publickey_rsa(suite) -> + []; +erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) -> + {ok,[[Home]]} = init:get_argument(home), + SrcDir = filename:join(Home, ".ssh"), + UserDir = ?config(priv_dir, Config), + Host = ssh_test_lib:hostname(), + + case ssh_test_lib:copyfile(SrcDir, UserDir, "id_rsa") of + {ok, _} -> + {ok, ConnectionRef} = + ssh:connect(Host, ?SSH_DEFAULT_PORT, + [{user_dir, UserDir}, + {public_key_alg, ssh_rsa}, + {user_interaction, false}, + silently_accept_hosts]), + {ok, Channel} = + ssh_connection:session_channel(ConnectionRef, infinity), + ok = ssh_connection:close(ConnectionRef, Channel), + ok = ssh:close(ConnectionRef), + ok = file:delete(filename:join(UserDir, "id_rsa")); + {error, enoent} -> + {skip, "no ~/.ssh/id_rsa"} + end. + +%%-------------------------------------------------------------------- +erlang_client_openssh_server_publickey_dsa(doc) -> + ["Validate using dsa publickey."]; +erlang_client_openssh_server_publickey_dsa(suite) -> + []; +erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) -> + {ok,[[Home]]} = init:get_argument(home), + SrcDir = filename:join(Home, ".ssh"), + UserDir = ?config(priv_dir, Config), + Host = ssh_test_lib:hostname(), + case ssh_test_lib:copyfile(SrcDir, UserDir, "id_dsa") of + {ok, _} -> + {ok, ConnectionRef} = + ssh:connect(Host, ?SSH_DEFAULT_PORT, + [{user_dir, UserDir}, + {public_key_alg, ssh_dsa}, + {user_interaction, false}, + silently_accept_hosts]), + {ok, Channel} = + ssh_connection:session_channel(ConnectionRef, infinity), + ok = ssh_connection:close(ConnectionRef, Channel), + ok = ssh:close(ConnectionRef), + ok = file:delete(filename:join(UserDir, "id_dsa")); + {error, enoent} -> + {skip, "no ~/.ssh/id_dsa"} + end. + +%%-------------------------------------------------------------------- +erlang_server_openssh_client_pulic_key_dsa(doc) -> + ["Validate using dsa publickey."]; + +erlang_server_openssh_client_pulic_key_dsa(suite) -> + []; + +erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) -> + SytemDir = ?config(data_dir, Config), + Host = ssh_test_lib:hostname(), + Port = ssh_test_lib:inet_port(), + {ok, Pid} = ssh:daemon(Port, [{system_dir, SytemDir}, + {public_key_alg, ssh_dsa}, + {failfun, fun ssh_test_lib:failfun/2}]), + + test_server:sleep(500), + + Cmd = "ssh -p " ++ integer_to_list(Port) ++ + " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.", + SshPort = open_port({spawn, Cmd}, [binary]), + + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + test_server:fail("Did not receive answer") + + end, + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +erlang_client_openssh_server_password(doc) -> + ["Test client password option"]; + +erlang_client_openssh_server_password(suite) -> + []; + +erlang_client_openssh_server_password(Config) when is_list(Config) -> + %% to make sure we don't public-key-auth + UserDir = ?config(data_dir, Config), + Host = ssh_test_lib:hostname(), + + {error, Reason0} = + ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + + test_server:format("Test of user foo that does not exist. " + "Error msg: ~p~n", [Reason0]), + + User = string:strip(os:cmd("whoami"), right, $\n), + + case length(string:tokens(User, " ")) of + 1 -> + {error, Reason1} = + ssh:connect(Host, ?SSH_DEFAULT_PORT, + [{silently_accept_hosts, true}, + {user, User}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + test_server:format("Test of wrong Pasword. " + "Error msg: ~p~n", [Reason1]); + _ -> + test_server:format("Whoami failed reason: ~n", []) + end. + +%%-------------------------------------------------------------------- +% +%% Not possible to send password with openssh without user interaction +%% +%%-------------------------------------------------------------------- +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- +receive_hej() -> + receive + <<"Hej\n">> = Hej-> + test_server:format("Expected result: ~p~n", [Hej]); + Info -> + test_server:format("Extra info: ~p~n", [Info]), + receive_hej() + end. diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..58f0a65cba --- /dev/null +++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 +jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ +ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe +uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 +nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq +mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 +2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS +QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C +ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 ++basD1iibtNHs9Edfdkm +-----END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..d83487fc50 --- /dev/null +++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin -- cgit v1.2.3 From ca09b09dff13a70ff07c835c2ae951f3d7a2ac07 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 15 Dec 2010 15:45:55 +0100 Subject: Convert ssh test cases to common test stardard --- lib/ssh/test/ssh.spec | 13 +++++++------ lib/ssh/test/ssh_SUITE.erl | 24 ++++++++++++++++-------- lib/ssh/test/ssh_basic_SUITE.erl | 20 ++++++++++++++------ lib/ssh/test/ssh_sftp_SUITE.erl | 26 ++++++++++++++++---------- lib/ssh/test/ssh_sftpd_SUITE.erl | 22 +++++++++++++++------- lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 17 ++++++++++++----- lib/ssh/test/ssh_to_openssh_SUITE.erl | 20 +++++++++++++------- 7 files changed, 93 insertions(+), 49 deletions(-) diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec index d99250654e..8de0fe44e4 100644 --- a/lib/ssh/test/ssh.spec +++ b/lib/ssh/test/ssh.spec @@ -1,6 +1,7 @@ -{topcase, {dir, "../ssh_test"}}. -{require_nodenames, 1}. -{skip, {ssh_ssh_SUITE, ssh, "Current implementation is timingdependent and -hence will succeed/fail on a whim"}}. -{skip, {ssh_ssh_SUITE, ssh_compressed, -"Current implementation is timingdependent hence will succeed/fail on a whim"}}. +{suites,"../ssh_test",all}. +{skip_cases,"../ssh_test",ssh_ssh_SUITE, + [ssh], + "Current implementation is timingdependent and\nhence will succeed/fail on a whim"}. +{skip_cases,"../ssh_test",ssh_ssh_SUITE, + [ssh_compressed], + "Current implementation is timingdependent hence will succeed/fail on a whim"}. diff --git a/lib/ssh/test/ssh_SUITE.erl b/lib/ssh/test/ssh_SUITE.erl index dd4571febe..aa321527b8 100644 --- a/lib/ssh/test/ssh_SUITE.erl +++ b/lib/ssh/test/ssh_SUITE.erl @@ -22,7 +22,7 @@ %%% Purpose:ssh application test suite. %%%----------------------------------------------------------------- -module(ssh_SUITE). --include("test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include("test_server_line.hrl"). % Default timetrap timeout (set in init_per_testcase). @@ -30,8 +30,8 @@ -define(application, ssh). % Test server specific exports --export([all/1]). --export([init_per_testcase/2, fin_per_testcase/2]). +-export([all/0,groups/0,init_per_group/2,end_per_group/2]). +-export([init_per_testcase/2, end_per_testcase/2]). % Test cases must be exported. -export([app_test/1]). @@ -40,15 +40,23 @@ %% %% all/1 %% -all(doc) -> - []; -all(suite) -> - [?cases]. +all() -> + [app_test]. + +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + init_per_testcase(_Case, Config) -> Dog=test_server:timetrap(?default_timeout), [{watchdog, Dog}|Config]. -fin_per_testcase(_Case, Config) -> +end_per_testcase(_Case, Config) -> Dog=?config(watchdog, Config), test_server:timetrap_cancel(Dog), ok. diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index d5eb5367e6..6062e2d789 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -21,7 +21,7 @@ -module(ssh_basic_SUITE). --include("test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include("test_server_line.hrl"). %% Note: This directive should only be used in test suites. @@ -97,12 +97,20 @@ end_per_testcase(_TestCase, _Config) -> %% Name of a test case. %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- -all(doc) -> - ["Test ssh API"]; - -all(suite) -> +all() -> [exec, exec_compressed, shell, daemon_allready_started, - server_password_option, server_userpassword_option, known_hosts]. + server_password_option, server_userpassword_option, + known_hosts]. + +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + %% Test cases starts here. %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index eb7fbd6998..4cc157ebd4 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -23,7 +23,7 @@ %% Note: This directive should only be used in test suites. -compile(export_all). --include("test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include("test_server_line.hrl"). -include_lib("kernel/include/file.hrl"). @@ -137,15 +137,21 @@ end_per_testcase(_Case, Config) -> %% Name of a test case. %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- -all(doc) -> - ["Test the sftp client"]; - -all(suite) -> - [ - open_close_file, open_close_dir, read_file, read_dir, write_file, - rename_file, mk_rm_dir, remove_file, links, retrieve_attributes, - set_attributes, async_read, async_write, position, pos_read, pos_write - ]. +all() -> + [open_close_file, open_close_dir, read_file, read_dir, + write_file, rename_file, mk_rm_dir, remove_file, links, + retrieve_attributes, set_attributes, async_read, + async_write, position, pos_read, pos_write]. + +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + %% Test cases starts here. %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 4ce6bd45b3..263eeefe66 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -23,7 +23,7 @@ %% Note: This directive should only be used in test suites. -compile(export_all). --include("test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include("test_server_line.hrl"). -include("ssh_xfer.hrl"). -include("ssh.hrl"). @@ -143,13 +143,21 @@ end_per_testcase(_TestCase, Config) -> %% Name of a test case. %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- -all(doc) -> - ["Test the sftp server"]; +all() -> + [open_close_file, open_close_dir, read_file, read_dir, + write_file, rename_file, mk_rm_dir, remove_file, + real_path, retrieve_attributes, set_attributes, links, + ver3_rename_OTP_6352, seq10670, sshd_read_file]. + +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. -all(suite) -> - [open_close_file, open_close_dir, read_file, read_dir, write_file, - rename_file, mk_rm_dir, remove_file, real_path, retrieve_attributes, - set_attributes, links, ver3_rename_OTP_6352, seq10670, sshd_read_file]. %% Test cases starts here. %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index 6ae5e73dcb..7e9b6024e5 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -23,7 +23,7 @@ %% Note: This directive should only be used in test suites. -compile(export_all). --include("test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include("test_server_line.hrl"). -include_lib("kernel/include/file.hrl"). @@ -147,13 +147,20 @@ end_per_testcase(_TestCase, Config) -> %% Name of a test case. %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- -all(doc) -> - ["Test ssh_sftpd"]; - -all(suite) -> +all() -> [close_file_OTP_6350, quit_OTP_6349, file_cb_OTP_6356, root_dir, list_dir_limited]. +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + + %% Test cases starts here. %%-------------------------------------------------------------------- close_file_OTP_6350(doc) -> diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 1b7a9b23ed..12a350903a 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -20,7 +20,7 @@ %% -module(ssh_to_openssh_SUITE). --include("test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include("test_server_line.hrl"). %% Note: This directive should only be used in test suites. @@ -90,13 +90,9 @@ end_per_testcase(_TestCase, _Config) -> %% Name of a test case. %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- -all(doc) -> - ["Test ssh API"]; - -all(suite) -> +all() -> case os:find_executable("ssh") of - false -> - {skip, "openSSH not installed on host"}; + false -> {skip, "openSSH not installed on host"}; _ -> [erlang_shell_client_openssh_server, erlang_client_openssh_server_exec, @@ -110,6 +106,16 @@ all(suite) -> erlang_client_openssh_server_password] end. +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + + %% TEST cases starts here. %%-------------------------------------------------------------------- erlang_shell_client_openssh_server(doc) -> -- cgit v1.2.3 From 694eba4f53b5a1f07b5d37cbe4112fdd1e403a27 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 12 Jan 2011 14:58:07 +0100 Subject: Add cover spec file --- lib/ssh/test/Makefile | 2 +- lib/ssh/test/ssh.cover | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 lib/ssh/test/ssh.cover diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 116f894493..78dcb9384b 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -115,7 +115,7 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) - $(INSTALL_DATA) ssh.spec $(RELSYSDIR) + $(INSTALL_DATA) ssh.spec ssh.cover $(RELSYSDIR) $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR) @for dir in $(DATA_DIRS); do \ if test ! -d $$dir ; then \ diff --git a/lib/ssh/test/ssh.cover b/lib/ssh/test/ssh.cover new file mode 100644 index 0000000000..a4221fbbbe --- /dev/null +++ b/lib/ssh/test/ssh.cover @@ -0,0 +1,2 @@ +{incl_app,ssh,details}. + -- cgit v1.2.3 From 2c0bd506cb99362635ebc0aafae36a95dc0a08b3 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 24 Jan 2011 13:33:13 +0100 Subject: Update init_per_suite so that tests are skipped if crypto/ssh cannot be started. --- lib/ssh/test/ssh_basic_SUITE.erl | 14 +++++++++----- lib/ssh/test/ssh_sftp_SUITE.erl | 22 +++++++++++++++------- lib/ssh/test/ssh_sftpd_SUITE.erl | 13 ++++++++++--- lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 25 ++++++++++++++----------- lib/ssh/test/ssh_to_openssh_SUITE.erl | 8 ++++++-- 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 6062e2d789..cb0d5483ab 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -39,11 +39,15 @@ %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - crypto:start(), - Dir = ?config(priv_dir, Config), - ssh_test_lib:save_known_hosts(Dir), - {ok, _} = ssh_test_lib:get_id_keys(Dir), - Config. + case catch crypto:start() of + ok -> + Dir = ?config(priv_dir, Config), + ssh_test_lib:save_known_hosts(Dir), + {ok, _} = ssh_test_lib:get_id_keys(Dir), + Config; + _Else -> + {skip, "Crypto could not be started!"} + end. %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 4cc157ebd4..ec2010e15a 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -46,13 +46,21 @@ %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - crypto:start(), - ssh:start(), - Dir = ?config(priv_dir, Config), - ssh_test_lib:save_known_hosts(Dir), - %% More like copy_id_keys!!! - {ok, _} = ssh_test_lib:get_id_keys(Dir), - Config. + case {catch crypto:start(),catch ssh:start()} of + {ok,ok} -> + Dir = ?config(priv_dir, Config), + ssh_test_lib:save_known_hosts(Dir), + %% More like copy_id_keys!!! + {ok, _} = ssh_test_lib:get_id_keys(Dir), + Config; + {ok,_} -> + {skip,"Could not start ssh!"}; + {_,ok} -> + {skip,"Could not start crypto!"}; + {_,_} -> + {skip,"Could not start crypto and ssh!"} + end. + %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ %% Config - [tuple()] diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 263eeefe66..59445135b4 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -53,9 +53,16 @@ %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - ssh:stop(), - crypto:start(), - Config. + case {catch ssh:stop(),catch crypto:start()} of + {ok,ok} -> + Config; + {ok,_} -> + {skip,"Could not start ssh!"}; + {_,ok} -> + {skip,"Could not start crypto!"}; + {_,_} -> + {skip,"Could not start crypto and ssh!"} + end. %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index 7e9b6024e5..6ad462deab 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -44,17 +44,20 @@ %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - ssh:stop(), - crypto:start(), - DataDir = ?config(data_dir, Config), - FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"), - c:c(FileAlt), - FileName = filename:join(DataDir, "test.txt"), - {ok, FileInfo} = file:read_file_info(FileName), - ok = file:write_file_info(FileName, - FileInfo#file_info{mode = 8#400}), - - Config. + catch ssh:stop(), + case catch crypto:start() of + ok -> + DataDir = ?config(data_dir, Config), + FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"), + c:c(FileAlt), + FileName = filename:join(DataDir, "test.txt"), + {ok, FileInfo} = file:read_file_info(FileName), + ok = file:write_file_info(FileName, + FileInfo#file_info{mode = 8#400}), + Config; + _Else -> + {skip,"Could not start ssh!"} + end. %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 12a350903a..69a57aad1b 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -40,8 +40,12 @@ %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - crypto:start(), - Config. + case catch crypto:start() of + ok -> + Config; + _Else -> + {skip,"Could not start crypto!"} + end. %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ -- cgit v1.2.3 From bafd9b83ef0e7b2ca40c43981eeb6fe8229804ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 26 Nov 2010 14:55:41 +0100 Subject: Add test suite for ssh --- lib/ssh/test/Makefile | 4 ++++ lib/ssh/test/ssh.spec | 9 +++++++++ lib/ssh/test/ssh_SUITE.erl | 2 +- lib/ssh/test/ssh_basic_SUITE.erl | 3 +-- lib/ssh/test/ssh_sftp_SUITE.erl | 4 ++-- lib/ssh/test/ssh_sftpd_SUITE.erl | 2 +- lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 3 +-- lib/ssh/test/ssh_to_openssh_SUITE.erl | 6 +++--- 8 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 78dcb9384b..fc88916e45 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -115,7 +115,11 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) +<<<<<<< HEAD $(INSTALL_DATA) ssh.spec ssh.cover $(RELSYSDIR) +======= + $(INSTALL_DATA) ssh.spec $(RELSYSDIR) +>>>>>>> Add test suite for ssh $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR) @for dir in $(DATA_DIRS); do \ if test ! -d $$dir ; then \ diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec index 8de0fe44e4..c420b119ac 100644 --- a/lib/ssh/test/ssh.spec +++ b/lib/ssh/test/ssh.spec @@ -1,3 +1,4 @@ +<<<<<<< HEAD {suites,"../ssh_test",all}. {skip_cases,"../ssh_test",ssh_ssh_SUITE, [ssh], @@ -5,3 +6,11 @@ {skip_cases,"../ssh_test",ssh_ssh_SUITE, [ssh_compressed], "Current implementation is timingdependent hence will succeed/fail on a whim"}. +======= +{topcase, {dir, "../ssh_test"}}. +{require_nodenames, 1}. +{skip, {ssh_ssh_SUITE, ssh, "Current implementation is timingdependent and +hence will succeed/fail on a whim"}}. +{skip, {ssh_ssh_SUITE, ssh_compressed, +"Current implementation is timingdependent hence will succeed/fail on a whim"}}. +>>>>>>> Add test suite for ssh diff --git a/lib/ssh/test/ssh_SUITE.erl b/lib/ssh/test/ssh_SUITE.erl index aa321527b8..953c9080f9 100644 --- a/lib/ssh/test/ssh_SUITE.erl +++ b/lib/ssh/test/ssh_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. 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/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index cb0d5483ab..2c0fd882a0 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2011. 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 @@ -115,7 +115,6 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - %% Test cases starts here. %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index ec2010e15a..0c4a7f3b3f 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2011. 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 @@ -60,7 +60,7 @@ init_per_suite(Config) -> {_,_} -> {skip,"Could not start crypto and ssh!"} end. - + %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ %% Config - [tuple()] diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 59445135b4..1afc206148 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% Copyright Ericsson AB 2006-2011. 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/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index 6ad462deab..c7107635c1 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% Copyright Ericsson AB 2007-2011. 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 @@ -163,7 +163,6 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - %% Test cases starts here. %%-------------------------------------------------------------------- close_file_OTP_6350(doc) -> diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 69a57aad1b..0c15c067a8 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2011. 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 @@ -96,7 +96,8 @@ end_per_testcase(_TestCase, _Config) -> %%-------------------------------------------------------------------- all() -> case os:find_executable("ssh") of - false -> {skip, "openSSH not installed on host"}; + false -> + {skip, "openSSH not installed on host"}; _ -> [erlang_shell_client_openssh_server, erlang_client_openssh_server_exec, @@ -119,7 +120,6 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - %% TEST cases starts here. %%-------------------------------------------------------------------- erlang_shell_client_openssh_server(doc) -> -- cgit v1.2.3 From 155763771ba8e581cec43732cf86fa781bbdd773 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Thu, 10 Feb 2011 10:14:22 +0100 Subject: Altering SSH test keys. --- lib/ssh/test/ssh_basic_SUITE.erl | 176 +++++----- lib/ssh/test/ssh_sftp_SUITE.erl | 14 +- lib/ssh/test/ssh_sftpd_SUITE.erl | 9 +- lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 3 +- lib/ssh/test/ssh_test_lib.erl | 497 ++++++++++++++++++++++++++++- lib/ssh/test/ssh_to_openssh_SUITE.erl | 108 +++---- 6 files changed, 629 insertions(+), 178 deletions(-) diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 2c0fd882a0..e801664ff2 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -76,7 +76,7 @@ end_per_suite(Config) -> %% Description: Initialization before each test case %%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config) -> - rename_known_hosts(backup), + ssh_test_lib:known_hosts(backup), ssh:start(), Config. @@ -90,7 +90,7 @@ init_per_testcase(_TestCase, Config) -> %%-------------------------------------------------------------------- end_per_testcase(_TestCase, _Config) -> ssh:stop(), - rename_known_hosts(restore), + ssh_test_lib:known_hosts(restore), ok. %%-------------------------------------------------------------------- @@ -117,6 +117,16 @@ end_per_group(_GroupName, Config) -> %% Test cases starts here. %%-------------------------------------------------------------------- +sign_and_verify_rsa(doc) -> + ["Test api function ssh:sign_data and ssh:verify_data"]; + +sign_and_verify_rsa(suite) -> + []; +sign_and_verify_rsa(Config) when is_list(Config) -> + Data = ssh:sign_data(<<"correct data">>, "ssh-rsa"), + ok = ssh:verify_data(<<"correct data">>, Data, "ssh-rsa"), + {error,invalid_signature} = ssh:verify_data(<<"incorrect data">>, Data,"ssh-rsa"). + exec(doc) -> ["Test api function ssh_connection:exec"]; @@ -127,13 +137,11 @@ exec(suite) -> exec(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = ?config(data_dir, Config), - Host = ssh_test_lib:hostname(), - Port = ssh_test_lib:inet_port(), - {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - {ok, ConnectionRef} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user_interaction, false}]), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_interaction, false}]), {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId0, "1+1.", infinity), @@ -171,15 +179,13 @@ exec_compressed(suite) -> exec_compressed(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = ?config(data_dir, Config), - Host = ssh_test_lib:hostname(), - Port = ssh_test_lib:inet_port(), - {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, - {compression, zlib}, - {failfun, fun ssh_test_lib:failfun/2}]), - - {ok, ConnectionRef} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user_interaction, false}]), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {compression, zlib}, + {failfun, fun ssh_test_lib:failfun/2}]), + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_interaction, false}]), {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId, "1+1.", infinity), @@ -204,9 +210,8 @@ shell(suite) -> shell(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = ?config(data_dir, Config), - Port = ssh_test_lib:inet_port(), - {ok, _Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), + {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), test_server:sleep(500), IO = ssh_test_lib:start_io_server(), @@ -265,21 +270,20 @@ shell(Config) when is_list(Config) -> end. %%-------------------------------------------------------------------- -daemon_allready_started(doc) -> +daemon_already_started(doc) -> ["Test that get correct error message if you try to start a daemon", - "on an adress that allready runs a daemon see also seq10667" ]; + "on an adress that already runs a daemon see also seq10667" ]; -daemon_allready_started(suite) -> +daemon_already_started(suite) -> []; -daemon_allready_started(Config) when is_list(Config) -> +daemon_already_started(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), - Port = ssh_test_lib:inet_port(), - {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - {error, eaddrinuse} = ssh:daemon(Port, [{system_dir, SystemDir}, - {failfun, - fun ssh_test_lib:failfun/2}]), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + {error, eaddrinuse} = ssh_test_lib:daemon(Host, Port, [{system_dir, SystemDir}, + {failfun, + fun ssh_test_lib:failfun/2}]), ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- @@ -290,26 +294,23 @@ server_password_option(suite) -> server_password_option(Config) when is_list(Config) -> UserDir = ?config(data_dir, Config), % to make sure we don't use SysDir = ?config(data_dir, Config), % public-key-auth - Port = ssh_test_lib:inet_port(), - {ok, Pid} = - ssh:daemon(Port, [{system_dir, SysDir}, - {password, "morot"}]), - Host = ssh_test_lib:hostname(), - - {ok, ConnectionRef} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {password, "morot"}]), + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), {error, Reason} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "vego"}, - {password, "foo"}, - {user_interaction, false}, - {user_dir, UserDir}]), - - test_server:format("Test of wrong pasword: Error msg: ~p ~n", [Reason]), + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + + test_server:format("Test of wrong password: Error msg: ~p ~n", [Reason]), ssh:close(ConnectionRef), ssh:stop_daemon(Pid). @@ -323,39 +324,36 @@ server_userpassword_option(suite) -> server_userpassword_option(Config) when is_list(Config) -> UserDir = ?config(data_dir, Config), % to make sure we don't use SysDir = ?config(data_dir, Config), % public-key-auth - Port = ssh_test_lib:inet_port(), - {ok, Pid} = - ssh:daemon(Port, [{system_dir, SysDir}, - {user_passwords, [{"vego", "morot"}]}]), - Host = ssh_test_lib:hostname(), - - {ok, ConnectionRef} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "vego"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_passwords, [{"vego", "morot"}]}]), + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), ssh:close(ConnectionRef), {error, Reason0} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), - + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + test_server:format("Test of user foo that does not exist. " "Error msg: ~p ~n", [Reason0]), {error, Reason1} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "vego"}, - {password, "foo"}, - {user_interaction, false}, - {user_dir, UserDir}]), - test_server:format("Test of wrong Pasword. " + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + test_server:format("Test of wrong Password. " "Error msg: ~p ~n", [Reason1]), - + ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- @@ -366,41 +364,27 @@ known_hosts(suite) -> known_hosts(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), UserDir = ?config(priv_dir, Config), - Port = ssh_test_lib:inet_port(), - {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), KnownHosts = filename:join(UserDir, "known_hosts"), file:delete(KnownHosts), {error, enoent} = file:read_file(KnownHosts), - Host = ssh_test_lib:hostname(), - {ok, ConnectionRef} = - ssh:connect(Host, Port, [{user_dir, UserDir}, - {user_interaction, false}, - silently_accept_hosts]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{user_dir, UserDir}, + {user_interaction, false}, + silently_accept_hosts]), {ok, _Channel} = ssh_connection:session_channel(ConnectionRef, infinity), ok = ssh:close(ConnectionRef), {ok, Binary} = file:read_file(KnownHosts), Lines = string:tokens(binary_to_list(Binary), "\n"), [Line] = Lines, - {ok, Hostname} = inet:gethostname(), [HostAndIp, Alg, _KeyData] = string:tokens(Line, " "), - [Hostname, _Ip] = string:tokens(HostAndIp, ","), + [Host, _Ip] = string:tokens(HostAndIp, ","), "ssh-" ++ _ = Alg, ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- - -rename_known_hosts(BR) -> - KnownHosts = ssh_file:file_name(user, "known_hosts", []), - B = KnownHosts ++ "xxx", - case BR of - backup -> - file:rename(KnownHosts, B); - restore -> - file:delete(KnownHosts), - file:rename(B, KnownHosts) - end. diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 0c4a7f3b3f..123a12773b 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -103,13 +103,13 @@ init_per_testcase(_Case, Config) -> {ok, ChannelPid, Connection} -> {ChannelPid, Connection}; _Error -> - {ok, _Sftpd} = - ssh:daemon(?SFPD_PORT, - [{system_dir, SysDir}, - {user_passwords, - [{?USER, ?PASSWD}]}, - {failfun, - fun ssh_test_lib:failfun/2}]), + {_Sftpd, _Host, _Port} = + ssh_test_lib:daemon(Host, ?SFPD_PORT, + [{system_dir, SysDir}, + {user_passwords, + [{?USER, ?PASSWD}]}, + {failfun, + fun ssh_test_lib:failfun/2}]), Result = (catch ssh_sftp:start_channel(Host, ?SFPD_PORT, [{user, ?USER}, {password, ?PASSWD}, diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 1afc206148..f5ed668fa6 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -93,16 +93,15 @@ init_per_testcase(TestCase, Config) -> SysDir = ?config(data_dir, Config), {ok, Sftpd} = ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SysDir}, - {user_passwords,[{?USER, ?PASSWD}]}]), - - Host = ssh_test_lib:hostname(), - {ok, Cm} = ssh:connect(Host, ?SFPD_PORT, + {user_passwords,[{?USER, ?PASSWD}]}]), + + Cm = ssh_test_lib:connect(?SFPD_PORT, [{silently_accept_hosts, true}, {user, ?USER}, {password, ?PASSWD}]), {ok, Channel} = ssh_connection:session_channel(Cm, ?XFER_WINDOW_SIZE, ?XFER_PACKET_SIZE, ?TIMEOUT), - + success = ssh_connection:subsystem(Cm, Channel, "sftp", ?TIMEOUT), ProtocolVer = case atom_to_list(TestCase) of diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index c7107635c1..db23a98225 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -115,9 +115,8 @@ init_per_testcase(TestCase, Config) -> {system_dir, DataDir}] end, - {ok, Sftpd} = ssh:daemon(any, ?SSHD_PORT, Options), + {Sftpd, Host, _Port} = ssh_test_lib:daemon(any, ?SSHD_PORT, Options), - Host = ssh_test_lib:hostname(), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, ?SSHD_PORT, [{silently_accept_hosts, true}, diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 2eb19cec22..c237e1ba5d 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. 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 @@ -24,12 +24,54 @@ %% Note: This directive should only be used in test suites. -compile(export_all). +-include_lib("public_key/include/public_key.hrl"). +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +-define(TIMEOUT, 50000). +-define(SSH_DEFAULT_PORT, 22). + +connect(Options) -> + connect(hostname(), inet_port(), Options). + +connect(Port, Options) when is_integer(Port) -> + connect(hostname(), Port, Options); +connect(Host, Options) -> + connect(Host, inet_port(), Options). + +connect(Host, Port, Options) -> + case ssh:connect(Host, Port, Options) of + {ok, ConnectionRef} -> + ConnectionRef; + Error -> + Error + end. + +daemon(Options) -> + daemon(any, inet_port(), Options). + +daemon(Port, Options) when is_integer(Port) -> + daemon(any, Port, Options); +daemon(Host, Options) -> + daemon(Host, inet_port(), Options). + +daemon(Host, Port, Options) -> + case ssh:daemon(Host, Port, Options) of + {ok, Pid} -> + {Pid, Host, Port}; + Error -> + Error + end. + + + + start_shell(Port, IOServer) -> spawn_link(?MODULE, init_shell, [Port, IOServer]). init_shell(Port, IOServer) -> - Host = ssh_test_lib:hostname(), - UserDir = ssh_test_lib:get_user_dir(), + Host = hostname(), + UserDir = get_user_dir(), Options = [{user_interaction, false}, {silently_accept_hosts, true}] ++ UserDir, group_leader(IOServer, self()), @@ -123,9 +165,9 @@ receive_exec_end(ConnectionRef, ChannelId) -> receive_exec_result(Data, ConnectionRef, ChannelId) -> Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}}, Closed = {ssh_cm, ConnectionRef,{closed, ChannelId}}, - expected = ssh_test_lib:receive_exec_result(Data), - expected = ssh_test_lib:receive_exec_result(Eof), - expected = ssh_test_lib:receive_exec_result(Closed). + expected = receive_exec_result(Data), + expected = receive_exec_result(Eof), + expected = receive_exec_result(Closed). inet_port()-> @@ -164,6 +206,18 @@ hostname() -> {ok,Host} = inet:gethostname(), Host. +known_hosts(BR) -> + KnownHosts = ssh_file:file_name(user, "known_hosts", []), + B = KnownHosts ++ "xxx", + case BR of + backup -> + file:rename(KnownHosts, B); + restore -> + file:delete(KnownHosts), + file:rename(B, KnownHosts) + end. + + save_known_hosts(PrivDir) -> Src = ssh_file:file_name(user, "known_hosts", []), Dst = filename:join(PrivDir, "kh_save"), @@ -187,3 +241,434 @@ get_user_dir() -> _ -> [] end. + + +%% Create certificates. +make_dsa_cert(Config) -> + + {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_dsa_cert_files("server", Config), + {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_dsa_cert_files("client", Config), + [{server_dsa_opts, [{ssl_imp, new},{reuseaddr, true}, + {cacertfile, ServerCaCertFile}, + {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]}, + {server_dsa_verify_opts, [{ssl_imp, new},{reuseaddr, true}, + {cacertfile, ClientCaCertFile}, + {certfile, ServerCertFile}, {keyfile, ServerKeyFile}, + {verify, verify_peer}]}, + {client_dsa_opts, [{ssl_imp, new},{reuseaddr, true}, + {cacertfile, ClientCaCertFile}, + {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]} + | Config]. + + + +make_dsa_cert_files(RoleStr, Config) -> + CaInfo = {CaCert, _} = make_cert([{key, dsa}]), + {Cert, CertKey} = make_cert([{key, dsa}, {issuer, CaInfo}]), + CaCertFile = filename:join(["/home/nick/trash/ssh/", + RoleStr, "dsa_cacerts.pem"]), + CertFile = filename:join(["/home/nick/trash/ssh/", + RoleStr, "dsa_cert.pem"]), + KeyFile = filename:join(["/home/nick/trash/ssh/", + RoleStr, "dsa_key.pem"]), +%% CaCertFile = filename:join([?config(priv_dir, Config), +%% RoleStr, "dsa_cacerts.pem"]), +%% CertFile = filename:join([?config(priv_dir, Config), +%% RoleStr, "dsa_cert.pem"]), +%% KeyFile = filename:join([?config(priv_dir, Config), +%% RoleStr, "dsa_key.pem"]), + + der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]), + der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]), + der_to_pem(KeyFile, [CertKey]), + {CaCertFile, CertFile, KeyFile}. + + +%%-------------------------------------------------------------------- +%% Create and return a der encoded certificate +%% Option Default +%% ------------------------------------------------------- +%% digest sha1 +%% validity {date(), date() + week()} +%% version 3 +%% subject [] list of the following content +%% {name, Name} +%% {email, Email} +%% {city, City} +%% {state, State} +%% {org, Org} +%% {org_unit, OrgUnit} +%% {country, Country} +%% {serial, Serial} +%% {title, Title} +%% {dnQualifer, DnQ} +%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created) +%% (obs IssuerKey migth be {Key, Password} +%% key = KeyFile|KeyBin|rsa|dsa Subject PublicKey rsa or dsa generates key +%% +%% +%% (OBS: The generated keys are for testing only) +%% make_cert([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()} +%%-------------------------------------------------------------------- +make_cert(Opts) -> + SubjectPrivateKey = get_key(Opts), + {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts), + Cert = public_key:pkix_sign(TBSCert, IssuerKey), + true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok + {Cert, encode_key(SubjectPrivateKey)}. + +%%-------------------------------------------------------------------- +%% Writes pem files in Dir with FileName ++ ".pem" and FileName ++ "_key.pem" +%% write_pem(::string(), ::string(), {Cert,Key}) -> ok +%%-------------------------------------------------------------------- +write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) -> + ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"), + [{'Certificate', Cert, not_encrypted}]), + ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]). + +%%-------------------------------------------------------------------- +%% Creates a rsa key (OBS: for testing only) +%% the size are in bytes +%% gen_rsa(::integer()) -> {::atom(), ::binary(), ::opaque()} +%%-------------------------------------------------------------------- +gen_rsa(Size) when is_integer(Size) -> + Key = gen_rsa2(Size), + {Key, encode_key(Key)}. + +%%-------------------------------------------------------------------- +%% Creates a dsa key (OBS: for testing only) +%% the sizes are in bytes +%% gen_dsa(::integer()) -> {::atom(), ::binary(), ::opaque()} +%%-------------------------------------------------------------------- +gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) -> + Key = gen_dsa2(LSize, NSize), + {Key, encode_key(Key)}. + +%%-------------------------------------------------------------------- +%% Verifies cert signatures +%% verify_signature(::binary(), ::tuple()) -> ::boolean() +%%-------------------------------------------------------------------- +verify_signature(DerEncodedCert, DerKey, _KeyParams) -> + Key = decode_key(DerKey), + case Key of + #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} -> + public_key:pkix_verify(DerEncodedCert, + #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}); + #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} -> + public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}}) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +get_key(Opts) -> + case proplists:get_value(key, Opts) of + undefined -> make_key(rsa, Opts); + rsa -> make_key(rsa, Opts); + dsa -> make_key(dsa, Opts); + Key -> + Password = proplists:get_value(password, Opts, no_passwd), + decode_key(Key, Password) + end. + +decode_key({Key, Pw}) -> + decode_key(Key, Pw); +decode_key(Key) -> + decode_key(Key, no_passwd). + + +decode_key(#'RSAPublicKey'{} = Key,_) -> + Key; +decode_key(#'RSAPrivateKey'{} = Key,_) -> + Key; +decode_key(#'DSAPrivateKey'{} = Key,_) -> + Key; +decode_key(PemEntry = {_,_,_}, Pw) -> + public_key:pem_entry_decode(PemEntry, Pw); +decode_key(PemBin, Pw) -> + [KeyInfo] = public_key:pem_decode(PemBin), + decode_key(KeyInfo, Pw). + +encode_key(Key = #'RSAPrivateKey'{}) -> + {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key), + {'RSAPrivateKey', list_to_binary(Der), not_encrypted}; +encode_key(Key = #'DSAPrivateKey'{}) -> + {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key), + {'DSAPrivateKey', list_to_binary(Der), not_encrypted}. + +make_tbs(SubjectKey, Opts) -> + Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))), + + IssuerProp = proplists:get_value(issuer, Opts, true), + {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey), + + {Algo, Parameters} = sign_algorithm(IssuerKey, Opts), + + SignAlgo = #'SignatureAlgorithm'{algorithm = Algo, + parameters = Parameters}, + Subject = case IssuerProp of + true -> %% Is a Root Ca + Issuer; + _ -> + subject(proplists:get_value(subject, Opts),false) + end, + + {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1, + signature = SignAlgo, + issuer = Issuer, + validity = validity(Opts), + subject = Subject, + subjectPublicKeyInfo = publickey(SubjectKey), + version = Version, + extensions = extensions(Opts) + }, IssuerKey}. + +issuer(true, Opts, SubjectKey) -> + %% Self signed + {subject(proplists:get_value(subject, Opts), true), SubjectKey}; +issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) -> + {issuer_der(Issuer), decode_key(IssuerKey)}; +issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) -> + {ok, [{cert, Cert, _}|_]} = pem_to_der(File), + {issuer_der(Cert), decode_key(IssuerKey)}. + +issuer_der(Issuer) -> + Decoded = public_key:pkix_decode_cert(Issuer, otp), + #'OTPCertificate'{tbsCertificate=Tbs} = Decoded, + #'OTPTBSCertificate'{subject=Subject} = Tbs, + Subject. + +subject(undefined, IsRootCA) -> + User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end, + Opts = [{email, User ++ "@erlang.org"}, + {name, User}, + {city, "Stockholm"}, + {country, "SE"}, + {org, "erlang"}, + {org_unit, "testing dep"}], + subject(Opts); +subject(Opts, _) -> + subject(Opts). + +subject(SubjectOpts) when is_list(SubjectOpts) -> + Encode = fun(Opt) -> + {Type,Value} = subject_enc(Opt), + [#'AttributeTypeAndValue'{type=Type, value=Value}] + end, + {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}. + +%% Fill in the blanks +subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}}; +subject_enc({email, Email}) -> {?'id-emailAddress', Email}; +subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}}; +subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}}; +subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}}; +subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}}; +subject_enc({country, Country}) -> {?'id-at-countryName', Country}; +subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial}; +subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}}; +subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ}; +subject_enc(Other) -> Other. + + +extensions(Opts) -> + case proplists:get_value(extensions, Opts, []) of + false -> + asn1_NOVALUE; + Exts -> + lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)]) + end. + +default_extensions(Exts) -> + Def = [{key_usage,undefined}, + {subject_altname, undefined}, + {issuer_altname, undefined}, + {basic_constraints, default}, + {name_constraints, undefined}, + {policy_constraints, undefined}, + {ext_key_usage, undefined}, + {inhibit_any, undefined}, + {auth_key_id, undefined}, + {subject_key_id, undefined}, + {policy_mapping, undefined}], + Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end, + Exts ++ lists:foldl(Filter, Def, Exts). + +extension({_, undefined}) -> []; +extension({basic_constraints, Data}) -> + case Data of + default -> + #'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA=true}, + critical=true}; + false -> + []; + Len when is_integer(Len) -> + #'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len}, + critical=true}; + _ -> + #'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = Data} + end; +extension({Id, Data, Critical}) -> + #'Extension'{extnID = Id, extnValue = Data, critical = Critical}. + + +publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) -> + Public = #'RSAPublicKey'{modulus=N, publicExponent=E}, + Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, + subjectPublicKey = Public}; +publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) -> + Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa', + parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}. + +validity(Opts) -> + DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), + DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), + {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), + Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end, + #'Validity'{notBefore={generalTime, Format(DefFrom)}, + notAfter ={generalTime, Format(DefTo)}}. + +sign_algorithm(#'RSAPrivateKey'{}, Opts) -> + Type = case proplists:get_value(digest, Opts, sha1) of + sha1 -> ?'sha1WithRSAEncryption'; + sha512 -> ?'sha512WithRSAEncryption'; + sha384 -> ?'sha384WithRSAEncryption'; + sha256 -> ?'sha256WithRSAEncryption'; + md5 -> ?'md5WithRSAEncryption'; + md2 -> ?'md2WithRSAEncryption' + end, + {Type, 'NULL'}; +sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) -> + {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}. + +make_key(rsa, _Opts) -> + %% (OBS: for testing only) + gen_rsa2(64); +make_key(dsa, _Opts) -> + gen_dsa2(128, 20). %% Bytes i.e. {1024, 160} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% RSA key generation (OBS: for testing only) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53, + 47,43,41,37,31,29,23,19,17,13,11,7,5,3]). + +gen_rsa2(Size) -> + P = prime(Size), + Q = prime(Size), + N = P*Q, + Tot = (P - 1) * (Q - 1), + [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES), + {D1,D2} = extended_gcd(E, Tot), + D = erlang:max(D1,D2), + case D < E of + true -> + gen_rsa2(Size); + false -> + {Co1,Co2} = extended_gcd(Q, P), + Co = erlang:max(Co1,Co2), + #'RSAPrivateKey'{version = 'two-prime', + modulus = N, + publicExponent = E, + privateExponent = D, + prime1 = P, + prime2 = Q, + exponent1 = D rem (P-1), + exponent2 = D rem (Q-1), + coefficient = Co + } + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% DSA key generation (OBS: for testing only) +%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm +%% and the fips_186-3.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +gen_dsa2(LSize, NSize) -> + Q = prime(NSize), %% Choose N-bit prime Q + X0 = prime(LSize), + P0 = prime((LSize div 2) +1), + + %% Choose L-bit prime modulus P such that p-1 is a multiple of q. + case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of + error -> + gen_dsa2(LSize, NSize); + P -> + G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q. + %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used. + + X = prime(20), %% Choose x by some random method, where 0 < x < q. + Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p. + + #'DSAPrivateKey'{version=0, p=P, q=Q, g=G, y=Y, x=X} + end. + +%% See fips_186-3.pdf +dsa_search(T, P0, Q, Iter) when Iter > 0 -> + P = 2*T*Q*P0 + 1, + case is_prime(crypto:mpint(P), 50) of + true -> P; + false -> dsa_search(T+1, P0, Q, Iter-1) + end; +dsa_search(_,_,_,_) -> + error. + + +%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +prime(ByteSize) -> + Rand = odd_rand(ByteSize), + crypto:erlint(prime_odd(Rand, 0)). + +prime_odd(Rand, N) -> + case is_prime(Rand, 50) of + true -> + Rand; + false -> + NotPrime = crypto:erlint(Rand), + prime_odd(crypto:mpint(NotPrime+2), N+1) + end. + +%% see http://en.wikipedia.org/wiki/Fermat_primality_test +is_prime(_, 0) -> true; +is_prime(Candidate, Test) -> + CoPrime = odd_rand(<<0,0,0,4, 10000:32>>, Candidate), + case crypto:mod_exp(CoPrime, Candidate, Candidate) of + CoPrime -> is_prime(Candidate, Test-1); + _ -> false + end. + +odd_rand(Size) -> + Min = 1 bsl (Size*8-1), + Max = (1 bsl (Size*8))-1, + odd_rand(crypto:mpint(Min), crypto:mpint(Max)). + +odd_rand(Min,Max) -> + Rand = <> = crypto:rand_uniform(Min,Max), + BitSkip = (Sz+4)*8-1, + case Rand of + Odd = <<_:BitSkip, 1:1>> -> Odd; + Even = <<_:BitSkip, 0:1>> -> + crypto:mpint(crypto:erlint(Even)+1) + end. + +extended_gcd(A, B) -> + case A rem B of + 0 -> + {0, 1}; + N -> + {X, Y} = extended_gcd(B, N), + {Y, X-Y*(A div B)} + end. + +pem_to_der(File) -> + {ok, PemBin} = file:read_file(File), + public_key:pem_decode(PemBin). + +der_to_pem(File, Entries) -> + PemBin = public_key:pem_encode(Entries), + file:write_file(File, PemBin). diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 0c15c067a8..cf3279df75 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -159,10 +159,8 @@ erlang_client_openssh_server_exec(suite) -> []; erlang_client_openssh_server_exec(Config) when is_list(Config) -> - Host = ssh_test_lib:hostname(), - {ok, ConnectionRef} = - ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user_interaction, false}]), + ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}]), {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId0, "echo testing", infinity), @@ -203,11 +201,9 @@ erlang_client_openssh_server_exec_compressed(suite) -> []; erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) -> - Host = ssh_test_lib:hostname(), - {ok, ConnectionRef} = - ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user_interaction, false}, - {compression, zlib}]), + ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}, + {compression, zlib}]), {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId, "echo testing", infinity), @@ -231,13 +227,11 @@ erlang_server_openssh_client_exec(suite) -> []; erlang_server_openssh_client_exec(Config) when is_list(Config) -> - SytemDir = ?config(data_dir, Config), - Host = ssh_test_lib:hostname(), - Port = ssh_test_lib:inet_port(), - - {ok, Pid} = ssh:daemon(Port, [{system_dir, SytemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - + SystemDir = ?config(data_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + test_server:sleep(500), @@ -262,12 +256,10 @@ erlang_server_openssh_client_exec_compressed(suite) -> []; erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) -> - SytemDir = ?config(data_dir, Config), - Host = ssh_test_lib:hostname(), - Port = ssh_test_lib:inet_port(), - {ok, Pid} = ssh:daemon(Port, [{system_dir, SytemDir}, - {compression, zlib}, - {failfun, fun ssh_test_lib:failfun/2}]), + SystemDir = ?config(data_dir, Config), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {compression, zlib}, + {failfun, fun ssh_test_lib:failfun/2}]), test_server:sleep(500), @@ -292,10 +284,9 @@ erlang_client_openssh_server_setenv(suite) -> []; erlang_client_openssh_server_setenv(Config) when is_list(Config) -> - Host = ssh_test_lib:hostname(), - {ok, ConnectionRef} = - ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user_interaction, false}]), + ConnectionRef = + ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}]), {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), Env = case ssh_connection:setenv(ConnectionRef, ChannelId, @@ -340,16 +331,14 @@ erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) -> {ok,[[Home]]} = init:get_argument(home), SrcDir = filename:join(Home, ".ssh"), UserDir = ?config(priv_dir, Config), - Host = ssh_test_lib:hostname(), - case ssh_test_lib:copyfile(SrcDir, UserDir, "id_rsa") of {ok, _} -> - {ok, ConnectionRef} = - ssh:connect(Host, ?SSH_DEFAULT_PORT, - [{user_dir, UserDir}, - {public_key_alg, ssh_rsa}, - {user_interaction, false}, - silently_accept_hosts]), + ConnectionRef = + ssh_test_lib:connect(?SSH_DEFAULT_PORT, + [{user_dir, UserDir}, + {public_key_alg, ssh_rsa}, + {user_interaction, false}, + silently_accept_hosts]), {ok, Channel} = ssh_connection:session_channel(ConnectionRef, infinity), ok = ssh_connection:close(ConnectionRef, Channel), @@ -368,15 +357,14 @@ erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) -> {ok,[[Home]]} = init:get_argument(home), SrcDir = filename:join(Home, ".ssh"), UserDir = ?config(priv_dir, Config), - Host = ssh_test_lib:hostname(), case ssh_test_lib:copyfile(SrcDir, UserDir, "id_dsa") of {ok, _} -> - {ok, ConnectionRef} = - ssh:connect(Host, ?SSH_DEFAULT_PORT, - [{user_dir, UserDir}, - {public_key_alg, ssh_dsa}, - {user_interaction, false}, - silently_accept_hosts]), + ConnectionRef = + ssh_test_lib:connect(?SSH_DEFAULT_PORT, + [{user_dir, UserDir}, + {public_key_alg, ssh_dsa}, + {user_interaction, false}, + silently_accept_hosts]), {ok, Channel} = ssh_connection:session_channel(ConnectionRef, infinity), ok = ssh_connection:close(ConnectionRef, Channel), @@ -394,13 +382,11 @@ erlang_server_openssh_client_pulic_key_dsa(suite) -> []; erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) -> - SytemDir = ?config(data_dir, Config), - Host = ssh_test_lib:hostname(), - Port = ssh_test_lib:inet_port(), - {ok, Pid} = ssh:daemon(Port, [{system_dir, SytemDir}, - {public_key_alg, ssh_dsa}, - {failfun, fun ssh_test_lib:failfun/2}]), - + SystemDir = ?config(data_dir, Config), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {public_key_alg, ssh_dsa}, + {failfun, fun ssh_test_lib:failfun/2}]), + test_server:sleep(500), Cmd = "ssh -p " ++ integer_to_list(Port) ++ @@ -426,15 +412,13 @@ erlang_client_openssh_server_password(suite) -> erlang_client_openssh_server_password(Config) when is_list(Config) -> %% to make sure we don't public-key-auth UserDir = ?config(data_dir, Config), - Host = ssh_test_lib:hostname(), - {error, Reason0} = - ssh:connect(Host, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), - + ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + test_server:format("Test of user foo that does not exist. " "Error msg: ~p~n", [Reason0]), @@ -443,12 +427,12 @@ erlang_client_openssh_server_password(Config) when is_list(Config) -> case length(string:tokens(User, " ")) of 1 -> {error, Reason1} = - ssh:connect(Host, ?SSH_DEFAULT_PORT, - [{silently_accept_hosts, true}, - {user, User}, - {password, "foo"}, - {user_interaction, false}, - {user_dir, UserDir}]), + ssh_test_lib:connect(?SSH_DEFAULT_PORT, + [{silently_accept_hosts, true}, + {user, User}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), test_server:format("Test of wrong Pasword. " "Error msg: ~p~n", [Reason1]); _ -> -- cgit v1.2.3 From 7bd8f67f619dc2bd626d85bb35519d03cf7ed4c0 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Thu, 3 Mar 2011 14:41:39 +0100 Subject: Added code for generating certificates. --- lib/ssh/test/ssh_test_lib.erl | 58 ++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index c237e1ba5d..e8197e32c2 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -27,9 +27,9 @@ -include_lib("public_key/include/public_key.hrl"). -include("test_server.hrl"). -include("test_server_line.hrl"). +-include("../src/ssh.hrl"). -define(TIMEOUT, 50000). --define(SSH_DEFAULT_PORT, 22). connect(Options) -> connect(hostname(), inet_port(), Options). @@ -243,46 +243,32 @@ get_user_dir() -> end. -%% Create certificates. -make_dsa_cert(Config) -> - - {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_dsa_cert_files("server", Config), - {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_dsa_cert_files("client", Config), - [{server_dsa_opts, [{ssl_imp, new},{reuseaddr, true}, - {cacertfile, ServerCaCertFile}, - {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]}, - {server_dsa_verify_opts, [{ssl_imp, new},{reuseaddr, true}, - {cacertfile, ClientCaCertFile}, - {certfile, ServerCertFile}, {keyfile, ServerKeyFile}, - {verify, verify_peer}]}, - {client_dsa_opts, [{ssl_imp, new},{reuseaddr, true}, - {cacertfile, ClientCaCertFile}, - {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]} - | Config]. - +make_dsa_cert_files(Config) -> + make_dsa_cert_files("", Config). - make_dsa_cert_files(RoleStr, Config) -> + CaInfo = {CaCert, _} = make_cert([{key, dsa}]), {Cert, CertKey} = make_cert([{key, dsa}, {issuer, CaInfo}]), - CaCertFile = filename:join(["/home/nick/trash/ssh/", - RoleStr, "dsa_cacerts.pem"]), - CertFile = filename:join(["/home/nick/trash/ssh/", - RoleStr, "dsa_cert.pem"]), - KeyFile = filename:join(["/home/nick/trash/ssh/", - RoleStr, "dsa_key.pem"]), -%% CaCertFile = filename:join([?config(priv_dir, Config), -%% RoleStr, "dsa_cacerts.pem"]), -%% CertFile = filename:join([?config(priv_dir, Config), -%% RoleStr, "dsa_cert.pem"]), -%% KeyFile = filename:join([?config(priv_dir, Config), -%% RoleStr, "dsa_key.pem"]), + CaCertFile = filename:join([?config(data_dir, Config), + RoleStr, "dsa_cacerts.pem"]), + CertFile = filename:join([?config(data_dir, Config), + RoleStr, "dsa_cert.pem"]), + KeyFile = filename:join([?config(data_dir, Config), + RoleStr, "dsa_key.pem"]), der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]), der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]), der_to_pem(KeyFile, [CertKey]), {CaCertFile, CertFile, KeyFile}. +make_dsa_public_key_file(P, Q, G, Y, Config) -> + PK = #ssh_key{type = dsa, public = {P,Q,G,Y}}, + Enc = ssh_file:encode_public_key(PK), + B64 = ssh_bits:b64_encode(Enc), + FileName = filename:join([?config(data_dir, Config), "ssh_host_dsa_key.pub"]), + file:write_file(FileName, <<"ssh-dss ", B64/binary>>). + %%-------------------------------------------------------------------- %% Create and return a der encoded certificate @@ -318,13 +304,13 @@ make_cert(Opts) -> {Cert, encode_key(SubjectPrivateKey)}. %%-------------------------------------------------------------------- -%% Writes pem files in Dir with FileName ++ ".pem" and FileName ++ "_key.pem" -%% write_pem(::string(), ::string(), {Cert,Key}) -> ok +%% Writes cert files in Dir with FileName and FileName ++ Suffix +%% write_cert(::string(), ::string(), {Cert,Key}) -> ok %%-------------------------------------------------------------------- -write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) -> - ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"), +write_cert(Dir, FileName, Suffix, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) -> + ok = der_to_pem(filename:join(Dir, FileName), [{'Certificate', Cert, not_encrypted}]), - ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]). + ok = der_to_pem(filename:join(Dir, FileName ++ Suffix), [Key]). %%-------------------------------------------------------------------- %% Creates a rsa key (OBS: for testing only) -- cgit v1.2.3 From a23f044daea7526a649c788b1a81000d833b1a3e Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Thu, 3 Mar 2011 16:21:34 +0100 Subject: Resolved merge issue. --- lib/ssh/test/Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index fc88916e45..c143181720 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2010. All Rights Reserved. +# Copyright Ericsson AB 2004-2011. 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 @@ -115,11 +115,7 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) -<<<<<<< HEAD $(INSTALL_DATA) ssh.spec ssh.cover $(RELSYSDIR) -======= - $(INSTALL_DATA) ssh.spec $(RELSYSDIR) ->>>>>>> Add test suite for ssh $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR) @for dir in $(DATA_DIRS); do \ if test ! -d $$dir ; then \ -- cgit v1.2.3 From 37bd65a4615ca9692c8ef363151559a3fe22cda4 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Thu, 3 Mar 2011 16:23:47 +0100 Subject: Resolved merge conflict. --- lib/ssh/test/ssh.spec | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec index c420b119ac..8de0fe44e4 100644 --- a/lib/ssh/test/ssh.spec +++ b/lib/ssh/test/ssh.spec @@ -1,4 +1,3 @@ -<<<<<<< HEAD {suites,"../ssh_test",all}. {skip_cases,"../ssh_test",ssh_ssh_SUITE, [ssh], @@ -6,11 +5,3 @@ {skip_cases,"../ssh_test",ssh_ssh_SUITE, [ssh_compressed], "Current implementation is timingdependent hence will succeed/fail on a whim"}. -======= -{topcase, {dir, "../ssh_test"}}. -{require_nodenames, 1}. -{skip, {ssh_ssh_SUITE, ssh, "Current implementation is timingdependent and -hence will succeed/fail on a whim"}}. -{skip, {ssh_ssh_SUITE, ssh_compressed, -"Current implementation is timingdependent hence will succeed/fail on a whim"}}. ->>>>>>> Add test suite for ssh -- cgit v1.2.3 From a488a4d45a392b5cf4cc46195a3ad2df32389582 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Mon, 7 Mar 2011 14:47:00 +0100 Subject: Corrected include path and spelling of a test case function. --- lib/ssh/test/ssh_basic_SUITE.erl | 2 +- lib/ssh/test/ssh_test_lib.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index e801664ff2..b51b17b2f4 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -102,7 +102,7 @@ end_per_testcase(_TestCase, _Config) -> %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- all() -> - [exec, exec_compressed, shell, daemon_allready_started, + [exec, exec_compressed, shell, daemon_already_started, server_password_option, server_userpassword_option, known_hosts]. diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index e8197e32c2..4fd47da090 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -27,7 +27,7 @@ -include_lib("public_key/include/public_key.hrl"). -include("test_server.hrl"). -include("test_server_line.hrl"). --include("../src/ssh.hrl"). +-include_lib("ssh/src/ssh.hrl"). -define(TIMEOUT, 50000). -- cgit v1.2.3 From 9100921827bdfb32bcfab2569618393997d5fef4 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Tue, 8 Mar 2011 14:27:33 +0100 Subject: Fixed include problem. --- lib/ssh/test/ssh_test_lib.erl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 4fd47da090..8b7d5e2992 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -27,10 +27,18 @@ -include_lib("public_key/include/public_key.hrl"). -include("test_server.hrl"). -include("test_server_line.hrl"). --include_lib("ssh/src/ssh.hrl"). -define(TIMEOUT, 50000). + +-record(ssh_key, + { + type, + public, + private, + comment = "" + }). + connect(Options) -> connect(hostname(), inet_port(), Options). -- cgit v1.2.3 From 61c134fa961a0aaa86be17d921dbe6727d0a7c1c Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Tue, 8 Mar 2011 15:18:49 +0100 Subject: Fixed host handling in ssh_test_lib (daemon and connect functions). --- lib/ssh/test/ssh_basic_SUITE.erl | 10 +++++----- lib/ssh/test/ssh_test_lib.erl | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index b51b17b2f4..f01b0a719e 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -279,11 +279,11 @@ daemon_already_started(suite) -> daemon_already_started(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - {error, eaddrinuse} = ssh_test_lib:daemon(Host, Port, [{system_dir, SystemDir}, - {failfun, - fun ssh_test_lib:failfun/2}]), + {Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + {error, eaddrinuse} = ssh_test_lib:daemon(Port, [{system_dir, SystemDir}, + {failfun, + fun ssh_test_lib:failfun/2}]), ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 8b7d5e2992..8c9fb9038d 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -44,9 +44,13 @@ connect(Options) -> connect(Port, Options) when is_integer(Port) -> connect(hostname(), Port, Options); +connect(any, Options) -> + connect(hostname(), inet_port(), Options); connect(Host, Options) -> connect(Host, inet_port(), Options). +connect(any, Port, Options) -> + connect(hostname(), Port, Options); connect(Host, Port, Options) -> case ssh:connect(Host, Port, Options) of {ok, ConnectionRef} -> @@ -65,6 +69,8 @@ daemon(Host, Options) -> daemon(Host, Port, Options) -> case ssh:daemon(Host, Port, Options) of + {ok, Pid} when Host == any -> + {Pid, hostname(), Port}; {ok, Pid} -> {Pid, Host, Port}; Error -> -- cgit v1.2.3 From 2fb636273a06d31f0c24dcecf9302cd6561f02af Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Thu, 31 Mar 2011 16:48:44 +0200 Subject: Some minor updates regarding how test data is generated. --- lib/ssh/test/Makefile | 2 +- lib/ssh/test/ssh_basic_SUITE.erl | 1 + lib/ssh/test/ssh_sftp_SUITE.erl | 1 + lib/ssh/test/ssh_sftpd_SUITE.erl | 1 + lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 1 + lib/ssh/test/ssh_test_lib.erl | 4 ++++ lib/ssh/test/ssh_to_openssh_SUITE.erl | 1 + 7 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index c143181720..a3518aef52 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -45,7 +45,7 @@ HRL_FILES_NEEDED_IN_TEST= \ ERL_FILES= $(MODULES:%=%.erl) -KEY_FILES= ssh_host_dsa_key ssh_host_dsa_key.pub +KEY_FILES= ssh_host_dsa_key #ssh_host_dsa_key.pub TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index f01b0a719e..c2d10b8266 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -44,6 +44,7 @@ init_per_suite(Config) -> Dir = ?config(priv_dir, Config), ssh_test_lib:save_known_hosts(Dir), {ok, _} = ssh_test_lib:get_id_keys(Dir), + ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), Config; _Else -> {skip, "Crypto could not be started!"} diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 123a12773b..caaf4e6243 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -52,6 +52,7 @@ init_per_suite(Config) -> ssh_test_lib:save_known_hosts(Dir), %% More like copy_id_keys!!! {ok, _} = ssh_test_lib:get_id_keys(Dir), + ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), Config; {ok,_} -> {skip,"Could not start ssh!"}; diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index f5ed668fa6..97857c98d9 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -55,6 +55,7 @@ init_per_suite(Config) -> case {catch ssh:stop(),catch crypto:start()} of {ok,ok} -> + ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), Config; {ok,_} -> {skip,"Could not start ssh!"}; diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index db23a98225..c571ac45f7 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -54,6 +54,7 @@ init_per_suite(Config) -> {ok, FileInfo} = file:read_file_info(FileName), ok = file:write_file_info(FileName, FileInfo#file_info{mode = 8#400}), + ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), Config; _Else -> {skip,"Could not start ssh!"} diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 8c9fb9038d..f2a6351f96 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -283,6 +283,10 @@ make_dsa_public_key_file(P, Q, G, Y, Config) -> FileName = filename:join([?config(data_dir, Config), "ssh_host_dsa_key.pub"]), file:write_file(FileName, <<"ssh-dss ", B64/binary>>). +make_dsa_private_key_file(LSize, NSize, Config) -> + {Key, EncodedKey} = gen_dsa(LSize, NSize), + FileName = filename:join([?config(data_dir, Config), "ssh_host_dsa_key"]), + file:write_file(FileName, EncodedKey). %%-------------------------------------------------------------------- %% Create and return a der encoded certificate diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index cf3279df75..c927dead04 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -42,6 +42,7 @@ init_per_suite(Config) -> case catch crypto:start() of ok -> + ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), Config; _Else -> {skip,"Could not start crypto!"} -- cgit v1.2.3 From 26e3b024571952284e026a4f8d3ef55777dc4386 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Mon, 16 May 2011 15:25:03 +0200 Subject: Generic key management for test suites. --- lib/ssh/test/Makefile | 10 ---- lib/ssh/test/ssh_basic_SUITE.erl | 4 +- lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key | 12 ---- .../test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub | 1 - lib/ssh/test/ssh_host_dsa_key | 12 ---- lib/ssh/test/ssh_host_dsa_key.pub | 1 - lib/ssh/test/ssh_sftp_SUITE.erl | 5 +- lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key | 12 ---- .../test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub | 1 - lib/ssh/test/ssh_sftpd_SUITE.erl | 13 ++-- lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key | 12 ---- .../test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub | 1 - lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 2 +- .../ssh_host_dsa_key | 12 ---- .../ssh_host_dsa_key.pub | 1 - lib/ssh/test/ssh_test_lib.erl | 69 +++++++++++++--------- lib/ssh/test/ssh_to_openssh_SUITE.erl | 2 +- .../ssh_to_openssh_SUITE_data/ssh_host_dsa_key | 12 ---- .../ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub | 1 - 19 files changed, 55 insertions(+), 128 deletions(-) delete mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key delete mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub delete mode 100644 lib/ssh/test/ssh_host_dsa_key delete mode 100644 lib/ssh/test/ssh_host_dsa_key.pub delete mode 100644 lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key delete mode 100644 lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub delete mode 100644 lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key delete mode 100644 lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub delete mode 100644 lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key delete mode 100644 lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub delete mode 100644 lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key delete mode 100644 lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index a3518aef52..5a2a6de24a 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -45,8 +45,6 @@ HRL_FILES_NEEDED_IN_TEST= \ ERL_FILES= $(MODULES:%=%.erl) -KEY_FILES= ssh_host_dsa_key #ssh_host_dsa_key.pub - TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) DATA_DIRS = $(MODULES:%=%_data) @@ -117,14 +115,6 @@ release_tests_spec: opt $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) $(INSTALL_DATA) ssh.spec ssh.cover $(RELSYSDIR) $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR) - @for dir in $(DATA_DIRS); do \ - if test ! -d $$dir ; then \ - echo "=== Skipping datadir $$dir" ; \ - else \ - echo "Installling $(KEY_FILES) in $$dir"; \ - $(INSTALL_DATA) $(KEY_FILES) $$dir; \ - fi ; \ - done chmod -f -R u+w $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index c2d10b8266..5ea0d98980 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -42,9 +42,8 @@ init_per_suite(Config) -> case catch crypto:start() of ok -> Dir = ?config(priv_dir, Config), - ssh_test_lib:save_known_hosts(Dir), {ok, _} = ssh_test_lib:get_id_keys(Dir), - ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), + ssh_test_lib:make_dsa_files(Config), Config; _Else -> {skip, "Crypto could not be started!"} @@ -60,7 +59,6 @@ end_per_suite(Config) -> Dir = ?config(priv_dir, Config), crypto:stop(), ssh_test_lib:remove_id_keys(Dir), - ssh_test_lib:restore_known_hosts(Dir), ok. %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key deleted file mode 100644 index 58f0a65cba..0000000000 --- a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 -jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ -ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe -uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 -nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq -mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 -2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS -QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C -ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 -+basD1iibtNHs9Edfdkm ------END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub deleted file mode 100644 index d83487fc50..0000000000 --- a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_host_dsa_key b/lib/ssh/test/ssh_host_dsa_key deleted file mode 100644 index 58f0a65cba..0000000000 --- a/lib/ssh/test/ssh_host_dsa_key +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 -jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ -ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe -uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 -nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq -mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 -2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS -QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C -ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 -+basD1iibtNHs9Edfdkm ------END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_host_dsa_key.pub deleted file mode 100644 index d83487fc50..0000000000 --- a/lib/ssh/test/ssh_host_dsa_key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index caaf4e6243..c96b6de3ea 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -49,10 +49,8 @@ init_per_suite(Config) -> case {catch crypto:start(),catch ssh:start()} of {ok,ok} -> Dir = ?config(priv_dir, Config), - ssh_test_lib:save_known_hosts(Dir), - %% More like copy_id_keys!!! {ok, _} = ssh_test_lib:get_id_keys(Dir), - ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), + ssh_test_lib:make_dsa_files(Config), Config; {ok,_} -> {skip,"Could not start ssh!"}; @@ -72,7 +70,6 @@ end_per_suite(Config) -> crypto:stop(), Dir = ?config(priv_dir, Config), ssh_test_lib:remove_id_keys(Dir), - ssh_test_lib:restore_known_hosts(Dir), Config. %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key deleted file mode 100644 index 58f0a65cba..0000000000 --- a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 -jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ -ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe -uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 -nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq -mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 -2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS -QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C -ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 -+basD1iibtNHs9Edfdkm ------END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub deleted file mode 100644 index d83487fc50..0000000000 --- a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 97857c98d9..bfe54a3e75 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -55,7 +55,7 @@ init_per_suite(Config) -> case {catch ssh:stop(),catch crypto:start()} of {ok,ok} -> - ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), + ssh_test_lib:make_dsa_files(Config), Config; {ok,_} -> {skip,"Could not start ssh!"}; @@ -94,11 +94,16 @@ init_per_testcase(TestCase, Config) -> SysDir = ?config(data_dir, Config), {ok, Sftpd} = ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SysDir}, - {user_passwords,[{?USER, ?PASSWD}]}]), + {user_passwords,[{?USER, ?PASSWD}]}, + {pwdfun, fun(_,_) -> true end}]), Cm = ssh_test_lib:connect(?SFPD_PORT, - [{silently_accept_hosts, true}, - {user, ?USER}, {password, ?PASSWD}]), + [{system_dir, SysDir}, + {user_dir, SysDir}, + {user, ?USER}, {password, ?PASSWD}, + {user_interaction, false}, + {silently_accept_hosts, true}, + {pwdfun, fun(_,_) -> true end}]), {ok, Channel} = ssh_connection:session_channel(Cm, ?XFER_WINDOW_SIZE, ?XFER_PACKET_SIZE, ?TIMEOUT), diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key deleted file mode 100644 index 58f0a65cba..0000000000 --- a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 -jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ -ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe -uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 -nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq -mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 -2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS -QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C -ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 -+basD1iibtNHs9Edfdkm ------END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub deleted file mode 100644 index d83487fc50..0000000000 --- a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index c571ac45f7..ebed8c0b54 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -54,7 +54,7 @@ init_per_suite(Config) -> {ok, FileInfo} = file:read_file_info(FileName), ok = file:write_file_info(FileName, FileInfo#file_info{mode = 8#400}), - ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), + ssh_test_lib:make_dsa_files(Config), Config; _Else -> {skip,"Could not start ssh!"} diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key deleted file mode 100644 index 58f0a65cba..0000000000 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 -jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ -ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe -uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 -nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq -mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 -2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS -QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C -ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 -+basD1iibtNHs9Edfdkm ------END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub deleted file mode 100644 index d83487fc50..0000000000 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index f2a6351f96..b11ebc1652 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -232,22 +232,6 @@ known_hosts(BR) -> end. -save_known_hosts(PrivDir) -> - Src = ssh_file:file_name(user, "known_hosts", []), - Dst = filename:join(PrivDir, "kh_save"), - Ok = file:copy(Src, Dst), - io:format("save ~p -> ~p : ~p", [Src, Dst, Ok]). - -restore_known_hosts(_PrivDir) -> - %% Race condition. - ok. -%% Src = filename:join(PrivDir, "kh_save"), -%% Dst = ssh_file:file_name(user, "known_hosts", []), -%% D1 = file:delete(Dst), -%% C = file:copy(Src, Dst), -%% D2 = file:delete(Src), -%% io:format("restore ~p -> ~p : ~p ~p ~p\n", [Src, Dst, D1, C, D2]). - get_user_dir() -> case os:type() of {win32, _} -> @@ -276,17 +260,48 @@ make_dsa_cert_files(RoleStr, Config) -> der_to_pem(KeyFile, [CertKey]), {CaCertFile, CertFile, KeyFile}. -make_dsa_public_key_file(P, Q, G, Y, Config) -> - PK = #ssh_key{type = dsa, public = {P,Q,G,Y}}, - Enc = ssh_file:encode_public_key(PK), - B64 = ssh_bits:b64_encode(Enc), - FileName = filename:join([?config(data_dir, Config), "ssh_host_dsa_key.pub"]), - file:write_file(FileName, <<"ssh-dss ", B64/binary>>). - -make_dsa_private_key_file(LSize, NSize, Config) -> - {Key, EncodedKey} = gen_dsa(LSize, NSize), - FileName = filename:join([?config(data_dir, Config), "ssh_host_dsa_key"]), - file:write_file(FileName, EncodedKey). +make_dsa_files(Config) -> + make_dsa_files(Config, rfc4716_public_key). +make_dsa_files(Config, Type) -> + {DSA, EncodedKey} = ssh_test_lib:gen_dsa(128, 20), + PKey = DSA#'DSAPrivateKey'.y, + P = DSA#'DSAPrivateKey'.p, + Q = DSA#'DSAPrivateKey'.q, + G = DSA#'DSAPrivateKey'.g, + Dss = #'Dss-Parms'{p=P, q=Q, g=G}, + {ok, Hostname} = inet:gethostname(), + {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet), + IP = lists:concat([A, ".", B, ".", C, ".", D]), + Attributes = [], % Could be [{comment,"user@" ++ Hostname}], + HostNames = [{hostnames,[IP, IP]}], + PublicKey = [{{PKey, Dss}, Attributes}], + KnownHosts = [{{PKey, Dss}, HostNames}], + + KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts), + KnownHosts = public_key:ssh_decode(KnownHostsEnc, known_hosts), + + PublicKeyEnc = public_key:ssh_encode(PublicKey, Type), +% PublicKey = public_key:ssh_decode(PublicKeyEnc, Type), + + SystemTmpDir = ?config(data_dir, Config), + filelib:ensure_dir(SystemTmpDir), + file:make_dir(SystemTmpDir), + + DSAFile = filename:join(SystemTmpDir, "ssh_host_dsa_key.pub"), + file:delete(DSAFile), + + DSAPrivateFile = filename:join(SystemTmpDir, "ssh_host_dsa_key"), + file:delete(DSAPrivateFile), + + KHFile = filename:join(SystemTmpDir, "known_hosts"), + file:delete(KHFile), + + PemBin = public_key:pem_encode([EncodedKey]), + + file:write_file(DSAFile, PublicKeyEnc), + file:write_file(KHFile, KnownHostsEnc), + file:write_file(DSAPrivateFile, PemBin), + ok. %%-------------------------------------------------------------------- %% Create and return a der encoded certificate diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index c927dead04..f959d50484 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -42,7 +42,7 @@ init_per_suite(Config) -> case catch crypto:start() of ok -> - ssh_test_lib:make_dsa_public_key_file(42, 43, 44, 45, Config), + ssh_test_lib:make_dsa_files(Config), Config; _Else -> {skip,"Could not start crypto!"} diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key deleted file mode 100644 index 58f0a65cba..0000000000 --- a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQC3s+bZJWOQnRXkzKLPPfaQOouLuLgrbM4Ac63QZOnJeRVas3c1 -jBk0Isp506RrKzhEop8z9OiKfqRteVntjjkcILwsQ/1veWgojdP/jHYl6pbJm6AQ -ETM7GvkpgRDTd4Bf/rbrhABczl1NatnJhMsES8n2zNiiAVRP0woVmMNnkQIVANUe -uFb3EPdFwPEjilQ5jANHQc7pAoGBAJSzGD9KW4AZYB0FTt/2rwB5VjayKudi8ZO0 -nTyVoDLz40yvWerL/PJMbAnMnbY7zuN/Y9cqnMJOdBkHPvOpLQVls/d/x5CHZxcq -mn3n+Jplr5tlKugpUCkvgNALH2o/DMrPh1DIiPqrH3Y0W8iKcG+zF9Z7FXbCswC5 -2TTFtuwNAoGAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVS -QGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2C -ZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4cCFFmAnw67 -+basD1iibtNHs9Edfdkm ------END DSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub deleted file mode 100644 index d83487fc50..0000000000 --- a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBALez5tklY5CdFeTMos899pA6i4u4uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM2KIBVE/TChWYw2eRAAAAFQDVHrhW9xD3RcDxI4pUOYwDR0HO6QAAAIEAlLMYP0pbgBlgHQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsfdjRbyIpwb7MX1nsVdsKzALnZNMW27A0AAACAfEIAb3mLjtFfiF/tsZb4/DGHdWSb6Ir0hFkoBUZ9ymBO70wlfZVSQGs240kZtOMpAOpJL1Dy8oH6PUQ+JyacwZIo8fdq19/Kwm6CPrpaEhzErmMvwT2CZJYZ+HOk55ljLkVCiyG7MzEj2+odLKym9yoQsbsJolHzIRpkLk45y4c= jakob@balin -- cgit v1.2.3 From 358af31ec75e32046e44645c6b6d511062e46393 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Wed, 18 May 2011 13:58:04 +0200 Subject: Removed unused record and fixed a few failing test cases, --- lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 17 ++++++++++++++++- lib/ssh/test/ssh_test_lib.erl | 9 --------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index ebed8c0b54..2209af05d5 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -94,7 +94,9 @@ init_per_testcase(TestCase, Config) -> ssh_sftpd:subsystem_spec([{file_handler, ssh_sftpd_file_alt}]), [{user_passwords,[{?USER, ?PASSWD}]}, + {pwdfun, fun(_,_) -> true end}, {system_dir, DataDir}, + {user_dir, DataDir}, {subsystems, [Spec]}]; "root_dir" -> Privdir = ?config(priv_dir, Config), @@ -102,17 +104,23 @@ init_per_testcase(TestCase, Config) -> file:make_dir(Root), Spec = ssh_sftpd:subsystem_spec([{root,Root}]), [{user_passwords,[{?USER, ?PASSWD}]}, + {pwdfun, fun(_,_) -> true end}, {system_dir, DataDir}, + {user_dir, DataDir}, {subsystems, [Spec]}]; "list_dir_limited" -> Spec = ssh_sftpd:subsystem_spec([{max_files,1}]), [{user_passwords,[{?USER, ?PASSWD}]}, + {pwdfun, fun(_,_) -> true end}, {system_dir, DataDir}, + {user_dir, DataDir}, {subsystems, [Spec]}]; _ -> [{user_passwords,[{?USER, ?PASSWD}]}, + {pwdfun, fun(_,_) -> true end}, + {user_dir, DataDir}, {system_dir, DataDir}] end, @@ -121,7 +129,11 @@ init_per_testcase(TestCase, Config) -> {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, ?SSHD_PORT, [{silently_accept_hosts, true}, - {user, ?USER}, {password, ?PASSWD}, {timeout, 30000}]), + {user, ?USER}, {password, ?PASSWD}, + {pwdfun, fun(_,_) -> true end}, + {system_dir, DataDir}, + {user_dir, DataDir}, + {timeout, 30000}]), TmpConfig = lists:keydelete(sftp, 1, Config), NewConfig = lists:keydelete(sftpd, 1, TmpConfig), [{sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig]. @@ -216,6 +228,9 @@ quit_OTP_6349(Config) when is_list(Config) -> timer:sleep(5000), {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, ?SSHD_PORT, [{silently_accept_hosts, true}, + {pwdfun, fun(_,_) -> true end}, + {system_dir, DataDir}, + {user_dir, DataDir}, {user, ?USER}, {password, ?PASSWD}]), {ok, <<_/binary>>} = ssh_sftp:read_file(NewSftp, FileName), diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index b11ebc1652..425fae22c1 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -30,15 +30,6 @@ -define(TIMEOUT, 50000). - --record(ssh_key, - { - type, - public, - private, - comment = "" - }). - connect(Options) -> connect(hostname(), inet_port(), Options). -- cgit v1.2.3