d89b1d57975b5b0141bad26c318ac1920464a05e
[pgp-tools.git] / gpgsigs / gpgsigs
1 #!/usr/bin/perl
2
3 # Copyright (c) 2004 Uli Martens <uli@youam.net>
4 # Copyright (c) 2004 Peter Palfrader <peter@palfrader.org>
5 # Copyright (c) 2004 Christoph Berg <cb@df7cb.de>
6 #
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions
11 # are met:
12 # 1. Redistributions of source code must retain the above copyright
13 # notice, this list of conditions and the following disclaimer.
14 # 2. Redistributions in binary form must reproduce the above copyright
15 # notice, this list of conditions and the following disclaimer in the
16 # documentation and/or other materials provided with the distribution.
17 # 3. The name of the author may not be used to endorse or promote products
18 # derived from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #
31 #
32 #
33 # Depends:
34 # libintl-perl (Locale::Recode)
35 # OR libtext-iconv-perl (Text::Iconv),
36 # OR the "recode" binary
37
38
39 use strict;
40 use warnings;
41 use File::Temp qw{tempdir};
42 use English;
43 use IPC::Open3;
44
45 my $r;
46 my $i;
47 if (eval "require Locale::Recode") {
48 $r = Locale::Recode->new (from => 'UTF-8',
49 to => 'ISO-8859-1');
50 } elsif (eval "require Text::Iconv") {
51 $i = Text::Iconv->new("UTF-8", "ISO-8859-1");
52 }
53
54 sub myrecode($) {
55 my ($text) = @_;
56 if (defined $r) {
57 my $orig = $text;
58 $r->recode($text);
59 #printf STDERR "perl: $orig to $text\n";
60 return $text;
61 } elsif (defined $i) {
62 $text = $i->convert($text);
63 } else {
64 my $pid = open3(\*WTRFH, \*RDRFH, \*ERRFH, 'recode', 'utf8..iso8859-1');
65 print WTRFH $text;
66 close WTRFH;
67 local $/ = undef;
68 my $result = <RDRFH>;
69 close RDRFH;
70 close ERRFH;
71 waitpid $pid, 0;
72
73 die ("'recode' failed, is it installed?\n") unless defined $result;
74 #printf STDERR "manual: $text to $result\n";
75 return $result;
76 };
77 }
78
79
80 my $EXPECTED_MD5 = '90 43 B8 1B';
81
82 my $mykey = uc(shift @ARGV);
83 my $keyring = shift @ARGV;
84 my $keytxt = shift @ARGV;
85 my $outfile = shift @ARGV;
86
87 $keyring = 'ksp-lt2k4.asc' unless defined $keyring;
88 $keytxt = 'ksp-lt2k4.txt' unless defined $keytxt;
89 $outfile = 'ksp-lt2k4-annotated.txt' unless defined $outfile;
90
91 if (!defined $mykey || scalar @ARGV || ($mykey !~ /^[0-9A-F]{16,16}$/ && $mykey !~ /^[0-9A-F]{8,8}$/)) {
92 print STDERR "Usage: $PROGRAM_NAME keyid [<keyring> [<keytxt> [<outfile]]]\n";
93 print STDERR "\n";
94 print STDERR "keyid is a long or short keyid (e.g. DE7AAF6E94C09C7F or 94C09C7F\n";
95 exit 1;
96 }
97
98 -r $keyring or die ("$keyring does not exist\n");
99 -r $keytxt or die ("$keytxt does not exist\n");
100
101
102 my $sigs;
103
104
105 my $tempdir = tempdir( "gpgsigs-XXXXX", DIR => '/tmp/', CLEANUP => 1);
106 $ENV{'GNUPGHOME'} = $tempdir;
107 print STDERR "Creating a temporary gnupghome and importing keys\n";
108 system(qw{gpg --import}, $keyring);
109
110 print STDERR "Running --list-sigs, this will take a while\n";
111 open SIGS, "gpg --fixed-list-mode --with-colons --list-sigs 2>/dev/null |"
112 or die "can't get gpg listing";
113
114 my $key;
115 my $uid;
116 while (<SIGS>) {
117 if ( m/^pub:(?:.*?:){3,3}([0-9A-F]{16,16}):/ ) {
118 $key = $1;
119 next;
120 }
121 if ( m/^uid:(?:.*?:){8,8}(.*):/ ) {
122 $uid = $1;
123 $uid = myrecode($uid);
124 next;
125 }
126 if ( m/^sig:(?:.*?:){3,3}([0-9A-F]{8})([0-9A-F]{8}):(?:.*?:){3,3}(.*):.*?:/ ) {
127 $sigs->{$key}->{$uid}->{$1.$2} = $3;
128 $sigs->{$key}->{$uid}->{$2} = $3;
129 next;
130 }
131 if ( m/^uat:/ ) {
132 $uid = "Photo ID";
133 next;
134 }
135 next if ( m/^(rev|sub|tru):/ );
136 warn "unknown value: '$_', key: ".(defined $key ? $key :'none')."\n";
137 }
138 close SIGS;
139
140 for my $k ( keys %{$sigs} ) {
141 if ( $k =~ m/^[0-9A-F]{8}([0-9A-F]{8})$/ ) {
142 $sigs->{$1} = $sigs->{$k};
143 }
144 }
145
146
147 open MD, "gpg --print-md md5 $keytxt|" or warn "can't get gpg md5";
148 my $MD5 = <MD>;
149 close MD;
150 open MD, "gpg --print-md sha1 $keytxt|" or warn "can't get gpg sha1";
151 my $SHA1 = <MD>;
152 close MD;
153
154 chomp $MD5;
155 chomp $SHA1;
156 my $metatxt = quotemeta($keytxt);
157 $MD5 =~ s/^$metatxt:\s*//;
158 $SHA1 =~ s/^$metatxt:\s*//;
159
160 if (defined $MD5) {
161 warn ("md5 of $keytxt does not begin with $EXPECTED_MD5") unless ($MD5 =~ /^$EXPECTED_MD5/);
162 };
163
164 print STDERR "Annotating $keytxt, writing into $outfile\n";
165 open (TXT, $keytxt) or die ("Cannot open $keytxt\n");
166 open (WRITE, '>'.$outfile) or die ("Cannot open $outfile for writing\n");
167 while (<TXT>) {
168 if (/^MD5 Checksum: __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __/ && defined $MD5) {
169 print WRITE "MD5 Checksum: $MD5 [ ]\n";
170 }
171 elsif (/^SHA1 Checksum: ____ ____ ____ ____ ____ ____ ____ ____ ____ ____/ && defined $SHA1) {
172 print WRITE "SHA1 Checksum: $SHA1 [ ]\n";
173 } else {
174 print WRITE;
175 };
176 if ( m/^([0-9]{3}) \[ \] Fingerprint OK \[ \] ID OK$/ ) {
177 $_ = <TXT>;
178 if ( m/^pub ( 768|1024|2048|4096)[DR]\/([0-9A-F]{8}) [0-9]{4}-[0-9]{2}-[0-9]{2} (.*)/ ) {
179 my $l2 = $_;
180 my $uid = $3;
181 my $keyid = $2;
182 if ( ! defined $sigs->{$keyid}->{$uid} ) {
183 warn "uid '$uid' not found on key $keyid";
184 };
185 print WRITE ( defined $sigs->{$keyid}->{$uid}->{$mykey} ? "(S)" : "( )" );
186 print WRITE " $l2";
187 $_ = <TXT>;
188 print WRITE $_;
189 while (<TXT>) {
190 my $l3 = $_;
191 if ( m/^uid (.*)$/ ) {
192 print WRITE defined $sigs->{$keyid}->{$1}
193 ? ( defined $sigs->{$keyid}->{$1}->{$mykey} ? "(S)" : "( )" )
194 : " ";
195 print WRITE " $l3";
196 } else {
197 print WRITE "$l3";
198 last;
199 }
200 }
201 } else {
202 print WRITE "$_";
203 }
204 }
205 }
206 close TXT