[Rt-commit] rt branch, 4.4/provide-more-public-key-details, created. rt-4.4.4-158-ga6a6c7eedd
Dianne Skoll
dianne at bestpractical.com
Thu Nov 12 17:07:59 EST 2020
The branch, 4.4/provide-more-public-key-details has been created
at a6a6c7eedd7207c2f26ffa458e1e2fdd81118708 (commit)
- Log -----------------------------------------------------------------
commit a468f47072a661761b5dfb166aa901468890bc3c
Author: Dianne Skoll <dianne at bestpractical.com>
Date: Thu Nov 12 10:08:23 2020 -0500
Add AgorithmName to info returned by ParseKeysInfo
diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index 06569ad9db..07ceff8fce 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1711,6 +1711,7 @@ sub ParseKeysInfo {
Empty Empty Capabilities Other
) } = split /:/, $line, 12;
+ $info{AlgorithmName} = $self->PubkeyAlgorithmToName($info{Algorithm}) if defined($info{Algorithm});
# workaround gnupg's wierd behaviour, --list-keys command report calculated trust levels
# for any model except 'always', so you can change models and see changes, but not for 'always'
# we try to handle it in a simple way - we set ultimate trust for any key with trust
@@ -1738,6 +1739,7 @@ sub ParseKeysInfo {
Created Expire Empty OwnerTrustChar
Empty Empty Capabilities Other
) } = split /:/, $line, 12;
+ $info{AlgorithmName} = $self->PubkeyAlgorithmToName($info{Algorithm}) if defined($info{Algorithm});
@info{qw(OwnerTrust OwnerTrustTerse OwnerTrustLevel)} =
_ConvertTrustChar( $info{'OwnerTrustChar'} );
$info{ $_ } = $self->ParseDate( $info{ $_ } )
@@ -1957,6 +1959,23 @@ sub _make_gpg_handles {
return ($handles, \%handle_map);
}
+# Given a PGP public-key algorithm number, return the algorithm name.
+# See https://tools.ietf.org/html/rfc4880#section-9
+sub PubkeyAlgorithmToName
+{
+ my ($self, $alg) = @_;
+ return 'RSA' if ($alg == 1);
+ return 'RSA Encrypt-Only' if ($alg == 2);
+ return 'RSA Sign-Only' if ($alg == 3);
+ return 'Elgamal Encrypt-Ony' if ($alg == 16);
+ return 'DSA' if ($alg == 17);
+ return 'Reserved for EC' if ($alg == 18);
+ return 'Reserved for ECDSA' if ($alg == 19);
+ return 'Reserved (formerly Elgamal)' if ($alg == 20);
+ return 'Reserved (DH)' if ($alg == 21);
+ return undef;
+}
+
RT::Base->_ImportOverlays();
1;
commit a6a6c7eedd7207c2f26ffa458e1e2fdd81118708
Author: Dianne Skoll <dianne at bestpractical.com>
Date: Thu Nov 12 17:06:48 2020 -0500
For GnuPG, add a tooltip with additional info about the signature, and add ability to download public key.
diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index 07ceff8fce..4ae1261121 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1489,6 +1489,15 @@ sub ParseStatus {
foreach my $line ( @status[ $i .. $#status ] ) {
next unless $line =~ /^VALIDSIG\s+(.*)/;
+ # Fingerprint = key fingerprint in hex
+ # CreationDate = key creation date (YYYY-MM-DD)
+ # Timestamp = signature creation time (seconds from UNIX epoch)
+ # ExpireTimestamp = signature expiration time (since epoch) or 0 for "never expires"
+ # Version = signature version straight from the packet
+ # PubkeyAlgo = Public key algorithm (https://tools.ietf.org/html/rfc4880#section-9.1)
+ # HashAlgo = Hash algorithm (https://tools.ietf.org/html/rfc4880#section-9.4)
+ # Class = Signature type (https://tools.ietf.org/html/rfc4880#section-5.2.1)
+ # PKFingerprint = Primary Key Fingerprint
@res{ qw(
Fingerprint
CreationDate
@@ -1502,6 +1511,8 @@ sub ParseStatus {
PKFingerprint
Other
) } = split /\s+/, $1, 10;
+ $res{HashAlgoName} = $self->HashAlgorithmToName($res{HashAlgo}) if defined($res{HashAlgo});
+ $res{PubkeyAlgoName} = $self->PubkeyAlgorithmToName($res{PubkeyAlgo}) if defined($res{PubkeyAlgo});
last;
}
push @res, \%res;
@@ -1959,8 +1970,24 @@ sub _make_gpg_handles {
return ($handles, \%handle_map);
}
+# Gigne a PGP hash algorithm number, return the algorithm name.
+# See https://tools.ietf.org/html/rfc4880#section-9.4
+sub HashAlgorithmToName
+{
+ my ($self, $alg) = @_;
+ return 'MD5' if ($alg == 1);
+ return 'SHA-1' if ($alg == 2);
+ return 'RIPE-MD/160' if ($alg == 3);
+ return 'Reserved' if ($alg >= 4 && $alg <= 7);
+ return 'SHA256' if ($alg == 8);
+ return 'SHA384' if ($alg == 9);
+ return 'SHA512' if ($alg == 10);
+ return 'SHA224' if ($alg == 11);
+ return undef;
+}
+
# Given a PGP public-key algorithm number, return the algorithm name.
-# See https://tools.ietf.org/html/rfc4880#section-9
+# See https://tools.ietf.org/html/rfc4880#section-9.1
sub PubkeyAlgorithmToName
{
my ($self, $alg) = @_;
@@ -1976,6 +2003,25 @@ sub PubkeyAlgorithmToName
return undef;
}
+# Given a public-key fingerprint, return the public key (in PEM format)
+# if we have it, undef if we do not.
+sub GetPubkey
+{
+ my ($self, $fingerprint) = @_;
+
+ # Sanity-check the fingerprint, which must be a string of
+ # hex digits
+ if ($fingerprint =~ /[^0-9a-fA-F]/) {
+ return undef;
+ }
+
+ my @pubkey;
+ my %res = $self->CallGnuPG(
+ Command => 'export_keys',
+ CommandArgs => $fingerprint,
+ Output => \@pubkey);
+ return join('', @pubkey);
+}
RT::Base->_ImportOverlays();
1;
diff --git a/share/html/Crypt/GetGPGPubkey.html b/share/html/Crypt/GetGPGPubkey.html
new file mode 100644
index 0000000000..eb10caa0e4
--- /dev/null
+++ b/share/html/Crypt/GetGPGPubkey.html
@@ -0,0 +1,77 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2020 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+<& /Elements/Header,
+ Title => $title
+ &>
+<& /Elements/Tabs &>
+
+<& /Elements/ListActions, actions => \@results &>
+
+<%ARGS>
+$Fingerprint => undef
+$title => loc('Download GnuPG Public Key')
+</%ARGS>
+
+<%INIT>
+my @results;
+if (!$Fingerprint) {
+ push(@results, loc('Fingerprint must be supplied to download a public key.'));
+} else {
+ my $key = RT::Crypt::GnuPG->GetPubkey($Fingerprint);
+ if (!$key) {
+ push(@results, loc('Could not find GnuPG public key with fingerprint [_1].'));
+ } else {
+ $r->content_type('application/pgp-keys');
+ $r->header_out('Content-Disposition' => "attachment; filename=\"$Fingerprint.pub\"");
+ $m->out($key);
+ $m->flush_buffer;
+ $m->abort();
+ }
+}
+
+</%INIT>
diff --git a/share/html/Elements/CryptStatus b/share/html/Elements/CryptStatus
index e6c0e7ba8f..f40f281767 100644
--- a/share/html/Elements/CryptStatus
+++ b/share/html/Elements/CryptStatus
@@ -71,6 +71,44 @@ foreach ( $Message->SplitHeaders ) {
return unless @runs or $needs_unsigned_warning;
+# Returns string representing a date in UNIX timestamp format
+sub DisplayDate {
+ my ($ts) = @_;
+ my $date = RT::Date->new($session{'CurrentUser'});
+ $date->Unix($ts);
+ return $date->AsString();
+}
+
+# Generate a little tooltip with additional info about a signature
+sub VerifyTooltip {
+ my ($line) = @_;
+ my $tooltip = '';
+ $tooltip .= "\n" . loc('Fingerprint:') . ' ' . $line->{Fingerprint} if $line->{Fingerprint};
+ $tooltip .= "\n" . loc('Signature Created:') . ' ' . DisplayDate($line->{Timestamp}) if $line->{Timestamp};
+ $tooltip .= "\n" . loc('Key Expires:') . ' ';
+ if ($line->{ExpireTimestamp}) {
+ $tooltip .= DisplayDate($line->{Timestamp});
+ } else {
+ $tooltip .= loc('Never');
+ }
+ $tooltip .= "\n" . loc('Public Key Algorithm:') . ' ' . $line->{PubkeyAlgoName} if $line->{PubkeyAlgoName};
+ $tooltip .= "\n" . loc('Hash Algorithm:') . ' ' . $line->{HashAlgoName} if $line->{HashAlgoName};
+ $tooltip =~ s/^\s+//;
+ return $tooltip;
+}
+
+# Generate a download link for the public key
+sub KeyDownloadLink {
+ my ($protocol, $line) = @_;
+ my $txt = '';
+ if ($protocol eq 'GnuPG') {
+ if ($line->{Fingerprint} && $line->{Fingerprint} !~ /[^0-9A-F]/i) {
+ $txt = '<a href="' . RT->Config->Get('WebPath') . '/Crypt/GetGPGPubkey.html?Fingerprint=' . $line->{Fingerprint} . '">' . loc(' (Download Public Key)') . '</a>';
+ }
+ }
+ return $txt;
+}
+
my $reverify_cb = sub {
my $top = shift;
@@ -170,7 +208,7 @@ foreach my $run ( @runs ) {
push @messages, {
Tag => $protocol,
Classes => ['verify', lc $line->{Status}, 'trust-'.($line->{Trust} || 'UNKNOWN')],
- Value => $m->interp->apply_escapes( loc( $line->{'Message'} ), 'h'),
+ Value => '<span title="' . $m->interp->apply_escapes(VerifyTooltip($line)) . '">' . $m->interp->apply_escapes( loc( $line->{'Message'} ), 'h') . '</span>' . KeyDownloadLink($protocol, $line),
};
}
else {
-----------------------------------------------------------------------
More information about the rt-commit
mailing list