Added ability to lock factoids to prevent editing; improved detection of ban-evasion by devalidating accounts on part/quit and devalidating existing accounts that match a banmask when a ban occurs

This commit is contained in:
Pragmatic Software 2013-09-13 21:48:19 +00:00
parent d739415a29
commit 23d2e57527
4 changed files with 54 additions and 10 deletions

View File

@ -65,7 +65,7 @@ sub ban_whitelisted {
$mask = lc $mask;
$self->{pbot}->logger->log("whitelist check: $channel, $mask\n");
return defined $self->{ban_whitelist}->hash->{$channel}->{$mask}->{ban_whitelisted} ? 1 : 0;
return (exists $self->{ban_whitelist}->hash->{$channel}->{$mask} and defined $self->{ban_whitelist}->hash->{$channel}->{$mask}->{ban_whitelisted}) ? 1 : 0;
}
sub whitelist {
@ -175,6 +175,8 @@ sub add_message {
$self->message_history->{$account}->{channels}->{$channel}{join_watch}++;
} else {
# PART or QUIT
$self->message_history->{$account}->{channels}->{$channel}{validated} = 0;
# check QUIT message for netsplits, and decrement joinwatch if found
if($text =~ /^QUIT .*\.net .*\.split/) {
$self->message_history->{$account}->{channels}->{$channel}{join_watch}--;
@ -396,7 +398,7 @@ sub prune_message_history {
next unless $length > 0;
my %last = %{ @{ $self->{message_history}->{$mask}->{channels}->{$channel}{messages} }[$length - 1] };
# delete channel key if no activity within 3 days
# delete channel key if no activity for a while
if(gettimeofday - $last{timestamp} >= 60 * 60 * 24 * 90) {
$self->{pbot}->logger->log("$mask in $channel hasn't spoken in ninety days; removing channel history.\n");
delete $self->{message_history}->{$mask}->{channels}->{$channel};
@ -491,6 +493,39 @@ sub address_to_mask {
return $banmask;
}
sub devalidate_accounts {
# remove validation on accounts in $channel that match a ban/quiet $mask
my ($self, $mask, $channel) = @_;
my ($nickserv_account, $ban_account);
if($mask =~ m/^\$a:(.*)/) {
$ban_account = lc $1;
} else {
$ban_account = "";
}
my $mask_original = $mask;
$mask = quotemeta $mask;
$mask =~ s/\\\*/.*?/g;
$mask =~ s/\\\?/./g;
foreach my $account (keys %{ $self->{message_history} }) {
if(exists $self->{message_history}->{$account}->{channels}->{$channel}) {
if(exists $self->{message_history}->{$account}->{nickserv_account}) {
$nickserv_account = $self->{message_history}->{$account}->{nickserv_account};
} else {
$nickserv_account = undef;
}
if((defined $nickserv_account and $nickserv_account eq $ban_account) or $account =~ m/^$mask$/i) {
$self->{pbot}->logger->log("anti-flood: [devalidate-accounts] $account matches $mask_original, devalidating\n");
$self->message_history->{$mask}->{channels}->{$channel}{validated} = 0;
}
}
}
}
sub check_bans {
my ($self, $mask, $channel) = @_;
my ($bans, $nickserv_account, $nick, $host);
@ -552,7 +587,7 @@ sub check_bans {
CHECKBAN:
if($check_ban) {
# $self->{pbot}->logger->log("anti-flood: [check-bans] checking for bans in $channel on $account\n");
# $self->{pbot}->logger->log("anti-flood: [check-bans] checking for bans in $channel on $account using $target_nickserv_account\n");
my $baninfos = $self->{pbot}->bantracker->get_baninfo($account, $channel, $target_nickserv_account);
if(defined $baninfos) {

View File

@ -70,18 +70,17 @@ sub get_baninfo {
foreach my $mode (keys %{ $self->{banlist}{$channel} }) {
foreach my $banmask (keys %{ $self->{banlist}{$channel}{$mode} }) {
my $banmask_key = $banmask;
$banmask = quotemeta $banmask;
$banmask =~ s/\\\*/.*?/g;
$banmask =~ s/\\\?/./g;
if($banmask =~ m/^\$a:(.*)/) {
$ban_account = lc $1;
} else {
$ban_account = "";
}
my $banmask_key = $banmask;
$banmask = quotemeta $banmask;
$banmask =~ s/\\\*/.*?/g;
$banmask =~ s/\\\?/./g;
if((defined $account and $account eq $ban_account) or $mask =~ m/^$banmask$/i) {
if(not defined $bans) {
$bans = [];
@ -136,6 +135,7 @@ sub track_mode {
if($mode eq "+b" or $mode eq "+q") {
$self->{pbot}->logger->log("ban-tracker: $target " . ($mode eq '+b' ? 'banned' : 'quieted') . " by $source in $channel.\n");
$self->{banlist}->{$channel}->{$mode}->{$target} = [ $source, gettimeofday ];
$self->{pbot}->antiflood->devalidate_accounts($target, $channel);
}
elsif($mode eq "-b" or $mode eq "-q") {
$self->{pbot}->logger->log("ban-tracker: $target " . ($mode eq '-b' ? 'unbanned' : 'unquieted') . " by $source in $channel.\n");

View File

@ -41,6 +41,7 @@ my %factoid_metadata_levels = (
type => 60,
edited_by => 60,
edited_on => 60,
locked => 10,
# all others are allowed to be factset by anybody/default to level 0
);
@ -425,6 +426,10 @@ sub factrem {
return "/msg $nick You are not the owner of '$trigger' for $chan";
}
if(exists $factoids->{$channel}->{$trigger}->{'locked'} and $factoids->{$channel}->{$trigger}->{'locked'} != 0) {
return "$trigger is locked; unlock before deleting.";
}
$self->{pbot}->logger->log("$nick!$user\@$host removed [$channel][$trigger][" . $factoids->{$channel}->{$trigger}->{action} . "]\n");
$self->{pbot}->factoids->remove_factoid($channel, $trigger);
return "/msg $nick $trigger removed from " . ($channel eq '.*' ? 'the global channel' : $channel) . ".";
@ -738,6 +743,10 @@ sub factchange {
return "/msg $nick $keyword not found in channel $from.";
}
if(not $self->{pbot}->admins->loggedin($from, "$nick!$user\@$host") and exists $factoids->{$channel}->{$trigger}->{'locked'} and $factoids->{$channel}->{$trigger}->{'locked'} != 0) {
return "$trigger is locked and cannot be changed.";
}
my $ret = eval {
if(not $factoids->{$channel}->{$trigger}->{action} =~ s|$tochange|$changeto|) {
$self->{pbot}->logger->log("($from) $nick!$user\@$host: failed to change '$trigger' 's$delim$tochange$delim$changeto$delim\n");

View File

@ -13,7 +13,7 @@ use warnings;
# These are set automatically by the build/commit script
use constant {
BUILD_NAME => "PBot",
BUILD_REVISION => 430,
BUILD_REVISION => 431,
BUILD_DATE => "2013-09-13",
};