118 lines
3.7 KiB
Perl
118 lines
3.7 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|Authenticate PLAIN failed)/) {
|
|
if($string =~ m/Connection closed \(client didn't send a cert\)/) {
|
|
$hostile = 1;
|
|
$reply = 'No certificate';
|
|
} elsif($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/client didn't send a cert/) {
|
|
$reply = 'No cert from client';
|
|
$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;
|
|
}
|
|
} elsif($string =~ m/Unsupported authentication mechanism/) {
|
|
$reply = 'Unsupported auth mechanism';
|
|
$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/Request timed out waiting for client to continue authentication/) {
|
|
$hostile = 0;
|
|
$reply = 'Timed out during auth';
|
|
} else {
|
|
$reply = 'No match for '.$string;
|
|
}
|
|
return { retval => 1, retmsg => $reply, hostile => $hostile, host => $host, string => $string };
|
|
}
|
|
|
|
1;
|