use Pod::Usage;
use Net::SMTP;
-use Date::Manip;
use Sys::Syslog qw(:DEFAULT setlogsock);
use Getopt::Long;
use Text::Wrap;
The fingerprint of the PGP key that signed TEXT, if available.
-=item ...
+=item sig_creation
+
+Epoch timestamp of signature.
+
+=item sig_expiration
+
+Epoch timestamp at which the signature expires, if the signature expires.
+This key is only present if the signature has an expiration date.
=back
if 0 == $ret{exitcode};
} elsif ($1 eq 'ERR') { # an ERRSIG line
$verdict_status++;
- if (m/\G(\d+)\s(\d+)\s([[:xdigit:]]{2})\s([-:T[:digit:]]+)\s(\d+)/gc) {
+ if (m/\G(\d+)\s(\d+)\s([[:xdigit:]]{2})\s([-:T[:digit:]Z+]+)\s(\d+)
+ /gcx) {
# $1 -- pubkey algorithm $2 -- digest algorithm
# $3 -- timestamp $4 -- result code
+ ftp_abort('gpgv returned an ISO8601 timestamp; implementation needed')
+ if $3 =~ m/T/;
+ $ret{sig_creation} = $3;
} else
{ push @{$ret{TILT}}, 'gpgv ERRSIG line failed parsing' }
$check_status++;
}
} elsif (m/\G(VALID)SIG\s([[:xdigit:]]+)\s(\d{4}-\d{2}-\d{2})\s
- ([-:T[:digit:]]+)\s([-:T[:digit:]]+)\s(\d+)\s(\S+)\s
+ ([-:T[:digit:]Z+]+)\s([-:T[:digit:]Z+]+)\s(\d+)\s(\S+)\s
(\d+)\s(\d+)\s([[:xdigit:]]{2})\s([[:xdigit:]]+)
/gcx) {
$verdict_status++;
# $11 -- primary key fingerprint
$ret{key_fingerprint} = $2;
$ret{key_longid} = substr $2,-16;
+ ftp_abort('gpgv returned an ISO8601 timestamp; implementation needed')
+ if $4 =~ m/T/ || $5 =~ m/T/;
+ $ret{sig_creation} = $4;
+ # GPG reports 0 if the signature does not expire
+ $ret{sig_expiration} = $5 if $5 > 0;
}
}
close $status or ftp_abort('close in-memory file for gpgv status');
# than the one for the last file that was uploaded
# This is only relevant when a 'filename' directive is present, hence the
# test of the $filename_required variable.
- if (($result->{raw_log} =~ /Signature made (.*)/)
+ if (defined $result->{sig_creation}
&& (exists($info{filename}))) {
- my $timestr = $1;
-
- ftp_syslog('debug', "DEBUG: Signature made $1") if DEBUG;
-
- # Some versions of GPG also mention the key used to make the signature
- # on this line, while others do not. The testing mock does.
- $timestr =~ s/ using .*//; # trim to only timestamp
-
- # If the time/date string starts with a weekday
- # (e.g. "Wed Apr 28 16:40:03 2004 EDT"), chop off the weekday -
- # Date::Manip doesn't like it
- $timestr =~ s/^[a-z]+? ([a-z]+)/$1/i;
-
- # We need to convert time/date strings like "Apr 28 16:40:03 2004 EDT" into
- # "Apr 28 16:40:03 2004 EDT" for Date::Manip to understand them...
- $timestr =~
- s/^([a-z]+? +\d{1,2}) (\d{2}:\d{2}:\d{2}) (\d{4}) (.*)$/$1 $3 $2 $4/i;
- my $date = ParseDate($timestr);
- my $epoch = UnixDate($date,"%s");
+ ftp_syslog('debug', "DEBUG: Signature made "
+ .strftime('%a %b %d %H:%M:%S %Y %Z',
+ localtime $result->{sig_creation})) if DEBUG;
# Verify that this timestamp is not too far in the future. We allow a
# discrepancy of 1 day so we don't have to worry about timezones
- my $now = time();
- if ($epoch > ($now + 24*3600)) {
+ if ($result->{sig_creation} > (time() + 24*3600)) {
fatal("GPG signed upload from the future - not allowed. "
."Please make sure your clock is set correctly, "
."resign the directive file, and upload again. "
my $full_filename = $info{"directory"} . '/' . $uploaded_file;
$full_filename =~ s/\/\//\//g; # Just in case...
- advance_timestamp_ratchet($full_filename, $epoch);
+ advance_timestamp_ratchet($full_filename, $result->{sig_creation});
} elsif (exists($info{filename})) {
fatal("gpg verification problem: could not extract timestamp",1);
}