2 require '/etc/news/innshellvars.pl';
4 # written April 1996, tale@isc.org (David C Lawrence)
5 # mostly rewritten 2001-03-21 by Marco d'Itri <md@linux.it>
9 # - perl 5.004_03 and working Sys::Syslog
12 # There is no locking because gpg is supposed to not need it and controlchan
13 # will serialize control messages processing anyway.
18 # if you keep your keyring somewhere that is not the default used by gpg,
19 # change the location below.
21 if ($inn::newsetc && -d "$inn::newsetc/pgp") {
22 $keyring = $inn::newsetc . '/pgp/pubring.gpg';
25 # If you have INN and the script is able to successfully include your
26 # innshellvars.pl file, the value of the next two variables will be
28 my $tmpdir = '/var/log/news/';
29 my $syslog_facility = 'news';
38 ### 2 unknown signature
40 ### 255 problem not directly related to gpg analysis of signature
42 ##############################################################################
43 ################ NO USER SERVICEABLE PARTS BELOW THIS COMMENT ################
44 ##############################################################################
45 my $tmp = ($inn::pathtmp ? $inn::pathtmp : $tmpdir) . "/pgp$$";
46 $syslog_facility = $inn::syslog_facility if $inn::syslog_facility;
49 $0 =~ s#^.*/##; # trim /path/to/prog to prog
51 die "Usage: $0 < message\n" if $#ARGV != -1;
58 foreach (split(/:/, $ENV{PATH}), qw(/usr/local/bin /opt/gnu/bin)) {
60 $gpg = "$_/gpgv"; last;
64 fail('cannot find the gpgv binary') if not $gpg;
66 # this is, by design, case-sensitive with regards to the headers it checks.
67 # it's also insistent about the colon-space rule.
68 my ($label, $value, %dup, %header);
70 # if a header line ends with \r\n, this article is in the encoding
71 # it would be in during an NNTP session. some article storage
72 # managers keep them this way for efficiency.
73 $nntp_format = /\r\n$/ if $. == 1;
77 if (/^(\S+):[ \t](.+)/) {
78 ($label, $value) = ($1, $2);
79 $dup{$label} = 1 if $header{$label};
80 $header{$label} = $value;
82 fail("non-header at line $.: $_") unless $label;
83 $header{$label} .= "\n$_";
85 fail("non-header at line $.: $_");
89 my $pgpheader = 'X-PGP-Sig';
90 $_ = $header{$pgpheader};
91 exit 1 if not $_; # no signature
93 # the $sep value means the separator between the radix64 signature lines
94 # can have any amount of spaces or tabs, but must have at least one space
95 # or tab, if there is a newline then the space or tab has to follow the
96 # newline. any number of newlines can appear as long as each is followed
97 # by at least one space or tab. *phew*
98 my $sep = "[ \t]*(\n?[ \t]+)+";
99 # match all of the characters in a radix64 string
100 my $r64 = '[a-zA-Z0-9+/]';
101 fail("$pgpheader not in expected format")
102 unless /^(\S+)$sep(\S+)(($sep$r64{64})+$sep$r64+=?=?$sep=$r64{4})$/;
104 my ($version, $signed_headers, $signature) = ($1, $3, $4);
105 $signature =~ s/$sep/\n/g;
107 my $message = "-----BEGIN PGP SIGNED MESSAGE-----\n\n"
108 . "X-Signed-Headers: $signed_headers\n";
110 foreach $label (split(',', $signed_headers)) {
111 fail("duplicate signed $label header, can't verify") if $dup{$label};
112 $message .= "$label: ";
113 $message .= $header{$label} if $header{$label};
116 $message .= "\n"; # end of headers
118 while (<STDIN>) { # read body lines
120 # check for end of article; some news servers (eg, Highwind's
121 # "Breeze") include the dot-CRLF of the NNTP protocol in the
122 # article data passed to this script
123 last if $_ eq ".\r\n";
125 # remove NNTP encoding
130 s/^-/- -/; # pgp quote ("ASCII armor") dashes
135 "\n-----BEGIN PGP SIGNATURE-----\n" .
136 "Version: $version\n" .
138 "\n-----END PGP SIGNATURE-----\n";
140 open(TMP, ">$tmp") or fail("open $tmp: $!");
142 close TMP or errmsg("close $tmp: $!");
144 my $opts = '--quiet --status-fd=1 --logger-fd=1';
145 $opts .= " --keyring=$keyring" if $keyring;
147 open(PGP, "$gpg $opts $tmp |") or fail("failed to execute $gpg: $!");
152 unlink $tmp or errmsg("unlink $tmp: $!");
156 my $status = $? >> 8;
157 errmsg("gpg exited status $status") if $status > 1;
159 errmsg('gpg died on signal ' . ($? & 255));
163 print STDERR $_ if $debug;
165 my $ok = 255; # default exit status
167 if (/^\[GNUPG:\]\s+GOODSIG\s+\S+\s+(\S+)/m) {
170 } elsif (/^\[GNUPG:\]\s+NODATA/m or /^\[GNUPG:\]\s+UNEXPECTED/m) {
172 } elsif (/^\[GNUPG:\]\s+NO_PUBKEY/m) {
174 } elsif (/^\[GNUPG:\]\s+BADSIG\s+/m) {
178 print "$signer\n" if $signer;
184 eval 'use Sys::Syslog qw(:DEFAULT setlogsock)';
185 die "$0: cannot use Sys::Syslog: $@ [$msg]\n" if $@;
187 die "$0: cannot set syslog method [$msg]\n"
188 if not (setlogsock('unix') or setlogsock('inet'));
190 $msg .= " processing $header{'Message-ID'}" if $header{'Message-ID'};
192 openlog($0, 'pid', $syslog_facility);
193 syslog('err', '%s', $msg);
205 # Copyright 2000 by Marco d'Itri
207 # License of the original version distributed by David C. Lawrence:
209 # Copyright (c) 1996 UUNET Technologies, Inc.
210 # All rights reserved.
212 # Redistribution and use in source and binary forms, with or without
213 # modification, are permitted provided that the following conditions
215 # 1. Redistributions of source code must retain the above copyright
216 # notice, this list of conditions and the following disclaimer.
217 # 2. Redistributions in binary form must reproduce the above copyright
218 # notice, this list of conditions and the following disclaimer in the
219 # documentation and/or other materials provided with the distribution.
220 # 3. All advertising materials mentioning features or use of this software
221 # must display the following acknowledgement:
222 # This product includes software developed by UUNET Technologies, Inc.
223 # 4. The name of UUNET Technologies ("UUNET") may not be used to endorse or
224 # promote products derived from this software without specific prior
225 # written permission.
227 # THIS SOFTWARE IS PROVIDED BY UUNET ``AS IS'' AND ANY EXPRESS OR
228 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
229 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
230 # ARE DISCLAIMED. IN NO EVENT SHALL UUNET BE LIABLE FOR ANY DIRECT,
231 # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
232 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
233 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
234 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
235 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
236 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
237 # OF THE POSSIBILITY OF SUCH DAMAGE.