From 757553ef8954e6af06ea70d08c6ae9ee8d7b4bf5 Mon Sep 17 00:00:00 2001 From: Timo Makinen Date: Thu, 24 Sep 2020 18:43:06 +0000 Subject: [PATCH] spamassassin-clamav: Initial version of role --- roles/spamassassin-clamav/files/ClamAV.pm | 115 ++++++++++++++++++++++ roles/spamassassin-clamav/files/clamav.cf | 8 ++ roles/spamassassin-clamav/meta/main.yml | 4 + roles/spamassassin-clamav/tasks/main.yml | 19 ++++ 4 files changed, 146 insertions(+) create mode 100644 roles/spamassassin-clamav/files/ClamAV.pm create mode 100644 roles/spamassassin-clamav/files/clamav.cf create mode 100644 roles/spamassassin-clamav/meta/main.yml create mode 100644 roles/spamassassin-clamav/tasks/main.yml diff --git a/roles/spamassassin-clamav/files/ClamAV.pm b/roles/spamassassin-clamav/files/ClamAV.pm new file mode 100644 index 0000000..1d98c99 --- /dev/null +++ b/roles/spamassassin-clamav/files/ClamAV.pm @@ -0,0 +1,115 @@ + +=head1 NAME + +ClamAV - ClamAV anti-virus check + +=head1 SYNOPSIS + + loadplugin Mail::SpamAssassin::Plugin::ClamAV + + full CLAMAV eval:check_clamav() + score CLAMAV 5 + + add_header all Virus _CLAMAV_ + +=head1 DESCRIPTION + +This plugin sends the mail to locally running ClamAV daemon for virus +detection. + +=cut + +package Mail::SpamAssassin::Plugin::ClamAV; + +use Mail::SpamAssassin::Plugin; +use Mail::SpamAssassin::Logger; + +use IO::Socket::UNIX; + +use strict; +use warnings; + +use vars qw(@ISA); +@ISA = qw(Mail::SpamAssassin::Plugin); + +sub new { + my $class = shift; + my $mailsa = shift; + + $class = ref($class) || $class; + my $self = $class->SUPER::new($mailsa); + bless ($self, $class); + + dbg("ClamAV: Registering ClamAV plugin rules"); + $self->register_eval_rule("check_clamav"); + + $self->set_config($mailsa->{conf}); + + return $self; +} + +sub set_config { + my ($self, $conf) = @_; + my @cmds; + +=head1 ADMINISTRATOR SETTINGS + +=over + +=item clamav_socket STRING (default: /var/run/clamav/clamd.sock) + +Full path to locally running ClamAV daemon socket. + +=cut + + push (@cmds, { + setting => "clamav_socket", + is_admin => 1, + default => "/var/run/clamav/clamd.sock", + type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, + }); + + $conf->{parser}->register_commands(\@cmds); + +} + +sub check_clamav { + my ($self, $permsg, $fulltext) = @_; + + my $socket = IO::Socket::UNIX->new( + Type => SOCK_STREAM, + Peer => Mail::SpamAssassin::Util::untaint_file_path($permsg->{conf}->{clamav_socket}) + ) or do { + $permsg->set_tag("CLAMAV", "Error"); + info("ClamAV: Failed to connect socket, skipping virus check"); + return; + }; + + $socket->send("nINSTREAM\n"); + $socket->send(pack("N", length($$fulltext))); + $socket->send($$fulltext); + $socket->send(pack("N", 0)); + + my $result = $socket->getline(); + if ($result =~ /^stream: (.+) FOUND/i) { + info("ClamAV: Found virus " . $1); + $permsg->set_tag("CLAMAV", $1); + my $rulename = $permsg->get_current_eval_rule_name(); + $permsg->{conf}->{descriptions}->{$rulename} = "Found virus " . $1; + $result = 1; + } elsif ($result =~ /^(.*) ERROR/i) { + $permsg->set_tag("CLAMAV", "Error"); + info("ClamAV: Error in scanning: " . $1); + $result = 0; + } else { + $permsg->set_tag("CLAMAV", "Clean"); + dbg("ClamAV: Message clean"); + $result = 0; + } + + $socket->send("QUIT\n"); + close $socket; + return $result; +} + +1; diff --git a/roles/spamassassin-clamav/files/clamav.cf b/roles/spamassassin-clamav/files/clamav.cf new file mode 100644 index 0000000..963d555 --- /dev/null +++ b/roles/spamassassin-clamav/files/clamav.cf @@ -0,0 +1,8 @@ +loadplugin Mail::SpamAssassin::Plugin::ClamAV ClamAV.pm + +full CLAMAV eval:check_clamav() +score CLAMAV 5 + +add_header all Virus _CLAMAV_ + +clamav_socket /run/clamd.scan/clamd.sock diff --git a/roles/spamassassin-clamav/meta/main.yml b/roles/spamassassin-clamav/meta/main.yml new file mode 100644 index 0000000..36a6c3d --- /dev/null +++ b/roles/spamassassin-clamav/meta/main.yml @@ -0,0 +1,4 @@ +--- + +dependencies: + - {role: clamav} diff --git a/roles/spamassassin-clamav/tasks/main.yml b/roles/spamassassin-clamav/tasks/main.yml new file mode 100644 index 0000000..c57dc9d --- /dev/null +++ b/roles/spamassassin-clamav/tasks/main.yml @@ -0,0 +1,19 @@ +--- + +- name: copy clamav plugin + copy: + src: ClamAV.pm + dest: /etc/mail/spamassassin/ClamAV.pm + mode: 0644 + owner: root + group: "{{ ansible_wheel }}" + notify: restart spamassassin + +- name: create spamassassin config + copy: + src: clamav.cf + dest: /etc/mail/spamassassin/clamav.cf + mode: 0644 + owner: root + group: "{{ ansible_wheel }}" + notify: restart spamassassin