#!/usr/bin/perl # Copyright (c) 2004 Uli Martens # Copyright (c) 2004 Peter Palfrader # Copyright (c) 2004 Christoph Berg # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # # Depends: # libintl-perl (Locale::Recode) # OR libtext-iconv-perl (Text::Iconv), # OR the "recode" binary use strict; use warnings; use File::Temp qw{tempdir}; use English; use IPC::Open3; my $r; my $i; if (eval "require Locale::Recode") { $r = Locale::Recode->new (from => 'UTF-8', to => 'ISO-8859-1'); } elsif (eval "require Text::Iconv") { $i = Text::Iconv->new("UTF-8", "ISO-8859-1"); } sub myrecode($) { my ($text) = @_; if (defined $r) { my $orig = $text; $r->recode($text); #printf STDERR "perl: $orig to $text\n"; return $text; } elsif (defined $i) { $text = $i->convert($text); } else { my $pid = open3(\*WTRFH, \*RDRFH, \*ERRFH, 'recode', 'utf8..iso8859-1'); print WTRFH $text; close WTRFH; local $/ = undef; my $result = ; close RDRFH; close ERRFH; waitpid $pid, 0; die ("'recode' failed, is it installed?\n") unless defined $result; #printf STDERR "manual: $text to $result\n"; return $result; }; } my $EXPECTED_MD5 = '90 43 B8 1B'; my $mykey = uc(shift @ARGV); my $keyring = shift @ARGV; my $keytxt = shift @ARGV; my $outfile = shift @ARGV; $keyring = 'ksp-lt2k4.asc' unless defined $keyring; $keytxt = 'ksp-lt2k4.txt' unless defined $keytxt; $outfile = 'ksp-lt2k4-annotated.txt' unless defined $outfile; if (!defined $mykey || scalar @ARGV || ($mykey !~ /^[0-9A-F]{16,16}$/ && $mykey !~ /^[0-9A-F]{8,8}$/)) { print STDERR "Usage: $PROGRAM_NAME keyid [ [ [ '/tmp/', CLEANUP => 1); $ENV{'GNUPGHOME'} = $tempdir; print STDERR "Creating a temporary gnupghome and importing keys\n"; system(qw{gpg --import}, $keyring); print STDERR "Running --list-sigs, this will take a while\n"; open SIGS, "gpg --fixed-list-mode --with-colons --list-sigs 2>/dev/null |" or die "can't get gpg listing"; my $key; my $uid; while () { if ( m/^pub:(?:.*?:){3,3}([0-9A-F]{16,16}):/ ) { $key = $1; next; } if ( m/^uid:(?:.*?:){8,8}(.*):/ ) { $uid = $1; $uid = myrecode($uid); next; } if ( m/^sig:(?:.*?:){3,3}([0-9A-F]{8})([0-9A-F]{8}):(?:.*?:){3,3}(.*):.*?:/ ) { $sigs->{$key}->{$uid}->{$1.$2} = $3; $sigs->{$key}->{$uid}->{$2} = $3; next; } if ( m/^uat:/ ) { $uid = "Photo ID"; next; } next if ( m/^(rev|sub|tru):/ ); warn "unknown value: '$_', key: ".(defined $key ? $key :'none')."\n"; } close SIGS; for my $k ( keys %{$sigs} ) { if ( $k =~ m/^[0-9A-F]{8}([0-9A-F]{8})$/ ) { $sigs->{$1} = $sigs->{$k}; } } open MD, "gpg --print-md md5 $keytxt|" or warn "can't get gpg md5"; my $MD5 = ; close MD; open MD, "gpg --print-md sha1 $keytxt|" or warn "can't get gpg sha1"; my $SHA1 = ; close MD; chomp $MD5; chomp $SHA1; my $metatxt = quotemeta($keytxt); $MD5 =~ s/^$metatxt:\s*//; $SHA1 =~ s/^$metatxt:\s*//; if (defined $MD5) { warn ("md5 of $keytxt does not begin with $EXPECTED_MD5") unless ($MD5 =~ /^$EXPECTED_MD5/); }; print STDERR "Annotating $keytxt, writing into $outfile\n"; open (TXT, $keytxt) or die ("Cannot open $keytxt\n"); open (WRITE, '>'.$outfile) or die ("Cannot open $outfile for writing\n"); while () { if (/^MD5 Checksum: __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __/ && defined $MD5) { print WRITE "MD5 Checksum: $MD5 [ ]\n"; } elsif (/^SHA1 Checksum: ____ ____ ____ ____ ____ ____ ____ ____ ____ ____/ && defined $SHA1) { print WRITE "SHA1 Checksum: $SHA1 [ ]\n"; } else { print WRITE; }; if ( m/^([0-9]{3}) \[ \] Fingerprint OK \[ \] ID OK$/ ) { $_ = ; if ( m/^pub ( 768|1024|2048|4096)[DR]\/([0-9A-F]{8}) [0-9]{4}-[0-9]{2}-[0-9]{2} (.*)/ ) { my $l2 = $_; my $uid = $3; my $keyid = $2; if ( ! defined $sigs->{$keyid}->{$uid} ) { warn "uid '$uid' not found on key $keyid"; }; print WRITE ( defined $sigs->{$keyid}->{$uid}->{$mykey} ? "(S)" : "( )" ); print WRITE " $l2"; $_ = ; print WRITE $_; while () { my $l3 = $_; if ( m/^uid (.*)$/ ) { print WRITE defined $sigs->{$keyid}->{$1} ? ( defined $sigs->{$keyid}->{$1}->{$mykey} ? "(S)" : "( )" ) : " "; print WRITE " $l3"; } else { print WRITE "$l3"; last; } } } else { print WRITE "$_"; } } } close TXT