/* This file is part of mailfrom filter Copyright (C) 2005, 2006 Sergey Poznyakoff This file is default configuration for mailfrom in Alt Linux. It written by Sergey Afonin. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include_once #include_once #include_once #pragma regex +extended +icase set mailfrom_address "" set graylistactive 0 set msg_header "" set msg_header_last_received "Received: from " set infected_received_from "" set mail_from "" set rcpt_to "" set queue_id "" set helo_from_remote "" set virusmaster "" set massallocated_chk_exclude "\n" set graylist_exclude "\n" set explain_msg "" set ma_check 2 #include_once #include_once prog connect do set queue_id $i if %ma_check = 1 and not match_cidr_list(${client_addr}, %massallocated_chk_exclude) = 1 and not dbmap("/etc/mailfromd/whitelist.db", "massallocated:" $client_addr, 1) set ma_hit_num massallocated_hit(${client_ptr}, %massallocated_regexps) if %ma_hit_num > 0 echo "%queue_id: client's IP [" ${client_ptr} "]. Hit to R" %ma_hit_num "." reject fi fi done prog helo do # Save the host name for further use set helo_from_remote $1 set msg_header_last_received %msg_header_last_received $1 " (" echo "%queue_id: helo=" %helo_from_remote " client_addr=" ${client_addr} done prog envfrom do if dbmap("/etc/mailfromd/whitelist.db", "global:" $client_addr, 1) or dbmap("/etc/mailfromd/whitelist.db", "global:" $client_addr "-" $f, 1) or dbmap("/etc/mailfromd/whitelist.db", "global:" $f, 1) accept fi set msg_header_last_received %msg_header_last_received hostname(${client_addr}) " ["${client_addr}"])\r\n\t" set msg_header_last_received %msg_header_last_received "by " %ehlo_domain " (" %__package__ "/" %__version__ ") id " $i ";\r\n\t" set msg_header_last_received %msg_header_last_received strftime('%a, %d %b %Y %T %z (%Z)', time()) set infected_received_from hostname(${client_addr}) " ["${client_addr}"]" set mail_from "<" $f ">" if %ma_check = 2 and not match_cidr_list(${client_addr}, %massallocated_chk_exclude) = 1 and not dbmap("/etc/mailfromd/whitelist.db", "massallocated:" $client_addr, 1) set ma_hit_num massallocated_hit(${client_ptr}, %massallocated_regexps) if %ma_hit_num > 0 reject 550 5.7.1 "Your reverse name is " ${client_ptr} "\nAccess from dsl/dial-up/cable/e.t.c. relays denied, client's IP [" ${client_addr} "]. Hit to R" %ma_hit_num ". " %explain_msg fi fi if hostname ${client_addr} = ${client_addr} or %helo_from_remote matches "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$" or not %helo_from_remote matches "\." echo "%queue_id: bad some data, graylistactive set to 1." set graylistactive 1 fi catch failure or temp_failure do echo "%queue_id: Caught exception " $2 ", graylistactive set to 1." set graylistactive 1 done if $f mx fnmatches "*.yahoo.com" or $f mx fnmatches "*.namaeserver.com" echo "%queue_id: server which always accepts bad rcpt to, graylisted." set graylistactive 1 fi if $f = "" or dbmap("/etc/mailfromd/whitelist.db", "from:" $client_addr, 1) or dbmap("/etc/mailfromd/whitelist.db", "from:" $client_addr "-" $f, 1) or dbmap("/etc/mailfromd/whitelist.db", "from:" $f, 1) pass else on poll $f do when success: pass when not_found: if %last_poll_recv = "" if not %cache_used echo "%queue_id: last_poll_recv empty, \"" $f "\" is not in cache" reject 550 5.1.0 "Sender validity for <" $f "> can not be confirm by MX" else reject 550 5.1.0 "Sender validity for <" $f "> hasn't been confirmed by MX, data has been cached for " %n_cache_time " sec." fi else reject 550 5.1.0 "Your MX reply is \"" %last_poll_recv "\"" "\nSender validity for <" $f "> not confirmed by MX \"" %last_poll_host "\"" fi when failure: echo "%queue_id: last_poll_recv = " %last_poll_recv " last_poll_host = " %last_poll_host reject 550 5.1.0 "Sender validity for <" $f "> can not be be verified, permanent error occurred" when temp_failure: if %last_poll_recv = "" tempfail 450 4.4.1 "Sender validity for <" $f "> not confirmed by MX, MX does not respond" elif %last_poll_recv = "nothing" tempfail 450 4.4.1 "Your MX has not replied a some command. Possible long timeout." "\nSender validity for <" $f "> not confirmed by MX \"" %last_poll_host "\"" else tempfail 450 4.7.1 "Your MX reply is \"" %last_poll_recv "\"" "\nSender validity for <" $f "> not confirmed by MX \"" %last_poll_host "\"" fi done fi if rate($f "-" ${client_addr}, interval("1 hour 30 minutes")) > 100 echo "%queue_id: WARNING: Too big rate for E-Mail:IP pair $f-${client_addr}" /* tempfail 450 4.7.0 "Mail sending rate exceeded. Try again later" */ fi done prog envrcpt do set rcpt_to %rcpt_to $1 "\r\n" set gltime interval("1 hour") if %graylistactive = 1 and not dbmap("/etc/mailfromd/whitelist.db", "graylist:" $client_addr, 1) and not match_cidr_list(${client_addr}, %graylist_exclude) = 1 if greylist($client_addr "-" $f "-" $rcpt_addr, %gltime) if %greylist_seconds_left = %gltime tempfail 450 4.7.0 "You are greylisted for " %gltime " seconds" else tempfail 450 4.7.0 "Still greylisted for " %greylist_seconds_left " seconds" fi fi fi done func log_header_line(string hdr_line) do set str1 substring(%hdr_line, 0, index(%hdr_line, "\n")-1) if index(%hdr_line, "\n") = -1 echo "%queue_id: " %str1 else echo "%queue_id: " %str1 set str2 substring(%hdr_line, index(%hdr_line, "\n")+1, -1) log_header_line(%str2) fi done prog header do set msg_header %msg_header $1 ": " $2 "\r\n" set full_header_line $1 ": " $2 log_header_line(%full_header_line) catch failure do echo "%queue_id: error decoding string of header, caught exception: $2" # reject 554 5.7.0 "error decoding string of header; input string is not RFC 2047 encoded" continue done if message_header_decode($2, "KOI-8R") matches "ò A ó ó ù ì ï þ ë é" reject 554 5.7.0 "Spam messages rejected" fi done prog eom do catch failure do echo "%queue_id: ERROR: mailfromd can not access to clamd, caught exception: $2" tempfail 451 4.3.0 "mailfromd can not access to clamd; please try again later" done if clamav(%clamd_port) set message <<- EOT Subject: Virus intercepted To: <%virusmaster> From: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Agent: %__package__ (%__version__) X-Infected-Received-From: %infected_received_from The message %queue_id that sent from %mail_from to %rcpt_to contained a virus "%clamav_virus_name" and has not been delivered. Message tested by ClamAV: http://www.clamav.net ----- The original (infected) message headers here: %msg_header_last_received %msg_header EOT echo "%queue_id: Virus founded: %clamav_virus_name from ${client_addr}" catch * do echo "%queue_id: WARNING: message from daemon was not been sent to administrator, caught exception: $2" reject 554 5.7.0 "virus %clamav_virus_name detected by ClamAV - http://www.clamav.net" done send_mail(%message, %virusmaster) reject 554 5.7.0 "virus %clamav_virus_name detected by ClamAV - http://www.clamav.net" fi done