Add check routines to sanitize user input.

Rename sanitize_revision to SanitizeRevision and move it to globals.pl.
Bug #261616 r=timeless
This commit is contained in:
cls%seawood.org 2004-11-30 23:56:13 +00:00
parent 89ac7432f0
commit 42bf1ea441
9 changed files with 200 additions and 23 deletions

View File

@ -49,6 +49,8 @@ sub url_quote {
# Quotify a string, suitable for output as form values
sub value_quote {
my ($var) = (@_);
return "" if (!defined($var));
$var =~ s/\&/\&/g;
$var =~ s/</\&lt;/g;
$var =~ s/>/\&gt;/g;
@ -75,19 +77,6 @@ sub url_encode2 {
return $s;
}
# Make sure CVS revisions are in a specific format
sub sanitize_revision {
my ($rev) = @_;
if ($rev =~ /^[A-Za-z]+/) {
$rev =~ s/^([\w-]+).*/$1/;
} elsif ($rev =~ /^\d+\.\d+/) {
$rev =~ s/^(\d+[\.\d+]+).*/$1/;
} elsif (defined($rev) && $rev ne "") {
$rev = "1.1";
}
return $rev;
}
##
## Routines to generate html as part of Bonsai
##

View File

@ -96,7 +96,7 @@ my $url_file_tail = url_quote($file_tail);
# Handle the "rev" argument
#
$::opt_rev = '';
$::opt_rev = sanitize_revision($::FORM{rev}) if
$::opt_rev = &SanitizeRevision($::FORM{rev}) if
defined $::FORM{rev} and $::FORM{rev} ne 'HEAD';
my $revstr = '';
$revstr = "&rev=$::opt_rev" unless $::opt_rev eq '';

View File

@ -27,7 +27,7 @@ require 'CGI.pl';
my $file= $::FORM{'file'};
my $mark= $::FORM{'mark'};
my $ln = ($mark > 10 ? $mark-10 : 1 );
my $rev = sanitize_revision($::FORM{'rev'});
my $rev = SanitizeRevision($::FORM{'rev'});
my $debug = $::FORM{'debug'};
print "Content-Type: text/html\n\n";

View File

@ -76,7 +76,7 @@ my $url_file_tail = url_quote($file_tail);
# Handle the "rev" argument
#
$::opt_rev = "";
$::opt_rev = sanitize_revision($::FORM{'rev'}) if
$::opt_rev = &SanitizeRevision($::FORM{'rev'}) if
defined $::FORM{'rev'} && $::FORM{'rev'} !~ m/^(HEAD|MAIN)$/;
my $revstr = '';
$revstr = "&rev=$::opt_rev" unless $::opt_rev eq '';

View File

@ -119,7 +119,7 @@ print "</td></tr>";
# Branch
#
if( defined $::FORM{branch} ){
$b = sanitize_revision($::FORM{branch});
$b = &SanitizeRevision($::FORM{branch});
} else {
$b = "HEAD";
}

View File

@ -122,17 +122,17 @@ $prefix = $script_name . $ENV{PATH_INFO} . '?' if (exists($ENV{PATH_INFO}));
# http://w3/cgi/cvsview.pl?subdir=foo&file=bar would assign
# $opt_subdir = foo and $opt_file = bar.
my $opt_rev1 = sanitize_revision($request->param('rev1'));
my $opt_rev2 = sanitize_revision($request->param('rev2'));
my $opt_rev1 = &SanitizeRevision($request->param('rev1'));
my $opt_rev2 = &SanitizeRevision($request->param('rev2'));
my $opt_root = $request->param('root');
my $opt_files = $request->param('files');
my $opt_skip = $request->param('skip') || 0;
my $opt_diff_mode = $request->param('diff_mode') || 'context';
my $opt_whitespace_mode = $request->param('whitespace_mode') || 'show';
my $opt_file = $request->param('file');
my $opt_rev = sanitize_revision($request->param('rev'));
my $opt_rev = &SanitizeRevision($request->param('rev'));
my $opt_subdir = $request->param('subdir');
my $opt_branch = sanitize_revision($request->param('branch'));
my $opt_branch = &SanitizeRevision($request->param('branch'));
my $opt_command = $request->param('command');
my $url_file = url_quote($opt_file);

View File

@ -25,6 +25,7 @@ $::TreeID = "default";
use strict;
use DBI;
use File::Basename;
use File::Path;
use Date::Format; # For time2str().
@ -1052,12 +1053,28 @@ sub validateRepository {
}
my $escaped_root = html_quote($root);
print "\n";
print "Invalid repository `$escaped_root' selected.\n";
print ConstructMailTo(Param('maintainer'), "Invalid Repository '$root'");
print " if you think this should have worked.\n";
exit;
}
# Verify that the current script is being called from a specific other script
sub validateReferer {
my (@scripts) = @_;
my $script;
my $found = 0;
my $script_path = dirname("$ENV{'SERVER_NAME'}$ENV{'SCRIPT_NAME'}");
my $referer = $ENV{'HTTP_REFERER'} || "";
foreach $script (@scripts) {
$found++ if
($referer =~ m@^http(s)?://(\w+(:\w+)?\@)?$script_path/$script(\?|$)@i);
}
die "This script cannot be called directly.\n" if (!$found);
}
sub formatSqlTime {
my ($date) = @_;
my $time = sprintf("%u", $date);
@ -1068,6 +1085,23 @@ sub formatSqlTime {
return $time;
}
##
## Miscelaneous routines from lloydcgi.pl
##
my @weekdays = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
my @months = ('Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec');
sub toGMTString {
my ($seconds) = $_[0];
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
= gmtime($seconds);
$year += 1900;
sprintf('%s, %02d-%s-%d %02d:%02d:%02d GMT',
$weekdays[$wday],$mday,$months[$mon],$year,$hour,$min,$sec);
}
# Returns true if the given directory or filename is one of the hidden ones
# that we don't want to show users.
@ -1118,6 +1152,8 @@ sub MarkUpText {
my $bugsmatch = Param('bugsmatch');
my %substs = ();
return $text if (!$bugsrpl);
$substs{'bug_id'} = '$1';
$bugsrpl = PerformSubsts($bugsrpl, \%substs);
@ -1251,8 +1287,160 @@ sub Fix_BonsaiLink {
# Quotify a string, suitable for invoking a shell process
sub shell_escape {
my ($file) = @_;
$file =~ s/\000/_NULL_/g;
$file =~ s/([ \"\'\`\~\^\?\$\&\|\!<>\(\)\[\]\;\:])/\\$1/g;
return $file;
}
#
# Routines to enforce certain input restrictions
#
sub ExpectCheckinId {
my ($id) = @_;
die("Invalid checkin id.\n") unless ($id =~ m/^::checkin_\d+_\d+$/);
return $id;
}
sub ExpectDate {
my ($date) = @_;
my $res;
return $date if ($date =~ m/^\d+$/);
$res = &str2time($date);
return $res if (defined($res));
die "Invalid date format.\n";
}
sub ExpectDigit {
my ($var, $str) = @_;
if (!defined($str) || $str !~ m/^\d+$/) {
print STDERR "Expecting digit for $var. Got \"" .
shell_escape($str) . "\" instead.\n";
die "Invalid format for $var.\n";
}
return $str;
}
# match types: match, regexp or notregexp
sub ExpectMatchtype {
my ($matchtype) = @_;
return $matchtype if (!defined($matchtype) || $matchtype eq '' ||
$matchtype eq 'match' || $matchtype eq 'regexp' ||
$matchtype eq 'notregexp');
die "Invalid matchtype.\n";
}
sub ExpectOnOff {
my ($var, $str) = @_;
if (!defined($str) || $str !~ m/^(on|off)/) {
print STDERR "Expecting on/off value for $var. Got \"" .
shell_escape($str) . "\" instead.\n";
die "Invalid format for $var.\n";
}
return $str;
}
# The mark argument expects a specific format
# digit or (d1)-(d2)
# where digit is the line number to mark
# and d1 & d2 are the optional beginning & ending of a range.
# If d1 & d2 are omitted, the entire file is marked
sub SanitizeMark {
my ($mark_arg) = @_;
my ($newmark) = "";
return "" if (!defined($mark_arg));
foreach my $mark (split ',', $mark_arg) {
if ($mark =~ m/^(\d*)-(\d*)$/) {
$newmark .= ",$1-$2";
} elsif ($mark =~ m/^\d+$/) {
$newmark .= ",$mark";
} else {
# Ignore invalid input
next;
}
}
$newmark =~ s/^,//;
return $newmark;
}
# Strip garbage from module name
# For now, assume: alphanumeric - . +
sub SanitizeModule {
my ($module) = @_;
return "" if (!defined($module));
$module =~ s/\000/_NULL_/g;
$module =~ s/([A-Za-z])([\w\-\.\+]*).*/$1$2/;
return $module;
}
# Make sure CVS revisions are in a specific format
sub SanitizeRevision {
my ($rev) = @_;
return "" if (!defined($rev) || $rev eq "");
if ($rev =~ /^[A-Za-z]+/) {
$rev =~ s/^([\w-]+).*/$1/;
} elsif ($rev =~ /^\d+\.\d+/) {
$rev =~ s/^(\d+[\.\d+]+).*/$1/;
} else {
die "Invalid revision format.\n";
}
return $rev;
}
# Allow alphanumeric usernames that start with alphas
# Also allow: % . - +
# Use 'nobody' if username doesn't match the modified format
sub SanitizeUsernames {
my ($users) = @_;
my $userlist = '';
return "" if (!defined($users));
foreach my $user (split(/,/, $users)) {
$user =~ s/\000/_NULL_/;
$user =~ s/([A-Za-z])([\w\%\.\-\+]*).*/$1$2/;
$userlist .= ",$user";
}
$userlist =~ s/^,//;
return $userlist;
}
#
# We should use the routine from File::Spec but perl 5.004 doesn't have it
#
sub canonpath {
my ($path) = @_;
my (@list);
return "" if (!defined($path) || $path eq "");
foreach my $dir (split('/', $path)) {
if ($dir eq "\.\.") {
pop @list;
} else {
push @list, $dir;
}
}
$path = join("/",@list);
$path =~ s@//+@/@g;
return $path;
}
# Do not allow access to files outside of cvsroot
sub ChrootFilename {
my ($root, $path) = @_;
my $cpath = canonpath($path);
#print STDERR "ChrootFilename($root, $path, $cpath)\n";
CheckHidden($path);
die "Browsing outside of cvsroot not allowed.\n"
unless ($cpath =~ m@^$root/@ || $cpath eq $root);
die "\nFiles in the CVSROOT are not accessible.\n" if
($cpath =~ m@$root/CVSROOT@);
}
1;

View File

@ -63,7 +63,7 @@ if( $form{"allchanges"} ){
}
else {
while( my ($k, $v) = each( %form ) ){
push( @revs, sanitize_revision($k) );
push( @revs, &SanitizeRevision($k) );
}
}

View File

@ -62,7 +62,7 @@ $dir =~ s/^\/([^:]*)/$1/;
$dir =~ s/([^:]*)\/$/$1/;
my $rev = '';
$rev = sanitize_revision($::FORM{"rev"}) if defined($::FORM{"rev"});
$rev = &SanitizeRevision($::FORM{"rev"}) if defined($::FORM{"rev"});
print "Content-type: text/html\n\n";