RIPE DB bug in notification [maintainer.pl]
- Date: Thu, 29 Dec 1994 16:07:20 +0100
Folks,
we found a bug in the notification code which caused notification of
maintainers to fail completely if the corresponding maintainer had
multiple mnt-nfy lines. The version of maintainer.pl below fixes this
problem. Please drop this in src/maintainer.pl go to the main db
directory and run "make". "make install" is not needed.
-Marten
# $RCSfile: maintainer.pl,v $
# $Revision: 1.6 $
# $Author: marten $
# $Date: 1994/12/29 15:04:08 $
# maintainer.pl - implements all functions associated with the maintainer
# attribute, as defined in ripe-??
# There is a few global variables it will use for authorisation:
#
# $FROM - contains From: field from mail header
# $PASSWD - contains password found in message
# Also, the last maintainer object is kept globally for simplicity.
# Otherwise we keep looking the stupid thing up again and again and again.....
# maintainer - this is the main routine. It will receive two objects,
# the new and old object, and starts processing from there.
#
# Here's the scoop:
#
# OldObject is empty: addition
# NewObject is empty: delete
# None empty: normal update
require "notify.pl";
require "entype.pl";
sub Maintainer {
local(*OldObject, *NewObject, $delete) = @_;
local($status) = 0;
local($returnstatus) = 0;
# No maintainers mentioned, just return OK.
return 1 if !$NewObject{"mb"} && !$OldObject{"mb"};
# Case 1: OldObject is empty, ie this is a new object.
# - just return if NewObject contains no maintainers
# - use maintainers in NewObject to verify if it has maintainers
if (!&entype(*OldObject) || !$OldObject{"mb"}) {
return if !$NewObject{"mb"};
$MatchingMaintainer = "";
foreach (split(/\s+/, $NewObject{"mb"})) {
$status = &VrfyMaint($_, *NewObject);
$MatchingMaintainer = $_ if $status;
last if $status;
}
if (!$status) {
# All maintainers will receive a copy of the object with
# a message (specified in config) that someone tried to
# update one of their objects, but failed authorisation.
&ForwardToMaint(*OldObject, *NewObject);
return 0;
}
# Notification that an object has been added/changed/deleted.
# For all maintainers, send them a notification if they have
# a mnt-nfy attribute specified in their object. Otherwise
# no notification is done to the maintainers. Routine itself
# is clever enough to figure out is this is a delete/add/update.
&NotifyMaintainers(*OldObject, *NewObject);
return 1;
}
# Case 2: Normal case, NewObject replaces OldObject or is a delete
if ($OldObject{"mb"}) {
$MatchingMaintainer = "";
foreach (split(/\s+/, $OldObject{"mb"})) {
$status = &VrfyMaint($_, *OldObject);
$MatchingMaintainer = $_ if $status;
last if $status;
}
if (!$status) {
# Auth failed. Bounce to originator and forward to maintainer
# Same as above.
&ForwardToMaint(*OldObject, *NewObject);
return 0;
}
# Notify maintainers if requested (as above) only if not uknown
# maintainer is added.
&NotifyMaintainers(*OldObject, *NewObject);
return 1;
}
}
sub GetMaintainer {
local($maintainername, $source) = @_;
local(*i) = 'curdb';
local(%nothing) = ();
local($normalized) = $maintainername;
local($dbfile);
$normalized =~ tr/A-Z/a-z/;
local(@keys) = ($normalized);
return 1 if ($CurMaintainer{"mt"} eq $maintainername);
if ($TYPE{$source} eq "SPLIT") {
$dbfile = "$DBFILE{$source}.mt";
} else {
$dbfile = $DBFILE{$source};
}
if (&dbopen(i, *nothing, 0, $dbfile)) {
local(@matches) = &dbmatch(*i, *keys, 1);
if ($#matches > 0) {
&syslog("ERRLOG","GetMaintainer - found more than one match for ".
"maintainer: $maintainername\n");
# Set error, should not happen!!!!!
&dbclose(*i);
return 0;
}
if (!$matches[0]) {
&syslog(
"ERRLOG",
"GetMaintainer() no match found for maintainer $maintainer"
);
&dbclose(*i);
return 0;
}
%CurMaintainer = &enread(i, $matches[0]);
$ExistMaintainer{$CurMaintainer{"mt"}} = 1;
&dbclose(*i);
return 1;
} else {
&syslog("ERRLOG",
"GetMaintainer - failed to open $DBFILE{$source}.mt\n"
);
return 0;
}
}
sub VrfyMaint {
local($maintainer, *object) = @_;
local($status);
local($source) = $object{"so"};
if (&GetMaintainer($maintainer, $source)) {
foreach (split(/\n/, $CurMaintainer{"at"})) {
$status = 0;
if ($_ eq "NONE") {
return 1;
}
if ($_ =~ /^MAIL-FROM/) {
$status = &CheckMailFrom($_);
return 1 if $status;
next;
}
if ($_ =~ /^CRYPT-PW/) {
$status = &CheckPassword($_);
return 1 if $status;
next;
}
}
return $status;
} else {
return 0;
}
}
sub CheckMailFrom {
local($line) = @_;
$line =~ m/MAIL-FROM\s+(.*)/;
local($regex) = $1;
return 1 if $FROM =~ /$regex/;
&syslog("AUDITLOG", "Auth email failure \"$FROM\" !~ \"$regex\"");
return 0;
}
sub CheckPassword {
local($line) = @_;
$line = m/CRYPT-PW\s+(\S+)/;
local($cpwd) = $1;
return 1 if crypt($PASSWORD, $cpwd) eq $cpwd;
&syslog("AUDITLOG", "Auth passwd failure \"$PASSWORD\" !~ \"$cpwd\"");
return 0;
}
# This routine will handle the mnt-nfy function in the maintainer object
# It will extract the email addresses from mnt-nfy attribute, and from
# there on, treat them as normal notifiers.
sub NotifyMaintainers {
local(*Oldobject, *NewObject) = @_;
local(@notif) = ();
local($line);
local($del) = 1 if !&entype(*NewObject);
local($m) = 0;
local($source);
if ($OldObject{"mb"}) {
foreach $line (split(/\n/, $OldObject{"mb"})) {
@notif = (@notif, split(/\s+/, $line));
$source = $OldObject{"so"};
}
} else {
foreach $line (split(/\n/, $NewObject{"mb"})) {
@notif = (@notif, split(/\s+/, $line));
$source = $NewObject{"so"};
}
}
foreach $m (0..$#notif) {
&GetMaintainer($notif[$m], $source);
if ($CurMaintainer{"mn"}) {
local(@mns);
foreach (split(/\n/, $CurMaintainer{"mn"})) {
@mns = (@mns, $_);
}
splice(@notif, $m, 1, @mns);
} else {
splice(@notif, $m, 1);
$m--;
}
}
&DoAddNotify(*notif, *OldObject, *NewObject, $del);
}
# This routine will forward objects to a all maintainers if authorisation
# failed. The message configured in config should make clear to the
# maintainer that the update actually failed, and they should take action
# as the proper maintainers.
# Notification of succeeded updates for maintainers is done through
# the normal notify mechanism only if maintainer object contains a
# mnt-nfy attribute.
sub ForwardToMaint {
local(*OldObject, *NewObject) = @_;
local($line);
local(@maintainers) = ();
local($oldtype) = &entype(*OldObject);
local($newtype) = &entype(*NewObject);
local($source);
local($email);
if ($OldObject{"mb"}) {
foreach $line (split(/\n/, $OldObject{"mb"})) {
@maintainers = (@maintainers, split(/\s+/, $line));
$source = $OldObject{"so"};
}
} else {
foreach $line (split(/\n/, $NewObject{"mb"})) {
@maintainers = (@maintainers, split(/\s+/, $line));
$source = $NewObject{"so"};
}
}
foreach (@maintainers) {
# The idea was to not send a notificatio to the matching
# maintainer. Let's forget about that one for now.
# next if $_ eq $MatchingMaintainer;
if (!&GetMaintainer($_, $source)) {
&syslog("ERRLOG",
"Failed to get maintainer $_ in fwd msg generation");
return;
}
foreach $email (split(/\n/, $CurMaintainer{"dt"})) {
if (!$forward{$email}) {
$forward{$email} = &ForwardTmpFile($email);
open(FORWARD, ">$forward{$email}") ||
&syslog("ERRLOG",
"Cannot create maintainer fwd file $forward{$email}");
&WriteForwardHeader(FORWARD, $email);
} else {
open(FORWARD, ">>$forward{$email}") ||
&syslog("ERRLOG",
"Cannot open maintainer fwd file $forward{$email}");
}
select(FORWARD);
if (!$newtype) { # Deletion
print "---\n";
print "DELETION REQUESTED FOR:\n\n";
print "\n" if &enwrite(*OldObject,1,0,1);
} elsif (!$oldtype) { # Addition
print "---\n";
print "ADDITION REQUESTED FOR:\n\n";
print "\n" if &enwrite(*NewObject,1,0,1);
} else { # Update
print "---\n";
print "UPDATE REQUESTED FOR:\n\n";
print "\n" if &enwrite(*NewObject,1,0,1);
}
close(FORWARD);
}
}
select(STDOUT);
}
sub ForwardTmpFile {
local($email) = @_;
return "$TMPDIR/$email.$$";
}
sub WriteForwardHeader {
local($filehandle, $email) = @_;
select($filehandle);
print $FWHEADER;
$email = $DEFMAIL if $TESTMODE;
print "To: $email\n";
print "\n";
eval "print \"$FWTEXT\n\";";
select(STDOUT);
}
sub SendForwardMails {
local($a);
foreach $a (keys %forward) {
system("$MAILCMD < $forward{$a}");
unlink($forward{$a});
}
}
1;