Bug 197153: Fix for insecure temporary filename handling.

Patch by Brad Baetz <bbaetz@acm.org> r= justdave, gerv a= justdave
parent e9841817
...@@ -873,14 +873,13 @@ END ...@@ -873,14 +873,13 @@ END
# Restrict access to .dot files to the public webdot server at research.att.com # Restrict access to .dot files to the public webdot server at research.att.com
# if research.att.com ever changed their IP, or if you use a different # if research.att.com ever changed their IP, or if you use a different
# webdot server, you'll need to edit this # webdot server, you'll need to edit this
<FilesMatch ^[0-9]+\.dot$> <FilesMatch \.dot$>
Allow from 192.20.225.10 Allow from 192.20.225.10
Deny from all Deny from all
</FilesMatch> </FilesMatch>
# Allow access by a local copy of 'dot' to .png, .gif, .jpg, and # Allow access to .png files created by a local copy of 'dot'
# .map files <FilesMatch \.png$>
<FilesMatch ^[0-9]+\.(png|gif|jpg|map)$>
Allow from all Allow from all
</FilesMatch> </FilesMatch>
......
...@@ -99,7 +99,7 @@ sub check_webdotbase { ...@@ -99,7 +99,7 @@ sub check_webdotbase {
# Check .htaccess allows access to generated images # Check .htaccess allows access to generated images
if(-e "data/webdot/.htaccess") { if(-e "data/webdot/.htaccess") {
open HTACCESS, "data/webdot/.htaccess"; open HTACCESS, "data/webdot/.htaccess";
if(! grep(/png/,<HTACCESS>)) { if(! grep(/ \\\.png\$/,<HTACCESS>)) {
return "Dependency graph images are not accessible.\nDelete data/webdot/.htaccess and re-run checksetup.pl to rectify.\n"; return "Dependency graph images are not accessible.\nDelete data/webdot/.htaccess and re-run checksetup.pl to rectify.\n";
} }
close HTACCESS; close HTACCESS;
......
...@@ -237,19 +237,21 @@ sub GenerateVersionTable { ...@@ -237,19 +237,21 @@ sub GenerateVersionTable {
my @list = sort { uc($a) cmp uc($b)} keys(%::versions); my @list = sort { uc($a) cmp uc($b)} keys(%::versions);
@::legal_product = @list; @::legal_product = @list;
my $tmpname = "data/versioncache.$$";
open(FID, ">$tmpname") || die "Can't create $tmpname";
print FID "#\n"; require File::Temp;
print FID "# DO NOT EDIT!\n"; my ($fh, $tmpname) = File::Temp::tempfile("versioncache.XXXXX",
print FID "# This file is automatically generated at least once every\n"; DIR => "data");
print FID "# hour by the GenerateVersionTable() sub in globals.pl.\n";
print FID "# Any changes you make will be overwritten.\n"; print $fh "#\n";
print FID "#\n"; print $fh "# DO NOT EDIT!\n";
print $fh "# This file is automatically generated at least once every\n";
print $fh "# hour by the GenerateVersionTable() sub in globals.pl.\n";
print $fh "# Any changes you make will be overwritten.\n";
print $fh "#\n";
require Data::Dumper; require Data::Dumper;
print FID Data::Dumper->Dump([\@::log_columns, \%::versions], print($fh,Data::Dumper->Dump([\@::log_columns, \%::versions],
['*::log_columns', '*::versions']); ['*::log_columns', '*::versions']));
foreach my $i (@list) { foreach my $i (@list) {
if (!defined $::components{$i}) { if (!defined $::components{$i}) {
...@@ -257,23 +259,23 @@ sub GenerateVersionTable { ...@@ -257,23 +259,23 @@ sub GenerateVersionTable {
} }
} }
@::legal_versions = sort {uc($a) cmp uc($b)} keys(%varray); @::legal_versions = sort {uc($a) cmp uc($b)} keys(%varray);
print FID Data::Dumper->Dump([\@::legal_versions, \%::components], print($fh,Data::Dumper->Dump([\@::legal_versions, \%::components],
['*::legal_versions', '*::components']); ['*::legal_versions', '*::components']));
@::legal_components = sort {uc($a) cmp uc($b)} keys(%carray); @::legal_components = sort {uc($a) cmp uc($b)} keys(%carray);
print FID Data::Dumper->Dump([\@::legal_components, \@::legal_product, print($fh,Data::Dumper->Dump([\@::legal_components, \@::legal_product,
\@::legal_priority, \@::legal_severity, \@::legal_priority, \@::legal_severity,
\@::legal_platform, \@::legal_opsys, \@::legal_platform, \@::legal_opsys,
\@::legal_bug_status, \@::legal_resolution], \@::legal_bug_status, \@::legal_resolution],
['*::legal_components', '*::legal_product', ['*::legal_components', '*::legal_product',
'*::legal_priority', '*::legal_severity', '*::legal_priority', '*::legal_severity',
'*::legal_platform', '*::legal_opsys', '*::legal_platform', '*::legal_opsys',
'*::legal_bug_status', '*::legal_resolution']); '*::legal_bug_status', '*::legal_resolution']));
print FID Data::Dumper->Dump([\@::settable_resolution, \%::proddesc, print($fh,Data::Dumper->Dump([\@::settable_resolution, \%::proddesc,
\@::enterable_products, \%::prodmaxvotes], \@::enterable_products, \%::prodmaxvotes],
['*::settable_resolution', '*::proddesc', ['*::settable_resolution', '*::proddesc',
'*::enterable_products', '*::prodmaxvotes']); '*::enterable_products', '*::prodmaxvotes']));
if ($dotargetmilestone) { if ($dotargetmilestone) {
# reading target milestones in from the database - matthew@zeroknowledge.com # reading target milestones in from the database - matthew@zeroknowledge.com
...@@ -296,12 +298,12 @@ sub GenerateVersionTable { ...@@ -296,12 +298,12 @@ sub GenerateVersionTable {
} }
} }
print FID Data::Dumper->Dump([\%::target_milestone, print($fh,Data::Dumper->Dump([\%::target_milestone,
\@::legal_target_milestone, \@::legal_target_milestone,
\%::milestoneurl], \%::milestoneurl],
['*::target_milestone', ['*::target_milestone',
'*::legal_target_milestone', '*::legal_target_milestone',
'*::milestoneurl']); '*::milestoneurl']));
} }
SendSQL("SELECT id, name FROM keyworddefs ORDER BY name"); SendSQL("SELECT id, name FROM keyworddefs ORDER BY name");
...@@ -312,11 +314,11 @@ sub GenerateVersionTable { ...@@ -312,11 +314,11 @@ sub GenerateVersionTable {
$::keywordsbyname{$name} = $id; $::keywordsbyname{$name} = $id;
} }
print FID Data::Dumper->Dump([\@::legal_keywords, \%::keywordsbyname], print($fh,Data::Dumper->Dump([\@::legal_keywords, \%::keywordsbyname],
['*::legal_keywords', '*::keywordsbyname']); ['*::legal_keywords', '*::keywordsbyname']));
print FID "1;\n"; print $fh "1;\n";
close FID; close $fh;
rename $tmpname, "data/versioncache" || die "Can't rename $tmpname to versioncache"; rename $tmpname, "data/versioncache" || die "Can't rename $tmpname to versioncache";
ChmodDataFile('data/versioncache', 0666); ChmodDataFile('data/versioncache', 0666);
......
...@@ -25,6 +25,8 @@ use strict; ...@@ -25,6 +25,8 @@ use strict;
use lib qw(.); use lib qw(.);
use File::Temp;
require "CGI.pl"; require "CGI.pl";
ConnectToDatabase(); ConnectToDatabase();
...@@ -62,11 +64,11 @@ sub CreateImagemap { ...@@ -62,11 +64,11 @@ sub CreateImagemap {
} }
sub AddLink { sub AddLink {
my ($blocked, $dependson) = (@_); my ($blocked, $dependson, $fh) = (@_);
my $key = "$blocked,$dependson"; my $key = "$blocked,$dependson";
if (!exists $edgesdone{$key}) { if (!exists $edgesdone{$key}) {
$edgesdone{$key} = 1; $edgesdone{$key} = 1;
print DOT "$blocked -> $dependson\n"; print $fh "$blocked -> $dependson\n";
$seen{$blocked} = 1; $seen{$blocked} = 1;
$seen{$dependson} = 1; $seen{$dependson} = 1;
} }
...@@ -78,12 +80,13 @@ if (!defined($::FORM{'id'}) && !defined($::FORM{'doall'})) { ...@@ -78,12 +80,13 @@ if (!defined($::FORM{'id'}) && !defined($::FORM{'doall'})) {
ThrowCodeError("missing_bug_id"); ThrowCodeError("missing_bug_id");
} }
my $filename = "data/webdot/$$.dot"; my ($fh, $filename) = File::Temp::tempfile("XXXXXXXXXX",
SUFFIX => '.dot',
DIR => "data/webdot");
my $urlbase = Param('urlbase'); my $urlbase = Param('urlbase');
open(DOT, ">$filename") || die "Can't create $filename"; print $fh "digraph G {";
print DOT "digraph G {"; print $fh qq{
print DOT qq{
graph [URL="${urlbase}query.cgi", rankdir=$::FORM{'rankdir'}, size="64,64"] graph [URL="${urlbase}query.cgi", rankdir=$::FORM{'rankdir'}, size="64,64"]
node [URL="${urlbase}show_bug.cgi?id=\\N", style=filled, color=lightgrey] node [URL="${urlbase}show_bug.cgi?id=\\N", style=filled, color=lightgrey]
}; };
...@@ -95,7 +98,7 @@ if ($::FORM{'doall'}) { ...@@ -95,7 +98,7 @@ if ($::FORM{'doall'}) {
while (MoreSQLData()) { while (MoreSQLData()) {
my ($blocked, $dependson) = FetchSQLData(); my ($blocked, $dependson) = FetchSQLData();
AddLink($blocked, $dependson); AddLink($blocked, $dependson, $fh);
} }
} else { } else {
foreach my $i (split('[\s,]+', $::FORM{'id'})) { foreach my $i (split('[\s,]+', $::FORM{'id'})) {
...@@ -119,7 +122,7 @@ if ($::FORM{'doall'}) { ...@@ -119,7 +122,7 @@ if ($::FORM{'doall'}) {
push @stack, $dependson; push @stack, $dependson;
} }
AddLink($blocked, $dependson); AddLink($blocked, $dependson, $fh);
} }
} }
...@@ -159,15 +162,15 @@ foreach my $k (keys(%seen)) { ...@@ -159,15 +162,15 @@ foreach my $k (keys(%seen)) {
} }
if (@params) { if (@params) {
print DOT "$k [" . join(',', @params) . "]\n"; print $fh "$k [" . join(',', @params) . "]\n";
} else { } else {
print DOT "$k\n"; print $fh "$k\n";
} }
} }
print DOT "}\n"; print $fh "}\n";
close DOT; close $fh;
chmod 0777, $filename; chmod 0777, $filename;
...@@ -180,11 +183,23 @@ if ($webdotbase =~ /^https?:/) { ...@@ -180,11 +183,23 @@ if ($webdotbase =~ /^https?:/) {
$vars->{'map_url'} = $url . ".map"; $vars->{'map_url'} = $url . ".map";
} else { } else {
# Local dot installation # Local dot installation
my $pngfilename = "data/webdot/$$.png"; my $dotfh;
my $mapfilename = "data/webdot/$$.map"; my ($pngfh, $pngfilename) = File::Temp::tempfile("XXXXXXXXXX",
system("$webdotbase","-Tpng","-o","$pngfilename","$filename"); SUFFIX => '.png',
DIR => 'data/webdot');
open (DOT, '-|') or exec ($webdotbase, "-Tpng", $filename);
print $pngfh $_ while <DOT>;
close DOT;
close $pngfh;
$vars->{'image_url'} = $pngfilename; $vars->{'image_url'} = $pngfilename;
system("$webdotbase","-Tismap","-o","$mapfilename","$filename");
my ($mapfh, $mapfilename) = File::Temp::tempfile("XXXXXXXXXX",
SUFFIX => '.map',
DIR => 'data/webdot');
open (DOT, '-|') or exec ($webdotbase, "-Tismap", $filename);
print $mapfh $_ while <DOT>;
close DOT;
close $mapfh;
$vars->{'image_map'} = CreateImagemap($mapfilename); $vars->{'image_map'} = CreateImagemap($mapfilename);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment