From a23da324a647296a31436631b958bc3443ceaaf2 Mon Sep 17 00:00:00 2001 From: "bugreport%peshkin.net" <> Date: Fri, 14 Oct 2005 06:58:24 +0000 Subject: Bug 204498 Add su (setuser) function Patch by A. Karl Kornel r=joel, a=justdave --- relogin.cgi | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 186 insertions(+), 12 deletions(-) (limited to 'relogin.cgi') diff --git a/relogin.cgi b/relogin.cgi index 1d682965d..58ac84769 100755 --- a/relogin.cgi +++ b/relogin.cgi @@ -20,29 +20,203 @@ # # Contributor(s): Terry Weissman # Gervase Markham +# A. Karl Kornel use strict; use lib qw(.); use Bugzilla; +use Bugzilla::Auth::Login::WWW; +use Bugzilla::CGI; use Bugzilla::Constants; use Bugzilla::Error; - -# We don't want to remove a random logincookie from the db, so -# call Bugzilla->login(). If we're logged in after this, then -# the logincookie must be correct -Bugzilla->login(LOGIN_OPTIONAL); - -Bugzilla->logout(); +use Bugzilla::User; +use Bugzilla::Util; +use Date::Format; my $template = Bugzilla->template; my $cgi = Bugzilla->cgi; -print $cgi->header(); + +my $action = $cgi->param('action') || 'logout'; my $vars = {}; -$vars->{'message'} = "logged_out"; -$template->process("global/message.html.tmpl", $vars) - || ThrowTemplateError($template->error()); +my $target; + +# sudo: Display the sudo information & login page +if ($action eq 'sudo') { + # We must have a logged-in user to do this + # That user must be in the 'bz_sudoers' group + my $user = Bugzilla->login(LOGIN_REQUIRED); + unless ($user->in_group('bz_sudoers')) { + ThrowUserError('auth_failure', { group => 'bz_sudoers', + action => 'begin', + object => 'sudo_session' } + ); + } + + # Do not try to start a new session if one is already in progress! + if (defined(Bugzilla->sudoer)) { + ThrowUserError('sudo-in-progress', { target => $user->login }); + } + + # We may have been given a value to put into the field + # Don't pass it through unless it's actually a user + # Could the default value be protected? Maybe, but we will save the + # disappointment for later! + if (defined($cgi->param('target_login')) && + Bugzilla::User::login_to_id($cgi->param('target_login')) != 0) + { + $vars->{'target_login_default'} = $cgi->param('target_login'); + } + + # Show the sudo page + $vars->{'will_logout'} = 1 if Bugzilla::Auth::Login::WWW->can_logout; + $target = 'admin/sudo.html.tmpl'; +} +# transition-sudo: Validate target, logout user, and redirect for session start +elsif ($action eq 'sudo-transition') { + # Get the current user + my $user = Bugzilla->login(LOGIN_REQUIRED); + unless ($user->in_group('bz_sudoers')) { + ThrowUserError('auth_failure', { group => 'bz_sudoers', + action => 'begin', + object => 'sudo_session' } + ); + } + + # Get & verify the target user (the user who we will be impersonating) + unless (defined($cgi->param('target_login')) && + Bugzilla::User::login_to_id($cgi->param('target_login')) != 0) + { + ThrowUserError('invalid_username', + { 'name' => $cgi->param('target_login') } + ); + } + my $target_user = new Bugzilla::User( + Bugzilla::User::login_to_id($cgi->param('target_login')) + ); + unless (defined($target_user) && + $target_user->id != 0) + { + ThrowUserError('invalid_username', + { 'name' => $cgi->param('target_login') } + ); + } + unless (defined($cgi->param('target_login')) && + $target_user->id != 0) + { + ThrowUserError('invalid_username', + { 'name' => $cgi->param('target_login') } + ); + } + if ($target_user->in_group('bz_sudo_protect')) { + ThrowUserError('sudo_protected', { login => $target_user->login }); + } + + # Log out and Redirect user to the new page + Bugzilla->logout(); + $target = 'relogin.cgi'; + print $cgi->redirect($target . '?action=begin-sudo&target_login=' . + url_quote($target_user->login)); + exit; +} +# begin-sudo: Confirm login and start sudo session +elsif ($action eq 'begin-sudo') { + # We must have a logged-in user to do this + # That user must be in the 'bz_sudoers' group + my $user = Bugzilla->login(LOGIN_REQUIRED); + unless ($user->in_group('bz_sudoers')) { + ThrowUserError('auth_failure', { group => 'bz_sudoers', + action => 'begin', + object => 'sudo_session' } + ); + } + + # Get & verify the target user (the user who we will be impersonating) + unless (defined($cgi->param('target_login')) && + Bugzilla::User::login_to_id($cgi->param('target_login')) != 0) + { + ThrowUserError('invalid_username', + { 'name' => $cgi->param('target_login') } + ); + } + my $target_user = new Bugzilla::User( + Bugzilla::User::login_to_id($cgi->param('target_login')) + ); + unless (defined($target_user) && + $target_user->id != 0) + { + ThrowUserError('invalid_username', + { 'name' => $cgi->param('target_login') } + ); + } + unless (defined($cgi->param('target_login')) && + $target_user->id != 0) + { + ThrowUserError('invalid_username', + { 'name' => $cgi->param('target_login') } + ); + } + if ($target_user->in_group('bz_sudo_protect')) { + ThrowUserError('sudo_protected', { login => $target_user->login }); + } + + # Calculate the session expiry time (T + 6 hours) + my $time_string = time2str('%a, %d-%b-%Y %T %Z', time+(6*60*60), 'GMT'); -exit; + # For future sessions, store the unique ID of the target user + Bugzilla->cgi->send_cookie('-name' => 'sudo', + '-expires' => $time_string, + '-value' => $target_user->id + ); + + # For the present, change the values of Bugzilla::user & Bugzilla::sudoer + Bugzilla->sudo_request($target_user, Bugzilla->user); + + # NOTE: If you want to log the start of an sudo session, do it here. + + $vars->{'message'} = 'sudo_started'; + $vars->{'target'} = $target_user->login; + $target = 'global/message.html.tmpl'; +} +# end-sudo: End the current sudo session (if one is in progress) +elsif ($action eq 'end-sudo') { + # Regardless of our state, delete the sudo cookie if it exists + $cgi->remove_cookie('sudo'); + # Are we in an sudo session? + Bugzilla->login(LOGIN_OPTIONAL); + my $sudoer = Bugzilla->sudoer; + if (defined($sudoer)) { + Bugzilla->logout_request(); + Bugzilla->sudo_request($sudoer, undef); + } + + # NOTE: If you want to log the end of an sudo session, so it here. + + $vars->{'message'} = 'sudo_ended'; + $target = 'global/message.html.tmpl'; +} +# Log out the currently logged-in user (this used to be the only thing this did) +elsif ($action eq 'logout') { + # We don't want to remove a random logincookie from the db, so + # call Bugzilla->login(). If we're logged in after this, then + # the logincookie must be correct + Bugzilla->login(LOGIN_OPTIONAL); + + $cgi->remove_cookie('sudo'); + + Bugzilla->logout(); + + my $template = Bugzilla->template; + my $cgi = Bugzilla->cgi; + print $cgi->header(); + + $vars->{'message'} = "logged_out"; + $target = 'global/message.html.tmpl'; +} + +# Display the template +print $cgi->header(); +$template->process($target, $vars) + || ThrowTemplateError($template->error()); -- cgit v1.2.3-24-g4f1b