aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/test/httpd_mod.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets/test/httpd_mod.erl')
-rw-r--r--lib/inets/test/httpd_mod.erl947
1 files changed, 947 insertions, 0 deletions
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
new file mode 100644
index 0000000000..b03f842e7c
--- /dev/null
+++ b/lib/inets/test/httpd_mod.erl
@@ -0,0 +1,947 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. 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(httpd_mod).
+-author('[email protected]').
+
+-include("test_server.hrl").
+-include("test_server_line.hrl").
+
+%% General testcases bodies called from httpd_SUITE
+-export([alias/4, actions/4, security/5, auth/4, auth_api/6,
+ auth_mnesia_api/4, htaccess/4,
+ cgi/4, esi/4, get/4, head/4, all/4]).
+
+%% Help functions
+-export([event/4, ssl_password_cb/0]).
+
+%% Seconds before successful auths timeout.
+-define(AUTH_TIMEOUT,5).
+
+
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
+alias(Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /pics/icon.sheet.gif "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type","image/gif"},
+ {header, "Server"},
+ {header, "Date"},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET / HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type","text/html"},
+ {header, "Server"},
+ {header, "Date"},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ "GET /misc/ HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type","text/html"},
+ {header, "Server"},
+ {header, "Date"},
+ {version, "HTTP/1.0"}]),
+
+ %% Check redirection if trailing slash is missing.
+ ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ "GET /misc HTTP/1.0\r\n\r\n",
+ [{statuscode, 301},
+ {header, "Location"},
+ {header, "Content-Type","text/html"},
+ {version, "HTTP/1.0"}]).
+
+%%-------------------------------------------------------------------------
+actions(Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "HEAD / HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]).
+
+%%-------------------------------------------------------------------------
+security(ServerRoot, Type, Port, Host, Node) ->
+ io:format(user, "~w:security -> entry with"
+ "~n ServerRoot: ~p"
+ "~n Type: ~p"
+ "~n Port: ~p"
+ "~n Host: ~p"
+ "~n Node: ~p"
+ "~n", [?MODULE, ServerRoot, Type, Port, Host, Node]),
+
+ global:register_name(mod_security_test, self()), % Receive events
+
+ test_server:sleep(5000),
+
+ OpenDir = filename:join([ServerRoot, "htdocs", "open"]),
+
+ %% Test blocking / unblocking of users.
+
+ %% /open, require user one Aladdin
+ remove_users(Node, ServerRoot, Host, Port, "open"),
+
+ auth_request(Type, Host, Port, Node, "/open/", "one", "onePassword",
+ [{statuscode, 401}]),
+ receive_security_event({event, auth_fail, Port, OpenDir,
+ [{user, "one"}, {password, "onePassword"}]},
+ Node, Port),
+
+ auth_request(Type,Host,Port,Node,"/open/", "two", "twoPassword",
+ [{statuscode, 401}]),
+ receive_security_event({event, auth_fail, Port, OpenDir,
+ [{user, "two"}, {password, "twoPassword"}]},
+ Node, Port),
+
+ auth_request(Type, Host, Port, Node,"/open/", "Aladdin",
+ "AladdinPassword", [{statuscode, 401}]),
+ receive_security_event({event, auth_fail, Port, OpenDir,
+ [{user, "Aladdin"},
+ {password, "AladdinPassword"}]},
+ Node, Port),
+
+ add_user(Node, ServerRoot, Port, "open", "one", "onePassword", []),
+ add_user(Node, ServerRoot, Port, "open", "two", "twoPassword", []),
+
+ auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
+ [{statuscode, 401}]),
+ receive_security_event({event, auth_fail, Port, OpenDir,
+ [{user, "one"}, {password, "WrongPassword"}]},
+ Node, Port),
+
+ auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
+ [{statuscode, 401}]),
+ receive_security_event({event, auth_fail, Port, OpenDir,
+ [{user, "one"}, {password, "WrongPassword"}]},
+ Node, Port),
+
+ receive_security_event({event, user_block, Port, OpenDir,
+ [{user, "one"}]}, Node, Port),
+
+ global:unregister_name(mod_security_test), % No more events.
+
+ auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
+ [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword",
+ [{statuscode, 403}]),
+
+ %% User "one" should be blocked now..
+ %% [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port),
+ case list_blocked_users(Node, Port) of
+ [{"one",_, Port, OpenDir,_}] ->
+ ok;
+ Blocked ->
+ io:format(user, "~w:security -> Blocked: ~p"
+ "~n", [?MODULE, Blocked]),
+ exit({unexpected_blocked, Blocked})
+ end,
+
+ [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port,OpenDir),
+
+ true = unblock_user(Node, "one", Port, OpenDir),
+ %% User "one" should not be blocked any more..
+ [] = list_blocked_users(Node, Port),
+ [] = list_blocked_users(Node, Port, OpenDir),
+ auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword",
+ [{statuscode, 200}]),
+
+ %% Test list_auth_users & auth_timeout
+ ["one"] = list_auth_users(Node, Port),
+ ["one"] = list_auth_users(Node, Port, OpenDir),
+ auth_request(Type, Host, Port, Node,"/open/", "two", "onePassword",
+ [{statuscode, 401}]),
+ ["one"] = list_auth_users(Node, Port),
+ ["one"] = list_auth_users(Node, Port, OpenDir),
+ auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword",
+ [{statuscode, 401}]),
+ ["one"] = list_auth_users(Node, Port),
+ ["one"] = list_auth_users(Node, Port, OpenDir),
+ %% Wait for successful auth to timeout.
+ test_server:sleep(?AUTH_TIMEOUT*1001),
+ [] = list_auth_users(Node, Port),
+ [] = list_auth_users(Node, Port, OpenDir),
+ %% "two" is blocked.
+ true = unblock_user(Node, "two", Port, OpenDir),
+ %% Test explicit blocking. Block user 'two'.
+ [] = list_blocked_users(Node,Port,OpenDir),
+ true = block_user(Node, "two", Port, OpenDir, 10),
+ auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword",
+ [{statuscode, 401}]).
+
+%%-------------------------------------------------------------------------
+auth(Type, Port, Host, Node) ->
+ %% Authentication required!
+ ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ "GET /open/ HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ "GET /secret/ HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ "GET /secret/top_secret/"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+
+ %% Authentication OK! ["one:OnePassword" user first in user list]
+ auth_request(Type, Host, Port, Node, "/open/dummy.html", "one",
+ "onePassword", [{statuscode, 200}]),
+ %% Authentication OK and a directory listing is supplied!
+ %% ["Aladdin:open sesame" user second in user list]
+ auth_request(Type, Host, Port, Node, "/open/","Aladdin",
+ "AladdinPassword", [{statuscode, 200}]),
+
+ %% User correct but wrong password! ["one:one" user first in user list]
+ auth_request(Type, Host, Port, Node, "/open/", "one", "one",
+ [{statuscode, 401},{header, "WWW-Authenticate"}]),
+ %% Make sure Authenticate header is received even the second time
+ %% we try a incorrect password! Otherwise a browser client will hang!
+ auth_request(Type, Host, Port, Node, "/open/", "one", "one",
+ [{statuscode, 401},{header, "WWW-Authenticate"}]),
+
+ %% Neither user or password correct! ["dummy:dummy"]
+ auth_request(Type, Host, Port, Node, "/open/", "dummy", "dummy",
+ [{statuscode, 401}]),
+
+ %% Authentication OK! ["two:TwoPassword" user in first group]
+ auth_request(Type, Host, Port, Node, "/secret/dummy.html", "two",
+ "twoPassword", [{statuscode, 200}]),
+ %% Authentication OK and a directory listing is supplied!
+ %% ["three:ThreePassword" user in second group]
+ auth_request(Type, Host, Port, Node,"/secret/", "three",
+ "threePassword", [{statuscode, 200}]),
+
+ %% User correct but wrong password! ["two:two" user in first group]
+ auth_request(Type, Host, Port, Node, "/secret/", "two", "two",
+ [{statuscode, 401}]),
+ %% Neither user or password correct! ["dummy:dummy"]
+ auth_request(Type, Host, Port, Node,"/secret/", "dummy", "dummy",
+ [{statuscode, 401}]),
+
+ %% Nested secret/top_secret OK! ["Aladdin:open sesame"]
+ auth_request(Type, Host, Port, Node, "/secret/top_secret/", "Aladdin",
+ "AladdinPassword", [{statuscode, 200}]),
+ %% Authentication still required!
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET /open/ "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET /secret/ "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /secret/top_secret/ "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]).
+
+
+%%-------------------------------------------------------------------------
+%% What to test here:
+%%
+%% /open - plain, require user one Aladdin
+%% /secret - plain, require group group1 group2
+%% /secret/top_secret - plain, require group group3
+%% /dets_open - dets, require user one Aladdin
+%% /dets_secret - dets, require group group1 group2
+%% /dets_secret/top_secret - dets, require group group3
+%% /mnesia_open/ - mnesia, require user one Aladdin
+%% /mnesia_secret/ - mnesia, require group group1 group2
+%% /mnesia_secret/top_secret/ - mnesia, require group group3
+auth_api(ServerRoot, AuthStoreType, Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET / HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ auth_request(Type, Host, Port, Node, "/", "one", "WrongPassword",
+ [{statuscode, 200}]),
+
+ %% Make sure Authenticate header is received even the second time
+ %% we try a incorrect password! Otherwise a browser client will hang!
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+ "dummy", "WrongPassword", [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+ "dummy", "WrongPassword", [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+
+ %% Change the password to DummyPassword then try to add a user
+ %% Get an error and set it to NoPassword
+ ok = update_password(Node, ServerRoot, Host, Port, AuthStoreType ++
+ "open", "NoPassword", "DummyPassword"),
+ {error,bad_password} =
+ add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "one",
+ "onePassword", []),
+ ok = update_password(Node, ServerRoot, Host, Port, AuthStoreType ++"open",
+ "DummyPassword", "NoPassword"),
+
+ %% Test /*open, require user one Aladdin
+ remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ "open"),
+
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+ "one", "onePassword", [{statuscode, 401}]),
+
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+ "two", "twoPassword", [{statuscode, 401}]),
+
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+ "Aladdin", "onePassword", [{statuscode, 401}]),
+
+ add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "one",
+ "onePassword", []),
+ add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "two",
+ "twoPassword", []),
+ add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "Aladdin",
+ "AladdinPassword", []),
+
+ {ok, [_|_]} = list_users(Node, ServerRoot, Host, Port,
+ AuthStoreType++"open"),
+ auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/",
+ "one", "WrongPassword", [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/",
+ "one", "onePassword", [{statuscode, 200}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+ "two", "twoPassword", [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/",
+ "Aladdin", "WrongPassword", [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+ "Aladdin", "AladdinPassword", [{statuscode, 200}]),
+
+ remove_users(Node, ServerRoot, Host, Port, AuthStoreType++"open"),
+ {ok, []} = list_users(Node, ServerRoot, Host, Port,
+ AuthStoreType++"open"),
+
+ %% Phase 2
+ remove_users(Node, ServerRoot, Host, Port, AuthStoreType++"secret"),
+ {ok, []} = list_users(Node, ServerRoot, Host, Port, AuthStoreType ++
+ "secret"),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+ "one", "onePassword", [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+ "two", "twoPassword", [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "secret/",
+ "three", "threePassword", [{statuscode, 401}]),
+ add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret", "one",
+ "onePassword",
+ []),
+ add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret",
+ "two", "twoPassword", []),
+ add_user(Node, ServerRoot, Port, AuthStoreType++"secret", "Aladdin",
+ "AladdinPassword",[]),
+ add_group_member(Node, ServerRoot, Port, AuthStoreType ++ "secret",
+ "one", "group1"),
+ add_group_member(Node, ServerRoot, Port, AuthStoreType ++ "secret",
+ "two", "group1"),
+ add_group_member(Node, ServerRoot, Port, AuthStoreType ++
+ "secret", "Aladdin", "group2"),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+ "one", "onePassword", [{statuscode, 200}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+ "two", "twoPassword", [{statuscode, 200}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+ "Aladdin", "AladdinPassword", [{statuscode, 200}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+ "three", "threePassword", [{statuscode, 401}]),
+ remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ "secret"),
+ {ok, []} = list_users(Node, ServerRoot, Host, Port,
+ AuthStoreType ++ "secret"),
+ remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++ "secret"),
+ Directory = filename:join([ServerRoot, "htdocs", AuthStoreType ++
+ "secret"]),
+ {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory),
+
+ %% Phase 3
+ remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++
+ "secret/top_secret"),
+ remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++
+ "secret/top_secret"),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+ "secret/top_secret/",
+ "three", "threePassword", [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+ "secret/top_secret/", "two", "twoPassword",
+ [{statuscode, 401}]),
+ add_user(Node, ServerRoot, Port, AuthStoreType ++
+ "secret/top_secret","three",
+ "threePassword",[]),
+ add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret/top_secret",
+ "two","twoPassword", []),
+ add_group_member(Node, ServerRoot, Port, AuthStoreType ++
+ "secret/top_secret",
+ "three", "group3"),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+ "secret/top_secret/", "three", "threePassword",
+ [{statuscode, 200}]),
+ auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+ "secret/top_secret/", "two", "twoPassword",
+ [{statuscode, 401}]),
+ add_group_member(Node, ServerRoot, Port, AuthStoreType ++
+ "secret/top_secret",
+ "two", "group3"),
+ auth_request(Type,Host,Port,Node,"/" ++ AuthStoreType ++
+ "secret/top_secret/",
+ "two", "twoPassword", [{statuscode, 200}]),
+ remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++
+ "secret/top_secret"),
+ {ok, []} = list_users(Node, ServerRoot, Host, Port,
+ AuthStoreType ++ "secret/top_secret"),
+ remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++
+ "secret/top_secret"),
+ Directory2 = filename:join([ServerRoot, "htdocs",
+ AuthStoreType ++ "secret/top_secret"]),
+ {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory2),
+ auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++
+ "secret/top_secret/", "two", "twoPassword",
+ [{statuscode, 401}]),
+ auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++
+ "secret/top_secret/","three", "threePassword",
+ [{statuscode, 401}]).
+
+%%--------------------------------------------------------------------------
+auth_mnesia_api(_Type, Port, _Host, _Node) ->
+ %% Create three groups:
+ %% group1 : one Aladdin
+ %% group2 : two
+ %% group3 : three
+ mod_auth_mnesia:store_user("one", "onePassword", Port,
+ "/mnesia_open", ""),
+ mod_auth_mnesia:store_user("Aladdin", "AladdinPassword", Port,
+ "/mnesia_open", ""),
+ mod_auth_mnesia:store_user("two", "twoPassword", Port,
+ "/mnesia_open", ""),
+ mod_auth_mnesia:store_user("three", "threePassword", Port,
+ "/mnesia_open", ""),
+ Users = mod_auth_mnesia:list_users(Port, "/mnesia_open"),
+
+ ok = check_lists_members(Users,["Aladdin","one","two","three"]),
+
+ true = mod_auth_mnesia:store_group_member("group1", "one", Port,
+ "/mnesia_open", ""),
+ true = mod_auth_mnesia:store_group_member("group1","Aladdin", Port,
+ "/mnesia_open", ""),
+ true = mod_auth_mnesia:store_group_member("group2","two", Port,
+ "/mnesia_open", ""),
+ true = mod_auth_mnesia:store_group_member("group3","three", Port,
+ "/mnesia_open", ""),
+ %% Check that all three created groups exist.
+ Groups = mod_auth_mnesia:list_groups(Port, "/mnesia_open"),
+ ok = check_lists_members(Groups, ["group1","group2","group3"]),
+
+ %% Check that the members of all groups are correct.
+ Group1 = mod_auth_mnesia:list_group_members("group1", Port,
+ "/mnesia_open"),
+ ok = check_lists_members(Group1,["one","Aladdin"]),
+ {ok,["two"]} = mod_auth_mnesia:list_group_members("group2", Port,
+ "/mnesia_open"),
+
+ {ok,["three"]} = mod_auth_mnesia:list_group_members("group3", Port,
+ "/mnesia_open"),
+
+ %% Delete user 'one' from group one and check that he was removed
+ %% correctly.
+ true = mod_auth_mnesia:remove_group_member("group1", "one", Port,
+ "/mnesia_open", ""),
+ {ok,["Aladdin"]} = mod_auth_mnesia:list_group_members("group1", Port,
+ "/mnesia_open"),
+
+ %% Remove group1 and check that the group was removed correctly.
+ true = mod_auth_mnesia:remove_group("group1", Port, "/mnesia_open", ""),
+ Groups_1 = mod_auth_mnesia:list_groups(Port, "/mnesia_open"),
+ ok = check_lists_members(Groups_1,["group2","group3"]),
+
+ %% Check that the other users still exist in their groups.
+ Users_1 = mod_auth_mnesia:list_users(Port, "/mnesia_open"),
+ ok = check_lists_members(Users_1,["Aladdin","one","two","three"]),
+ {ok,["two"]} = mod_auth_mnesia:list_group_members("group2", Port,
+ "/mnesia_open"),
+ {ok,["three"]} = mod_auth_mnesia:list_group_members("group3", Port,
+ "/mnesia_open"),
+
+ %% Remove the remaining groups/users and check that all
+ %% users/groups are removed.
+ true = mod_auth_mnesia:remove_group("group2", Port, "/mnesia_open", ""),
+ true = mod_auth_mnesia:remove_group("group3", Port, "/mnesia_open", ""),
+ {ok, []} = mod_auth_mnesia:list_groups(Port, "/mnesia_open"),
+ true = mod_auth_mnesia:remove_user("one", Port, "/mnesia_open", ""),
+ true = mod_auth_mnesia:remove_user("Aladdin", Port, "/mnesia_open", ""),
+ true = mod_auth_mnesia:remove_user("two", Port, "/mnesia_open", ""),
+ true = mod_auth_mnesia:remove_user("three", Port, "/mnesia_open", ""),
+ {ok, []} = mod_auth_mnesia:list_users(Port, "/mnesia_open"),
+ ok.
+%%--------------------------------------------------------------------------
+htaccess(Type, Port, Host, Node) ->
+ %% Control that authentication required!
+ %% Control that the pages that shall be
+ %% authenticated really need authenticatin
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /ht/open/ HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /ht/secret/ HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /ht/secret/top_secret/ "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+
+ %% Make sure Authenticate header is received even the second time
+ %% we try a incorrect password! Otherwise a browser client will hang!
+ auth_request(Type, Host, Port, Node,"/ht/open/",
+ "dummy", "WrongPassword", [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+ auth_request(Type, Host, Port, Node,"/ht/open/",
+ "dummy", "WrongPassword", [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+
+ %% Control that not just the first user in the list is valid
+ %% Control the first user
+ %% Authennticating ["one:OnePassword" user first in user list]
+ auth_request(Type, Host, Port, Node, "/ht/open/dummy.html", "one",
+ "OnePassword", [{statuscode, 200}]),
+
+ %% Control the second user
+ %% Authentication OK and a directory listing is supplied!
+ %% ["Aladdin:open sesame" user second in user list]
+ auth_request(Type, Host, Port, Node, "/ht/open/","Aladdin",
+ "AladdinPassword", [{statuscode, 200}]),
+
+ %% Contro that bad passwords and userids get a good denial
+ %% User correct but wrong password! ["one:one" user first in user list]
+ auth_request(Type, Host, Port, Node, "/ht/open/", "one", "one",
+ [{statuscode, 401}]),
+ %% Neither user or password correct! ["dummy:dummy"]
+ auth_request(Type, Host, Port, Node, "/ht/open/", "dummy", "dummy",
+ [{statuscode, 401}]),
+
+ %% Control that authetication still works, even if its a member in a group
+ %% Authentication OK! ["two:TwoPassword" user in first group]
+ auth_request(Type, Host, Port, Node, "/ht/secret/dummy.html", "two",
+ "TwoPassword", [{statuscode, 200}]),
+
+ %% Authentication OK and a directory listing is supplied!
+ %% ["three:ThreePassword" user in second group]
+ auth_request(Type, Host, Port, Node,"/ht/secret/", "three",
+ "ThreePassword", [{statuscode, 200}]),
+
+ %% Deny users with bad passwords even if the user is a group member
+ %% User correct but wrong password! ["two:two" user in first group]
+ auth_request(Type, Host, Port, Node, "/ht/secret/", "two", "two",
+ [{statuscode, 401}]),
+ %% Neither user or password correct! ["dummy:dummy"]
+ auth_request(Type, Host, Port, Node,"/ht/secret/", "dummy", "dummy",
+ [{statuscode, 401}]),
+
+ %% control that we deny the users that are in subnet above the allowed
+ auth_request(Type, Host, Port, Node,"/ht/blocknet/dummy.html", "four",
+ "FourPassword", [{statuscode, 403}]),
+ %% Control that we only applies the rules to the right methods
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "HEAD /ht/blocknet/dummy.html"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ %% Control that the rerquire directive can be overrideen
+ auth_request(Type, Host, Port, Node,
+ "/ht/secret/top_secret/", "Aladdin", "AladdinPassword",
+ [{statuscode, 401}]),
+
+ %% Authentication still required!
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET /ht/open/ "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /ht/secret/ HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /ht/secret/top_secret/ "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {version, "HTTP/1.0"},
+ {header, "WWW-Authenticate"}]).
+%%--------------------------------------------------------------------
+cgi(Type, Port, Host, Node) ->
+ {Script, Script2, Script3} =
+ case test_server:os_type() of
+ {win32, _} ->
+ {"printenv.bat", "printenv.sh", "cgi_echo.exe"};
+ _ ->
+ {"printenv.sh", "printenv.bat", "cgi_echo"}
+ end,
+
+ %% The length (> 100) is intentional
+ ok = httpd_test_lib:
+ verify_request(Type, Host, Port, Node,
+ "POST /cgi-bin/" ++ Script3 ++
+ " HTTP/1.0\r\n"
+ "Content-Length:100 \r\n\r\n "
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ " \r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"},
+ {header, "content-type", "text/plain"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/not_there "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},{statuscode, 500},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/"++ Script ++
+ "?Nisse:kkk?sss/lll HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /cgi-bin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /htbin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /htbin/not_there "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},{statuscode, 500},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /htbin/"++ Script ++
+ "?Nisse:kkk?sss/lll HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /htbin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /htbin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ %% Execute an existing, but bad CGI script..
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /htbin/"++ Script2 ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /cgi-bin/"++ Script2 ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},
+ {version, "HTTP/1.0"}]),
+ ok.
+
+%%--------------------------------------------------------------------
+esi(Type, Port, Host, Node) ->
+ %% Check "ErlScriptAlias" and "EvalScriptAlias" directives
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /eval?httpd_example:print(\"Hi!\")"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /eval?not_allowed:print(\"Hi!\")"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 403},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /eval?httpd_example:undef(\"Hi!\")"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 500},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 400},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:get "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:"
+ "get?input=4711"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:"
+ "post HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/not_allowed:post "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 403},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:undef "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example/yahoo"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 302},
+ {version, "HTTP/1.0"}]),
+ ok.
+%%--------------------------------------------------------------------
+get(Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /index.html HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /fsize.shtml HTTP/1.1\r\nHost:"
+ ++ Host ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /fsize.shtml HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type"},
+ {header, "Server"},
+ {header, "Date"},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /secret/dummy.html "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 401},
+ {header, "WWW-Authenticate"},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /index.html HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Server"},
+ {header, "Date"},
+ {header, "Content-Type",
+ "text/html"},
+ {version, "HTTP/1.0"}]),
+ ok.
+
+%%--------------------------------------------------------------------
+head(Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "HEAD /index.html HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok.
+%%--------------------------------------------------------------------
+all(Type, Port, Host, Node) ->
+ actions(Type, Port, Host, Node),
+ alias(Type, Port, Host, Node),
+ auth(Type, Port, Host, Node),
+ cgi(Type, Port, Host, Node),
+ esi(Type, Port, Host, Node),
+ get(Type, Port, Host, Node),
+ head(Type, Port, Host, Node),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+auth_request(Type, Host, Port, Node, URI, User, Passwd, Expect) ->
+ Req = ["GET ", URI, " HTTP/1.0\r\n",
+ "Authorization: Basic ",
+ base64:encode_to_string(User++":"++Passwd),
+ "\r\n\r\n"],
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ lists:flatten(Req),
+ [{version, "HTTP/1.0"} | Expect]).
+
+remove_users(Node, ServerRoot, Host, Port, Dir) ->
+ %% List users, delete them, and make sure they are gone.
+ case list_users(Node, ServerRoot, Host, Port, Dir) of
+ {ok, Users} ->
+ lists:foreach(fun(User) ->
+ delete_user(Node, ServerRoot, Host,
+ Port, Dir, User)
+ end,
+ Users),
+ {ok, []} = list_users(Node, ServerRoot, Host, Port, Dir);
+ _ ->
+ ok
+ end.
+
+add_user(Node, Root, Port, Dir, User, Password, UserData) ->
+ Addr = undefined,
+ Directory = filename:join([Root, "htdocs", Dir]),
+ rpc:call(Node, mod_auth, add_user,
+ [User, Password, UserData, Addr, Port, Directory]).
+
+delete_user(Node, Root, _Host, Port, Dir, User) ->
+ Addr = undefined,
+ Directory = filename:join([Root, "htdocs", Dir]),
+ rpc:call(Node, mod_auth, delete_user, [User, Addr, Port, Directory]).
+
+list_users(Node, Root, _Host, Port, Dir) ->
+ Addr = undefined,
+ Directory = filename:join([Root, "htdocs", Dir]),
+ rpc:call(Node, mod_auth, list_users, [Addr, Port, Directory]).
+
+receive_security_event(Event, Node, Port) ->
+ io:format(user, "~w:receive_security_event -> entry with"
+ "~n Event: ~p"
+ "~n Node: ~p"
+ "~n Port: ~p"
+ "~n", [?MODULE, Event, Node, Port]),
+ receive
+ Event ->
+ ok;
+ {'EXIT', _, _} ->
+ receive_security_event(Event, Node, Port);
+ Other ->
+ test_server:fail({unexpected_event,
+ {expected, Event}, {received, Other}})
+ after 5000 ->
+ test_server:fail(no_event_recived)
+
+ end.
+
+list_blocked_users(Node,Port) ->
+ Addr = undefined, % Assumed to be on the same host
+ rpc:call(Node, mod_security, list_blocked_users, [Addr,Port]).
+
+list_blocked_users(Node,Port,Dir) ->
+ Addr = undefined, % Assumed to be on the same host
+ rpc:call(Node, mod_security, list_blocked_users, [Addr,Port,Dir]).
+
+block_user(Node,User,Port,Dir,Sec) ->
+ Addr = undefined, % Assumed to be on the same host
+ rpc:call(Node, mod_security, block_user, [User, Addr, Port, Dir, Sec]).
+
+unblock_user(Node,User,Port,Dir) ->
+ Addr = undefined, % Assumed to be on the same host
+ rpc:call(Node, mod_security, unblock_user, [User, Addr, Port, Dir]).
+
+list_auth_users(Node,Port) ->
+ Addr = undefined, % Assumed to be on the same host
+ rpc:call(Node, mod_security, list_auth_users, [Addr,Port]).
+
+list_auth_users(Node,Port,Dir) ->
+ Addr = undefined, % Assumed to be on the same host
+ rpc:call(Node, mod_security, list_auth_users, [Addr,Port,Dir]).
+
+update_password(Node, ServerRoot, _Address, Port, Dir, Old, New)->
+ Directory = filename:join([ServerRoot, "htdocs", Dir]),
+ rpc:call(Node, mod_auth, update_password,
+ [undefined, Port, Directory, Old, New, New]).
+
+remove_groups(Node, ServerRoot, Host, Port, Dir) ->
+ Directory = filename:join([ServerRoot, "htdocs", Dir]),
+ {ok, Groups} = list_groups(Node, ServerRoot, Host, Port, Directory),
+ lists:foreach(fun(Group) ->
+ delete_group(Node, Group, Port, Directory)
+ end,
+ Groups),
+ {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory),
+ ok.
+
+delete_group(Node, Group, Port, Dir) ->
+ Addr = undefined,
+ rpc:call(Node, mod_auth, delete_group, [Group, Addr, Port, Dir]).
+
+list_groups(Node, _, _, Port, Dir) ->
+ Addr = undefined,
+ rpc:call(Node, mod_auth, list_groups, [Addr, Port, Dir]).
+
+add_group_member(Node, ServerRoot, Port, Dir, User, Group) ->
+ Addr = undefined,
+ rpc:call(Node, mod_auth, add_group_member, [Group, User, Addr, Port,
+ filename:join(
+ [ServerRoot,
+ "htdocs",Dir])]).
+event(What, Port, Dir, Data) ->
+ Msg = {event, What, Port, Dir, Data},
+ case global:whereis_name(mod_security_test) of
+ undefined ->
+ ok;
+ _Pid ->
+ global:send(mod_security_test, Msg)
+ end.
+
+ssl_password_cb() ->
+ "dummy-ssl-password".
+
+check_lists_members({ok,L},L) ->
+ ok;
+check_lists_members({ok,L1},L2) ->
+ check_lists_members1(lists:sort(L1),lists:sort(L2));
+check_lists_members(Error,_L) ->
+ Error.
+
+check_lists_members1(L,L) ->
+ ok;
+check_lists_members1(L1,L2) ->
+ {error,{lists_not_equal,L1,L2}}.