Changed Perl scripts to use #!/usr/bin/env perl
[WebKit-https.git] / BugsSite / relogin.cgi
1 #!/usr/bin/env perl -wT
2 # -*- Mode: perl; indent-tabs-mode: nil -*-
3 #
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/
8 #
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.
13 #
14 # The Original Code is the Bugzilla Bug Tracking System.
15 #
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
19 # Rights Reserved.
20 #
21 # Contributor(s): Terry Weissman <terry@mozilla.org>
22 #                 Gervase Markham <gerv@gerv.net>
23 #                 A. Karl Kornel <karl@kornel.name>
24
25 use strict;
26 use lib qw(. lib);
27
28 use Bugzilla;
29 use Bugzilla::Mailer;
30 use Bugzilla::Constants;
31 use Bugzilla::Error;
32 use Bugzilla::Token;
33 use Bugzilla::User;
34 use Bugzilla::Util;
35 use Date::Format;
36
37 my $template = Bugzilla->template;
38 my $cgi = Bugzilla->cgi;
39
40 my $action = $cgi->param('action') || 'logout';
41
42 my $vars = {};
43 my $target;
44
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',
52                                          action => 'begin',
53                                          object => 'sudo_session' }
54         );
55     }
56     
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 });
60     }
61
62     # Keep a temporary record of the user visiting this page
63     $vars->{'token'} = issue_session_token('sudo_prepared');
64
65     # Show the sudo page
66     $vars->{'target_login_default'} = $cgi->param('target_login');
67     $vars->{'reason_default'} = $cgi->param('reason');
68     $target = 'admin/sudo.html.tmpl';
69 }
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
73     # and password.
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). 
77
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')))
82     {
83         $credentials_provided = 1;
84     }
85     
86     # Next, log in the user
87     my $user = Bugzilla->login(LOGIN_REQUIRED);
88     
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')});
96     }
97     
98     # The user must be in the 'bz_sudoers' group
99     unless ($user->in_group('bz_sudoers')) {
100         ThrowUserError('auth_failure', {  group => 'bz_sudoers',
101                                          action => 'begin',
102                                          object => 'sudo_session' }
103         );
104     }
105     
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 });
109     }
110
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'))
119     {
120         ThrowUserError('sudo_preparation_required', 
121                        { target_login => scalar $cgi->param('target_login'),
122                                reason => scalar $cgi->param('reason')});
123     }
124     delete_token($cgi->param('token'));
125
126     # Get & verify the target user (the user who we will be impersonating)
127     my $target_user = 
128         new Bugzilla::User({ name => $cgi->param('target_login') });
129     unless (defined($target_user)
130             && $target_user->id
131             && $user->can_see_user($target_user))
132     {
133         ThrowUserError('user_match_failed',
134                        { 'name' => $cgi->param('target_login') }
135         );
136     }
137     if ($target_user->in_group('bz_sudo_protect')) {
138         ThrowUserError('sudo_protected', { login => $target_user->login });
139     }
140
141     # If we have a reason passed in, keep it under 200 characters
142     my $reason = $cgi->param('reason') || '';
143     $reason = substr($reason, $[, 200);
144     
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');
147
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
152     );
153     
154     # For the present, change the values of Bugzilla::user & Bugzilla::sudoer
155     Bugzilla->sudo_request($target_user, $user);
156     
157     # NOTE: If you want to log the start of an sudo session, do it here.
158
159     # Go ahead and send out the message now
160     my $message;
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);
165
166     $vars->{'message'} = 'sudo_started';
167     $vars->{'target'} = $target_user->login;
168     $target = 'global/message.html.tmpl';
169 }
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');
174
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);
180     }
181
182     # NOTE: If you want to log the end of an sudo session, so it here.
183     
184     $vars->{'message'} = 'sudo_ended';
185     $target = 'global/message.html.tmpl';
186 }
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);
193
194     $cgi->remove_cookie('sudo');
195
196     Bugzilla->logout();
197
198     $vars->{'message'} = "logged_out";
199     $target = 'global/message.html.tmpl';
200 }
201 # No valid action found
202 else {
203     Bugzilla->login(LOGIN_OPTIONAL);
204     ThrowCodeError('unknown_action', {action => $action});
205 }
206
207 # Display the template
208 print $cgi->header();
209 $template->process($target, $vars)
210       || ThrowTemplateError($template->error());