nntp2http.com
Posting
Suche
Optionen
Hilfe & Kontakt

Cancel-Lock Verarbeitung für INN ohne kompletten cleanfeed

Von: Holger Marzen (holger@marzen.de) [Profil]
Datum: 29.07.2007 15:02
Message-ID: <f8i34e$gbp$1@news.marzen.de>
Newsgroup: de.comm.software.newsserver
Liebe Leute,

ich habe cleanfeed und die Key-Verify-Routinen von Alexander so
zusammengestrichen, dass ich das minimale Setup dafür habe, dass das
Canclen und Superseden von Artikeln mit gesetztem Cancel-Lock nur mit
dem passenen Key funktioniert.

Dazu habe ich ein mini-cleanfeed.pl, auf das der Symlink filter_innd.pl
in /etc/news/filter (bei INN auf Debian Sarge) zeigt.

Vielleicht findet es jemand nützlich und/oder findet Fehler.

-- schnipp ------------------------------


#
#-- Minimal version of Cleanfeed for INN
#   Copyright 2007 Holger Marzen <holger@marzen.de>
#
#   Based on Cleanfeed
#     Copyright 1999 Jeremy Nixon <jeremy@exit109.com>
#     Copyright 2001 Marco d'Itri <md@linux.it>
#
#   Key verify code:
#     Alexander Bartolich <alexander.bartolich@gmx.at>
#
# This software is distributed under the terms of the Artistic License.
# Please see the mini-cleanfeed.LICENSE file in the distribution.
#
# Syntax check:
#   perl -wc mini-cleanfeed.pl
#
# Reload:
#   ctlinnd reload filter.perl "mini-cleanfeed"
#

use MIME::Base64();
use Digest::SHA1();
use Digest::HMAC_SHA1();

sub filter_art {

#-- break out newsgroups into an array
@groups = split(/[,\s]+/, $hdr{Newsgroups});
if ($hdr{'Followup-To'}) {
@followups = split(/[,\s]+/, $hdr{'Followup-To'});
} else {
@followups = @groups;
}

#-- Supersedes
if ($hdr{Supersedes}) {
my @result = local_filter_supersede();
return reject(@result) if $result[0];
}

#-- Cancel
if ($hdr{Control} =~ /^\s*cancel/) {
my @result = local_filter_cancel();
return reject(@result) if $result[0];
}

}

sub reject {
my ($reason) = @_;
return $reason;
}

sub local_filter_supersede
{
unless($hdr{Supersedes} =~ m/^(<[^>]+>)/i)
{ return "Supersede with broken target ID"; }
return verify_cancel(\%hdr, $1, 'Supersede');
}

sub local_filter_cancel
{
unless($hdr{Control} =~ m/^cancel\s+(<[^>]+>)/i)
{ return "Cancel with broken target ID"; }
return verify_cancel(\%hdr, $1, 'Cancel');
}

sub verify_cancel($$$)
{
my $r_hdr = shift || die;
my $target = shift;
my $descr = shift;

my $headers = INN::head($target) ||
return "$descr of non-existing ID $target";

my %headers;
for my $line(split(/\s*\n/, $headers))
{
if ($line =~ m/^([[:alnum:]-]+):\s+(.*)/)
{ $headers{$1} = $2; }
}

my $lock = $headers{'Cancel-Lock'};
if (defined($lock))
{
my $key = $r_hdr->{'Cancel-Key'} ||
return "$descr of $target without Cancel-Key";
return verify_cancel_key($key, $lock, $descr . ' target=' . $target);
}

return undef;
}

sub verify_cancel_key($$$)
{
my $cancel_key = shift;
my $cancel_lock = shift;
my $msg = shift;

$msg = '' unless(defined($msg));

my %lock;
for my $l(split(/\s+/, $cancel_lock))
{
next unless($l =~ m/^(sha1|md5):(\S+)/);
$lock{$2} = $1;
}

for my $k(split(/\s+/, $cancel_key))
{
unless($k =~ m/^(sha1|md5):(\S+)/)
{
INN::syslog('notice', "Invalid Cancel-Key syntax '$k'. $msg");
next;
}

my $key;
if ($1 eq 'sha1')
{ $key = Digest::SHA1::sha1($2); }
elsif ($1 eq 'md5')
{ $key = Digest::MD5::md5($2); }
$key = MIME::Base64::encode_base64($key, '');

if (exists($lock{$key}))
{
INN::syslog('notice', "Valid Cancel-Key $key found. $msg");
return undef;
}
}

INN::syslog('notice',
"No Cancel-Key[$cancel_key] matches Cancel-Lock[$cancel_lock] $msg"
);
return "No Cancel-Key matches Cancel-Lock. $msg";
}

[ Auf dieses Posting antworten ]