summaryrefslogtreecommitdiffstats
path: root/utils/cgp_rspamd.pl
diff options
context:
space:
mode:
Diffstat (limited to 'utils/cgp_rspamd.pl')
-rw-r--r--utils/cgp_rspamd.pl452
1 files changed, 225 insertions, 227 deletions
diff --git a/utils/cgp_rspamd.pl b/utils/cgp_rspamd.pl
index e55ac5791..1d4d4406f 100644
--- a/utils/cgp_rspamd.pl
+++ b/utils/cgp_rspamd.pl
@@ -21,278 +21,276 @@ my $request_timeout = 15; # 15 seconds by default
my $reject_message = "Spam message rejected";
GetOptions(
- "host=s" => \$rspamd_host,
- "header=s" => \$header,
- "reject-message=s" => \$reject_message,
- "max-size=i" => \$max_size,
- "timeout=f" => \$request_timeout,
- "help|?" => \$help,
- "man" => \$man
+ "host=s" => \$rspamd_host,
+ "header=s" => \$header,
+ "reject-message=s" => \$reject_message,
+ "max-size=i" => \$max_size,
+ "timeout=f" => \$request_timeout,
+ "help|?" => \$help,
+ "man" => \$man
) or pod2usage(2);
pod2usage(1) if $help;
pod2usage( -exitval => 0, -verbose => 2 ) if $man;
my $main_domain = cgp_main_domain();
-my $scanned = 0;
+my $scanned = 0;
# Turn off bufferization as required by CGP
$| = 1;
sub cgp_main_domain {
- if ( open(my $fh, 'Settings/Main.settings') ) {
- while (<$fh>) {
- if ( /^\s+DomainName\s+=\s+([^;]+);/ ) {
- return $1;
- }
+ if ( open( my $fh, 'Settings/Main.settings' ) ) {
+ while (<$fh>) {
+ if (/^\s+DomainName\s+=\s+([^;]+);/) {
+ return $1;
+ }
+ }
}
- }
}
sub cgp_string {
- my ($in) = @_;
+ my ($in) = @_;
- $in =~ s/\"/\\"/g;
- $in =~ s/\n/\\n/gms;
- $in =~ s/\r/\\r/mgs;
- $in =~ s/\t/ /g;
+ $in =~ s/\"/\\"/g;
+ $in =~ s/\n/\\n/gms;
+ $in =~ s/\r/\\r/mgs;
+ $in =~ s/\t/ /g;
- return "\"$in\"";
+ return "\"$in\"";
}
sub rspamd_scan {
- my ( $tag, $file ) = @_;
-
- my $http_callback = sub {
- my ( $body, $hdr ) = @_;
-
- if ( $hdr && $hdr->{Status} =~ /^2/ ) {
- my $js = eval('decode_json($body)');
- $scanned++;
-
- if ( !$js ) {
- print "* Rspamd: Bad response for $file: invalid JSON: parse error\n";
- print "$tag FAILURE\n";
- }
- else {
- my $def = $js;
- my $headers = "";
-
- if ( !$def ) {
- print
-"* Rspamd: Bad response for $file: invalid JSON: default is missing\n";
- print "$tag FAILURE\n";
- }
- else {
- my $action = $def->{'action'};
- my $id = $js->{'message-id'};
-
- my $symbols = "";
- while ( my ( $k, $s ) = each( %{$def->{'symbols'}}) ) {
- $symbols .= sprintf "%s(%.2f);", $k, $s->{'score'};
- }
-
- printf
-"* Rspamd: Scanned %s; id: <%s>; Score: %.2f / %.2f; Symbols: [%s]\n",
- $file, $id, $def->{'score'}, $def->{'required_score'}, $symbols;
-
- if ( $js->{'dkim-signature'} ) {
- $headers .= "DKIM-Signature: " . $js->{'dkim-signature'};
- }
-
- if ( $js->{'milter'} ) {
- my $block = $js->{'milter'};
-
- if ( $block->{'add_headers'} ) {
- while ( my ( $h, $v ) = each( %{ $block->{'add_headers'} } ) ) {
- if (ref($v) eq 'HASH') {
- if ($headers eq "") {
- $headers .= "$h: $v->{value}";
- }
- else {
- $headers .= "\\e$h: $v->{value}";
- }
+ my ( $tag, $file ) = @_;
+
+ my $http_callback = sub {
+ my ( $body, $hdr ) = @_;
+
+ if ( $hdr && $hdr->{Status} =~ /^2/ ) {
+ my $js = eval('decode_json($body)');
+ $scanned++;
+
+ if ( !$js ) {
+ print "* Rspamd: Bad response for $file: invalid JSON: parse error\n";
+ print "$tag FAILURE\n";
+ }
+ else {
+ my $def = $js;
+ my $headers = "";
+
+ if ( !$def ) {
+ print "* Rspamd: Bad response for $file: invalid JSON: default is missing\n";
+ print "$tag FAILURE\n";
}
else {
- if ($headers eq "") {
- $headers .= "$h: $v";
- }
- else {
- $headers .= "\\e$h: $v";
- }
+ my $action = $def->{'action'};
+ my $id = $js->{'message-id'};
+
+ my $symbols = "";
+ while ( my ( $k, $s ) = each( %{ $def->{'symbols'} } ) ) {
+ $symbols .= sprintf "%s(%.2f);", $k, $s->{'score'};
+ }
+
+ printf
+ "* Rspamd: Scanned %s; id: <%s>; Score: %.2f / %.2f; Symbols: [%s]\n",
+ $file, $id, $def->{'score'}, $def->{'required_score'}, $symbols;
+
+ if ( $js->{'dkim-signature'} ) {
+ $headers .= "DKIM-Signature: " . $js->{'dkim-signature'};
+ }
+
+ if ( $js->{'milter'} ) {
+ my $block = $js->{'milter'};
+
+ if ( $block->{'add_headers'} ) {
+ while ( my ( $h, $v ) = each( %{ $block->{'add_headers'} } ) ) {
+ if ( ref($v) eq 'HASH' ) {
+ if ( $headers eq "" ) {
+ $headers .= "$h: $v->{value}";
+ }
+ else {
+ $headers .= "\\e$h: $v->{value}";
+ }
+ }
+ else {
+ if ( $headers eq "" ) {
+ $headers .= "$h: $v";
+ }
+ else {
+ $headers .= "\\e$h: $v";
+ }
+ }
+ }
+ }
+ }
+
+ if ( $action eq 'reject' ) {
+ print "$tag DISCARD\n";
+ return;
+ }
+ elsif ( $action eq 'add header' || $action eq 'rewrite subject' ) {
+ if ( $headers eq "" ) {
+ $headers .= "$header";
+ }
+ else {
+ $headers .= "\\e$header";
+ }
+ }
+ elsif ( $action eq 'soft reject' ) {
+ print "$tag REJECT Try again later\n";
+ return;
+ }
+
+ if ( $headers eq "" ) {
+ print "$tag OK\n";
+ }
+ else {
+ print "$tag ADDHEADER " . cgp_string($headers) . " OK\n";
+ }
}
- }
}
- }
-
- if ( $action eq 'reject' ) {
- print "$tag DISCARD\n";
- return;
- }
- elsif ( $action eq 'add header' || $action eq 'rewrite subject' ) {
- if ( $headers eq "" ) {
- $headers .= "$header";
+ }
+ else {
+ if ($hdr) {
+ print "* Rspamd: Bad response for $file: HTTP error: $hdr->{Status} $hdr->{Reason}\n";
}
else {
- $headers .= "\\e$header";
+ print "* Rspamd: Bad response for $file: IO error: $!\n";
}
- }
- elsif ( $action eq 'soft reject' ) {
- print "$tag REJECT Try again later\n";
- return;
- }
-
- if ( $headers eq "" ) {
- print "$tag OK\n";
- }
- else {
- print "$tag ADDHEADER " . cgp_string($headers) . " OK\n";
- }
+ print "$tag FAILURE\n";
}
- }
+ };
+
+ if ($local) {
+
+ # Use file scan
+ # XXX: not implemented now due to CGP queue format
+ http_get(
+ "http://$rspamd_host/symbols?file=$file",
+ timeout => $request_timeout,
+ $http_callback
+ );
}
else {
- if ($hdr) {
- print
-"* Rspamd: Bad response for $file: HTTP error: $hdr->{Status} $hdr->{Reason}\n";
- }
- else {
- print "* Rspamd: Bad response for $file: IO error: $!\n";
- }
- print "$tag FAILURE\n";
- }
- };
-
- if ($local) {
-
- # Use file scan
- # XXX: not implemented now due to CGP queue format
- http_get(
- "http://$rspamd_host/symbols?file=$file",
- timeout => $request_timeout,
- $http_callback
- );
- }
- else {
- my $sb = stat($file);
-
- if ( !$sb || $sb->size > $max_size ) {
- if ($sb) {
- print "* File $file is too large: " . $sb->size . "\n$tag FAILURE\n";
-
- }
- else {
- print "* Cannot stat $file: $!\n$tag FAILURE\n";
- }
- return;
- }
- aio_load(
- $file,
- sub {
- my ($data) = @_;
-
- if ( !$data ) {
- print "* Cannot open $file: $!\n$tag FAILURE\n";
- return;
- }
+ my $sb = stat($file);
+
+ if ( !$sb || $sb->size > $max_size ) {
+ if ($sb) {
+ print "* File $file is too large: " . $sb->size . "\n$tag FAILURE\n";
- # Parse CGP format
- $data =~ s/^((?:[^\n]*\n)*?)\n(.*)$/$2/ms;
- my @envelope = split /\n/, $1;
- chomp(@envelope);
- my $from;
- my @rcpts;
- my $ip;
- my $user;
-
- foreach my $elt (@envelope) {
- if ( $elt =~ /^P\s[^<]*(<[^>]*>).*$/ ) {
- $from = $1;
- }
- elsif ( $elt =~ /^R\s[^<]*(<[^>]*>).*$/ ) {
- push @rcpts, $1;
- }
- elsif ( $elt =~ /^S (?:<([^>]+)> )?(?:SMTP|HTTPU?|AIRSYNC|XIMSS) \[([0-9a-f.:]+)\]/ ) {
- if ($1) {
- $user = $1;
- }
- if ($2) {
- $ip = $2;
}
- }
- elsif ( $elt =~ /^S (?:<([^>]+)> )?(?:DSN|GROUP|LIST|PBX|PIPE|RULE) \[0\.0\.0\.0\]/ ) {
- if ($1) {
- $user = $1;
+ else {
+ print "* Cannot stat $file: $!\n$tag FAILURE\n";
}
- $ip = '127.2.4.7';
- }
+ return;
}
+ aio_load(
+ $file,
+ sub {
+ my ($data) = @_;
+
+ if ( !$data ) {
+ print "* Cannot open $file: $!\n$tag FAILURE\n";
+ return;
+ }
- my $headers = {};
- if ( $file =~ /\/([^\/.]+)\.msg$/ ) {
- $headers->{'Queue-ID'} = $1;
- }
- if ($from) {
- $headers->{From} = $from;
- }
- if ( scalar(@rcpts) > 0 ) {
+ # Parse CGP format
+ $data =~ s/^((?:[^\n]*\n)*?)\n(.*)$/$2/ms;
+ my @envelope = split /\n/, $1;
+ chomp(@envelope);
+ my $from;
+ my @rcpts;
+ my $ip;
+ my $user;
+
+ foreach my $elt (@envelope) {
+ if ( $elt =~ /^P\s[^<]*(<[^>]*>).*$/ ) {
+ $from = $1;
+ }
+ elsif ( $elt =~ /^R\s[^<]*(<[^>]*>).*$/ ) {
+ push @rcpts, $1;
+ }
+ elsif ( $elt =~ /^S (?:<([^>]+)> )?(?:SMTP|HTTPU?|AIRSYNC|XIMSS) \[([0-9a-f.:]+)\]/ ) {
+ if ($1) {
+ $user = $1;
+ }
+ if ($2) {
+ $ip = $2;
+ }
+ }
+ elsif ( $elt =~ /^S (?:<([^>]+)> )?(?:DSN|GROUP|LIST|PBX|PIPE|RULE) \[0\.0\.0\.0\]/ ) {
+ if ($1) {
+ $user = $1;
+ }
+ $ip = '127.2.4.7';
+ }
+ }
- # XXX: Anyevent cannot parse headers with multiple values
- $headers->{Rcpt} = join(',', @rcpts);
- }
- if ($ip) {
- $headers->{IP} = $ip;
- }
- if ($user) {
- $headers->{User} = $user;
- }
- if ($main_domain) {
- $headers->{'MTA-Tag'} = $main_domain;
- }
+ my $headers = {};
+ if ( $file =~ /\/([^\/.]+)\.msg$/ ) {
+ $headers->{'Queue-ID'} = $1;
+ }
+ if ($from) {
+ $headers->{From} = $from;
+ }
+ if ( scalar(@rcpts) > 0 ) {
- http_post(
- "http://$rspamd_host/checkv2", $data,
- timeout => $request_timeout,
- headers => $headers,
- $http_callback
+ # XXX: Anyevent cannot parse headers with multiple values
+ $headers->{Rcpt} = join( ',', @rcpts );
+ }
+ if ($ip) {
+ $headers->{IP} = $ip;
+ }
+ if ($user) {
+ $headers->{User} = $user;
+ }
+ if ($main_domain) {
+ $headers->{'MTA-Tag'} = $main_domain;
+ }
+
+ http_post(
+ "http://$rspamd_host/checkv2", $data,
+ timeout => $request_timeout,
+ headers => $headers,
+ $http_callback
+ );
+ }
);
- }
- );
- }
+ }
}
# Show informational message
print "* Rspamd CGP filter has been started\n";
my $w = AnyEvent->io(
- fh => \*STDIN,
- poll => 'r',
- cb => sub {
- chomp( my $input = <STDIN> );
-
- if ( $input =~ /^(\d+)\s+(\S+)(\s+(\S+)\s*)?$/ ) {
- my $tag = $1;
- my $cmd = $2;
-
- if ( $cmd eq "INTF" ) {
- print "$input\n";
- }
- elsif ( $cmd eq "FILE" && $4 ) {
- my $file = $4;
- print "* Scanning file $file\n";
- rspamd_scan $tag, $file;
- }
- elsif ( $cmd eq "QUIT" ) {
- print "* Terminating after scanning of $scanned files\n";
- print "$tag OK\n";
- exit 0;
- }
- else {
- print "* Unknown command $cmd\n";
- print "$tag FAILURE\n";
- }
+ fh => \*STDIN,
+ poll => 'r',
+ cb => sub {
+ chomp( my $input = <STDIN> );
+
+ if ( $input =~ /^(\d+)\s+(\S+)(\s+(\S+)\s*)?$/ ) {
+ my $tag = $1;
+ my $cmd = $2;
+
+ if ( $cmd eq "INTF" ) {
+ print "$input\n";
+ }
+ elsif ( $cmd eq "FILE" && $4 ) {
+ my $file = $4;
+ print "* Scanning file $file\n";
+ rspamd_scan $tag, $file;
+ }
+ elsif ( $cmd eq "QUIT" ) {
+ print "* Terminating after scanning of $scanned files\n";
+ print "$tag OK\n";
+ exit 0;
+ }
+ else {
+ print "* Unknown command $cmd\n";
+ print "$tag FAILURE\n";
+ }
+ }
}
- }
);
EV::run;