1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% 21 22-module(httpd_mod). 23 24-include_lib("common_test/include/ct.hrl"). 25 26%% General testcases bodies called from httpd_SUITE 27-export([alias/4, actions/4, security/5, auth/4, auth_api/6, 28 auth_mnesia_api/4, htaccess/4, 29 cgi/4, esi/4, get/4, head/4, all/4]). 30 31%% Help functions 32-export([event/4, ssl_password_cb/0]). 33 34%% Seconds before successful auths timeout. 35-define(AUTH_TIMEOUT,5). 36 37 38%%------------------------------------------------------------------------- 39%% Test cases starts here. 40%%------------------------------------------------------------------------- 41alias(Type, Port, Host, Node) -> 42 %% This is very crude, but... 43 Opts = [], 44 ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, 45 "GET /pics/icon.sheet.gif " 46 "HTTP/1.0\r\n\r\n", 47 [{statuscode, 200}, 48 {header, "Content-Type","image/gif"}, 49 {header, "Server"}, 50 {header, "Date"}, 51 {version, "HTTP/1.0"}]), 52 53 ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, 54 "GET / HTTP/1.0\r\n\r\n", 55 [{statuscode, 200}, 56 {header, "Content-Type","text/html"}, 57 {header, "Server"}, 58 {header, "Date"}, 59 {version, "HTTP/1.0"}]), 60 61 ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, 62 "GET /misc/ HTTP/1.0\r\n\r\n", 63 [{statuscode, 200}, 64 {header, "Content-Type","text/html"}, 65 {header, "Server"}, 66 {header, "Date"}, 67 {version, "HTTP/1.0"}]), 68 69 %% Check redirection if trailing slash is missing. 70 ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, 71 "GET /misc HTTP/1.0\r\n\r\n", 72 [{statuscode, 301}, 73 {header, "Location"}, 74 {header, "Content-Type","text/html"}, 75 {version, "HTTP/1.0"}]). 76 77%%------------------------------------------------------------------------- 78actions(Type, Port, Host, Node) -> 79 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 80 "HEAD / HTTP/1.0\r\n\r\n", 81 [{statuscode, 200}, 82 {version, "HTTP/1.0"}]). 83 84 85%%------------------------------------------------------------------------- 86security(ServerRoot, Type, Port, Host, Node) -> 87 88 global:register_name(mod_security_test, self()), % Receive events 89 90 ct:sleep(5000), 91 92 OpenDir = filename:join([ServerRoot, "htdocs", "open"]), 93 94 %% Test blocking / unblocking of users. 95 96 %% /open, require user one Aladdin 97 98 remove_users(Node, ServerRoot, Host, Port, "open"), 99 100 auth_request(Type, Host, Port, Node, "/open/", "one", "onePassword", 101 [{statuscode, 401}]), 102 103 receive_security_event({event, auth_fail, Port, OpenDir, 104 [{user, "one"}, {password, "onePassword"}]}, 105 Node, Port), 106 107 auth_request(Type,Host,Port,Node,"/open/", "two", "twoPassword", 108 [{statuscode, 401}]), 109 110 receive_security_event({event, auth_fail, Port, OpenDir, 111 [{user, "two"}, {password, "twoPassword"}]}, 112 Node, Port), 113 auth_request(Type, Host, Port, Node,"/open/", "Aladdin", 114 "AladdinPassword", [{statuscode, 401}]), 115 116 receive_security_event({event, auth_fail, Port, OpenDir, 117 [{user, "Aladdin"}, 118 {password, "AladdinPassword"}]}, 119 Node, Port), 120 add_user(Node, ServerRoot, Port, "open", "one", "onePassword", []), 121 122 add_user(Node, ServerRoot, Port, "open", "two", "twoPassword", []), 123 124 auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", 125 [{statuscode, 401}]), 126 receive_security_event({event, auth_fail, Port, OpenDir, 127 [{user, "one"}, {password, "WrongPassword"}]}, 128 Node, Port), 129 auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", 130 [{statuscode, 401}]), 131 132 receive_security_event({event, auth_fail, Port, OpenDir, 133 [{user, "one"}, {password, "WrongPassword"}]}, 134 Node, Port), 135 receive_security_event({event, user_block, Port, OpenDir, 136 [{user, "one"}]}, Node, Port), 137 138 global:unregister_name(mod_security_test), % No more events. 139 140 auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", 141 [{statuscode, 401}]), 142 auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword", 143 [{statuscode, 403}]), 144 145 %% User "one" should be blocked now.. 146 case list_blocked_users(Node, Port) of 147 [{"one",_, Port, OpenDir,_}] -> 148 ok; 149 Blocked -> 150 exit({unexpected_blocked, Blocked}) 151 end, 152 153 [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node, Port, OpenDir), 154 155 true = unblock_user(Node, "one", Port, OpenDir), 156 %% User "one" should not be blocked any more. 157 158 [] = list_blocked_users(Node, Port), 159 160 auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword", 161 [{statuscode, 200}]), 162 163 164 165 %% Test list_auth_users & auth_timeout 166 ["one"] = list_auth_users(Node, Port), 167 168 auth_request(Type, Host, Port, Node,"/open/", "two", "onePassword", 169 [{statuscode, 401}]), 170 ["one"] = list_auth_users(Node, Port), 171 172 ["one"] = list_auth_users(Node, Port, OpenDir), 173 174 auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword", 175 [{statuscode, 401}]), 176 177 ["one"] = list_auth_users(Node, Port), 178 179 ["one"] = list_auth_users(Node, Port, OpenDir), 180 181 %% Wait for successful auth to timeout. 182 ct:sleep(?AUTH_TIMEOUT*1001), 183 184 [] = list_auth_users(Node, Port), 185 186 187 [] = list_auth_users(Node, Port, OpenDir), 188 189 %% "two" is blocked. 190 191 true = unblock_user(Node, "two", Port, OpenDir), 192 %% Test explicit blocking. Block user 'two'. 193 194 [] = list_blocked_users(Node,Port,OpenDir), 195 196 true = block_user(Node, "two", Port, OpenDir, 10), 197 auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword", 198 [{statuscode, 401}]). 199 200%%------------------------------------------------------------------------- 201auth(Type, Port, Host, Node) -> 202 203 %% Authentication required! 204 ok = httpd_test_lib:verify_request(Type,Host,Port,Node, 205 "GET /open/ HTTP/1.0\r\n\r\n", 206 [{statuscode, 401}, 207 {version, "HTTP/1.0"}, 208 {header, "WWW-Authenticate"}]), 209 ok = httpd_test_lib:verify_request(Type,Host,Port,Node, 210 "GET /secret/ HTTP/1.0\r\n\r\n", 211 [{statuscode, 401}, 212 {version, "HTTP/1.0"}, 213 {header, "WWW-Authenticate"}]), 214 ok = httpd_test_lib:verify_request(Type,Host,Port,Node, 215 "GET /secret/top_secret/" 216 " HTTP/1.0\r\n\r\n", 217 [{statuscode, 401}, 218 {version, "HTTP/1.0"}, 219 {header, "WWW-Authenticate"}]), 220 221 %% Authentication OK! ["one:OnePassword" user first in user list] 222 auth_request(Type, Host, Port, Node, "/open/dummy.html", "one", 223 "onePassword", [{statuscode, 200}]), 224 %% Authentication OK and a directory listing is supplied! 225 %% ["Aladdin:open sesame" user second in user list] 226 auth_request(Type, Host, Port, Node, "/open/","Aladdin", 227 "AladdinPassword", [{statuscode, 200}]), 228 229 %% User correct but wrong password! ["one:one" user first in user list] 230 auth_request(Type, Host, Port, Node, "/open/", "one", "one", 231 [{statuscode, 401},{header, "WWW-Authenticate"}]), 232 %% Make sure Authenticate header is received even the second time 233 %% we try a incorrect password! Otherwise a browser client will hang! 234 auth_request(Type, Host, Port, Node, "/open/", "one", "one", 235 [{statuscode, 401},{header, "WWW-Authenticate"}]), 236 237 %% Neither user or password correct! ["dummy:dummy"] 238 auth_request(Type, Host, Port, Node, "/open/", "dummy", "dummy", 239 [{statuscode, 401}]), 240 241 %% Authentication OK! ["two:TwoPassword" user in first group] 242 auth_request(Type, Host, Port, Node, "/secret/dummy.html", "two", 243 "twoPassword", [{statuscode, 200}]), 244 %% Authentication OK and a directory listing is supplied! 245 %% ["three:ThreePassword" user in second group] 246 auth_request(Type, Host, Port, Node,"/secret/", "three", 247 "threePassword", [{statuscode, 200}]), 248 249 %% User correct but wrong password! ["two:two" user in first group] 250 auth_request(Type, Host, Port, Node, "/secret/", "two", "two", 251 [{statuscode, 401}]), 252 %% Neither user or password correct! ["dummy:dummy"] 253 auth_request(Type, Host, Port, Node,"/secret/", "dummy", "dummy", 254 [{statuscode, 401}]), 255 256 %% Nested secret/top_secret OK! ["Aladdin:open sesame"] 257 auth_request(Type, Host, Port, Node, "/secret/top_secret/", "Aladdin", 258 "AladdinPassword", [{statuscode, 200}]), 259 %% Authentication still required! 260 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET /open/ " 261 "HTTP/1.0\r\n\r\n", 262 [{statuscode, 401}, 263 {version, "HTTP/1.0"}, 264 {header, "WWW-Authenticate"}]), 265 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET /secret/ " 266 "HTTP/1.0\r\n\r\n", 267 [{statuscode, 401}, 268 {version, "HTTP/1.0"}, 269 {header, "WWW-Authenticate"}]), 270 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 271 "GET /secret/top_secret/ " 272 "HTTP/1.0\r\n\r\n", 273 [{statuscode, 401}, 274 {version, "HTTP/1.0"}, 275 {header, "WWW-Authenticate"}]). 276 277 278%%------------------------------------------------------------------------- 279%% What to test here: 280%% 281%% /open - plain, require user one Aladdin 282%% /secret - plain, require group group1 group2 283%% /secret/top_secret - plain, require group group3 284%% /dets_open - dets, require user one Aladdin 285%% /dets_secret - dets, require group group1 group2 286%% /dets_secret/top_secret - dets, require group group3 287%% /mnesia_open/ - mnesia, require user one Aladdin 288%% /mnesia_secret/ - mnesia, require group group1 group2 289%% /mnesia_secret/top_secret/ - mnesia, require group group3 290auth_api(ServerRoot, AuthStoreType, Type, Port, Host, Node) -> 291 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 292 "GET / HTTP/1.0\r\n\r\n", 293 [{statuscode, 200}, 294 {version, "HTTP/1.0"}]), 295 auth_request(Type, Host, Port, Node, "/", "one", "WrongPassword", 296 [{statuscode, 200}]), 297 298 %% Make sure Authenticate header is received even the second time 299 %% we try a incorrect password! Otherwise a browser client will hang! 300 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/", 301 "dummy", "WrongPassword", [{statuscode, 401}, 302 {header, "WWW-Authenticate"}]), 303 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/", 304 "dummy", "WrongPassword", [{statuscode, 401}, 305 {header, "WWW-Authenticate"}]), 306 307 %% Change the password to DummyPassword then try to add a user 308 %% Get an error and set it to NoPassword 309 ok = update_password(Node, ServerRoot, Host, Port, AuthStoreType ++ 310 "open", "NoPassword", "DummyPassword"), 311 {error,bad_password} = 312 add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "one", 313 "onePassword", []), 314 ok = update_password(Node, ServerRoot, Host, Port, AuthStoreType ++"open", 315 "DummyPassword", "NoPassword"), 316 317 %% Test /*open, require user one Aladdin 318 remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ "open"), 319 320 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/", 321 "one", "onePassword", [{statuscode, 401}]), 322 323 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/", 324 "two", "twoPassword", [{statuscode, 401}]), 325 326 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/", 327 "Aladdin", "onePassword", [{statuscode, 401}]), 328 329 add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "one", 330 "onePassword", []), 331 add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "two", 332 "twoPassword", []), 333 add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "Aladdin", 334 "AladdinPassword", []), 335 336 {ok, [_|_]} = list_users(Node, ServerRoot, Host, Port, 337 AuthStoreType++"open"), 338 auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/", 339 "one", "WrongPassword", [{statuscode, 401}]), 340 auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/", 341 "one", "onePassword", [{statuscode, 200}]), 342 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/", 343 "two", "twoPassword", [{statuscode, 401}]), 344 auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/", 345 "Aladdin", "WrongPassword", [{statuscode, 401}]), 346 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/", 347 "Aladdin", "AladdinPassword", [{statuscode, 200}]), 348 349 remove_users(Node, ServerRoot, Host, Port, AuthStoreType++"open"), 350 {ok, []} = list_users(Node, ServerRoot, Host, Port, 351 AuthStoreType++"open"), 352 353 %% Phase 2 354 remove_users(Node, ServerRoot, Host, Port, AuthStoreType++"secret"), 355 {ok, []} = list_users(Node, ServerRoot, Host, Port, AuthStoreType ++ 356 "secret"), 357 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/", 358 "one", "onePassword", [{statuscode, 401}]), 359 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/", 360 "two", "twoPassword", [{statuscode, 401}]), 361 auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "secret/", 362 "three", "threePassword", [{statuscode, 401}]), 363 add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret", "one", 364 "onePassword", 365 []), 366 add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret", 367 "two", "twoPassword", []), 368 add_user(Node, ServerRoot, Port, AuthStoreType++"secret", "Aladdin", 369 "AladdinPassword",[]), 370 add_group_member(Node, ServerRoot, Port, AuthStoreType ++ "secret", 371 "one", "group1"), 372 add_group_member(Node, ServerRoot, Port, AuthStoreType ++ "secret", 373 "two", "group1"), 374 add_group_member(Node, ServerRoot, Port, AuthStoreType ++ 375 "secret", "Aladdin", "group2"), 376 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/", 377 "one", "onePassword", [{statuscode, 200}]), 378 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/", 379 "two", "twoPassword", [{statuscode, 200}]), 380 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/", 381 "Aladdin", "AladdinPassword", [{statuscode, 200}]), 382 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/", 383 "three", "threePassword", [{statuscode, 401}]), 384 remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ "secret"), 385 {ok, []} = list_users(Node, ServerRoot, Host, Port, 386 AuthStoreType ++ "secret"), 387 remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++ "secret"), 388 Directory = filename:join([ServerRoot, "htdocs", AuthStoreType ++ 389 "secret"]), 390 {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory), 391 392 %% Phase 3 393 remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ 394 "secret/top_secret"), 395 remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++ 396 "secret/top_secret"), 397 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ 398 "secret/top_secret/", 399 "three", "threePassword", [{statuscode, 401}]), 400 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ 401 "secret/top_secret/", "two", "twoPassword", 402 [{statuscode, 401}]), 403 add_user(Node, ServerRoot, Port, AuthStoreType ++ 404 "secret/top_secret","three", 405 "threePassword",[]), 406 add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret/top_secret", 407 "two","twoPassword", []), 408 add_group_member(Node, ServerRoot, Port, AuthStoreType ++ 409 "secret/top_secret", 410 "three", "group3"), 411 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ 412 "secret/top_secret/", "three", "threePassword", 413 [{statuscode, 200}]), 414 auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ 415 "secret/top_secret/", "two", "twoPassword", 416 [{statuscode, 401}]), 417 add_group_member(Node, ServerRoot, Port, AuthStoreType ++ 418 "secret/top_secret", 419 "two", "group3"), 420 auth_request(Type,Host,Port,Node,"/" ++ AuthStoreType ++ 421 "secret/top_secret/", 422 "two", "twoPassword", [{statuscode, 200}]), 423 remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ 424 "secret/top_secret"), 425 {ok, []} = list_users(Node, ServerRoot, Host, Port, 426 AuthStoreType ++ "secret/top_secret"), 427 remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++ 428 "secret/top_secret"), 429 Directory2 = filename:join([ServerRoot, "htdocs", 430 AuthStoreType ++ "secret/top_secret"]), 431 {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory2), 432 auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ 433 "secret/top_secret/", "two", "twoPassword", 434 [{statuscode, 401}]), 435 auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ 436 "secret/top_secret/","three", "threePassword", 437 [{statuscode, 401}]). 438 439%%-------------------------------------------------------------------------- 440auth_mnesia_api(_Type, Port, _Host, _Node) -> 441 %% Create three groups: 442 %% group1 : one Aladdin 443 %% group2 : two 444 %% group3 : three 445 mod_auth_mnesia:store_user("one", "onePassword", Port, 446 "/mnesia_open", ""), 447 mod_auth_mnesia:store_user("Aladdin", "AladdinPassword", Port, 448 "/mnesia_open", ""), 449 mod_auth_mnesia:store_user("two", "twoPassword", Port, 450 "/mnesia_open", ""), 451 mod_auth_mnesia:store_user("three", "threePassword", Port, 452 "/mnesia_open", ""), 453 Users = mod_auth_mnesia:list_users(Port, "/mnesia_open"), 454 455 ok = check_lists_members(Users,["Aladdin","one","two","three"]), 456 457 true = mod_auth_mnesia:store_group_member("group1", "one", Port, 458 "/mnesia_open", ""), 459 true = mod_auth_mnesia:store_group_member("group1","Aladdin", Port, 460 "/mnesia_open", ""), 461 true = mod_auth_mnesia:store_group_member("group2","two", Port, 462 "/mnesia_open", ""), 463 true = mod_auth_mnesia:store_group_member("group3","three", Port, 464 "/mnesia_open", ""), 465 %% Check that all three created groups exist. 466 Groups = mod_auth_mnesia:list_groups(Port, "/mnesia_open"), 467 ok = check_lists_members(Groups, ["group1","group2","group3"]), 468 469 %% Check that the members of all groups are correct. 470 Group1 = mod_auth_mnesia:list_group_members("group1", Port, 471 "/mnesia_open"), 472 ok = check_lists_members(Group1,["one","Aladdin"]), 473 {ok,["two"]} = mod_auth_mnesia:list_group_members("group2", Port, 474 "/mnesia_open"), 475 476 {ok,["three"]} = mod_auth_mnesia:list_group_members("group3", Port, 477 "/mnesia_open"), 478 479 %% Delete user 'one' from group one and check that he was removed 480 %% correctly. 481 true = mod_auth_mnesia:remove_group_member("group1", "one", Port, 482 "/mnesia_open", ""), 483 {ok,["Aladdin"]} = mod_auth_mnesia:list_group_members("group1", Port, 484 "/mnesia_open"), 485 486 %% Remove group1 and check that the group was removed correctly. 487 true = mod_auth_mnesia:remove_group("group1", Port, "/mnesia_open", ""), 488 Groups_1 = mod_auth_mnesia:list_groups(Port, "/mnesia_open"), 489 ok = check_lists_members(Groups_1,["group2","group3"]), 490 491 %% Check that the other users still exist in their groups. 492 Users_1 = mod_auth_mnesia:list_users(Port, "/mnesia_open"), 493 ok = check_lists_members(Users_1,["Aladdin","one","two","three"]), 494 {ok,["two"]} = mod_auth_mnesia:list_group_members("group2", Port, 495 "/mnesia_open"), 496 {ok,["three"]} = mod_auth_mnesia:list_group_members("group3", Port, 497 "/mnesia_open"), 498 499 %% Remove the remaining groups/users and check that all 500 %% users/groups are removed. 501 true = mod_auth_mnesia:remove_group("group2", Port, "/mnesia_open", ""), 502 true = mod_auth_mnesia:remove_group("group3", Port, "/mnesia_open", ""), 503 {ok, []} = mod_auth_mnesia:list_groups(Port, "/mnesia_open"), 504 true = mod_auth_mnesia:remove_user("one", Port, "/mnesia_open", ""), 505 true = mod_auth_mnesia:remove_user("Aladdin", Port, "/mnesia_open", ""), 506 true = mod_auth_mnesia:remove_user("two", Port, "/mnesia_open", ""), 507 true = mod_auth_mnesia:remove_user("three", Port, "/mnesia_open", ""), 508 {ok, []} = mod_auth_mnesia:list_users(Port, "/mnesia_open"), 509 ok. 510%%-------------------------------------------------------------------------- 511htaccess(Type, Port, Host, Node) -> 512 %% Control that authentication required! 513 %% Control that the pages that shall be 514 %% authenticated really need authenticatin 515 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 516 "GET /ht/open/ HTTP/1.0\r\n\r\n", 517 [{statuscode, 401}, 518 {version, "HTTP/1.0"}, 519 {header, "WWW-Authenticate"}]), 520 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 521 "GET /ht/secret/ HTTP/1.0\r\n\r\n", 522 [{statuscode, 401}, 523 {version, "HTTP/1.0"}, 524 {header, "WWW-Authenticate"}]), 525 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 526 "GET /ht/secret/top_secret/ " 527 "HTTP/1.0\r\n\r\n", 528 [{statuscode, 401}, 529 {version, "HTTP/1.0"}, 530 {header, "WWW-Authenticate"}]), 531 532 %% Make sure Authenticate header is received even the second time 533 %% we try a incorrect password! Otherwise a browser client will hang! 534 auth_request(Type, Host, Port, Node,"/ht/open/", 535 "dummy", "WrongPassword", [{statuscode, 401}, 536 {header, "WWW-Authenticate"}]), 537 auth_request(Type, Host, Port, Node,"/ht/open/", 538 "dummy", "WrongPassword", [{statuscode, 401}, 539 {header, "WWW-Authenticate"}]), 540 541 %% Control that not just the first user in the list is valid 542 %% Control the first user 543 %% Authennticating ["one:OnePassword" user first in user list] 544 auth_request(Type, Host, Port, Node, "/ht/open/dummy.html", "one", 545 "OnePassword", [{statuscode, 200}]), 546 547 %% Control the second user 548 %% Authentication OK and a directory listing is supplied! 549 %% ["Aladdin:open sesame" user second in user list] 550 auth_request(Type, Host, Port, Node, "/ht/open/","Aladdin", 551 "AladdinPassword", [{statuscode, 200}]), 552 553 %% Contro that bad passwords and userids get a good denial 554 %% User correct but wrong password! ["one:one" user first in user list] 555 auth_request(Type, Host, Port, Node, "/ht/open/", "one", "one", 556 [{statuscode, 401}]), 557 %% Neither user or password correct! ["dummy:dummy"] 558 auth_request(Type, Host, Port, Node, "/ht/open/", "dummy", "dummy", 559 [{statuscode, 401}]), 560 561 %% Control that authetication still works, even if its a member in a group 562 %% Authentication OK! ["two:TwoPassword" user in first group] 563 auth_request(Type, Host, Port, Node, "/ht/secret/dummy.html", "two", 564 "TwoPassword", [{statuscode, 200}]), 565 566 %% Authentication OK and a directory listing is supplied! 567 %% ["three:ThreePassword" user in second group] 568 auth_request(Type, Host, Port, Node,"/ht/secret/", "three", 569 "ThreePassword", [{statuscode, 200}]), 570 571 %% Deny users with bad passwords even if the user is a group member 572 %% User correct but wrong password! ["two:two" user in first group] 573 auth_request(Type, Host, Port, Node, "/ht/secret/", "two", "two", 574 [{statuscode, 401}]), 575 %% Neither user or password correct! ["dummy:dummy"] 576 auth_request(Type, Host, Port, Node,"/ht/secret/", "dummy", "dummy", 577 [{statuscode, 401}]), 578 579 %% control that we deny the users that are in subnet above the allowed 580 auth_request(Type, Host, Port, Node,"/ht/blocknet/dummy.html", "four", 581 "FourPassword", [{statuscode, 403}]), 582 %% Control that we only applies the rules to the right methods 583 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 584 "HEAD /ht/blocknet/dummy.html" 585 " HTTP/1.0\r\n\r\n", 586 [{statuscode, 200}, 587 {version, "HTTP/1.0"}]), 588 589 %% Control that the rerquire directive can be overrideen 590 auth_request(Type, Host, Port, Node, 591 "/ht/secret/top_secret/", "Aladdin", "AladdinPassword", 592 [{statuscode, 401}]), 593 594 %% Authentication still required! 595 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET /ht/open/ " 596 "HTTP/1.0\r\n\r\n", 597 [{statuscode, 401}, 598 {version, "HTTP/1.0"}, 599 {header, "WWW-Authenticate"}]), 600 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 601 "GET /ht/secret/ HTTP/1.0\r\n\r\n", 602 [{statuscode, 401}, 603 {version, "HTTP/1.0"}, 604 {header, "WWW-Authenticate"}]), 605 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 606 "GET /ht/secret/top_secret/ " 607 "HTTP/1.0\r\n\r\n", 608 [{statuscode, 401}, 609 {version, "HTTP/1.0"}, 610 {header, "WWW-Authenticate"}]). 611%%-------------------------------------------------------------------- 612cgi(Type, Port, Host, Node) -> 613 {Script, Script2, Script3} = 614 case test_server:os_type() of 615 {win32, _} -> 616 {"printenv.bat", "printenv.sh", "cgi_echo.exe"}; 617 _ -> 618 {"printenv.sh", "printenv.bat", "cgi_echo"} 619 end, 620 621 %% The length (> 100) is intentional 622 ok = httpd_test_lib: 623 verify_request(Type, Host, Port, Node, 624 "POST /cgi-bin/" ++ Script3 ++ 625 " HTTP/1.0\r\n" 626 "Content-Length:100 \r\n\r\n " 627 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 628 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 629 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 630 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 631 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 632 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 633 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 634 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 635 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 636 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 637 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 638 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 639 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 640 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 641 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 642 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 643 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 644 " \r\n\r\n", 645 [{statuscode, 200}, 646 {version, "HTTP/1.0"}, 647 {header, "content-type", "text/plain"}]), 648 649 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 650 "GET /cgi-bin/"++ Script ++ 651 " HTTP/1.0\r\n\r\n", 652 [{statuscode, 200}, 653 {version, "HTTP/1.0"}]), 654 655 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 656 "GET /cgi-bin/not_there " 657 "HTTP/1.0\r\n\r\n", 658 [{statuscode, 404},{statuscode, 500}, 659 {version, "HTTP/1.0"}]), 660 661 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 662 "GET /cgi-bin/"++ Script ++ 663 "?Nisse:kkk?sss/lll HTTP/1.0\r\n\r\n", 664 [{statuscode, 200}, 665 {version, "HTTP/1.0"}]), 666 667 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 668 "POST /cgi-bin/"++ Script ++ 669 " HTTP/1.0\r\n\r\n", 670 [{statuscode, 200}, 671 {version, "HTTP/1.0"}]), 672 673 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 674 "GET /htbin/"++ Script ++ 675 " HTTP/1.0\r\n\r\n", 676 [{statuscode, 200}, 677 {version, "HTTP/1.0"}]), 678 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 679 "GET /htbin/not_there " 680 "HTTP/1.0\r\n\r\n", 681 [{statuscode, 404},{statuscode, 500}, 682 {version, "HTTP/1.0"}]), 683 684 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 685 "GET /htbin/"++ Script ++ 686 "?Nisse:kkk?sss/lll HTTP/1.0\r\n\r\n", 687 [{statuscode, 200}, 688 {version, "HTTP/1.0"}]), 689 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 690 "POST /htbin/"++ Script ++ 691 " HTTP/1.0\r\n\r\n", 692 [{statuscode, 200}, 693 {version, "HTTP/1.0"}]), 694 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 695 "POST /htbin/"++ Script ++ 696 " HTTP/1.0\r\n\r\n", 697 [{statuscode, 200}, 698 {version, "HTTP/1.0"}]), 699 700 %% Execute an existing, but bad CGI script.. 701 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 702 "POST /htbin/"++ Script2 ++ 703 " HTTP/1.0\r\n\r\n", 704 [{statuscode, 404}, 705 {version, "HTTP/1.0"}]), 706 707 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 708 "POST /cgi-bin/"++ Script2 ++ 709 " HTTP/1.0\r\n\r\n", 710 [{statuscode, 404}, 711 {version, "HTTP/1.0"}]), 712 713 %% Check "ScriptNoCache" directive (default: false) 714 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 715 "GET /cgi-bin/" ++ Script ++ 716 " HTTP/1.0\r\n\r\n", 717 [{statuscode, 200}, 718 {no_header, "cache-control"}, 719 {version, "HTTP/1.0"}]). 720 721%%-------------------------------------------------------------------- 722esi(Type, Port, Host, Node) -> 723 %% Check "ErlScriptAlias" and "EvalScriptAlias" directives 724 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 725 "GET /eval?httpd_example:print(\"Hi!\")" 726 " HTTP/1.0\r\n\r\n", 727 [{statuscode, 200}, 728 {version, "HTTP/1.0"}]), 729 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 730 "GET /eval?not_allowed:print(\"Hi!\")" 731 " HTTP/1.0\r\n\r\n", 732 [{statuscode, 403}, 733 {version, "HTTP/1.0"}]), 734 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 735 "GET /eval?httpd_example:undef(\"Hi!\")" 736 " HTTP/1.0\r\n\r\n", 737 [{statuscode, 500}, 738 {version, "HTTP/1.0"}]), 739 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 740 "GET /cgi-bin/erl/httpd_example " 741 "HTTP/1.0\r\n\r\n", 742 [{statuscode, 400}, 743 {version, "HTTP/1.0"}]), 744 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 745 "GET /cgi-bin/erl/httpd_example:get " 746 "HTTP/1.0\r\n\r\n", 747 [{statuscode, 200}, 748 {version, "HTTP/1.0"}]), 749 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 750 "GET /cgi-bin/erl/httpd_example:" 751 "get?input=4711" 752 " HTTP/1.0\r\n\r\n", 753 [{statuscode, 200}, 754 {version, "HTTP/1.0"}]), 755 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 756 "GET /cgi-bin/erl/httpd_example:" 757 "post HTTP/1.0\r\n\r\n", 758 [{statuscode, 200}, 759 {version, "HTTP/1.0"}]), 760 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 761 "GET /cgi-bin/erl/not_allowed:post " 762 "HTTP/1.0\r\n\r\n", 763 [{statuscode, 403}, 764 {version, "HTTP/1.0"}]), 765 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 766 "GET /cgi-bin/erl/httpd_example:undef " 767 "HTTP/1.0\r\n\r\n", 768 [{statuscode, 404}, 769 {version, "HTTP/1.0"}]), 770 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 771 "GET /cgi-bin/erl/httpd_example/yahoo" 772 " HTTP/1.0\r\n\r\n", 773 [{statuscode, 302}, 774 {version, "HTTP/1.0"}]), 775 %% Check "ErlScriptNoCache" directive (default: false) 776 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 777 "GET /cgi-bin/erl/httpd_example:get" 778 " HTTP/1.0\r\n\r\n", 779 [{statuscode, 200}, 780 {no_header, "cache-control"}, 781 {version, "HTTP/1.0"}]), 782 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 783 "GET /cgi-bin/erl/httpd_example:new_status_and_location" 784 " HTTP/1.1\r\n\r\n", 785 [{statuscode, 201}, 786 {header, "Location"}, 787 {version, "HTTP/1.1"}]), 788 ok. 789 790%%-------------------------------------------------------------------- 791get(Type, Port, Host, Node) -> 792 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 793 "GET /index.html HTTP/1.0\r\n\r\n", 794 [{statuscode, 200}, 795 {header, "Content-Type", "text/html"}, 796 {header, "Date"}, 797 {header, "Server"}, 798 {version, "HTTP/1.0"}]), 799 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 800 "GET /fsize.shtml HTTP/1.1\r\nHost:" 801 ++ Host ++ "\r\n\r\n", 802 [{statuscode, 200}, 803 {header, "Content-Type", "text/html"}, 804 {header, "Date"}, 805 {header, "Server"}]), 806 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 807 "GET /fsize.shtml HTTP/1.0\r\n\r\n", 808 [{statuscode, 200}, 809 {header, "Content-Type"}, 810 {header, "Server"}, 811 {header, "Date"}, 812 {version, "HTTP/1.0"}]), 813 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 814 "GET /secret/dummy.html " 815 "HTTP/1.0\r\n\r\n", 816 [{statuscode, 401}, 817 {header, "WWW-Authenticate"}, 818 {version, "HTTP/1.0"}]), 819 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 820 "GET /index.html HTTP/1.0\r\n\r\n", 821 [{statuscode, 200}, 822 {header, "Server"}, 823 {header, "Date"}, 824 {header, "Content-Type", 825 "text/html"}, 826 {version, "HTTP/1.0"}]), 827 ok. 828 829%%-------------------------------------------------------------------- 830head(Type, Port, Host, Node) -> 831 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 832 "HEAD /index.html HTTP/1.0\r\n\r\n", 833 [{statuscode, 200}, 834 {version, "HTTP/1.0"}]), 835 ok. 836%%-------------------------------------------------------------------- 837all(Type, Port, Host, Node) -> 838 actions(Type, Port, Host, Node), 839 alias(Type, Port, Host, Node), 840 auth(Type, Port, Host, Node), 841 cgi(Type, Port, Host, Node), 842 esi(Type, Port, Host, Node), 843 get(Type, Port, Host, Node), 844 head(Type, Port, Host, Node), 845 ok. 846 847%%-------------------------------------------------------------------- 848%% Internal functions 849%%-------------------------------------------------------------------- 850auth_request(Type, Host, Port, Node, URI, User, Passwd, Expect) -> 851 Req = ["GET ", URI, " HTTP/1.0\r\n", 852 "Authorization: Basic ", 853 base64:encode_to_string(User++":"++Passwd), 854 "\r\n\r\n"], 855 ok = httpd_test_lib:verify_request(Type, Host, Port, Node, 856 lists:flatten(Req), 857 [{version, "HTTP/1.0"} | Expect]). 858 859remove_users(Node, ServerRoot, Host, Port, Dir) -> 860 %% List users, delete them, and make sure they are gone. 861 case list_users(Node, ServerRoot, Host, Port, Dir) of 862 {ok, Users} -> 863 lists:foreach(fun(User) -> 864 delete_user(Node, ServerRoot, Host, 865 Port, Dir, User) 866 end, 867 Users), 868 {ok, []} = list_users(Node, ServerRoot, Host, Port, Dir); 869 _ -> 870 ok 871 end. 872 873add_user(Node, Root, Port, Dir, User, Password, UserData) -> 874 Addr = undefined, 875 Directory = filename:join([Root, "htdocs", Dir]), 876 rpc:call(Node, mod_auth, add_user, 877 [User, Password, UserData, Addr, Port, Directory]). 878 879delete_user(Node, Root, _Host, Port, Dir, User) -> 880 Addr = undefined, 881 Directory = filename:join([Root, "htdocs", Dir]), 882 rpc:call(Node, mod_auth, delete_user, [User, Addr, Port, Directory]). 883 884list_users(Node, Root, _Host, Port, Dir) -> 885 Addr = undefined, 886 Directory = filename:join([Root, "htdocs", Dir]), 887 rpc:call(Node, mod_auth, list_users, [Addr, Port, Directory]). 888 889 890receive_security_event(Event, Node, Port) -> 891 receive 892 Event -> 893 ok; 894 {'EXIT', _, _} -> 895 receive_security_event(Event, Node, Port) 896 after 5000 -> 897 %% Flush the message queue, to see if we got something... 898 Msgs = inets_test_lib:flush(), 899 ct:fail({expected_event_not_received, Msgs}) 900 901 end. 902 903%% receive_security_event(Event, Node, Port) -> 904%% io:format(user, "~w:receive_security_event -> entry with" 905%% "~n Event: ~p" 906%% "~n Node: ~p" 907%% "~n Port: ~p" 908%% "~n", [?MODULE, Event, Node, Port]), 909%% receive 910%% Event -> 911%% ok; 912%% {'EXIT', _, _} -> 913%% receive_security_event(Event, Node, Port); 914%% Other -> 915%% ct:fail({unexpected_event, 916%% {expected, Event}, {received, Other}}) 917%% after 5000 -> 918%% ct:fail(no_event_recived) 919 920%% end. 921 922list_blocked_users(Node,Port) -> 923 Addr = undefined, % Assumed to be on the same host 924 rpc:call(Node, mod_security, list_blocked_users, [Addr,Port]). 925 926list_blocked_users(Node,Port,Dir) -> 927 Addr = undefined, % Assumed to be on the same host 928 rpc:call(Node, mod_security, list_blocked_users, [Addr,Port,Dir]). 929 930block_user(Node,User,Port,Dir,Sec) -> 931 Addr = undefined, % Assumed to be on the same host 932 rpc:call(Node, mod_security, block_user, [User, Addr, Port, Dir, Sec]). 933 934unblock_user(Node,User,Port,Dir) -> 935 Addr = undefined, % Assumed to be on the same host 936 rpc:call(Node, mod_security, unblock_user, [User, Addr, Port, Dir]). 937 938list_auth_users(Node,Port) -> 939 Addr = undefined, % Assumed to be on the same host 940 rpc:call(Node, mod_security, list_auth_users, [Addr,Port]). 941 942list_auth_users(Node,Port,Dir) -> 943 Addr = undefined, % Assumed to be on the same host 944 rpc:call(Node, mod_security, list_auth_users, [Addr,Port,Dir]). 945 946update_password(Node, ServerRoot, _Address, Port, Dir, Old, New)-> 947 Directory = filename:join([ServerRoot, "htdocs", Dir]), 948 rpc:call(Node, mod_auth, update_password, 949 [undefined, Port, Directory, Old, New, New]). 950 951remove_groups(Node, ServerRoot, Host, Port, Dir) -> 952 Directory = filename:join([ServerRoot, "htdocs", Dir]), 953 {ok, Groups} = list_groups(Node, ServerRoot, Host, Port, Directory), 954 lists:foreach(fun(Group) -> 955 delete_group(Node, Group, Port, Directory) 956 end, 957 Groups), 958 {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory), 959 ok. 960 961delete_group(Node, Group, Port, Dir) -> 962 Addr = undefined, 963 rpc:call(Node, mod_auth, delete_group, [Group, Addr, Port, Dir]). 964 965list_groups(Node, _, _, Port, Dir) -> 966 Addr = undefined, 967 rpc:call(Node, mod_auth, list_groups, [Addr, Port, Dir]). 968 969add_group_member(Node, ServerRoot, Port, Dir, User, Group) -> 970 Addr = undefined, 971 rpc:call(Node, mod_auth, add_group_member, [Group, User, Addr, Port, 972 filename:join( 973 [ServerRoot, 974 "htdocs",Dir])]). 975event(What, Port, Dir, Data) -> 976 Msg = {event, What, Port, Dir, Data}, 977 case global:whereis_name(mod_security_test) of 978 undefined -> 979 ok; 980 _Pid -> 981 global:send(mod_security_test, Msg) 982 end. 983 984ssl_password_cb() -> 985 "dummy-ssl-password". 986 987check_lists_members({ok,L},L) -> 988 ok; 989check_lists_members({ok,L1},L2) -> 990 check_lists_members1(lists:sort(L1),lists:sort(L2)); 991check_lists_members(Error,_L) -> 992 Error. 993 994check_lists_members1(L,L) -> 995 ok; 996check_lists_members1(L1,L2) -> 997 {error,{lists_not_equal,L1,L2}}. 998 999 1000 1001