RT 4.0.22
[freeside.git] / rt / t / security / CVE-2011-2084-cf-values.t
diff --git a/rt/t/security/CVE-2011-2084-cf-values.t b/rt/t/security/CVE-2011-2084-cf-values.t
new file mode 100644 (file)
index 0000000..1178b15
--- /dev/null
@@ -0,0 +1,132 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef;
+use JSON qw(decode_json);
+
+my ($base, $m) = RT::Test->started_ok;
+
+my $cf1 = RT::Test->load_or_create_custom_field(
+    Name            => 'cf1',
+    Type            => 'Select',
+    MaxValues       => 1,
+    Queue           => 0,
+);
+ok $cf1->id, "created cf1";
+
+my $cf2 = RT::Test->load_or_create_custom_field(
+    Name            => 'cf2',
+    Type            => 'Select',
+    MaxValues       => 1,
+    Queue           => 0,
+);
+ok $cf2->id, "created cf2";
+
+ok( $cf1->AddValue( Name => "cf1 value $_" ) ) for qw(a b c);
+ok( $cf2->AddValue( Name => "cf2 value $_" ) ) for qw(x y z);
+
+sub ac {
+    my (%args) = (
+        CF          => $cf1->id,
+        Term        => "%",
+        Context     => undef,
+        ContextId   => undef,
+        ContextType => undef,
+        @_
+    );
+    $args{term} = delete $args{Term};
+
+    if (my $obj = delete $args{Context}) {
+        $args{ContextId}   = $obj->Id  unless defined $args{ContextId};
+        $args{ContextType} = ref($obj) unless defined $args{ContextType};
+    }
+
+    $args{"Object---CustomField-$args{CF}-Values"} = "";
+    delete $args{CF};
+
+    delete $args{$_} for grep {not defined $args{$_}} keys %args;
+
+    my $URI = URI->new("$base/Helpers/Autocomplete/CustomFieldValues");
+    $URI->query_form( %args );
+    $m->get_ok($URI, "GET to autocompleter");
+    return decode_json($m->content);
+}
+
+$m->login;
+is_deeply ac(CF => 12345, ContextId => 1, ContextType => "RT::Queue"),
+    [], 'nothing for invalid CF';
+
+is_deeply ac(),
+    [], "Nothing without a context id";
+is_deeply ac( ContextId => 12345, ContextType => "RT::Queue"),
+    [], "Nothing with invalid contextid id";
+is_deeply ac( ContextId => 12, ContextType => "RT::User"),
+    [], "Nothing with invalid contextid type";
+
+
+
+my $user = RT::Test->load_or_create_user(
+    Name        => 'user',
+    Password    => 'password',
+    Privileged  => 1,
+);
+my $queue = RT::Test->load_or_create_queue( Name => 'CF Test' );
+ok $queue->id, 'found or created queue';
+my $ticket = RT::Test->create_ticket(
+    Queue => $queue->id,
+    Subject => "CF application",
+);
+ok $queue->id, 'created ticket';
+
+$m->logout;
+$m->login('user','password');
+
+is_deeply ac( Context => $queue ), [], 'queue context, no permissions, no result';
+is_deeply ac( Context => $ticket ), [], 'ticket context, no permissions, no result';
+
+ok( RT::Test->set_rights(
+    { Principal => $user, Right => [qw(SeeCustomField)], Object => $queue },
+), 'add queue level CF viewing rights');
+
+my $cfvalues = [ ( map { { value => "cf1 value $_" , label => "cf1 value $_" } } qw(a b c) ) ];
+is_deeply ac( Context => $queue ), $cfvalues, 'queue context, with permissions get result';
+is_deeply ac( Context => $ticket ), $cfvalues, 'ticket context, with permissions get result';
+
+{
+    diag "Switching to non-global CFs";
+    my $globalq = RT::Queue->new( RT->SystemUser );
+    my ($status, $msg) = $cf1->RemoveFromObject( $globalq );
+    ok($status, "Removed CF1 globally: $msg");
+    ($status, $msg) = $cf1->AddToObject( $queue );
+    ok($status, "Added CF1 to queue @{[$queue->id]}: $msg");
+    ($status, $msg) = $cf2->RemoveFromObject( $globalq );
+    ok($status, "Removed CF2 globally: $msg");
+}
+
+is_deeply ac( CF => $cf2->id, Context => $queue ), [], 'queue context, but not applied, get no result';
+is_deeply ac( CF => $cf2->id, Context => $ticket ), [], 'ticket context, but not applied, get no result';
+
+is_deeply ac( Context => $queue ), $cfvalues, 'queue context, applied correctly, get result';
+is_deeply ac( Context => $ticket ), $cfvalues, 'ticket context, applied correctly, get result';
+
+
+
+diag "Ticket-level rights";
+
+ok( RT::Test->set_rights(
+    { Principal => "Owner", Right => [qw(SeeCustomField)], Object => $queue },
+    { Principal => $user,   Right => [qw(OwnTicket SeeTicket)], Object => RT->System },
+), 'add owner level CF viewing rights');
+
+is_deeply ac( Context => $queue ), [], 'queue context, but not owner';
+is_deeply ac( Context => $ticket ), [], 'ticket context, but not owner';
+
+my ($status, $msg) = $ticket->SetOwner( $user->id );
+ok( $status, "Set owner to user: $msg" );
+
+is_deeply ac( Context => $queue ), [], 'queue context is not enough';
+is_deeply ac( Context => $ticket ), $cfvalues, 'ticket context, get values';
+
+
+undef $m;
+done_testing;