Files
parserfilter/lib/dovecot_parser.pm
2024-03-09 15:36:42 +01:00

114 lines
3.4 KiB
Perl

package My::parser::dovecot_parser;
use strict;
use warnings;
sub new {
my $class = shift;
my $self = {};
bless ($self, $class);
return $self;
}
sub parser {
my $self = shift;
my $string = shift;
my ($reply,$hostile,$host) = ("No match for $string",0,'');
my $re_host = qr/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/;
my $re_usr = qr/[a-zA-Z0-9_-]*/;
my $re_pid = qr/[0-9]*/;
my $re_uid = qr/[a-zA-Z0-9_\-+:\/]*/;
my $re_info = qr/\($re_usr\)\<$re_pid\>\<$re_uid\>/;
if($string =~ m/ Info: Disconnected: Logged out /) {
$reply = 'Normal logout';
} elsif($string =~ m/ imap-login: (Info: |)Login: /) {
$reply = 'Normal login';
} elsif($string =~ m/ indexer-worker$re_info: Info: /) {
$reply = 'Indexer worker message';
} elsif($string =~ m/ Disconnected (in IDLE|for inactivity) /) {
$reply = 'Idle disconnect';
} elsif($string =~ m/imap($re_info): (Info: |Disconnected: |)Connection closed/) {
$reply = 'Normal connection closed';
} elsif($string =~ m/ imap$re_info: (Info: |)Disconnected: Logged out /) {
$reply = 'Normal log out';
} elsif($string =~ m/ master: Warning: Time moved /) {
$reply = 'Clock adjustment';
} elsif($string =~ m/auth failed/) {
$_ = $string;
$reply = 'Auth failure';
$hostile = 1;
PARSER:
m/ (rip=($re_host)) /gcix && do {
$host = $2;
};
} elsif($string =~ m/(Authentication error (\(Password mismatch\?\)|unknown user))/) {
$_ = $string;
$reply = 'Unknown user or auth error';
$hostile = 1;
PARSER:
m/(([a-zA-Z0-9@._-]*),($re_host),.*\): pam_authenticate\(\) failed: (Authentication error \(Password mismatch\?\)|unknown user))/gi && do {
$host = $3;
};
} elsif($string =~ m/unknown user/) {
$_ = $string;
$reply = 'Unknown user';
$hostile = 1;
PARSER:
m/(((Info: |)conn unix:auth-worker \(uid=([0-9]{1,9})\): auth-worker<([0-9]{1,9}>: pam\(([a-zA-Z0-9@._-]*),($re_host),<($re_uid)>\): unknown user)))/gi && do {
$host = $7;
};
} elsif($string =~ m/ imap-login: (Info: |)Disconnected/) {
if($string =~ m/Connection closed/) {
$hostile = 0;
$reply = 'Disconnecting is legit';
} elsif($string =~ m/ TLS handshaking: /) {
$reply = 'TLS error';
$hostile = 1;
} elsif($string =~ m/Too many invalid commands/) {
$reply = 'Too many invalid commands';
$hostile = 1;
} elsif($string =~ m/TLS: Disconnected,/) {
$reply = 'Likely a sleeping android';
$hostile = 0;
} elsif($string =~ m/client didn't finish SASL auth/) {
$reply = 'Timeout waiting for SASL auth';
$hostile = 1;
} elsif($string =~ m/no auth attempts in/) {
if($string =~ m/, secured/) {
$reply = 'Secured Disconnect during auth, either sleeping phone or attack on webmail';
$hostile = 0;
} else {
$reply = 'Non-secure disconnect during auth';
$hostile = 1;
}
}
if($hostile) {
$_ = $string;
PARSER:
m/\ (rip=($re_host))/gcix && do {
$host = $2;
};
}
} elsif($string =~ m/ imap-login: (Info: |) Aborted login /) {
$_ = $string;
$reply = 'Aborted login';
$hostile = 1;
PARSER:
m/ (rip=($re_host)) /gcix && do {
$host = $2;
};
} elsif($string =~ m/unknown user$/) {
$_ = $string;
$hostile = 1;
$reply = 'Unknown user';
PARSER:
m/Info: pam\([a-zA-Z0-9@._-]*,($re_host),\<.*\>\): unknown user/gi && do {
$host = $1;
};
} else {
$reply = 'No match for '.$string;
}
return { retval => 1, retmsg => $reply, hostile => $hostile, host => $host, string => $string };
}
1;