1 #!/usr/bin/env perl -wT
2 # -*- Mode: perl; indent-tabs-mode: nil -*-
4 # The contents of this file are subject to the Mozilla Public
5 # License Version 1.1 (the "License"); you may not use this file
6 # except in compliance with the License. You may obtain a copy of
7 # the License at http://www.mozilla.org/MPL/
9 # Software distributed under the License is distributed on an "AS
10 # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 # implied. See the License for the specific language governing
12 # rights and limitations under the License.
14 # The Original Code is the Bugzilla Bug Tracking System.
16 # The Initial Developer of the Original Code is Netscape Communications
17 # Corporation. Portions created by Netscape are
18 # Copyright (C) 1998 Netscape Communications Corporation. All
21 # Contributor(s): Terry Weissman <terry@mozilla.org>
22 # Gervase Markham <gerv@gerv.net>
23 # A. Karl Kornel <karl@kornel.name>
30 use Bugzilla
::Constants
;
37 my $template = Bugzilla
->template;
38 my $cgi = Bugzilla
->cgi;
40 my $action = $cgi->param('action') || 'logout';
45 # prepare-sudo: Display the sudo information & login page
46 if ($action eq 'prepare-sudo') {
47 # We must have a logged-in user to do this
48 # That user must be in the 'bz_sudoers' group
49 my $user = Bugzilla
->login(LOGIN_REQUIRED
);
50 unless ($user->in_group('bz_sudoers')) {
51 ThrowUserError
('auth_failure', { group
=> 'bz_sudoers',
53 object
=> 'sudo_session' }
57 # Do not try to start a new session if one is already in progress!
58 if (defined(Bugzilla
->sudoer)) {
59 ThrowUserError
('sudo_in_progress', { target
=> $user->login });
62 # Keep a temporary record of the user visiting this page
63 $vars->{'token'} = issue_session_token
('sudo_prepared');
66 $vars->{'target_login_default'} = $cgi->param('target_login');
67 $vars->{'reason_default'} = $cgi->param('reason');
68 $target = 'admin/sudo.html.tmpl';
70 # begin-sudo: Confirm login and start sudo session
71 elsif ($action eq 'begin-sudo') {
72 # We must be sure that the user is authenticating by providing a login
74 # We only need to do this for authentication methods that involve Bugzilla
75 # directly obtaining a login (i.e. normal CGI login), as opposed to other
76 # methods (like Environment vars login).
78 # First, record if Bugzilla_login and Bugzilla_password were provided
79 my $credentials_provided;
80 if (defined($cgi->param('Bugzilla_login'))
81 && defined($cgi->param('Bugzilla_password')))
83 $credentials_provided = 1;
86 # Next, log in the user
87 my $user = Bugzilla
->login(LOGIN_REQUIRED
);
89 # At this point, the user is logged in. However, if they used a method
90 # where they could have provided a username/password (i.e. CGI), but they
91 # did not provide a username/password, then throw an error.
92 if ($user->authorizer->can_login && !$credentials_provided) {
93 ThrowUserError
('sudo_password_required',
94 { target_login
=> $cgi->param('target_login'),
95 reason
=> $cgi->param('reason')});
98 # The user must be in the 'bz_sudoers' group
99 unless ($user->in_group('bz_sudoers')) {
100 ThrowUserError
('auth_failure', { group
=> 'bz_sudoers',
102 object
=> 'sudo_session' }
106 # Do not try to start a new session if one is already in progress!
107 if (defined(Bugzilla
->sudoer)) {
108 ThrowUserError
('sudo_in_progress', { target
=> $user->login });
111 # Did the user actually go trough the 'sudo-prepare' action? Do some
112 # checks on the token the action should have left.
113 my ($token_user, $token_timestamp, $token_data) =
114 Bugzilla
::Token
::GetTokenData
($cgi->param('token'));
115 unless (defined($token_user)
116 && defined($token_data)
117 && ($token_user == $user->id)
118 && ($token_data eq 'sudo_prepared'))
120 ThrowUserError
('sudo_preparation_required',
121 { target_login
=> scalar $cgi->param('target_login'),
122 reason
=> scalar $cgi->param('reason')});
124 delete_token
($cgi->param('token'));
126 # Get & verify the target user (the user who we will be impersonating)
128 new Bugzilla
::User
({ name
=> $cgi->param('target_login') });
129 unless (defined($target_user)
131 && $user->can_see_user($target_user))
133 ThrowUserError
('user_match_failed',
134 { 'name' => $cgi->param('target_login') }
137 if ($target_user->in_group('bz_sudo_protect')) {
138 ThrowUserError
('sudo_protected', { login
=> $target_user->login });
141 # If we have a reason passed in, keep it under 200 characters
142 my $reason = $cgi->param('reason') || '';
143 $reason = substr($reason, $[, 200);
145 # Calculate the session expiry time (T + 6 hours)
146 my $time_string = time2str
('%a, %d-%b-%Y %T %Z', time+(6*60*60), 'GMT');
148 # For future sessions, store the unique ID of the target user
149 $cgi->send_cookie('-name' => 'sudo',
150 '-expires' => $time_string,
151 '-value' => $target_user->id
154 # For the present, change the values of Bugzilla::user & Bugzilla::sudoer
155 Bugzilla
->sudo_request($target_user, $user);
157 # NOTE: If you want to log the start of an sudo session, do it here.
159 # Go ahead and send out the message now
161 my $mail_template = Bugzilla
->template_inner($target_user->settings->{'lang'}->{'value'});
162 $mail_template->process('email/sudo.txt.tmpl', { reason
=> $reason }, \
$message);
163 Bugzilla
->template_inner("");
164 MessageToMTA
($message);
166 $vars->{'message'} = 'sudo_started';
167 $vars->{'target'} = $target_user->login;
168 $target = 'global/message.html.tmpl';
170 # end-sudo: End the current sudo session (if one is in progress)
171 elsif ($action eq 'end-sudo') {
172 # Regardless of our state, delete the sudo cookie if it exists
173 $cgi->remove_cookie('sudo');
175 # Are we in an sudo session?
176 Bugzilla
->login(LOGIN_OPTIONAL
);
177 my $sudoer = Bugzilla
->sudoer;
178 if (defined($sudoer)) {
179 Bugzilla
->sudo_request($sudoer, undef);
182 # NOTE: If you want to log the end of an sudo session, so it here.
184 $vars->{'message'} = 'sudo_ended';
185 $target = 'global/message.html.tmpl';
187 # Log out the currently logged-in user (this used to be the only thing this did)
188 elsif ($action eq 'logout') {
189 # We don't want to remove a random logincookie from the db, so
190 # call Bugzilla->login(). If we're logged in after this, then
191 # the logincookie must be correct
192 Bugzilla
->login(LOGIN_OPTIONAL
);
194 $cgi->remove_cookie('sudo');
198 $vars->{'message'} = "logged_out";
199 $target = 'global/message.html.tmpl';
201 # No valid action found
203 Bugzilla
->login(LOGIN_OPTIONAL
);
204 ThrowCodeError
('unknown_action', {action
=> $action});
207 # Display the template
208 print $cgi->header();
209 $template->process($target, $vars)
210 || ThrowTemplateError
($template->error());