]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 287109: [SECURITY] Names of private products/components can be exposed on certain...
authormkanat%kerio.com <>
Thu, 12 May 2005 09:08:34 +0000 (09:08 +0000)
committermkanat%kerio.com <>
Thu, 12 May 2005 09:08:34 +0000 (09:08 +0000)
Patch By Frederic Buclin <LpSolit@gmail.com> r=myk, a=justdave

enter_bug.cgi
globals.pl
post_bug.cgi
process_bug.cgi
reports.cgi
template/en/default/global/user-error.html.tmpl

index 0b30f65e697d9b67d71d359f1dae23fbf4a78ed1..d41ea4fd024cc1ac6cef65803c888830c3983000 100755 (executable)
@@ -223,17 +223,10 @@ Bugzilla->login(LOGIN_REQUIRED) if (!(AnyEntryGroups()));
 
 # We need to check and make sure
 # that the user has permission to enter a bug against this product.
-if(!CanEnterProduct($product))
-{
-    ThrowUserError("entry_access_denied", { product => $product});         
-}
+CanEnterProductOrWarn($product);
 
 GetVersionTable();
 
-if (lsearch(\@::enterable_products, $product) == -1) {
-    ThrowUserError("invalid_product_name", { product => $product});
-}
-
 my $product_id = get_product_id($product);
 
 if (0 == @{$::components{$product}}) {        
index c4cb8d33a298035702b962be5c281f3af437ed7a..99a58dadedd66690f6b4b42d06e5c4e3aaf8a5b5 100644 (file)
@@ -493,11 +493,16 @@ sub CanEditProductId {
     return (!defined($result));
 }
 
-#
-# This function determines if a user can enter bugs in the named
-# product.
+# This function determines whether or not a user can enter
+# bugs into the named product.
 sub CanEnterProduct {
-    my ($productname) = @_;
+    my ($productname, $verbose) = @_;
+    my $dbh = Bugzilla->dbh;
+
+    return unless defined($productname);
+    trick_taint($productname);
+
+    # First check whether or not the user has access to that product.
     my $query = "SELECT group_id IS NULL " .
                 "FROM products " .
                 "LEFT JOIN group_control_map " .
@@ -507,12 +512,51 @@ sub CanEnterProduct {
         $query .= "AND group_id NOT IN(" . 
                    join(',', values(%{Bugzilla->user->groups})) . ") ";
     }
-    $query .= "WHERE products.name = " . SqlQuote($productname) . " LIMIT 1";
-    PushGlobalSQLState();
-    SendSQL($query);
-    my ($ret) = FetchSQLData();
-    PopGlobalSQLState();
-    return ($ret);
+    $query .= "WHERE products.name = ? LIMIT 1";
+
+    my $has_access = $dbh->selectrow_array($query, undef, $productname);
+    if (!$has_access) {
+        # Do we require the exact reason why we cannot enter
+        # bugs into that product? Returning -1 explicitely
+        # means the user has no access to the product or the
+        # product does not exist.
+        return (defined($verbose)) ? -1 : 0;
+    }
+
+    # Check if the product is open for new bugs and has
+    # at least one component.
+    my $allow_new_bugs =
+        $dbh->selectrow_array("SELECT CASE WHEN disallownew = 0 THEN 1 ELSE 0 END
+                               FROM products INNER JOIN components
+                               ON components.product_id = products.id
+                               WHERE products.name = ? LIMIT 1",
+                               undef, $productname);
+
+    # Return 1 if the user can enter bugs into that product;
+    # return 0 if the product is closed for new bug entry;
+    # return undef if the product has no component.
+    return $allow_new_bugs;
+}
+
+# Call CanEnterProduct() and display an error message
+# if the user cannot enter bugs into that product.
+sub CanEnterProductOrWarn {
+    my ($product) = @_;
+
+    if (!defined($product)) {
+        ThrowUserError("no_products");
+    }
+    my $status = CanEnterProduct($product, 1);
+    trick_taint($product);
+
+    if (!defined($status)) {
+        ThrowUserError("no_components", { product => $product});
+    } elsif (!$status) {
+        ThrowUserError("product_disabled", { product => $product});
+    } elsif ($status < 0) {
+        ThrowUserError("entry_access_denied", { product => $product});
+    }
+    return $status;
 }
 
 sub GetEnterableProducts {
index 56e57c5125f4976c83958dc5d9bfe78783ffd952..514e57a31186053b9e6e255e5b17453db0e8c2ae 100755 (executable)
@@ -78,11 +78,10 @@ $template->process($format->{'template'}, $vars, \$comment)
 ValidateComment($comment);
 
 # Check that the product exists and that the user
-# is allowed to submit bugs in this product.
+# is allowed to enter bugs into this product.
 my $product = $::FORM{'product'};
-if (!CanEnterProduct($product)) {
-    ThrowUserError("entry_access_denied", {product => $product});
-}
+CanEnterProductOrWarn($product);
+
 my $product_id = get_product_id($product);
 
 # Set cookies
index 3dd5f52ee32c84ce4c51953daec1e22e8cf10248..61270c4675d69e4fb4e15be3efbf7dcc6dcf2054 100755 (executable)
@@ -45,7 +45,8 @@ use Bugzilla::Flag;
 
 # Shut up misguided -w warnings about "used only once":
 
-use vars qw(%versions
+use vars qw(@legal_product
+          %versions
           %components
           %COOKIE
           %legal_opsys
@@ -247,8 +248,24 @@ if ((($::FORM{'id'} && $::FORM{'product'} ne $::oldproduct)
                        "abort");
     }
  
-    CheckFormField(\%::FORM, 'product', \@::legal_product);
     my $prod = $::FORM{'product'};
+    trick_taint($prod);
+
+    # If at least one bug does not belong to the product we are
+    # moving to, we have to check whether or not the user is
+    # allowed to enter bugs into that product.
+    # Note that this check must be done early to avoid the leakage
+    # of component, version and target milestone names.
+    my $check_can_enter =
+        $dbh->selectrow_array("SELECT 1 FROM bugs
+                               INNER JOIN products
+                               ON bugs.product_id = products.id
+                               WHERE products.name != ?
+                               AND bugs.bug_id IN
+                               (" . join(',', @idlist) . ") LIMIT 1",
+                               undef, $prod) || 0;
+
+    if ($check_can_enter) { CanEnterProductOrWarn($prod) }
 
     # note that when this script is called from buglist.cgi (rather
     # than show_bug.cgi), it's possible that the product will be changed
@@ -708,6 +725,7 @@ if ($::FORM{'component'} ne $::FORM{'dontchange'}) {
                                 product => $::FORM{'product'}});
     
     DoComma();
+    $::FORM{'component_id'} = $comp_id;
     $::query .= "component_id = $comp_id";
 }
 
@@ -1122,17 +1140,6 @@ foreach my $id (@idlist) {
             "group_control_map READ");
     my @oldvalues = SnapShotBug($id);
     my %oldhash;
-    # Fun hack.  @::log_columns only contains the component_id,
-    # not the name (since bug 43600 got fixed).  So, we need to have
-    # this id ready for the loop below, otherwise anybody can
-    # change the component of a bug (we checked product above).
-    # http://bugzilla.mozilla.org/show_bug.cgi?id=180545
-    my $product_id = get_product_id($::FORM{'product'});
-    
-    if ($::FORM{'component'} ne $::FORM{'dontchange'}) {
-        $::FORM{'component_id'} = 
-                            get_component_id($product_id, $::FORM{'component'});
-    }
     
     my $i = 0;
     foreach my $col (@::log_columns) {
@@ -1183,13 +1190,6 @@ foreach my $id (@idlist) {
                       { product => $oldhash{'product'} }, "abort");
     }
 
-    if (defined $::FORM{'product'} 
-        && $::FORM{'product'} ne $::FORM{'dontchange'} 
-        && $::FORM{'product'} ne $oldhash{'product'}
-        && !CanEnterProduct($::FORM{'product'})) {
-        ThrowUserError("entry_access_denied",
-                       { product => $::FORM{'product'} }, "abort");
-    }
     if ($requiremilestone) {
         # musthavemilestoneonaccept applies only if at least two
         # target milestones are defined for the current product.
index a3e2c740e0e1f5d2a9814917ec1960eb9bd7485d..c5314b33e79161fb959ec538382a1d84da51552e 100755 (executable)
@@ -85,9 +85,7 @@ if (! defined $cgi->param('product')) {
 
     # We don't want people to be able to view
     # reports for products they don't have permissions for...
-    if (($product ne '-All-') && (!CanEnterProduct($product))) {
-        ThrowUserError("report_access_denied");
-    }
+    if ($product ne '-All-') { CanEnterProductOrWarn($product) }
           
     # We've checked that the product exists, and that the user can see it
     # This means that is OK to detaint
index f0c94ef9322503d1a5c25a397d4d3546fb1124c2..aaf53a205813eccbcdbbab45fc9107e6b4385c12 100644 (file)
 
   [% ELSIF error == "entry_access_denied" %]
     [% title = "Permission Denied" %]
-    Sorry; you do not have the permissions necessary to enter [% terms.abug %]
-    against the [% product FILTER html %] product.
+    Sorry, either the product <em>[% product FILTER html %]</em> does not
+    exist, or you don't have the required permissions to
+    enter [% terms.abug %] against that product.
 
   [% ELSIF error == "file_not_specified" %]
     [% title = "No File Specified" %]
     Patches cannot be more than [% Param('maxpatchsize') %] KB in size.
     Try breaking your patch into several pieces.
 
+  [% ELSIF error == "product_disabled" %]
+    [% title = BLOCK %]Product closed for [% terms.Bugs %] Entry[% END %]
+    Sorry, entering [% terms.bugs %] into
+    product <em>[% product FILTER html %]</em> has been disabled.
+
   [% ELSIF error == "product_edit_denied" %]
     [% title = "Product Edit Access Denied" %]
     You are not permitted to edit [% terms.bugs %] in product