{ return join("\n", map join(': ', @$_), @{(shift)->{trace}})."\n" }
}
+{
+ package Local::Exception::known_vulnerability;
+ {our @ISA = qw(Local::Exception)}
+
+ sub summary { return 'upload found vulnerable to '
+ .join(', ', sort keys %{(shift)->{issues}}) }
+
+ sub message {
+ my $self = shift;
+
+ my $text = "file rejected because:\n";
+
+ # Because CVE-2012-3386 was not fixed until 1.11.6 / 1.12.2, we point
+ # people to that version instead of 1.11.1, which fixes
+ # CVE-2009-4029. Ward, 2012-07-20
+ $text .= <<"END" if $self->{issues}{'CVE-2009-4029'};
+$self->{file} contains a vulnerable Makefile.in (CVE-2009-4029).
+ Regenerate it with automake 1.11.6 / 1.12.2 or newer.
+END
+ $text .= <<"END" if $self->{issues}{'CVE-2012-3386'};
+$self->{file} contains a vulnerable Makefile.in (CVE-2012-3386).
+ Regenerate it with automake 1.11.6 / 1.12.2 or newer.
+END
+
+ return $text
+ }
+}
+
{
package Local::Exception::signature_from_future;
{our @ISA = qw(Local::Exception)}
}
}
+=item automake_tests ( $upload_file )
+
+Examine UPLOAD_FILE for known vulnerabilities that certain (now ancient)
+versions of GNU Automake can introduce. Returns nothing, but throws an
+exception if UPLOAD_FILE is found to be exploitable.
+
+=cut
+
sub automake_tests {
my $upload_file = shift;
- my $error_string = '';
-
- return "Error: $upload_file not found\n\n"
+ die "file not found: $upload_file"
unless -e $upload_file;
- return "Error: $upload_file is unreadable\n\n"
+ die "file not readable: $upload_file"
unless -r $upload_file;
# Reject an upload tarball if it contains a Makefile.in vulnerable
if DEBUG;
my @tar_cmd = (qw(/bin/tar -tf), $upload_file);
open TAR, '-|', @tar_cmd
- or return 'Error: failed to run command: '.join(' ',@tar_cmd)."\n\n";
+ or die 'failed to run command: '.join(' ',@tar_cmd).": $!";
my $found_makefile = 0;
while (<TAR>) { $found_makefile++, last if m/Makefile.in/i }
close TAR; # We don't care about errors here; the pipe can cause
# non-zero exit codes when tar is unhappy that it's asked
# to stop
- return '' unless $found_makefile;
+ return unless $found_makefile;
# If it does, check inside them
- my $found_cve_2009_4029 = 0;
- my $found_cve_2012_3386 = 0;
+ my %issues = ();
ftp_syslog('debug',"DEBUG: found Makefile.in, "
."testing for CVE-2009-4029 and CVE-2012-3386")
if DEBUG;
@tar_cmd = (qw(/bin/tar --to-stdout -x -f), $upload_file,
qw(Makefile.in --wildcards */Makefile.in));
open TAR, '-|', @tar_cmd
- or return 'Error: failed to run command: '.join(' ',@tar_cmd)."\n\n";
+ or die 'failed to run command: '.join(' ',@tar_cmd).": $!";
while (<TAR>) {
- $found_cve_2009_4029 = 1
+ $issues{'CVE-2009-4029'} = 1
if m/perm -777 -exec chmod a\+rwx|chmod 777 \$\(distdir\)/;
- $found_cve_2012_3386 = 1
+ $issues{'CVE-2012-3386'} = 1
if m/chmod a\+w \$\(distdir\)/;
}
close TAR; # We don't care about errors here; the pipe can cause
# non-zero exit codes when tar is unhappy that it's asked
# to stop
- # Because CVE-2012-3386 was not fixed until 1.11.6 / 1.12.2, we point
- # people to that version instead of 1.11.1, which fixes
- # CVE-2009-4029. Ward, 2012-07-20
- $error_string .= "file rejected: $upload_file contains a vulnerable "
- . "Makefile.in (CVE-2009-4029);\n"
- . "Regenerate it with automake 1.11.6 / 1.12.2 or newer.\n\n"
- if $found_cve_2009_4029;
+ throw known_vulnerability => file => $upload_file, issues => \%issues
+ if %issues;
+ }
+}
- $error_string .= "file rejected: $upload_file contains a vulnerable "
- . "Makefile.in (CVE-2012-3386);\n"
- . "Regenerate it with automake 1.11.6 / 1.12.2 or newer.\n\n"
- if $found_cve_2012_3386;
+=item check_vulnerabilities ( $upload_file )
- }
+Examine UPLOAD_FILE for known vulnerabilities. This is only used for
+issues related to packaging; notably an old issue in GNU Automake.
- return $error_string;
-}
+Returns nothing on success and throws an exception if a known vulnerability
+is found in UPLOAD_FILE.
+
+=cut
sub check_vulnerabilities {
my $upload_file = shift;
- my $error_string = automake_tests($upload_file);
-
- return $error_string;
+ automake_tests($upload_file);
}
\f
fatal("gpg verify of upload file ($header->{filename}) failed",1)
unless $valid;
- my $error_string = check_vulnerabilities($upload_file);
-
- fatal($error_string,1,'',3) if ($error_string ne '');
+ check_vulnerabilities($upload_file);
ftp_syslog('debug', "DEBUG: "
."tested negative for CVE-2009-4029 and CVE-2012-3386") if DEBUG;