# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # This Source Code Form is "Incompatible With Secondary Licenses", as # defined by the Mozilla Public License, v. 2.0. use 5.14.0; use strict; use warnings; use FindBin qw($RealBin); use lib "$RealBin/../lib"; use Test::More "no_plan"; use QA::Util; my ($sel, $config) = get_selenium(); # Turn on the usevisibilitygroups param so that some users are invisible. log_in($sel, $config, 'admin'); set_parameters($sel, { "Group Security" => {"usevisibilitygroups-on" => undef} }); # You can see all users from editusers.cgi, but once you leave this page, # usual group visibility restrictions apply and the "powerless" user cannot # be sudo'ed as he is in no group. go_to_admin($sel); $sel->click_ok("link=Users"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Search users"); $sel->type_ok("matchstr", $config->{unprivileged_user_login}); $sel->select_ok("matchtype", "label=exact (find this user)"); $sel->click_ok("search"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Edit user no-privs <$config->{unprivileged_user_login}>"); $sel->value_is("login", $config->{unprivileged_user_login}); $sel->click_ok("link=Impersonate this user"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Begin sudo session"); $sel->value_is("target_login", $config->{unprivileged_user_login}); $sel->type_ok("reason", "Selenium test about sudo sessions"); $sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password"); $sel->click_ok('//input[@value="Begin Session"]'); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Match Failed"); my $error_msg = trim($sel->get_text("error_msg")); ok($error_msg eq "$config->{unprivileged_user_login} does not exist or you are not allowed to see that user.", "Cannot impersonate users you cannot see"); # Turn off the usevisibilitygroups param so that all users are visible again. set_parameters($sel, { "Group Security" => {"usevisibilitygroups-off" => undef} }); # The "powerless" user can now be sudo'ed. go_to_admin($sel); $sel->click_ok("link=Users"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Search users"); $sel->type_ok("matchstr", $config->{unprivileged_user_login}); $sel->select_ok("matchtype", "label=exact (find this user)"); $sel->click_ok("search"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Edit user no-privs <$config->{unprivileged_user_login}>"); $sel->value_is("login", $config->{unprivileged_user_login}); $sel->click_ok("link=Impersonate this user"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Begin sudo session"); $sel->value_is("target_login", $config->{unprivileged_user_login}); $sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password"); $sel->click_ok('//input[@value="Begin Session"]'); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Sudo session started"); my $text = trim($sel->get_text("message")); ok($text =~ /The sudo session has been started/, "The sudo session has been started"); # Make sure this user is not an admin and has no privs at all, and that # he cannot access editusers.cgi (despite the sudoer can). $sel->click_ok("link=Preferences"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("General Preferences"); $sel->click_ok("link=Permissions"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Permissions"); $sel->is_text_present_ok("There are no permission bits set on your account"); # We access the page directly as there is no link pointing to it. $sel->open_ok("/$config->{bugzilla_installation}/editusers.cgi"); $sel->title_is("Authorization Required"); $error_msg = trim($sel->get_text("error_msg")); ok($error_msg =~ /^Sorry, you aren't a member of the 'editusers' group/, "Not a member of the editusers group"); $sel->click_ok("link=end session"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Sudo session complete"); $sel->is_text_present_ok("Your sudo session has ended"); # Try to access the sudo page directly, with no credentials. $sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=begin-sudo&target_login=$config->{admin_user_login}"); $sel->title_is("Password Required"); # Now try to start a sudo session directly, with all required credentials. $sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=begin-sudo&password=$config->{admin_user_passwd}&target_login=$config->{unprivileged_user_login}", undef, "Impersonate a user directly by providing all required data"); # A direct access to the page is supposed to have no Referer header set, # which would trigger the "Untrusted Authentication Request" error, but # due to the way Selenium works, the Referer header is set and the # "Preparation Required" error is thrown instead. In any case, one of # those two errors must be thrown. my $title = $sel->get_title(); ok($title eq "Untrusted Authentication Request" || $title eq "Preparation Required", $title); # Now try to sudo an admin, which is not allowed. $sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=prepare-sudo&target_login=$config->{admin_user_login}"); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Begin sudo session"); $sel->value_is("target_login", $config->{admin_user_login}); $sel->type_ok("reason", "Selenium hack"); $sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password"); $sel->click_ok('//input[@value="Begin Session"]'); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("User Protected"); $error_msg = trim($sel->get_text("error_msg")); ok($error_msg =~ /^The user $config->{admin_user_login} may not be impersonated by sudoers/, "Cannot impersonate administrators"); # Now try to sudo a non-existing user account, with no password. $sel->go_back_ok(); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Begin sudo session"); # Starting with 5.0, the password field is a type=password and is marked # "required". This means that we need to remove the required attribute from # the input so that it can still be checked by the backend code. my $script = q{ document.getElementById('password').removeAttribute('required'); }; $sel->run_script($script); $sel->type_ok("target_login", 'foo@bar.com'); $sel->click_ok('//input[@value="Begin Session"]'); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Password Required"); # Same as above, but with your password. $sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=prepare-sudo&target_login=foo\@bar.com"); $sel->title_is("Begin sudo session"); $sel->value_is("target_login", 'foo@bar.com'); $sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password"); $sel->click_ok('//input[@value="Begin Session"]'); $sel->wait_for_page_to_load_ok(WAIT_TIME); $sel->title_is("Match Failed"); $error_msg = trim($sel->get_text("error_msg")); ok($error_msg eq 'foo@bar.com does not exist or you are not allowed to see that user.', "Cannot impersonate non-existing accounts"); logout($sel);