# Rights Reserved.
#
# Contributor(s): Myk Melez <myk@mozilla.org>
+# Frédéric Buclin <LpSolit@gmail.com>
################################################################################
# Module Initialization
use Date::Format;
use Date::Parse;
+use File::Basename;
+
+use base qw(Exporter);
+
+@Bugzilla::Token::EXPORT = qw(issue_session_token check_token_data delete_token);
# This module requires that its caller have said "require globals.pl" to import
# relevant functions from that script.
Bugzilla::BugMail::MessageToMTA($message);
}
-sub IssueSessionToken {
+sub issue_session_token {
# Generates a random token, adds it to the tokens table, and returns
# the token to the caller.
Bugzilla::BugMail::MessageToMTA($message);
# Delete the token from the database.
- DeleteToken($token);
+ delete_token($token);
}
sub DeletePasswordTokens {
my ($token) = @_;
return unless defined $token;
+ $token = clean_text($token);
trick_taint($token);
my $dbh = Bugzilla->dbh;
WHERE token = ?", undef, $token);
}
-sub DeleteToken {
+sub delete_token {
# Deletes specified token
my ($token) = @_;
$dbh->bz_unlock_tables();
}
+# Given a token, makes sure it comes from the currently logged in user
+# and match the expected event. Returns 1 on success, else displays a warning.
+# Note: this routine must not be called while tables are locked as it will try
+# to lock some tables itself, see CleanTokenTable().
+sub check_token_data {
+ my ($token, $expected_action) = @_;
+ my $user = Bugzilla->user;
+ my $template = Bugzilla->template;
+ my $cgi = Bugzilla->cgi;
+
+ my ($creator_id, $date, $token_action) = GetTokenData($token);
+ unless ($creator_id
+ && $creator_id == $user->id
+ && $token_action eq $expected_action)
+ {
+ # Something is going wrong. Ask confirmation before processing.
+ # It is possible that someone tried to trick an administrator.
+ # In this case, we want to know his name!
+ require Bugzilla::User;
+
+ my $vars = {};
+ $vars->{'abuser'} = Bugzilla::User->new($creator_id)->identity;
+ $vars->{'token_action'} = $token_action;
+ $vars->{'expected_action'} = $expected_action;
+ $vars->{'script_name'} = basename($0);
+
+ # Now is a good time to remove old tokens from the DB.
+ CleanTokenTable();
+
+ # If no token was found, create a valid token for the given action.
+ unless ($creator_id) {
+ $token = issue_session_token($expected_action);
+ $cgi->param('token', $token);
+ }
+
+ print $cgi->header();
+
+ $template->process('admin/confirm-action.html.tmpl', $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
+ return 1;
+}
+
################################################################################
# Internal Functions
################################################################################
use Bugzilla::Error;
use Bugzilla::Config qw($datadir);
use Bugzilla::Classification;
+use Bugzilla::Token;
require "globals.pl";
#
my $action = trim($cgi->param('action') || '');
my $class_name = trim($cgi->param('classification') || '');
-
+my $token = $cgi->param('token');
+
#
# action='' -> Show nice list of classifications
#
#
if ($action eq 'add') {
+ $vars->{'token'} = issue_session_token('add_classification');
LoadTemplate($action);
}
#
if ($action eq 'new') {
-
+ check_token_data($token, 'add_classification');
$class_name || ThrowUserError("classification_not_specified");
my $classification =
unlink "$datadir/versioncache";
$vars->{'classification'} = $class_name;
-
+ delete_token($token);
LoadTemplate($action);
}
}
$vars->{'classification'} = $classification;
-
+ $vars->{'token'} = issue_session_token('delete_classification');
LoadTemplate($action);
}
#
if ($action eq 'delete') {
-
+ check_token_data($token, 'delete_classification');
my $classification =
Bugzilla::Classification::check_classification($class_name);
unlink "$datadir/versioncache";
$vars->{'classification'} = $classification;
-
+ delete_token($token);
LoadTemplate($action);
}
Bugzilla::Classification::check_classification($class_name);
$vars->{'classification'} = $classification;
-
+ $vars->{'token'} = issue_session_token('edit_classification');
LoadTemplate($action);
}
#
if ($action eq 'update') {
-
+ check_token_data($token, 'edit_classification');
$class_name || ThrowUserError("classification_not_specified");
my $class_old_name = trim($cgi->param('classificationold') || '');
}
$dbh->bz_unlock_tables();
-
+ delete_token($token);
LoadTemplate($action);
}
WHERE name = ?");
if (defined $cgi->param('add_products')) {
+ check_token_data($token, 'reclassify_classifications');
if (defined $cgi->param('prodlist')) {
foreach my $prod ($cgi->param("prodlist")) {
trick_taint($prod);
$sth->execute($classification->id, $prod);
}
}
+ delete_token($token);
} elsif (defined $cgi->param('remove_products')) {
+ check_token_data($token, 'reclassify_classifications');
if (defined $cgi->param('myprodlist')) {
foreach my $prod ($cgi->param("myprodlist")) {
trick_taint($prod);
$sth->execute(1,$prod);
}
}
+ delete_token($token);
}
my @classifications =
Bugzilla::Classification::get_all_classifications;
$vars->{'classifications'} = \@classifications;
$vars->{'classification'} = $classification;
-
+ $vars->{'token'} = issue_session_token('reclassify_classifications');
LoadTemplate($action);
}
use Bugzilla::Product;
use Bugzilla::Component;
use Bugzilla::Bug;
+use Bugzilla::Token;
my $cgi = Bugzilla->cgi;
my $dbh = Bugzilla->dbh;
my $comp_name = trim($cgi->param('component') || '');
my $action = trim($cgi->param('action') || '');
my $showbugcounts = (defined $cgi->param('showbugcounts'));
+my $token = $cgi->param('token');
#
# product = '' -> Show nice list of products
#
if ($action eq 'add') {
-
+ $vars->{'token'} = issue_session_token('add_component');
$vars->{'product'} = $product->name;
$template->process("admin/components/create.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'new') {
-
+ check_token_data($token, 'add_component');
# Do the user matching
Bugzilla::User::match_field ($cgi, {
'initialowner' => { 'type' => 'single' },
$vars->{'name'} = $comp_name;
$vars->{'product'} = $product->name;
+ delete_token($token);
$template->process("admin/components/created.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'del') {
-
+ $vars->{'token'} = issue_session_token('delete_component');
$vars->{'comp'} =
Bugzilla::Component::check_component($product, $comp_name);
#
if ($action eq 'delete') {
-
+ check_token_data($token, 'delete_component');
my $component =
Bugzilla::Component::check_component($product, $comp_name);
$vars->{'name'} = $component->name;
$vars->{'product'} = $product->name;
+ delete_token($token);
$template->process("admin/components/deleted.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
exit;
#
if ($action eq 'edit') {
-
+ $vars->{'token'} = issue_session_token('edit_component');
$vars->{'comp'} =
Bugzilla::Component::check_component($product, $comp_name);
#
if ($action eq 'update') {
-
+ check_token_data($token, 'edit_component');
# Do the user matching
Bugzilla::User::match_field ($cgi, {
'initialowner' => { 'type' => 'single' },
$vars->{'name'} = $comp_name;
$vars->{'product'} = $product->name;
+ delete_token($token);
$template->process("admin/components/updated.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
use Bugzilla::FlagType;
use Bugzilla::Group;
use Bugzilla::Util;
+use Bugzilla::Token;
my $template = Bugzilla->template;
my $vars = {};
# Determine whether to use the action specified by the user or the default.
my $action = $cgi->param('action') || 'list';
+my $token = $cgi->param('token');
my @categoryActions;
if (@categoryActions = grep(/^categoryAction-.+/, $cgi->param())) {
$categoryActions[0] =~ s/^categoryAction-//;
- processCategoryChange($categoryActions[0]);
+ processCategoryChange($categoryActions[0], $token);
exit;
}
elsif ($action eq 'enter') { edit(); }
elsif ($action eq 'copy') { edit(); }
elsif ($action eq 'edit') { edit(); }
-elsif ($action eq 'insert') { insert(); }
-elsif ($action eq 'update') { update(); }
+elsif ($action eq 'insert') { insert($token); }
+elsif ($action eq 'update') { update($token); }
elsif ($action eq 'confirmdelete') { confirmDelete(); }
-elsif ($action eq 'delete') { deleteType(); }
-elsif ($action eq 'deactivate') { deactivate(); }
+elsif ($action eq 'delete') { deleteType($token); }
+elsif ($action eq 'deactivate') { deactivate($token); }
else {
ThrowCodeError("action_unrecognized", { action => $action });
}
$vars->{'last_action'} = $cgi->param('action');
if ($cgi->param('action') eq 'enter' || $cgi->param('action') eq 'copy') {
$vars->{'action'} = "insert";
+ $vars->{'token'} = issue_session_token('add_flagtype');
}
else {
$vars->{'action'} = "update";
+ $vars->{'token'} = issue_session_token('edit_flagtype');
}
# If copying or editing an existing flag type, retrieve it.
}
sub processCategoryChange {
- my $categoryAction = shift;
+ my ($categoryAction, $token) = @_;
validateIsActive();
validateIsRequestable();
validateIsRequesteeble();
$type->{'inclusions'} = \%inclusions;
$type->{'exclusions'} = \%exclusions;
$vars->{'type'} = $type;
-
+ $vars->{'token'} = $token;
+
# Return the appropriate HTTP response headers.
print $cgi->header();
}
sub insert {
+ my $token = shift;
+ check_token_data($token, 'add_flagtype');
my $name = validateName();
my $description = validateDescription();
my $cc_list = validateCCList();
$vars->{'name'} = $cgi->param('name');
$vars->{'message'} = "flag_type_created";
+ delete_token($token);
# Return the appropriate HTTP response headers.
print $cgi->header();
sub update {
+ my $token = shift;
+ check_token_data($token, 'edit_flagtype');
my $id = validateID();
my $name = validateName();
my $description = validateDescription();
$vars->{'name'} = $cgi->param('name');
$vars->{'message'} = "flag_type_changes_saved";
+ delete_token($token);
# Return the appropriate HTTP response headers.
print $cgi->header();
if ($count > 0) {
$vars->{'flag_type'} = Bugzilla::FlagType::get($id);
$vars->{'flag_count'} = scalar($count);
-
+ $vars->{'token'} = issue_session_token('delete_flagtype');
# Return the appropriate HTTP response headers.
print $cgi->header();
|| ThrowTemplateError($template->error());
}
else {
- deleteType();
+ my $token = issue_session_token('delete_flagtype');
+ deleteType($token);
}
}
sub deleteType {
+ my $token = shift;
+ check_token_data($token, 'delete_flagtype');
my $id = validateID();
my $dbh = Bugzilla->dbh;
$dbh->bz_unlock_tables();
$vars->{'message'} = "flag_type_deleted";
+ delete_token($token);
# Return the appropriate HTTP response headers.
print $cgi->header();
sub deactivate {
+ my $token = shift;
+ check_token_data($token, 'delete_flagtype');
my $id = validateID();
validateIsActive();
$vars->{'message'} = "flag_type_deactivated";
$vars->{'flag_type'} = Bugzilla::FlagType::get($id);
-
+ delete_token($token);
+
# Return the appropriate HTTP response headers.
print $cgi->header();
use Bugzilla::Config qw(:DEFAULT :admin);
use Bugzilla::Group;
use Bugzilla::User;
+use Bugzilla::Token;
require "globals.pl";
my $cgi = Bugzilla->cgi;
object => "groups"});
my $action = trim($cgi->param('action') || '');
+my $token = $cgi->param('token');
# RederiveRegexp: update user_group_map with regexp-based grants
sub RederiveRegexp
$vars->{'isactive'} = $isactive;
$vars->{'isbuggroup'} = $isbuggroup;
$vars->{'groups'} = \@groups;
+ $vars->{'token'} = issue_session_token('edit_group');
print $cgi->header();
$template->process("admin/groups/edit.html.tmpl", $vars)
#
if ($action eq 'add') {
+ $vars->{'token'} = issue_session_token('add_group');
print $cgi->header();
$template->process("admin/groups/create.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'new') {
+ check_token_data($token, 'add_group');
# Check that a not already used group name is given, that
# a description is also given and check if the regular
# expression is valid (if any).
undef, ($gid, CONTROLMAPSHOWN, CONTROLMAPNA));
}
RederiveRegexp($regexp, $gid);
+ delete_token($token);
print $cgi->header();
$template->process("admin/groups/created.html.tmpl", $vars)
$vars->{'hasproduct'} = $hasproduct;
$vars->{'hasflags'} = $hasflags;
$vars->{'buglist'} = $buglist;
+ $vars->{'token'} = issue_session_token('delete_group');
print $cgi->header();
$template->process("admin/groups/delete.html.tmpl", $vars)
#
if ($action eq 'delete') {
+ check_token_data($token, 'delete_group');
# Check that an existing group ID is given
my $gid = CheckGroupID($cgi->param('group'));
my ($name, $isbuggroup) =
$dbh->do('DELETE FROM groups WHERE id = ?',
undef, $gid);
+ delete_token($token);
+
print $cgi->header();
$template->process("admin/groups/deleted.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'postchanges') {
+ check_token_data($token, 'edit_group');
# ZLL: Bug 181589: we need to have something to remove explicitly listed users from
# groups in order for the conversion to 2.18 groups to work
my $action;
if ($action == 2) {
$vars->{'regexp'} = $regexp;
}
-
+ delete_token($token);
+
print $cgi->header();
$template->process("admin/groups/change.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Config qw(:DEFAULT $datadir);
+use Bugzilla::Token;
my $cgi = Bugzilla->cgi;
my $dbh = Bugzilla->dbh;
object => "keywords"});
my $action = trim($cgi->param('action') || '');
+my $token = $cgi->param('token');
$vars->{'action'} = $action;
if ($action eq 'add') {
+ $vars->{'token'} = issue_session_token('add_keyword');
print $cgi->header();
$template->process("admin/keywords/create.html.tmpl", $vars)
#
if ($action eq 'new') {
+ check_token_data($token, 'add_keyword');
# Cleanups and validity checks
my $name = trim($cgi->param('name') || '');
# Make versioncache flush
unlink "$datadir/versioncache";
+ delete_token($token);
print $cgi->header();
$vars->{'name'} = $name;
$vars->{'description'} = $description;
$vars->{'bug_count'} = $bugs;
+ $vars->{'token'} = issue_session_token('edit_keyword');
print $cgi->header();
#
if ($action eq 'update') {
+ check_token_data($token, 'edit_keyword');
my $id = ValidateKeyID(scalar $cgi->param('id'));
my $name = trim($cgi->param('name') || '');
# Make versioncache flush
unlink "$datadir/versioncache";
+ delete_token($token);
print $cgi->header();
WHERE keywordid = ?',
undef, $id);
+ # We need this token even if there is no bug using this keyword.
+ $token = issue_session_token('delete_keyword');
+
if ($bugs) {
$vars->{'bug_count'} = $bugs;
$vars->{'keyword_id'} = $id;
$vars->{'name'} = $name;
+ $vars->{'token'} = $token;
print $cgi->header();
exit;
}
}
+ # We cannot do this check earlier as we have to check 'reallydelete' first.
+ check_token_data($token, 'delete_keyword');
$dbh->do('DELETE FROM keywords WHERE keywordid = ?', undef, $id);
$dbh->do('DELETE FROM keyworddefs WHERE id = ?', undef, $id);
# Make versioncache flush
unlink "$datadir/versioncache";
+ delete_token($token);
print $cgi->header();
# Matt Masson <matthew@zeroknowledge.com>
#
# Contributors : Gavin Shelley <bugzilla@chimpychompy.org>
-# Frédéric Buclin <LpSolit@gmail.com>
+# Frédéric Buclin <LpSolit@gmail.com>
#
use Bugzilla::Product;
use Bugzilla::Milestone;
use Bugzilla::Bug;
+use Bugzilla::Token;
my $cgi = Bugzilla->cgi;
my $dbh = Bugzilla->dbh;
my $sortkey = trim($cgi->param('sortkey') || 0);
my $action = trim($cgi->param('action') || '');
my $showbugcounts = (defined $cgi->param('showbugcounts'));
+my $token = $cgi->param('token');
#
# product = '' -> Show nice list of products
#
if ($action eq 'add') {
-
+ $vars->{'token'} = issue_session_token('add_milestone');
$vars->{'product'} = $product->name;
$template->process("admin/milestones/create.html.tmpl",
$vars)
#
if ($action eq 'new') {
-
+ check_token_data($token, 'add_milestone');
$milestone_name || ThrowUserError('milestone_blank_name');
if (length($milestone_name) > 20) {
# Make versioncache flush
unlink "$datadir/versioncache";
+ delete_token($token);
$vars->{'name'} = $milestone_name;
$vars->{'product'} = $product->name;
}
$vars->{'bug_count'} = $milestone->bug_count;
+ $vars->{'token'} = issue_session_token('delete_milestone');
$template->process("admin/milestones/confirm-delete.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'delete') {
-
+ check_token_data($token, 'delete_milestone');
my $milestone =
Bugzilla::Milestone::check_milestone($product,
$milestone_name);
undef, ($product->id, $milestone->name));
unlink "$datadir/versioncache";
+ delete_token($token);
$template->process("admin/milestones/deleted.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
$vars->{'sortkey'} = $milestone->sortkey;
$vars->{'name'} = $milestone->name;
$vars->{'product'} = $product->name;
+ $vars->{'token'} = issue_session_token('edit_milestone');
$template->process("admin/milestones/edit.html.tmpl",
$vars)
#
if ($action eq 'update') {
-
+ check_token_data($token, 'edit_milestone');
my $milestone_old_name = trim($cgi->param('milestoneold') || '');
my $milestone_old =
Bugzilla::Milestone::check_milestone($product,
}
$dbh->bz_unlock_tables();
+ delete_token($token);
$vars->{'name'} = $milestone_name;
$vars->{'product'} = $product->name;
use Bugzilla::Constants;
use Bugzilla::Config qw(:DEFAULT :admin :params $datadir);
use Bugzilla::Config::Common;
+use Bugzilla::Token;
require "globals.pl";
use vars qw(@parampanels);
object => "parameters"});
my $action = trim($cgi->param('action') || '');
+my $token = $cgi->param('token');
my $current_panel = $cgi->param('section') || 'core';
$current_panel =~ /^([A-Za-z0-9_-]+)$/;
$current_panel = $1;
$vars->{panels} = \@panels;
if ($action eq 'save' && $current_module) {
+ check_token_data($token, 'edit_parameters');
my @changes = ();
my @module_param_list = "Bugzilla::Config::${current_module}"->get_param_list();
WriteParams();
unlink "$datadir/versioncache";
+ delete_token($token);
}
+$vars->{'token'} = issue_session_token('edit_parameters');
+
$template->process("admin/params/editparams.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
use Bugzilla::Product;
use Bugzilla::Classification;
use Bugzilla::Milestone;
+use Bugzilla::Token;
# Shut up misguided -w warnings about "used only once". "use vars" just
# doesn't work for me.
my $product_name = trim($cgi->param('product') || '');
my $action = trim($cgi->param('action') || '');
my $showbugcounts = (defined $cgi->param('showbugcounts'));
+my $token = $cgi->param('token');
#
# product = '' -> Show nice list of classifications (if
Bugzilla::Classification::check_classification($classification_name);
$vars->{'classification'} = $classification;
}
+ $vars->{'token'} = issue_session_token('add_product');
+
$template->process("admin/products/create.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'new') {
-
+ check_token_data($token, 'add_product');
# Cleanups and validity checks
my $classification_id = 1;
}
# Make versioncache flush
unlink "$datadir/versioncache";
+ delete_token($token);
$vars->{'product'} = $product;
}
$vars->{'product'} = $product;
+ $vars->{'token'} = issue_session_token('delete_product');
$template->process("admin/products/confirm-delete.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'delete') {
+ check_token_data($token, 'delete_product');
# First make sure the product name is valid.
my $product = Bugzilla::Product::check_product($product_name);
$dbh->bz_unlock_tables();
unlink "$datadir/versioncache";
+ delete_token($token);
$template->process("admin/products/deleted.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}
}
$vars->{'group_controls'} = $group_controls;
-
$vars->{'product'} = $product;
-
+ $vars->{'token'} = issue_session_token('edit_product');
+
$template->process("admin/products/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'updategroupcontrols') {
+ check_token_data($token, 'edit_group_controls');
# First make sure the product name is valid.
my $product = Bugzilla::Product::check_product($product_name);
}
$dbh->bz_unlock_tables();
- $vars->{'removed_na'} = \@removed_na;
+ delete_token($token);
+ $vars->{'removed_na'} = \@removed_na;
$vars->{'added_mandatory'} = \@added_mandatory;
-
$vars->{'product'} = $product;
$template->process("admin/products/groupcontrol/updated.html.tmpl", $vars)
# action='update' -> update the product
#
if ($action eq 'update') {
-
+ check_token_data($token, 'edit_product');
my $product_old_name = trim($cgi->param('product_old_name') || '');
my $description = trim($cgi->param('description') || '');
my $disallownew = trim($cgi->param('disallownew') || '');
$vars->{'confirmedbugs'} = \@updated_bugs;
$vars->{'changer'} = $user->login;
}
+ delete_token($token);
$vars->{'old_product'} = $product_old;
$vars->{'product'} = $product;
$vars->{'product'} = $product;
$vars->{'groups'} = $groups;
+ $vars->{'token'} = issue_session_token('edit_group_controls');
$vars->{'const'} = {
'CONTROLMAPNA' => CONTROLMAPNA,
use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::User::Setting;
+use Bugzilla::Token;
require "globals.pl";
object => "settings"});
my $action = trim($cgi->param('action') || 'load');
+my $token = $cgi->param('token');
if ($action eq 'update') {
+ check_token_data($token, 'edit_settings');
SaveSettings();
+ delete_token($token);
$vars->{'changes_saved'} = 1;
$template->process("admin/settings/updated.html.tmpl", $vars)
if ($action eq 'load') {
LoadSettings();
+ $vars->{'token'} = issue_session_token('edit_settings');
$template->process("admin/settings/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
use Bugzilla::Util;
use Bugzilla::Field;
use Bugzilla::Group;
+use Bugzilla::Token;
my $user = Bugzilla->login(LOGIN_REQUIRED);
my $action = $cgi->param('action') || 'search';
my $otherUserID = $cgi->param('userid');
my $otherUserLogin = $cgi->param('user');
+my $token = $cgi->param('token');
# Prefill template vars with data used in all or nearly all templates
$vars->{'editusers'} = $editusers;
action => "add",
object => "users"});
+ $vars->{'token'} = issue_session_token('add_user');
+
$template->process('admin/users/create.html.tmpl', $vars)
|| ThrowTemplateError($template->error());
action => "add",
object => "users"});
+ check_token_data($token, 'add_user');
my $login = $cgi->param('login');
my $password = $cgi->param('password');
my $realname = trim($cgi->param('name') || '');
$dbh->bz_unlock_tables();
userDataToVars($new_user_id);
+ delete_token($token);
+
+ # We already display the updated page. We have to recreate a token now.
+ $vars->{'token'} = issue_session_token('edit_user');
$vars->{'message'} = 'account_created';
$template->process('admin/users/edit.html.tmpl', $vars)
|| ThrowTemplateError($template->error());
###########################################################################
} elsif ($action eq 'update') {
+ check_token_data($token, 'edit_user');
my $otherUser = check_user($otherUserID, $otherUserLogin);
$otherUserID = $otherUser->id;
# XXX: userDataToVars may be off when editing ourselves.
userDataToVars($otherUserID);
+ delete_token($token);
$vars->{'message'} = 'account_updated';
$vars->{'loginold'} = $loginold;
$vars->{'groups_removed_from'} = \@groupsRemovedFrom;
$vars->{'groups_granted_rights_to_bless'} = \@groupsGrantedRightsToBless;
$vars->{'groups_denied_rights_to_bless'} = \@groupsDeniedRightsToBless;
+ # We already display the updated page. We have to recreate a token now.
+ $vars->{'token'} = issue_session_token('edit_user');
+
$template->process('admin/users/edit.html.tmpl', $vars)
|| ThrowTemplateError($template->error());
AND mailto_type = ?
},
undef, ($otherUserID, MAILTO_USER));
+ $vars->{'token'} = issue_session_token('delete_user');
$template->process('admin/users/confirm-delete.html.tmpl', $vars)
|| ThrowTemplateError($template->error());
###########################################################################
} elsif ($action eq 'delete') {
+ check_token_data($token, 'delete_user');
my $otherUser = check_user($otherUserID, $otherUserLogin);
$otherUserID = $otherUser->id;
$dbh->do('DELETE FROM profiles WHERE userid = ?', undef, $otherUserID);
$dbh->bz_unlock_tables();
+ delete_token($token);
$vars->{'message'} = 'account_deleted';
$vars->{'otheruser'}{'login'} = $otherUser->login;
object => "user"});
userDataToVars($otherUser->id);
+ $vars->{'token'} = issue_session_token('edit_user');
$template->process('admin/users/edit.html.tmpl', $vars)
|| ThrowTemplateError($template->error());
use Bugzilla::Error;
use Bugzilla::Constants;
use Bugzilla::Config qw(:DEFAULT :admin :locations);
+use Bugzilla::Token;
# List of different tables that contain the changeable field values
# (the old "enums.") Keep them in alphabetical order by their
my $value = trim($cgi->param('value') || '');
my $sortkey = trim($cgi->param('sortkey') || '0');
my $action = trim($cgi->param('action') || '');
+my $token = $cgi->param('token');
# Gives the name of the parameter associated with the field
# and representing its default value.
$vars->{'value'} = $value;
$vars->{'field'} = $field;
+ $vars->{'token'} = issue_session_token('add_field_value');
+
$template->process("admin/fieldvalues/create.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
# action='new' -> add field value entered in the 'action=add' screen
#
if ($action eq 'new') {
+ check_token_data($token, 'add_field_value');
FieldMustExist($field);
trick_taint($field);
$sth->execute($value, $sortkey);
unlink "$datadir/versioncache";
+ delete_token($token);
$vars->{'value'} = $value;
$vars->{'field'} = $field;
$vars->{'value'} = $value;
$vars->{'field'} = $field;
$vars->{'param_name'} = $defaults{$field};
+ $vars->{'token'} = issue_session_token('delete_field_value');
+
$template->process("admin/fieldvalues/confirm-delete.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
# action='delete' -> really delete the field value
#
if ($action eq 'delete') {
+ check_token_data($token, 'delete_field_value');
ValueMustExist($field, $value);
if ($value eq Param($defaults{$field})) {
ThrowUserError('fieldvalue_is_default', {field => $field,
$dbh->bz_unlock_tables();
unlink "$datadir/versioncache";
+ delete_token($token);
$vars->{'value'} = $value;
$vars->{'field'} = $field;
$vars->{'value'} = $value;
$vars->{'field'} = $field;
+ $vars->{'token'} = issue_session_token('edit_field_value');
$template->process("admin/fieldvalues/edit.html.tmpl",
$vars)
# action='update' -> update the field value
#
if ($action eq 'update') {
+ check_token_data($token, 'edit_field_value');
my $valueold = trim($cgi->param('valueold') || '');
my $sortkeyold = trim($cgi->param('sortkeyold') || '0');
unlink "$datadir/versioncache";
$vars->{'default_value_updated'} = 1;
}
+ delete_token($token);
$vars->{'value'} = $value;
$vars->{'field'} = $field;
# Contributor(s): Holger Schurig <holgerschurig@nikocity.de>
# Terry Weissman <terry@mozilla.org>
# Gavin Shelley <bugzilla@chimpychompy.org>
-# Frédéric Buclin <LpSolit@gmail.com>
+# Frédéric Buclin <LpSolit@gmail.com>
#
#
# Direct any questions on this source code to
use Bugzilla::Config qw(:DEFAULT $datadir);
use Bugzilla::Product;
use Bugzilla::Version;
+use Bugzilla::Token;
my $cgi = Bugzilla->cgi;
my $dbh = Bugzilla->dbh;
my $version_name = trim($cgi->param('version') || '');
my $action = trim($cgi->param('action') || '');
my $showbugcounts = (defined $cgi->param('showbugcounts'));
+my $token = $cgi->param('token');
#
# product = '' -> Show nice list of products
#
if ($action eq 'add') {
-
+ $vars->{'token'} = issue_session_token('add_version');
$vars->{'product'} = $product->name;
$template->process("admin/versions/create.html.tmpl",
$vars)
#
if ($action eq 'new') {
-
+ check_token_data($token, 'add_version');
# Cleanups and validity checks
$version_name || ThrowUserError('version_blank_name');
# Make versioncache flush
unlink "$datadir/versioncache";
+ delete_token($token);
$vars->{'name'} = $version_name;
$vars->{'product'} = $product->name;
$vars->{'bug_count'} = $bugs;
$vars->{'name'} = $version->name;
$vars->{'product'} = $product->name;
+ $vars->{'token'} = issue_session_token('delete_version');
+
$template->process("admin/versions/confirm-delete.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'delete') {
-
+ check_token_data($token, 'delete_version');
my $version = Bugzilla::Version::check_version($product,
$version_name);
undef, ($product->id, $version->name));
unlink "$datadir/versioncache";
+ delete_token($token);
$vars->{'name'} = $version->name;
$vars->{'product'} = $product->name;
$vars->{'name'} = $version->name;
$vars->{'product'} = $product->name;
+ $vars->{'token'} = issue_session_token('edit_version');
$template->process("admin/versions/edit.html.tmpl",
$vars)
#
if ($action eq 'update') {
-
+ check_token_data($token, 'edit_version');
$version_name || ThrowUserError('version_not_specified');
# Remove unprintable characters
$vars->{'updated_name'} = 1;
}
- $dbh->bz_unlock_tables();
+ $dbh->bz_unlock_tables();
+ delete_token($token);
$vars->{'name'} = $version_name;
$vars->{'product'} = $product->name;
use Bugzilla::Constants;
use Bugzilla::User;
use Bugzilla::Group;
+use Bugzilla::Token;
+
# require the user to have logged in
my $user = Bugzilla->login(LOGIN_REQUIRED);
my $dbh = Bugzilla->dbh;
my $userid = $user->id;
-
+my $token = $cgi->param('token');
my $sth; # database statement handle
# $events is a hash ref, keyed by event id, that stores the active user's
# removed, then what was altered.
if ($cgi->param('update')) {
+ check_token_data($token, 'edit_whine');
if ($cgi->param("add_event")) {
# we create a new event
$sth = $dbh->prepare("INSERT INTO whine_events " .
}
}
}
+ delete_token($token);
}
$vars->{'mail_others'} = $can_mail_others;
while (my ($query) = $sth->fetchrow_array) {
push @{$vars->{'available_queries'}}, $query;
}
+$vars->{'token'} = issue_session_token('edit_whine');
$template->process("whine/schedule.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}
# Keep a temporary record of the user visiting this page
- $vars->{'token'} = Bugzilla::Token::IssueSessionToken('sudo_prepared');
+ $vars->{'token'} = issue_session_token('sudo_prepared');
# Show the sudo page
$vars->{'target_login_default'} = $cgi->param('target_login');
{ target_login => scalar $cgi->param('target_login'),
reason => scalar $cgi->param('reason')});
}
- Bugzilla::Token::DeleteToken($cgi->param('token'));
+ delete_token($cgi->param('token'));
# Get & verify the target user (the user who we will be impersonating)
my $target_user =
#message
{
- border: 1px solid red;
+ border: 1px solid red;
- padding: 0.3em;
- color: green;
+ padding: 0.3em;
+ color: green;
}
/* header (end) */
}
table#flags th, table#flags td { vertical-align: baseline; text-align: left; }
+
+.throw_error {
+ background-color: #ff0000;
+ color: black;
+ font-size: 120%;
+ margin: 1em;
+ padding: 0.5em 1em;
+}
<hr>
<input type=submit value="Add">
<input type=hidden name="action" value="new">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</FORM>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
<input type=submit value="Yes, delete">
<input type=hidden name="action" value="delete">
<input type=hidden name="classification" value="[% classification.name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
<input type=hidden name="classificationold"
value="[% classification.name FILTER html %]">
<input type=hidden name="action" value="update">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type=submit value="Update">
</form>
<input type=hidden name="action" value="reclassify">
<input type=hidden name="classification" value="[% classification.name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>,
<input type="hidden" name="action" value="delete">
<input type="hidden" name="product" value="[% prod.name FILTER html %]">
<input type="hidden" name="component" value="[% comp.name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
[% END %]
<input type="hidden" name='open_name' value='All Open'>
<input type="hidden" name='nonopen_name' value='All Closed'>
<input type="hidden" name='product' value="[% product FILTER html %]">
-
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
[% PROCESS admin/components/footer.html.tmpl %]
<input type="hidden" name="action" value="update">
<input type="hidden" name="componentold" value="[% comp.name FILTER html %]">
<input type="hidden" name="product" value="[% prod.name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="submit" value="Update"> or <a
href="editcomponents.cgi?action=del&product=
[%- prod.name FILTER url_quote %]&component=
--- /dev/null
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Frédéric Buclin.
+ #
+ # Contributor(s): Frédéric Buclin <LpSolit@gmail.com>
+ #%]
+
+[%# INTERFACE:
+ # abuser: identity of the user who created the (invalid?) token.
+ # token_action: the action the token was supposed to serve.
+ # expected_action: the action the user was going to do.
+ # script_name: the script generating this warning.
+ #%]
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+
+[% PROCESS global/header.html.tmpl title = "Suspicious Action"
+ style_urls = ['skins/standard/global.css'] %]
+
+[% IF abuser %]
+ <div class="throw_error">
+ <p>When you view an administrative form in [% terms.Bugzilla %], a token string
+ is randomly generated and stored both in the database and in the form you loaded,
+ to make sure that the requested changes are being made as a result of submitting
+ a form generated by [% terms.Bugzilla %]. Unfortunately, the token used right now
+ is incorrect, meaning that it looks like you didn't come from the right page.
+ The following token has been used :</p>
+
+ <table border="0" cellpadding="5" cellspacing="0">
+ [% IF token_action != expected_action %]
+ <tr>
+ <th>Action stored:</th>
+ <td>[% token_action FILTER html %]</td>
+ </tr>
+ <tr>
+ <th> </th>
+ <td>
+ This action doesn't match the one expected ([% expected_action FILTER html %]).
+ </td>
+ </tr>
+ [% END %]
+
+ [% IF abuser != user.identity %]
+ <tr>
+ <th>Generated by:</th>
+ <td>[% abuser FILTER html %]</td>
+ </tr>
+ <tr>
+ <th> </th>
+ <td>
+ This token has not been generated by you. It is possible that someone
+ tried to trick you!
+ </td>
+ </tr>
+ [% END %]
+ </table>
+
+ <p>Please report this problem to [%+ Param("maintainer") FILTER html %].</p>
+ </div>
+[% ELSE %]
+ <div class="throw_error">
+ It looks like you didn't come from the right page (you have no valid token for
+ the <em>[% expected_action FILTER html %]</em> action while processing the
+ '[% script_name FILTER html%]' script). The reason could be one of:<br>
+ <ul>
+ <li>You clicked the "Back" button of your web browser after having successfully
+ submitted changes, which is generally not a good idea (but harmless).</li>
+ <li>You entered the URL in the address bar of your web browser directly,
+ which should be safe.</li>
+ <li>You clicked on a URL which redirected you here <b>without your consent</b>,
+ in which case this action is much more critical.</li>
+ </ul>
+ Are you sure you want to commit these changes anyway? This may result in
+ unexpected and undesired results.
+ </div>
+
+ <form name="check" id="check" method="post" action="[% script_name FILTER html %]">
+ [% PROCESS "global/hidden-fields.html.tmpl"
+ exclude="^(Bugzilla_login|Bugzilla_password)$" %]
+ <input type="submit" id="confirm" value="Confirm Changes">
+ </form>
+ <p>Or throw away these changes and go back to <a href="[% script_name FILTER html %]">
+ [%- script_name FILTER html %]</a>.</p>
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
<input type="hidden" name="action" value="delete">
<input type="hidden" name="field" value="[% field FILTER html %]">
<input type="hidden" name="value" value="[% value FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
[% END %]
<input type="submit" value="Add">
<input type="hidden" name="action" value="new">
<input type="hidden" name='field' value="[% field FILTER html %]">
-
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p>
<input type="hidden" name="sortkeyold" value="[% sortkey FILTER html %]">
<input type="hidden" name="action" value="update">
<input type="hidden" name="field" value="[% field FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="submit" value="Update">
-
</form>
<p>
[% PROCESS global/variables.none.tmpl %]
-[%# Filter off the name here to be used multiple times below %]
-[% name = BLOCK %][% flag_type.name FILTER html %][% END %]
+[% title = BLOCK %]Confirm Deletion of Flag Type '[% flag_type.name FILTER html %]'[% END %]
-[% PROCESS global/header.html.tmpl
- title = "Confirm Deletion of Flag Type '$name'"
-%]
+[% PROCESS global/header.html.tmpl title = title %]
<p>
- There are [% flag_count %] flags of type [% name FILTER html %].
+ There are [% flag_count %] flags of type [% flag_type.name FILTER html %].
If you delete this type, those flags will also be deleted. Note that
instead of deleting the type you can
- <a href="editflagtypes.cgi?action=deactivate&id=[% flag_type.id %]">deactivate it</a>,
+ <a href="editflagtypes.cgi?action=deactivate&id=[% flag_type.id %]&token=
+ [%- token FILTER html %]">deactivate it</a>,
in which case the type and its flags will remain in the database
but will not appear in the [% terms.Bugzilla %] UI.
</p>
</tr>
<tr>
<td>
- <a href="editflagtypes.cgi?action=delete&id=[% flag_type.id %]">
- Yes, delete
+ <a href="editflagtypes.cgi?action=delete&id=[% flag_type.id %]&token=
+ [%- token FILTER html %]">Yes, delete
</a>
</td>
<td align="right">
<form method="post" action="editflagtypes.cgi">
<input type="hidden" name="action" value="[% action %]">
<input type="hidden" name="id" value="[% type.id %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="hidden" name="target_type" value="[% type.target_type %]">
[% FOREACH category = type.inclusions %]
<input type="hidden" name="inclusions" value="[% category.value FILTER html %]">
<a href="editflagtypes.cgi?action=enter&target_type=attachment">Create Flag Type For Attachments</a>
</p>
-<script type="text/javascript">
- <!--
- function confirmDelete(id, name, count)
- {
- if (count > 0) {
- var msg = 'There are ' + count + ' flags of type ' + name + '. ' +
- 'If you delete this type, those flags will also be ' +
- 'deleted.\n\nNote: to deactivate the type instead ' +
- 'of deleting it, edit it and uncheck its "is active" ' +
- 'flag.\n\nDo you really want to delete this flag type?';
- if (!confirm(msg)) return false;
- }
- location.href = "editflagtypes.cgi?action=delete&id=" + id;
- return false; // prevent strict JavaScript warning that this function
- // does not always return a value
- }
- //-->
-</script>
-
[% PROCESS global/footer.html.tmpl %]
<td>[% type.description FILTER html %]</td>
<td>
<a href="editflagtypes.cgi?action=copy&id=[% type.id %]">Copy</a>
- | <a href="editflagtypes.cgi?action=confirmdelete&id=[% type.id %]"
- onclick="return confirmDelete([% type.id %], '[% type.name FILTER js FILTER html %]',
- [% type.flag_count %]);">Delete</a>
+ | <a href="editflagtypes.cgi?action=confirmdelete&id=[% type.id %]">Delete</a>
</td>
</tr>
Insert new group into all existing products.<p>
<input type="submit" value="Add">
<input type="hidden" name="action" value="new">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p><b>Name</b> is what is used with the UserInGroup() function in any
<p><input type="submit" value="Yes, delete">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="group" value="[% gid FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
Go back to the <a href="editgroups.cgi">group list</a>.
<input type="hidden" name="action" value="postchanges">
<input type="hidden" name="group" value="[% group_id FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
Back to the <a href="editgroups.cgi">group list</a>.
<input type="hidden" name="id" value="[% keyword_id %]">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="reallydelete" value="1">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="submit" value="Yes, really delete the keyword">
</form>
<input type="hidden" name="id" value="-1">
<input type="submit" value="Add">
<input type="hidden" name="action" value="new">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p><a href="editkeywords.cgi">Edit other keywords</a>.</p>
<input type="submit" value="Update">
<input type="hidden" name="action" value="update">
<input type="hidden" name="id" value="[% keyword_id %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p><a href="editkeywords.cgi">Edit other keywords</a>.</p>
<input type="hidden" name="action" value="delete">
<input type="hidden" name="product" value="[% product FILTER html %]">
<input type="hidden" name="milestone" value="[% name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
[% PROCESS admin/milestones/footer.html.tmpl %]
<input type="submit" value="Add">
<input type="hidden" name="action" value="new">
<input type="hidden" name='product' value="[% product FILTER html %]">
-
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p>
<input type="hidden" name="action" value="update">
<input type="hidden" name="product" value="[% product FILTER html %]">
<input type="submit" value="Update">
-
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p>
[% PROCESS admin/params/common.html.tmpl panel = current_panel %]
<input type="hidden" name="section" value="[% current_panel.name FILTER html %]">
<input type="hidden" name="action" value="save">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="reset" value="Reset form">
<input type="submit" name="action" value="Save Changes">
</form>
<input type="submit" value="Yes, delete">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="product" value="[% product.name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="hidden" name="classification"
value="[% classification.name FILTER html %]">
</form>
<input type="hidden" name="subcategory" value="-All-">
<input type="hidden" name="open_name" value="All Open">
<input type="hidden" name="action" value="new">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="hidden" name="classification"
value="[% classification.name FILTER html %]">
</form>
<input type="hidden" name="product_old_name"
value="[% product.name FILTER html %]">
<input type="hidden" name="action" value="update">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="hidden" name="classification"
value="[% classification.name FILTER html %]">
<input type="submit" name="submit" value="Update">
<form method="post" action="editproducts.cgi">
<input type="hidden" name="action" value="updategroupcontrols">
<input type="hidden" name="product" value="[% product.name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="hidden" name="classification"
value="[% classification.name FILTER html %]">
</table>
<input type="hidden" name="action" value="update">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<table>
<tr>
<td width="150"></td>
<input type="submit" value="Yes, delete" />
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="userid" value="[% otheruser.id %]" />
+ <input type="hidden" name="token" value="[% token FILTER html %]">
[% INCLUDE listselectionhiddenfields %]
</p>
</form>
<p>
<input type="submit" value="Add" />
<input type="hidden" name="action" value="new" />
+ <input type="hidden" name="token" value="[% token FILTER html %]">
[% INCLUDE listselectionhiddenfields %]
</p>
</form>
<input type="submit" value="Update" />
<input type="hidden" name="userid" value="[% otheruser.id %]" />
<input type="hidden" name="action" value="update" />
+ <input type="hidden" name="token" value="[% token FILTER html %]">
[% INCLUDE listselectionhiddenfields %]
</p>
</form>
<input type="hidden" name="action" value="delete">
<input type="hidden" name="product" value="[% product FILTER html %]">
<input type="hidden" name="version" value="[% name FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
[% END %]
<input type="submit" value="Add">
<input type="hidden" name="action" value="new">
<input type="hidden" name='product' value="[% product FILTER html %]">
-
+ <input type="hidden" name="token" value="[% token FILTER html %]">
</form>
<p>
<input type="hidden" name="versionold" value="[% name FILTER html %]">
<input type="hidden" name="action" value="update">
<input type="hidden" name="product" value="[% product FILTER html %]">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
<input type="submit" value="Update">
-
</form>
<p>
'admin/flag-type/list.html.tmpl' => [
'type.id',
- 'type.flag_count',
],
<input type="submit" value="Update / Commit" name="commit"
style="visibility: hidden">
<input type="hidden" name="update" value="1">
+<input type="hidden" name="token" value="[% token FILTER html %]">
[% FOREACH event = events %]