Skip to content

Commit 10bf6d4

Browse files
committed
Bug 1317965 - Flag permission checks broken by bug 1257662 allowing unauthorized flag modification
1 parent 648ddd3 commit 10bf6d4

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

Bugzilla/Flag.pm

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -768,23 +768,11 @@ sub _check_setter {
768768
# to the new flag status.
769769
my $status = $self->status;
770770

771-
# Make sure the user is authorized to modify flags, see bug 180879:
772-
# - The flag exists and is unchanged.
773-
# - The flag setter can unset flag.
774-
# - Users in the request_group can clear pending requests
775-
# - Users in the grant_group can set/cleari/request flags, including "+" and "-".
776-
unless (($status eq $self->{_old_status})
777-
|| ($status eq 'X' && $setter->id == Bugzilla->user->id)
778-
|| (($status eq 'X' || $status eq '?')
779-
&& $setter->can_request_flag($self->type))
780-
|| $setter->can_unset_flag($self->type, $self->{_old_status})
781-
|| $setter->can_set_flag($self->type))
782-
{
783-
ThrowUserError('flag_update_denied',
784-
{ name => $self->type->name,
785-
status => $status,
786-
old_status => $self->{_old_status} });
787-
}
771+
ThrowUserError('flag_update_denied',
772+
{ name => $self->type->name,
773+
status => $status,
774+
old_status => $self->{_old_status} })
775+
unless $setter->can_change_flag($self->type, $self->{_old_status} || 'X', $status);
788776

789777
# If the request is being retargetted, we don't update
790778
# the setter, so that the setter gets the notification.

Bugzilla/User.pm

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,52 @@ sub check_can_admin_flagtype {
15831583
return wantarray ? ($flagtype, $can_fully_edit) : $flagtype;
15841584
}
15851585

1586+
sub can_change_flag {
1587+
my ($self, $flag_type, $old_status, $new_status) = @_;
1588+
1589+
# "old_status:new_status" => [OR conditions
1590+
state $flag_transitions = {
1591+
'X:-' => ['grant_group'],
1592+
'X:+' => ['grant_group'],
1593+
'X:?' => ['request_group'],
1594+
1595+
'?:X' => ['request_group', 'is_setter'],
1596+
'?:-' => ['grant_group'],
1597+
'?:+' => ['grant_group'],
1598+
1599+
'+:X' => ['grant_group'],
1600+
'+:-' => ['grant_group'],
1601+
'+:?' => ['grant_group'],
1602+
1603+
'-:X' => ['grant_group'],
1604+
'-:+' => ['grant_group'],
1605+
'-:?' => ['grant_group'],
1606+
};
1607+
1608+
return 1 if $new_status eq $old_status;
1609+
1610+
my $action = "$old_status:$new_status";
1611+
my %bool = (
1612+
request_group => $self->can_request_flag($flag_type),
1613+
grant_group => $self->can_set_flag($flag_type),
1614+
is_setter => $self->id == Bugzilla->user->id,
1615+
);
1616+
1617+
my $cond = $flag_transitions->{$action};
1618+
if ($cond) {
1619+
if (any { $bool{ $_ } } @$cond) {
1620+
return 1;
1621+
}
1622+
else {
1623+
return 0;
1624+
}
1625+
}
1626+
else {
1627+
warn "unknown flag transition blocked: $action";
1628+
return 0;
1629+
}
1630+
}
1631+
15861632
sub can_request_flag {
15871633
my ($self, $flag_type) = @_;
15881634

0 commit comments

Comments
 (0)