From 628553c2946649ef1715feacc05e8f75d38ef2e3 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 8 Sep 2015 16:39:38 +0200 Subject: inets: Add test suite for socket_wrap feature On Linux systems a socket may be opened pre starting Erlang and then passed to Erlangs ftpd or httpd daemon. This is useful as the wrap program can open a privileged port and Erlang does not have to be run as root. The test program will only open a random port, but it exercises the code so that the feature will remain intact. --- lib/inets/test/inets_socketwrap_SUITE.erl | 154 ++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 lib/inets/test/inets_socketwrap_SUITE.erl (limited to 'lib/inets/test/inets_socketwrap_SUITE.erl') diff --git a/lib/inets/test/inets_socketwrap_SUITE.erl b/lib/inets/test/inets_socketwrap_SUITE.erl new file mode 100644 index 0000000000..cfbda3ccf5 --- /dev/null +++ b/lib/inets/test/inets_socketwrap_SUITE.erl @@ -0,0 +1,154 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% +-module(inets_socketwrap_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include("inets_test_lib.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + [start_httpd_fd, start_tftpd_fd]. + +init_per_suite(Config) -> + case os:type() of + {unix, linux} -> + Config; + _ -> + {skip, linux_feature} + end. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +init_per_testcase(Case, Config) -> + end_per_testcase(Case, Config), + Config. + +end_per_testcase(_, Config) -> + inets:stop(), + Config. + +%%------------------------------------------------------------------------- +start_httpd_fd() -> + [{doc, "Start/stop of httpd service with socket wrapper"}]. +start_httpd_fd(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + DataDir = ?config(data_dir, Config), + HttpdConf = [{port, 80}, {ipfamily, inet}, + {server_name, "httpd_fd_test"}, {server_root, PrivDir}, + {document_root, PrivDir}, {bind_address, any}], + case setup_node_info(node()) of + {skip, _} = Skip -> + Skip; + {Node, NodeArg} -> + InetPort = inets_test_lib:inet_port(node()), + ct:pal("Node: ~p Port ~p~n", [Node, InetPort]), + Wrapper = filename:join(DataDir, "setuid_socket_wrap"), + Cmd = Wrapper ++ + " -s -httpd_80,0:" ++ integer_to_list(InetPort) + ++ " -p " ++ os:find_executable("erl") ++ + " -- " ++ NodeArg, + ct:pal("cmd: ~p~n", [Cmd]), + case open_port({spawn, Cmd}, [stderr_to_stdout]) of + Port when is_port(Port) -> + wait_node_up(Node, 10), + ct:pal("~p", [rpc:call(Node, init, get_argument, [httpd_80])]), + ok = rpc:call(Node, inets, start, []), + {ok, Pid} = rpc:call(Node, inets, start, [httpd, HttpdConf]), + [{port, InetPort}] = rpc:call(Node, httpd, info, [Pid, [port]]), + rpc:call(Node, erlang, halt, []); + _ -> + ct:fail(open_port_failed) + end + end. +%%------------------------------------------------------------------------- +start_tftpd_fd() -> + [{doc, "Start/stop of tfpd service with socket wrapper"}]. +start_tftpd_fd(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + case setup_node_info(node()) of + {skip, _} = Skip -> + Skip; + {Node, NodeArg} -> + InetPort = inets_test_lib:inet_port(node()), + ct:pal("Node: ~p~n", [Node]), + Wrapper = filename:join(DataDir, "setuid_socket_wrap"), + Cmd = Wrapper ++ + " -s -tftpd_69,0:" ++ integer_to_list(InetPort) + ++ " -p " ++ os:find_executable("erl") ++ + " -- " ++ NodeArg, + ct:pal("cmd: ~p~n", [Cmd]), + case open_port({spawn, Cmd}, [stderr_to_stdout]) of + Port when is_port(Port) -> + wait_node_up(Node, 10), + ct:pal("~p", [rpc:call(Node, init, get_argument, [tftpd_69])]), + ok = rpc:call(Node, inets, start, []), + {ok, Pid} = rpc:call(Node, inets, start, + [tftpd,[{host, "localhost"}]]), + {ok, Info} = rpc:call(Node, tftp, info, [Pid]), + {value,{port, InetPort}} = lists:keysearch(port, 1, Info), + rpc:call(Node, erlang, halt, []); + _ -> + ct:fail(open_port_failed) + end + end. +%%------------------------------------------------------------------------- +%% Internal functions +%%------------------------------------------------------------------------- +setup_node_info(nonode@nohost) -> + {skip, needs_distributed_node}; +setup_node_info(Node) -> + Static = "-detached -noinput", + Name = "inets_fd_test", + NameSw = case net_kernel:longnames() of + false -> "-sname "; + _ -> "-name " + end, + StrNode = + Static ++ " " + ++ NameSw ++ " " ++ Name ++ " " + ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()), + [_, Location] = string:tokens(atom_to_list(Node), "$@"), + TestNode = Name ++ "@" ++ Location, + {list_to_atom(TestNode), StrNode}. + +wait_node_up(Node, 0) -> + ct:fail({failed_to_start_node, Node}); +wait_node_up(Node, N) -> + ct:pal("(Node ~p: net_adm:ping(~p)~n", [node(), Node]), + case net_adm:ping(Node) of + pong -> + ok; + pang -> + ct:sleep(5000), + wait_node_up(Node, N-1) + end. -- cgit v1.2.3