Gentoo Archives: gentoo-server

From: Ben Munat <bent@×××××.com>
To: gentoo-server@l.g.o
Subject: Re: [gentoo-server] amavisd-new disaster
Date: Fri, 03 Aug 2007 19:19:23
Message-Id: 46B37E94.6040903@munat.com
In Reply to: [gentoo-server] amavisd-new disaster by Jonathan Nichols
1 After my last hair-pulling experience with amavis, here's what I would do: amavisd usually logs to
2 /var/amavis/amavis.log; check in there for error messages.
3
4 If there's anything in there about permissions (or could not read file, or something like that),
5 then you've probably been bitten by the amavis/clamd ownership issues like I was. If amavisd is is
6 running as the amavis user, then there is clamd stuff needs to be writable by amavis... meaning
7 either give it a common group or just chown it to amavis.
8
9 Sorry I can't remember the specifics, but this should nudge you in the right direction...uh, unless
10 it's not a permission thing at all of course.
11
12 Hope this helps,
13
14 Ben
15
16
17 Jonathan Nichols wrote:
18 > Hey everyone. I just today updated to amavisd-new 2.4.1 and am having a
19 > problem that I cannot solve.
20 >
21 > Here's my forum post about it:
22 >
23 > http://forums.gentoo.org/viewtopic-p-4171870.html#4171870
24 >
25 > If anybody has any ideas, let me know. It's listening properly but not
26 > scanning anything at all.
27 >
28 > Here's my entire amavisd.conf file if anyone has any ideas.
29 >
30 >
31 >
32 > use strict;
33 >
34 > # Sample configuration file for amavisd-new (traditional style, chatty,
35 > # you may prefer to start with the more concise supplied amavisd.conf)
36 > #
37 > # See amavisd.conf-default for a list of all variables with their defaults;
38 > # for more details see documentation in INSTALL, README_FILES/*
39 > # and at http://www.ijs.si/software/amavisd/amavisd-new-docs.html
40 >
41 > # This software is licensed under the GNU General Public License (GPL).
42 > # See comments at the start of amavisd-new for the whole license text.
43 >
44 > #Sections:
45 > # Section I - Essential daemon and MTA settings
46 > # Section II - MTA specific
47 > # Section III - Logging
48 > # Section IV - Notifications/DSN, bounce/reject/discard/pass, quarantine
49 > # Section V - Per-recipient and per-sender handling, whitelisting, etc.
50 > # Section VI - Resource limits
51 > # Section VII - External programs, virus scanners, SpamAssassin
52 > # Section VIII - Debugging
53 > # Section IX - Policy banks (dynamic policy switching)
54 >
55 > #GENERAL NOTES:
56 > # This file is a normal Perl code, interpreted by Perl itself.
57 > # - make sure this file (or directory where it resides) is NOT WRITABLE
58 > # by mere mortals (not even vscan/amavis; best to make it owned by
59 > root),
60 > # otherwise it can represent a severe security risk!
61 > # - for values which are interpreted as booleans, it is recommended
62 > # to use 1 for true, and 0 or undef or '' for false;
63 > # Note that this interpretation of boolean values does not apply
64 > directly
65 > # to LDAP and SQL lookups, which follow their own rules - see
66 > README.lookups
67 > # and README.ldap (in short: use Y/N in SQL, and TRUE/FALSE in LDAP);
68 > # - Perl syntax applies. Most notably: strings in "" may include variables
69 > # (which start with $ or @); to include characters $ and @ and \ in
70 > double
71 > # quoted strings precede them by a backslash; in single-quoted strings
72 > # the $ and @ lose their special meaning, so it is usually easier to use
73 > # single quoted strings (or qw operator) for e-mail addresses.
74 > # In both types of quoting a backslash should to be doubled.
75 > # - variables with names starting with a '@' are lists, the values
76 > assigned
77 > # to them should be lists too, e.g. ('one@foo', $mydomain, "three");
78 > # note the comma-separation and parenthesis. If strings in the list
79 > # do not contain spaces nor variables, a Perl operator qw() may be used
80 > # as a shorthand to split its argument on whitespace and produce a list
81 > # of strings, e.g. qw( one@foo example.com three ); Note that the
82 > argument
83 > # to qw is quoted implicitly and no variable interpretation is done
84 > within
85 > # (no '$' variable evaluations). The #-initiated comments can NOT be
86 > used
87 > # within a string. In other words, $ and # lose their special meaning
88 > # within a qw argument, just like within '...' strings.
89 > # - all e-mail addresses in this file and as used internally by the daemon
90 > # are in their raw (rfc2821-unquoted and non-bracketed) form, i.e.
91 > # Bob "Funny" Dude@×××××××.com, not: "Bob \"Funny\" Dude"@example.com
92 > # and not <"Bob \"Funny\" Dude"@example.com>; also: '' and not '<>'.
93 > # - the term 'default value' in examples below refers to the value of a
94 > # variable pre-assigned to it by the program; any explicit assignment
95 > # to a variable in this configuration file overrides the default value;
96 >
97 >
98 > #
99 > # Section I - Essential daemon and MTA settings
100 > #
101 >
102 > # $MYHOME serves as a quick default for some other configuration settings.
103 > # More refined control is available with each individual setting further
104 > down.
105 > # $MYHOME is not used directly by the program. No trailing slash!
106 > $MYHOME = '/var/run/amavis'; # (default is '/var/amavis')
107 >
108 > # $mydomain serves as a quick default for some other configuration
109 > settings.
110 > # More refined control is available with each individual setting further
111 > down.
112 > # $mydomain is never used directly by the program.
113 > $mydomain = 'pbp.net'; # (no useful default)
114 >
115 > # $myhostname = 'host.example.com'; # fqdn of this host, default by
116 > uname(3)
117 > $myhostname = 'mailgate.pbp.net';
118 >
119 > # Set the user and group to which the daemon will change if started as root
120 > # (otherwise just keeps the UID unchanged, and these settings have no
121 > effect):
122 > $daemon_user = 'amavis'; # (no default; customary: vscan or amavis)
123 > $daemon_group = 'amavis'; # (no default; customary: vscan or amavis
124 > or sweep)
125 >
126 > # Runtime working directory (cwd), and a place where
127 > # temporary directories for unpacking mail are created.
128 > # (no trailing slash, may be a scratch file system)
129 > #$TEMPBASE = $MYHOME; # (must be set if other config vars use
130 > is)
131 > $TEMPBASE = "$MYHOME/tmp"; # prefer to keep home dir /var/amavis clean?
132 >
133 > #$db_home = "$MYHOME/db"; # DB databases directory, default "$MYHOME/db"
134 >
135 > # $helpers_home sets environment variable HOME, and is passed as option
136 > # 'home_dir_for_helpers' to Mail::SpamAssassin::new. It should be a
137 > directory
138 > # on a normal persistent file system, not a scratch or temporary file
139 > system
140 > #$helpers_home = $MYHOME; # (defaults to $MYHOME)
141 >
142 > # Run the daemon in the specified chroot jail if nonempty:
143 > #$daemon_chroot_dir = $MYHOME; # (default is undef, meaning: do not
144 > chroot)
145 >
146 > $pid_file = "$MYHOME/amavisd.pid"; # (default is "$MYHOME/amavisd.pid")
147 > #$lock_file = "$MYHOME/amavisd.lock"; # (default is "$MYHOME/amavisd.lock")
148 >
149 > # set environment variables if you want (no defaults):
150 > $ENV{TMPDIR} = $TEMPBASE; # wise to set TMPDIR, but not obligatory
151 > #...
152 >
153 > $enable_db = 1; # enable use of BerkeleyDB/libdb (SNMP and
154 > nanny)
155 > $enable_global_cache = 1; # enable use of libdb-based cache if
156 > $enable_db=1
157 >
158 > # MTA SETTINGS, UNCOMMENT AS APPROPRIATE,
159 > # both $forward_method and $notify_method default to
160 > 'smtp:[127.0.0.1]:10025'
161 >
162 > # POSTFIX, or SENDMAIL in dual-MTA setup, or EXIM V4
163 > # (set host and port number as required; host can be specified
164 > # as an IP address or a DNS name (A or CNAME, but MX is ignored)
165 > #$forward_method = 'smtp:[127.0.0.1]:10025'; # where to forward checked
166 > mail
167 > #$notify_method = $forward_method; # where to submit
168 > notifications
169 >
170 > #$os_fingerprint_method = 'p0f:127.0.0.1:2345'; # query p0f-analyzer.pl
171 >
172 > # To make it possible for several hosts to share one content checking
173 > daemon,
174 > # the IP address and/or the port number in $forward_method and
175 > $notify_method
176 > # may be spacified as an asterisk. An asterisk in the colon-separated
177 > # second field (host) will be replaced by the SMTP client peer address,
178 > # An asterisk in the third field (tcp port) will be replaced by the
179 > incoming
180 > # SMTP/LMTP session port number plus one. This obsoletes the previously
181 > used
182 > # less flexible configuration parameter $relayhost_is_client. An example:
183 > # $forward_method = 'smtp:*:*'; $notify_method = 'smtp:*:10587';
184 >
185 >
186 > # NOTE: The defaults (above) are good for Postfix or dual-sendmail. You
187 > MUST
188 > # uncomment the appropriate settings below if using other setups!
189 >
190 > # SENDMAIL MILTER, using amavis-milter.c helper program:
191 > #$forward_method = undef; # no explicit forwarding, sendmail does it by
192 > itself
193 > # milter; option -odd is needed to avoid deadlocks
194 > #$notify_method = 'pipe:flags=q argv=/usr/sbin/sendmail -Ac -i -odd -f
195 > ${sender} -- ${recipient}';
196 > # just a thought: can we use use -Am instead of -odd ?
197 >
198 > # SENDMAIL (old non-milter setup, as relay, deprecated):
199 > #$forward_method = 'pipe:flags=q argv=/usr/sbin/sendmail
200 > -C/etc/sendmail.orig.cf -i -f ${sender} -- ${recipient}';
201 > #$notify_method = $forward_method;
202 >
203 > # SENDMAIL (old non-milter setup, amavis.c calls local delivery agent,
204 > deprecated):
205 > #$forward_method = undef; # no explicit forwarding, amavis.c will call LDA
206 > #$notify_method = 'pipe:flags=q argv=/usr/sbin/sendmail -Ac -i -f
207 > ${sender} -- ${recipient}';
208 >
209 > # EXIM v3 (not recommended with v4 or later, which can use SMTP setup
210 > instead):
211 > #$forward_method = 'pipe:flags=q argv=/usr/sbin/exim -oMr scanned-ok -i
212 > -f ${sender} -- ${recipient}';
213 > #$notify_method = $forward_method;
214 >
215 > # prefer to collect mail for forwarding as BSMTP files?
216 > #$forward_method = "bsmtp:$MYHOME/out-%i-%n.bsmtp";
217 > #$notify_method = $forward_method;
218 >
219 >
220 > # Net::Server pre-forking settings
221 > # The $max_servers should match the width of your MTA pipe
222 > # feeding amavisd, e.g. with Postfix the 'Max procs' field in the
223 > # master.cf file, like the '2' in the: smtp-amavis unix - - n - 2 smtp
224 > #
225 > $max_servers = 4; # number of pre-forked children (default 2)
226 > $max_requests = 20; # retire a child after that many accepts (default 10)
227 >
228 > $child_timeout=5*60; # abort child if it does not complete its
229 > processing in
230 > # approximately n seconds (default: 8*60 seconds)
231 >
232 > $smtpd_timeout = 120; # disconnect session if client is idle for too long
233 > # (default: 8*60 seconds); should be higher than a
234 > # Postfix setting max_idle (default 100s)
235 >
236 > # Here is a QUICK WAY to completely DISABLE some sections of code
237 > # that WE DO NOT WANT (it won't even be compiled-in).
238 > # For more refined controls leave the following two lines commented out,
239 > # and see further down what these two lookup lists really mean.
240 > #
241 > # @bypass_virus_checks_maps = (1); # uncomment to DISABLE anti-virus code
242 > # @bypass_spam_checks_maps = (1); # uncomment to DISABLE anti-spam code
243 > #
244 > # Any setting can be changed with a new assignment, so make sure
245 > # you do not unintentionally override these settings further down!
246 >
247 > # Check also the settings of @av_scanners at the end if you want to use
248 > # virus scanners. If not, you may want to delete the whole long assignment
249 > # to the variable @av_scanners and @av_scanners_backup, which will also
250 > # remove the virus checking code (e.g. if you only want to do spam
251 > scanning).
252 >
253 >
254 > # Lookup list of local domains (see README.lookups for syntax details)
255 > #
256 > # @local_domains_maps list of lookup tables are used in deciding whether a
257 > # recipient is local or not, or in other words, if the message is outgoing
258 > # or not. This affects inserting spam-related headers for local recipients,
259 > # limiting recipient virus notifications (if enabled) to local recipients,
260 > # in deciding if address extension may be appended, and in SQL lookups
261 > # for non-fqdn addresses. Set it up correctly if you need features
262 > # that rely on this setting (or just leave empty otherwise).
263 > #
264 > # With Postfix (2.0) a quick hint on what local domains normally are:
265 > # a union of domains specified in: mydestination, virtual_alias_domains,
266 > # virtual_mailbox_domains, and relay_domains.
267 >
268 > #@local_domains_maps = ( [".$mydomain"] ); # $mydomain and its subdomains
269 > #@local_domains_maps = ( ["."] ); # everything is local
270 > # @local_domains_maps = (); # default is empty list, no recip.
271 > considered local
272 > # @local_domains_maps = # using ACL lookup table
273 > # ( [ ".$mydomain", 'sub.example.net', '.example.com' ] );
274 > # @local_domains_maps = # similar, split list elements on whitespace
275 > # ( [qw( .example.com !host.sub.example.net .sub.example.net )] );
276 > # @local_domains_maps = ( new_RE( qr'[@.]example\.com$'i ) ); # using
277 > regexp
278 > # @local_domains_maps = ( read_hash("$MYHOME/local_domains") ); # using
279 > hash
280 > #@local_domains_maps = ( read_hash("/etc/postfix/relay") ); # using hash
281 >
282 >
283 > #or try..
284 > #@local_domains_maps = ( ["."] ); # everything is local
285 >
286 > #didn't work
287 > #@local_domains_maps = ( '.' ); # everything is local
288 >
289 > #didn't work
290 > #@local_domains_maps = ( 1 );
291 >
292 > #@local_domains_acl = qw();
293 >
294 > # perhaps combined with Postfix: mydestination =
295 > /var/amavis/local_domains
296 > # for debugging purposes: dump_hash($local_domains_maps[0]);
297 > #
298 > # Section II - MTA specific (defaults should be ok)
299 > #
300 >
301 > #$insert_received_line = 1; # behave like MTA: insert 'Received:'
302 > header
303 > # (does not apply to sendmail/milter)
304 > # (default is true)
305 >
306 > # AMAVIS-CLIENT PROTOCOL INPUT SETTINGS (e.g. with sendmail milter)
307 > # (used with amavis helper clients like amavis-milter.c and amavis.c,
308 > # NOT needed for Postfix or Exim or dual-sendmail - keep it undefined.
309 > $unix_socketname = "$MYHOME/amavisd.sock"; # amavis helper protocol socket
310 > #$unix_socketname = undef; # disable listening on a unix socket
311 > # (default is undef, i.e. disabled)
312 > # (usual setting is $MYHOME/amavisd.sock)
313 >
314 > # SMTP SERVER (INPUT) PROTOCOL SETTINGS (e.g. with Postfix, Exim v4, ...)
315 > # (used when MTA is configured to pass mail to amavisd via SMTP or LMTP)
316 > $inet_socket_port = 10024; # accept SMTP on this local TCP port
317 > # (default is undef, i.e. disabled)
318 > # multiple ports may be provided: $inet_socket_port = [10024, 10026,
319 > 10028];
320 >
321 > # SMTP SERVER (INPUT) access control
322 > # - do not allow free access to the amavisd SMTP port !!!
323 > #
324 > # when MTA is at the same host, use the following (one or the other or
325 > both):
326 > #$inet_socket_bind = '127.0.0.1'; # limit socket bind to loopback interface
327 > # (default is '127.0.0.1')
328 > @inet_acl = qw(127.0.0.1 [::1]); # allow SMTP access only from
329 > localhost IP
330 > # (default is qw(127.0.0.1 [::1]) )
331 >
332 > # when MTA (one or more) is on a different host, use the following:
333 > #@inet_acl = qw(127.0.0.0/8 [::1] 10.1.0.1 10.1.0.2); # adjust list as
334 > needed
335 > #$inet_socket_bind = undef; # bind to all IP interfaces if undef
336 >
337 > #
338 > # Example1:
339 > # @inet_acl = qw( 127/8 10/8 172.16/12 192.168/16 );
340 > # permit only SMTP access from loopback and rfc1918 private address space
341 > #
342 > # Example2:
343 > # @inet_acl = qw( !192.168.1.12 172.16.3.3 !172.16.3/255.255.255.0
344 > # 127.0.0.1 10/8 172.16/12 192.168/16 );
345 > # matches loopback and rfc1918 private address space except host
346 > 192.168.1.12
347 > # and net 172.16.3/24 (but host 172.16.3.3 within 172.16.3/24 still
348 > matches)
349 > #
350 > # Example3:
351 > # @inet_acl = qw( 127/8
352 > # !172.16.3.0 !172.16.3.127 172.16.3.0/25
353 > # !172.16.3.128 !172.16.3.255 172.16.3.128/25 );
354 > # matches loopback and both halves of the 172.16.3/24 C-class,
355 > # split into two subnets, except all four broadcast addresses
356 > # for these subnets
357 >
358 >
359 > # @mynetworks is an IP access list which determines if the original SMTP
360 > client
361 > # IP address belongs to our internal networks, i.e. mail is coming from
362 > inside.
363 > # It is much like the Postfix parameter 'mynetworks' in semantics and
364 > similar
365 > # in syntax, and its value should normally match the Postfix counterpart.
366 > # It only affects the value of a macro %l (=sender-is-local),
367 > # and the loading of policy 'MYNETS' if present (see below).
368 > # Note that '-o smtp_send_xforward_command=yes' (or its lmtp counterpart)
369 > # must be enabled in the Postfix service that feeds amavisd, otherwise
370 > # client IP address is not available to amavisd-new.
371 > #
372 > # @mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10
373 > # 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 ); # default
374 > #
375 > # A list of networks can also be read from a file, either as an IP acl in
376 > # CIDR notation, one address per line (comments and empty lines are
377 > allowed):
378 > # @mynetworks_maps = (read_array('/etc/amavisd-mynetworks'),
379 > \@mynetworks);
380 > #
381 > # or less flexibly (but provides faster lookups for large lists) by reading
382 > # into a hash lookup table, which only allows for full addresses or
383 > classful
384 > # IPv4 subnets with truncated octets, such as 127, 10, 192.168,
385 > 10.11.12.13,
386 > # one address per line (comments and empty lines are allowed):
387 > # @mynetworks_maps = (read_hash('/etc/amavisd-mynetworks'),
388 > \@mynetworks);
389 >
390 > # See README.lookups for details on specifying access control lists.
391 >
392 >
393 > #
394 > # Section III - Logging
395 > #
396 >
397 > # true (e.g. 1) => syslog; false (e.g. 0) => logging to file
398 > $DO_SYSLOG = 1; # (defaults to 0)
399 >
400 > $syslog_ident = 'amavis'; # Syslog ident string (defaults to 'amavis')
401 > $syslog_facility = 'mail'; # Syslog facility as a string
402 > # e.g.: mail, daemon, user, local0, ... local7, ...
403 > $syslog_priority = 'debug'; # Syslog base (minimal) priority as a string,
404 > # choose from: emerg, alert, crit, err, warning, notice,
405 > info, debug
406 >
407 > # Log file (if not using syslog)
408 > $LOGFILE = "$MYHOME/amavis.log"; # (defaults to empty, no log)
409 >
410 > #NOTE: levels are not strictly observed and are somewhat arbitrary
411 > # 0: startup/exit/failure messages, viruses detected
412 > # 1: args passed from client, some more interesting messages
413 > # 2: virus scanner output, timing
414 > # 3: server, client
415 > # 4: decompose parts
416 > # 5: more debug details
417 > $log_level = 2; # (defaults to 0)
418 >
419 > # Customizable template for the most interesting log file entry (e.g. with
420 > # $log_level=0) (take care to properly quote Perl special characters
421 > like '\')
422 > # For a list of available macros see README.customize .
423 >
424 > # $log_templ = undef; # undef disables by-message level-0 log entries
425 > $log_recip_templ = undef; # undef disables by-recipient level-0 log
426 > entries
427 >
428 >
429 > # log both infected and noninfected messages (as deflt, with
430 > size,subj,tests):
431 > # (remove the leading '#' and a space in the following lines to activate)
432 >
433 > # $log_templ = <<'EOD';
434 > # [?%#D|#|Passed #
435 > # [? [:ccat_maj] |OTHER|CLEAN|TEMPFAIL|OVERSIZED|BAD-HEADER|SPAMMY|SPAM|\
436 > # UNCHECKED|BANNED (%F)|INFECTED (%V)]#
437 > # #([:ccat_maj],[:ccat_min])#
438 > # , [? %p ||%p ][?%a||[?%l||LOCAL ]\[%a\] ][?%e||\[%e\] ]%s -> [%D|,]#
439 > # [? %q ||, quarantine: %q]#
440 > # [? %Q ||, Queue-ID: %Q]#
441 > # [? %m ||, Message-ID: %m]#
442 > # [? %r ||, Resent-Message-ID: %r]#
443 > # , mail_id: %i#
444 > # , Hits: %c#
445 > # , size: %z#
446 > # [~[:remote_mta_smtp_response]|["^$"]||[", queued_as: "]]\
447 > # [remote_mta_smtp_response|[~%x|["queued as
448 > ([0-9A-Z]+)$"]|["%1"]|["%0"]]|/]#
449 > # [? %j ||, Subject: "%j\"]#
450 > # [? %#T ||, Tests: \[[%T|,]\]]#
451 > # , %y ms#
452 > # ]
453 > # [?%#O|#|Blocked #
454 > # [? [:ccat_maj] |OTHER|CLEAN|TEMPFAIL|OVERSIZED|BAD-HEADER|SPAMMY|SPAM|\
455 > # UNCHECKED|BANNED (%F)|INFECTED (%V)]#
456 > # #([:ccat_maj],[:ccat_min])#
457 > # , [? %p ||%p ][?%a||[?%l||LOCAL ]\[%a\] ][?%e||\[%e\] ]%s -> [%O|,]#
458 > # [? %q ||, quarantine: %q]#
459 > # [? %Q ||, Queue-ID: %Q]#
460 > # [? %m ||, Message-ID: %m]#
461 > # [? %r ||, Resent-Message-ID: %r]#
462 > # , mail_id: %i#
463 > # , Hits: %c#
464 > # , size: %z#
465 > # #, smtp_resp: [:smtp_response]#
466 > # [? %j ||, Subject: "%j\"]#
467 > # [? %#T ||, Tests: \[[%T|,]\]]#
468 > # , %y ms#
469 > # ]
470 > # EOD
471 >
472 > #
473 > # Section IV - Notifications/DSN, bounce/reject/discard/pass, quarantine
474 > #
475 >
476 > # Select notifications text encoding when Unicode-aware Perl is converting
477 > # text from internal character representation to external encoding (charset
478 > # in MIME terminology). Used as argument to Perl Encode::encode subroutine.
479 > #
480 > # to be used in RFC 2047-encoded header field bodies, e.g. in Subject:
481 > #$hdr_encoding = 'iso-8859-1'; # MIME charset (default: 'iso-8859-1')
482 > #$hdr_encoding_qb = 'Q'; # MIME encoding: quoted-printable (default)
483 > #$hdr_encoding_qb = 'B'; # MIME encoding: base64
484 > #
485 > # to be used in notification body text: its encoding and
486 > Content-type.charset
487 > #$bdy_encoding = 'iso-8859-1'; # (default: 'iso-8859-1')
488 >
489 > # Default template texts for notifications may be overruled by directly
490 > # assigning new text to template variables, or by reading template text
491 > # from files. A second argument may be specified in a call to read_text(),
492 > # specifying character encoding layer to be used when reading from the
493 > # external file, e.g. 'utf8', 'iso-8859-1', or often just $bdy_encoding.
494 > # Text will be converted to internal character representation by Perl 5.8.0
495 > # or later; second argument is ignored otherwise. See PerlIO::encoding,
496 > # Encode::PerlIO and perluniintro man pages.
497 > #
498 > # $notify_sender_templ = read_text("$MYHOME/notify_sender.txt");
499 > # $notify_virus_sender_templ= read_text("$MYHOME/notify_virus_sender.txt");
500 > # $notify_virus_admin_templ = read_text("$MYHOME/notify_virus_admin.txt");
501 > # $notify_virus_recips_templ= read_text("$MYHOME/notify_virus_recips.txt");
502 > # $notify_spam_sender_templ = read_text("$MYHOME/notify_spam_sender.txt");
503 > # $notify_spam_admin_templ = read_text("$MYHOME/notify_spam_admin.txt");
504 >
505 > # If notification template files are collectively available in some
506 > directory,
507 > # one may call read_l10n_templates which invokes read_text for each known
508 > # template. This is primarily a Debian-specific feature, but was
509 > incorporated
510 > # into base code to facilitate porting.
511 > #
512 > # read_l10n_templates('/etc/amavis/en_US');
513 > #
514 > # If read_l10n_templates is called, a localization template directory must
515 > # contain the following files:
516 > # charset this file should contain a one-line name
517 > # of the character set used in the template
518 > # files (e.g. utf8, iso-8859-2, ...) and is
519 > # passed as the second argument to
520 > read_text;
521 > # template-dsn.txt content fills the $notify_sender_templ
522 > # template-virus-sender.txt content fills the
523 > $notify_virus_sender_templ
524 > # template-virus-admin.txt content fills the
525 > $notify_virus_admin_templ
526 > # template-virus-recipient.txt content fills the
527 > $notify_virus_recips_templ
528 > # template-spam-sender.txt content fills the
529 > $notify_spam_sender_templ
530 > # template-spam-admin.txt content fills the
531 > $notify_spam_admin_templ
532 >
533 > # Here is an overall picture (sequence of events) of how pieces fit
534 > together
535 > #
536 > # bypass_virus_checks set for all recipients? ==> PASS
537 > # no viruses? ==> PASS
538 > # log virus if $log_templ is nonempty
539 > # quarantine if $virus_quarantine_to is nonempty
540 > # notify admin if $virus_admin (lookup) nonempty
541 > # notify recips if $warnvirusrecip and (recipient is local or
542 > $warn_offsite)
543 > # add address extensions for local recipients (when enabled)
544 > # send (non-)delivery notifications
545 > # to sender if DSN needed (BOUNCE or ($warnvirussender and D_PASS))
546 > # virus_lovers or final_destiny==D_PASS ==> PASS
547 > # DISCARD (2xx) or REJECT (5xx) (depending on final_*_destiny)
548 > #
549 > # Equivalent flow diagram applies for spam checks.
550 > # If a virus is detected, spam checking is skipped entirely.
551 >
552 > # The following symbolic constants can be used in *_destiny settings:
553 > #
554 > # D_PASS mail will pass to recipients, regardless of bad contents;
555 > #
556 > # D_DISCARD mail will not be delivered to its recipients, sender will
557 > NOT be
558 > # notified. Effectively we lose mail (but will be quarantined
559 > # unless disabled). Losing mail is not decent for a mailer,
560 > # but might be desired.
561 > #
562 > # D_BOUNCE mail will not be delivered to its recipients, a non-delivery
563 > # notification (bounce) will be sent to the sender by
564 > amavisd-new;
565 > # Exception: bounce (DSN) will not be sent if a virus name
566 > matches
567 > # @viruses_that_fake_sender_maps, or to messages from mailing
568 > lists
569 > # (Precedence: bulk|list|junk), or for spam level that exceeds
570 > # the $sa_dsn_cutoff_level.
571 > #
572 > # D_REJECT mail will not be delivered to its recipients, sender should
573 > # preferably get a reject, e.g. SMTP permanent reject response
574 > # (e.g. with milter), or non-delivery notification from MTA
575 > # (e.g. Postfix). If this is not possible (e.g. different
576 > recipients
577 > # have different tolerances to bad mail contents and not
578 > using LMTP)
579 > # amavisd-new sends a bounce by itself (same as D_BOUNCE).
580 > # Not to be used with Postfix or dual-MTA setups!
581 > #
582 > # Notes:
583 > # D_REJECT and D_BOUNCE are similar, the difference is in who is
584 > responsible
585 > # for informing the sender about non-delivery, and how
586 > informative
587 > # the notification can be (amavisd-new knows more than MTA);
588 > # With D_REJECT, MTA may reject original SMTP, or send DSN (delivery
589 > status
590 > # notification, colloquially called 'bounce') - depending on
591 > MTA;
592 > # Best suited for sendmail milter and Courier, especially for
593 > spam.
594 > # With D_BOUNCE, amavisd-new (not MTA) sends DSN (can better explain the
595 > # reason for mail non-delivery or even suppress DSN, but unable
596 > # to reject the original SMTP session). Best suited to reporting
597 > # viruses, and for Postfix and other dual-MTA setups, which
598 > can't
599 > # reject original client SMTP session, as the mail has already
600 > # been enqueued.
601 >
602 > # Alternatives to consider for spam:
603 > # - use D_PASS if clients will do filtering based on inserted
604 > # mail headers or added address extensions ('plus-addressing')2;
605 > # - use D_DISCARD, if kill_level is set comfortably high;
606 > #
607 > # D_BOUNCE is preferred for viruses, but consider:
608 > # - use D_PASS (or virus_lovers) to deliver viruses;
609 > # - use D_REJECT instead of D_BOUNCE if using Courier or milter and
610 > under heavy
611 > # virus storm;
612 >
613 >
614 > # The use of new *_by_ccat hashes is illustrated by the following examples
615 > # on configuring final_*_destiny.
616 >
617 >
618 > # using traditional settings of $final_*_destiny variables, relying on a
619 > # default setting of an associative array %final_destiny_by_ccat which is
620 > # backwards compatible and contains references to these traditional
621 > variables:
622 > #
623 > #$final_virus_destiny = D_DISCARD; # (defaults to D_DISCARD)
624 > #$final_banned_destiny = D_BOUNCE; # (defaults to D_BOUNCE)
625 > #$final_spam_destiny = D_BOUNCE; # (defaults to D_BOUNCE)
626 > #$final_bad_header_destiny = D_PASS; # (defaults to D_PASS)
627 >
628 > ########
629 > #
630 > # Please think about what you are doing when you set these options.
631 > # If necessary, question your origanization's e-mail policies:
632 > #
633 > # D_BOUNCE contributes to the overall spread of virii and spam on the
634 > # internet. Both the envelope and header from addresses can be forged
635 > # accurately with no effort, causing the bounces to go to innocent parties,
636 > # whose addresses have been forged.
637 > #
638 > # D_DISCARD breaks internet mail specifications. However, with a
639 > # properly implemented Quaratine system, the concern for breaking the
640 > # specification is addressed to some extent.
641 > #
642 > # D_PASS is the safest way to handle e-mails. You must implement
643 > # client-side filtering to handle this method.
644 > #
645 > # -Cory Visi <merlin@g.o> 07/28/04
646 > #
647 > #######
648 >
649 >
650 >
651 > # to explicitly list all (or most) possible contents category (ccat) keys:
652 > %final_destiny_by_ccat = (
653 > CC_VIRUS, D_DISCARD,
654 > CC_BANNED, D_BOUNCE,
655 > CC_UNCHECKED, D_PASS,
656 > CC_SPAM, D_DISCARD,
657 > CC_BADH, D_PASS,
658 > CC_OVERSIZED, D_BOUNCE,
659 > CC_CLEAN, D_PASS,
660 > CC_CATCHALL, D_PASS,
661 > );
662 >
663 > # to rely on a catchall ccat key and only list exceptions (alternative 1):
664 > #%final_destiny_by_ccat = (
665 > # CC_VIRUS, D_DISCARD,
666 > # CC_BANNED, D_BOUNCE,
667 > # CC_SPAM, D_BOUNCE,
668 > # CC_BADH.',4', D_BOUNCE, # BadHdrSpace
669 > # CC_BADH.',3', D_BOUNCE, # BadHdrChar
670 > # CC_OVERSIZED, D_BOUNCE,
671 > # CC_CATCHALL, D_PASS,
672 > #);
673 >
674 > # to rely on a catchall ccat key and list exceptions (alternative 2):
675 > #%final_destiny_by_ccat = (
676 > # CC_VIRUS, D_DISCARD,
677 > # CC_UNCHECKED, D_PASS,
678 > # CC_BADH.',6', D_PASS, # BadHdrSyntax
679 > # CC_BADH.',5', D_PASS, # BadHdrLong
680 > # CC_BADH.',2', D_PASS, # BadHdr8bit
681 > # CC_BADH.',1', D_PASS, # BadHdrMime
682 > # CC_CLEAN, D_PASS,
683 > # CC_CATCHALL, D_BOUNCE,
684 > #);
685 >
686 > # to rely on a catchall ccat key and list exceptions (alternative 3):
687 > #%final_destiny_by_ccat = (
688 > # CC_VIRUS, D_DISCARD,
689 > # CC_UNCHECKED, D_PASS,
690 > # CC_BADH.',4', D_BOUNCE, # BadHdrSpace
691 > # CC_BADH.',3', D_BOUNCE, # BadHdrChar
692 > # CC_BADH, D_PASS, # sub-catchall for CC_BADH
693 > # CC_CLEAN, D_PASS,
694 > # CC_CATCHALL, D_BOUNCE,
695 > #);
696 >
697 > # to rely on a default %final_destiny_by_ccat and only change few settings:
698 > #$final_destiny_by_ccat{CC_SPAM} = D_PASS;
699 > #$final_destiny_by_ccat{CC_BADH} = D_BOUNCE;
700 > #$final_destiny_by_ccat{CC_BADH.',2'} = D_PASS; # BadHdr8bit
701 >
702 >
703 >
704 > # For monitoring / testing purposes let the administrator receive a copy
705 > # of certain delivery status notifications that are mailed back to senders:
706 > #
707 > #%dsn_bcc_by_ccat = (
708 > # CC_BANNED, undef,
709 > # CC_SPAM, undef,
710 > # CC_BADH, undef,
711 > # CC_CATCHALL, 'admin+test@×××××××.com',
712 > #);
713 > #
714 > # or use a simpler form, taking advantage of defaults in %dsn_bcc_by_ccat:
715 > #$dsn_bcc = 'admin+test@×××××××.com';
716 >
717 >
718 > # The following $warn*sender settings are ONLY used when mail is
719 > # actually passed to recipients ($final_*_destiny=D_PASS, or *_lovers*).
720 > # Bounces or rejects produce non-delivery status notification regardless.
721 > #
722 > # Notify sender of banned files?
723 > #$warnbannedsender = 1; # (defaults to false (undef))
724 > #
725 > # Notify sender of syntactically invalid header containing non-ASCII chars?
726 > #$warnbadhsender = 1; # (defaults to false (undef))
727 >
728 > # Notify virus (or banned files or bad headers) RECIPIENT?
729 > # (not very useful, but some policies demand it)
730 > #$warnvirusrecip = 1; # (defaults to false (undef))
731 > #$warnbannedrecip = 1; # (defaults to false (undef))
732 > #$warnbadhrecip = 1; # (defaults to false (undef))
733 >
734 > # Notify also non-local virus/banned recipients if $warn*recip is true?
735 > # (including those not matching local_domains*)
736 > #$warn_offsite = 1; # (defaults to false (undef), i.e. only notify
737 > locals)
738 >
739 >
740 > # Treat envelope sender address as unreliable and don't send sender
741 > # notification / bounces if name(s) of detected virus(es) match the list.
742 > # Note that virus names are supplied by external virus scanner(s) and are
743 > # not standardized, so virus names may need to be adjusted.
744 > # See README.lookups for syntax, check also README.policy-on-notifications.
745 > # If the intention is to treat all viruses as faking the sender address, it
746 > # is equivalent but more efficient to just set
747 > $final_virus_destiny=D_DISCARD;
748 > #
749 > @viruses_that_fake_sender_maps = (new_RE(
750 > qr'nimda|hybris|klez|bugbear|yaha|braid|sobig|fizzer|palyh|peido|holar'i,
751 > qr'tanatos|lentin|bridex|mimail|trojan\.dropper|dumaru|parite|spaces'i,
752 > qr'dloader|galil|gibe|swen|netwatch|bics|sbrowse|sober|rox|val(hal)?la'i,
753 >
754 > qr'frethem|sircam|be?agle|tanx|mydoom|novarg|shimg|netsky|somefool|moodown'i,
755 >
756 > qr'@mm|@MM', # mass mailing viruses as labeled by f-prot and uvscan
757 > qr'Worm'i, # worms as labeled by ClamAV, Kaspersky, etc
758 > # [qr'^(EICAR|Joke\.|Junk\.)'i => 0],
759 > # [qr'^(WM97|OF97|W95/CIH-|JS/Fort)'i => 0],
760 > [qr/^/ => 1], # true by default (remove or comment-out if undesired)
761 > ));
762 >
763 > # where to send ADMIN VIRUS NOTIFICATIONS (should be a fully qualified
764 > address)
765 > # - the administrator envelope address may be a simple fixed e-mail address
766 > # (a scalar), or may depend on the RECIPIENT address (e.g. its domain).
767 > #
768 > # Empty or undef lookup disables virus admin notifications.
769 >
770 > # The full set of configurable administrator addresses is:
771 > # @virus_admin_maps ... notifications to admin about viruses
772 > # @newvirus_admin_maps ... newly encountered viruses since amavisd
773 > startup
774 > # @spam_admin_maps ... notifications to admin about spam
775 > # @banned_admin_maps ... notifications to admin about banned contents
776 > # @bad_header_admin_maps ... notifications to admin about bad headers
777 >
778 > $virus_admin = "virusalert\@$mydomain";
779 > # $virus_admin = 'virus-admin@×××××××.com';
780 > # $virus_admin = undef; # do not send virus admin notifications (default)
781 > #
782 > #@virus_admin_maps = ( # by-recipient maps
783 > # {'not.example.com' => '',
784 > # '.' => 'virusalert@×××××××.com'},
785 > # $virus_admin, # the usual default
786 > #);
787 >
788 > # equivalent to $virus_admin, but for spam admin notifications:
789 > # $spam_admin = "spamalert\@$mydomain";
790 > # $spam_admin = undef; # do not send spam admin notifications (default)
791 > #@spam_admin_maps = ( # by-recipient maps
792 > # {'not.example.com' => '',
793 > # '.' => 'spamalert@×××××××.com'},
794 > # $spam_admin, # the usual default
795 > #);
796 >
797 > # receive a copy of all delivery status notifications sent;
798 > # useful for testing or monitoring
799 > #$dsn_bcc = "mailadmin\@$mydomain";
800 >
801 > #advanced example, using a hash lookup table and a scalar default,
802 > #lookup key is a recipient envelope address:
803 > #@virus_admin_maps = ( # by-recipient maps
804 > # { 'baduser@××××××××××××.com' => 'HisBoss@××××××××××××.com',
805 > # '.sub1.example.com' => 'virusalert@××××××××××××.com',
806 > # '.sub2.example.com' => '', # don't send admin
807 > notifications
808 > # 'a.sub3.example.com' => 'abuse@××××××××××××.com',
809 > # '.sub3.example.com' => 'virusalert@××××××××××××.com',
810 > # '.example.com' => 'noc@×××××××.com', # default for our virus
811 > senders
812 > # },
813 > # 'virusalert@××××××××××.com', # catchall for the rest
814 > #);
815 >
816 > # sender envelope address, from which notification reports are sent from;
817 > # may be a null reverse path, or a fully qualified address:
818 > # (admin and recip sender addresses default to a null return path).
819 > # If using strings in double quotes, don't forget to quote @, i.e. \@
820 > #
821 > $mailfrom_notify_admin = "virusalert\@$mydomain";
822 > $mailfrom_notify_recip = "virusalert\@$mydomain";
823 > $mailfrom_notify_spamadmin = "spam.police\@$mydomain";
824 >
825 > # 'From' HEADER FIELD for sender and admin notifications.
826 > # This should be a replyable address, see rfc1894. Not to be confused
827 > # with $mailfrom_notify_sender, which is the envelope return address
828 > # and can be empty (null reverse path) according to rfc2821.
829 > #
830 > # The syntax of the 'From' header field is specified in rfc2822, section
831 > # '3.4. Address Specification'. Note in particular that display-name
832 > must be
833 > # a quoted-string if it contains any special characters like spaces and
834 > dots.
835 > #
836 > # $hdrfrom_notify_sender = "amavisd-new <postmaster\@$mydomain>";
837 > # $hdrfrom_notify_sender = 'amavisd-new <postmaster@×××××××.com>';
838 > # $hdrfrom_notify_sender = '"Content-Filter Master"
839 > <postmaster@×××××××.com>';
840 > # $hdrfrom_notify_admin = $mailfrom_notify_admin;
841 > # $hdrfrom_notify_spamadmin = $mailfrom_notify_spamadmin;
842 > # (default: "\"Content-filter at $myhostname\"
843 > <postmaster\@$myhostname>")
844 >
845 > # whom quarantined messages appear to be sent from (envelope sender);
846 > # keeps original sender if undef, or set it explicitly, default is undef
847 > $mailfrom_to_quarantine = ''; # override sender address with null
848 > return path
849 >
850 >
851 > # Location to put infected mail into: (applies to 'local:' quarantine
852 > method)
853 > # empty for not quarantining, may be a file (Unix-style mailbox),
854 > # or a directory (no trailing slash)
855 > # (the default value is undef, meaning no quarantine)
856 > #
857 > $QUARANTINEDIR = "$MYHOME/quarantine";
858 >
859 > #$quarantine_subdir_levels = 1; # add level of subdirs to disperse
860 > quarantine
861 >
862 > #$clean_quarantine_method = 'local:clean-%m'; # disabled by
863 > default
864 > #$virus_quarantine_method = 'local:virus-%m'; # default
865 > #$spam_quarantine_method = 'local:spam-%m.gz'; # default
866 > #$banned_files_quarantine_method = 'local:banned-%m'; # default
867 > #$bad_header_quarantine_method = 'local:badh-%m'; # default
868 >
869 > # Separate quarantine subdirectories virus, spam, banned and badh within
870 > # the directory $QUARANTINEDIR may be specified by the following settings
871 > # (the subdirectories need to exist - must be created manually):
872 > #$clean_quarantine_method = 'local:clean/%m';
873 > #$virus_quarantine_method = 'local:virus/%m';
874 > #$spam_quarantine_method = 'local:spam/%m.gz';
875 > #$banned_files_quarantine_method = 'local:banned/%m';
876 > #$bad_header_quarantine_method = 'local:badh/%m';
877 > #
878 > #use the 'bsmtp:' method as an alternative to the default 'local:'
879 > #$virus_quarantine_method = "bsmtp:$QUARANTINEDIR/virus-%m.bsmtp";
880 > #$spam_quarantine_method = "bsmtp:$QUARANTINEDIR/spam-%m.bsmtp";
881 > #
882 > #using the 'pipe:' method might be useful for some special purpose:
883 > #$mailfrom_to_quarantine = undef; # pass on the original sender address
884 > #$spam_quarantine_method = 'pipe:argv=/usr/bin/myscript.sh spam-%b
885 > ${sender}';
886 > #
887 > #using the 'sql:' method to store quarantined message to a SQL database:
888 > #$virus_quarantine_method = $spam_quarantine_method =
889 > # $banned_files_quarantine_method = $bad_header_quarantine_method =
890 > 'sql:';
891 >
892 >
893 > # When using the 'local:' quarantine method (default), the following
894 > applies:
895 > #
896 > # A finer control of quarantining is available through
897 > # variables $virus_quarantine_method/$spam_quarantine_method/
898 > # $banned_files_quarantine_method/$bad_header_quarantine_method.
899 > #
900 > # The value of scalar $virus_quarantine_to/$spam_quarantine_to (or a
901 > # per-recipient lookup result from lookup tables @virus_quarantine_to_maps)
902 > # is/are interpreted as follows:
903 > #
904 > # VARIANT 1:
905 > # empty or undef disables quarantine;
906 > #
907 > # VARIANT 2:
908 > # a string NOT containing an '@';
909 > # amavisd will behave as a local delivery agent (LDA) and will quarantine
910 > # viruses to local files according to hash %local_delivery_aliases (pseudo
911 > # aliases map) - see subroutine mail_to_local_mailbox() for details.
912 > # Some of the predefined aliases are 'virus-quarantine' and
913 > 'spam-quarantine'.
914 > # Setting $virus_quarantine_to ($spam_quarantine_to) to this string will:
915 > #
916 > # * if $QUARANTINEDIR is a directory, each quarantined virus will go
917 > # to a separate file in the $QUARANTINEDIR directory (traditional
918 > # amavis style, similar to maildir mailbox format);
919 > #
920 > # * otherwise $QUARANTINEDIR is treated as a file name of a Unix-style
921 > # mailbox. All quarantined messages will be appended to this file.
922 > # Amavisd child process must obtain an exclusive lock on the file during
923 > # delivery, so this may be less efficient than using individual files
924 > # or forwarding to MTA, and it may not work across NFS or other non-local
925 > # file systems (but may be handy for pickup of quarantined files via IMAP
926 > # for example);
927 > #
928 > # VARIANT 3:
929 > # any email address (must contain '@').
930 > # The e-mail messages to be quarantined will be handed to MTA
931 > # for delivery to the specified address. If a recipient address local to
932 > MTA
933 > # is desired, you may leave the domain part empty, e.g. 'infected@', but
934 > the
935 > # '@' character must nevertheless be included to distinguish it from
936 > variant 2.
937 > #
938 > # This variant enables more refined delivery control made available by MTA
939 > # (e.g. its aliases file, other local delivery agents, dealing with
940 > # privileges and file locking when delivering to user's mailbox, nonlocal
941 > # delivery and forwarding, fan-out lists). Make sure the
942 > mail-to-be-quarantined
943 > # will not be handed back to amavisd for checking, as this will cause a
944 > loop
945 > # (hopefully broken at some stage)! If this can be assured, notifications
946 > # will benefit too from not being unnecessarily virus-scanned.
947 > #
948 > # By default this is safe to do with Postfix and Exim v4 and dual-sendmail
949 > # setup, but probably not safe with sendmail milter interface without
950 > tricks.
951 >
952 > # (default values are: virus-quarantine, banned-quarantine,
953 > spam-quarantine)
954 >
955 > $virus_quarantine_to = 'virus-quarantine'; # traditional local
956 > quarantine
957 > #$virus_quarantine_to = 'infected@'; # forward to MTA for
958 > delivery
959 > #$virus_quarantine_to = "virus-quarantine\@$mydomain"; # similar
960 > #$virus_quarantine_to = 'virus-quarantine@×××××××.com'; # similar
961 > #$virus_quarantine_to = undef; # no quarantine
962 > #
963 > # lookup key is envelope recipient address:
964 > #@virus_quarantine_to_maps = ( # per-recip multiple quarantines
965 > # new_RE( [qr'^user@example\.com$'i => 'infected@'],
966 > # [qr'^(.*)@example\.com$'i => 'virus-${1}@example.com'],
967 > # [qr'^(.*)(@[^@])?$'i => 'virus-${1}${2}'] ),
968 > # $virus_quarantine_to, # the usual default
969 > #);
970 >
971 > # similar for banned names and bad headers and spam (set to undef to
972 > disable)
973 > $banned_quarantine_to = 'banned-quarantine'; # local quarantine
974 > $bad_header_quarantine_to = 'bad-header-quarantine'; # local quarantine
975 > $spam_quarantine_to = 'spam-quarantine'; # local quarantine
976 >
977 > # or to a mailbox:
978 > #$spam_quarantine_to = "spam-quarantine\@$mydomain";
979 > #
980 > #@spam_quarantine_to_maps = ( # per-recip multiple quarantines
981 > # new_RE( [qr'^(.*)@example\.com$'i => 'spam-${1}@example.com'] ),
982 > # $spam_quarantine_to, # the usual default
983 > #);
984 >
985 >
986 > # In addition to per-recip quarantine, a by-sender lookup is possible.
987 > # It is similar to $spam_quarantine_to, but the lookup key is the
988 > # envelope sender address:
989 > #$spam_quarantine_bysender_to = undef; # dflt: no by-sender spam
990 > quarantine
991 >
992 >
993 > # Spam level beyond which quarantining is disabled (global value):
994 > #$sa_quarantine_cutoff_level = 20; # dflt: undef, which disables this
995 > feature
996 >
997 > #@spam_quarantine_cutoff_level_maps = ( # per-recip. quarantine cutoff
998 > levels
999 > # { 'user1@×××××××.com' => 20.5,
1000 > # 'postmaster@×××××××.com' => 9999,
1001 > # '.example.com' => 25 },
1002 > # \$sa_quarantine_cutoff_level, # catchall default
1003 > #);
1004 >
1005 >
1006 > # Add X-Virus-Scanned header field to mail?
1007 > $X_HEADER_TAG = 'X-Virus-Scanned'; # (default: 'X-Virus-Scanned')
1008 >
1009 > # Set to empty to add no header field # (dflt "$myproduct_name at
1010 > $mydomain")
1011 > # $X_HEADER_LINE = "$myproduct_name at $mydomain";
1012 > # $X_HEADER_LINE = "by $myproduct_name using ClamAV at $mydomain";
1013 > # $X_HEADER_LINE = "$myproduct_name $myversion_id ($myversion_date) at
1014 > $mydomain";
1015 >
1016 > # a string to prepend to Subject (for local recipients only) if mail could
1017 > # not be decoded or checked entirely, e.g. due to password-protected
1018 > archives
1019 > $undecipherable_subject_tag = '***UNCHECKED*** '; # undef disables it
1020 >
1021 > # MIME defanging wraps the entire original mail in a MIME container of type
1022 > # 'Content-type: multipart/mixed', where the first part is a text/plain
1023 > with
1024 > # a short explanation, and the second part is a complete original mail,
1025 > # enclosed in a 'Content-type: message/rfc822' MIME part.
1026 > # Defanging is only done when enabled (selectively by malware type),
1027 > # and mail is considered malware (virus/spam/...), and the malware is
1028 > allowed
1029 > # to pass (*_lovers or *_destiny=D_PASS)
1030 > #
1031 > $defang_virus = 1; # default is false: don't modify mail body
1032 > $defang_banned = 1; # default is false: don't modify mail body
1033 > # $defang_bad_header = 1; # default is false: don't modify mail body
1034 > # $defang_undecipherable = 1; # default is false: don't modify mail body
1035 > # $defang_spam = 1; # default is false: don't modify mail body
1036 >
1037 > $remove_existing_x_scanned_headers = 0; # leave existing X-Virus-Scanned
1038 > alone
1039 > #$remove_existing_x_scanned_headers= 1; # remove existing headers
1040 > # (defaults to false)
1041 > #$remove_existing_spam_headers = 0; # leave existing X-Spam* headers
1042 > alone
1043 > $remove_existing_spam_headers = 1; # remove existing spam headers if
1044 > # spam scanning is enabled (default)
1045 >
1046 > # set $bypass_decode_parts to true if you only do spam scanning, or if you
1047 > # have a good virus scanner that can deal with compression and recursively
1048 > # unpacking archives by itself, and save amavisd the trouble.
1049 > # Disabling decoding also causes banned_files checking to only see
1050 > # MIME names and MIME content types, not the content classification types
1051 > # as provided by the file(1) utility.
1052 > # It is a double-edged sword, make sure you know what you are doing!
1053 > #
1054 > #$bypass_decode_parts = 1; # (defaults to false)
1055 >
1056 > # don't trust this file type or corresponding unpacker for this file type,
1057 > # keep both the original and the unpacked file for a virus checker to see
1058 > # (lookup key is what file(1) utility returned):
1059 > #
1060 > @keep_decoded_original_maps = (new_RE(
1061 > # qr'^MAIL$', # retain full original message for virus checking (can
1062 > be slow)
1063 > qr'^MAIL-UNDECIPHERABLE$', # retain full mail if it contains
1064 > undecipherables
1065 > qr'^(ASCII(?! cpio)|text|uuencoded|xxencoded|binhex)'i,
1066 > # qr'^Zip archive data', # don't trust Archive::Zip
1067 > ));
1068 >
1069 >
1070 > # Checking for banned MIME types and names. If any mail part matches,
1071 > # the whole mail is rejected. Object $banned_filename_re provides a list
1072 > # of Perl regular expressions to be matched against each part's:
1073 > #
1074 > # * Content-Type value (both declared and effective mime-type),
1075 > # such as the possible security-risk content types
1076 > # 'message/partial' and 'message/external-body', as specified in rfc2046
1077 > # or 'application/x-msdownload' and 'application/x-msdos-program';
1078 > #
1079 > # * declared (recommended) file names as specified by MIME subfields
1080 > # Content-Disposition.filename and Content-Type.name, both in their
1081 > # raw (encoded) form and in rfc2047-decoded form if applicable
1082 > # as well as (recommended) file names specified in archives;
1083 > #
1084 > # * file content type as guessed by 'file(1)' utility, mapped
1085 > # (by @map_full_type_to_short_type_maps) into short type names such as
1086 > # .asc, .txt, .html, .doc, .jpg, .pdf, .zip, .exe-ms, ..., which always
1087 > # starts with a dot. These short types are available unless
1088 > # $bypass_decode_parts is true.
1089 > #
1090 > # All nodes (mail parts) of the fully recursively decoded mail and embedded
1091 > # archives are checked, each node independently from remaining nodes.
1092 > #
1093 > # For each node all its ancestor nodes including itself are checked against
1094 > # $banned_filename_re lookup list, top-down. The search for a node stops
1095 > # at the first match, the right-hand side of the matching key determines
1096 > # the result (true or false, absent right-hand side implies true, as
1097 > explained
1098 > # in README.lookups).
1099 > #
1100 > # Although repeatedly re-checking ancestor nodes may seem excessive, it
1101 > gives
1102 > # the opportunity to specify rules which make a particular node hide its
1103 > # descendents, e.g. allow any name or file type within a .zip, even though
1104 > # .exe files may otherwise not be allowed.
1105 > #
1106 > # Leave $banned_filename_re undefined to disable these checks
1107 > # (giving an empty list to new_RE() will also always return false)
1108 >
1109 > $banned_filename_re = new_RE(
1110 > # qr'^UNDECIPHERABLE$', # is or contains any undecipherable components
1111 >
1112 > # block certain double extensions anywhere in the base name
1113 > qr'\.[^./]*[A-Za-z][^./]*\.(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)\.?$'i,
1114 >
1115 > # qr'\{[0-9a-z]{4,}(-[0-9a-z]{4,}){0,7}\}?'i, # Class ID extensions -
1116 > CLSID
1117 >
1118 > qr'^application/x-msdownload$'i, # block these MIME
1119 > types
1120 > qr'^application/x-msdos-program$'i,
1121 > qr'^application/hta$'i,
1122 >
1123 > # qr'^(application/x-msmetafile|image/x-wmf)$'i, # Windows Metafile MIME
1124 > # qr'^\.wmf$', # Windows Metafile file(1) type
1125 >
1126 > # qr'^message/partial$'i, # rfc2046 MIME type
1127 >
1128 > # qr'^message/external-body$'i, # rfc2046 MIME type
1129 > # (btw, note that allowing 'message/external-body' is probably no worse
1130 > # than allowing mail with HTML and/or allowing a user to browse the web)
1131 >
1132 > # [ qr'^\.(Z|gz|bz2)$' => 0 ], # allow any in Unix-compressed
1133 > [ qr'^\.(rpm|cpio|tar)$' => 0 ], # allow any in Unix-type archives
1134 > # [ qr'^\.(zip|rar|arc|arj|zoo)$'=> 0 ], # allow any within such archives
1135 >
1136 > qr'.\.(exe|vbs|pif|scr|bat|cmd|com|cpl)$'i, # banned extension - basic
1137 > # qr'.\.(ade|adp|app|bas|bat|chm|cmd|com|cpl|crt|emf|exe|fxp|grp|hlp|hta|
1138 > # inf|ins|isp|js|jse|lnk|mda|mdb|mde|mdw|mdt|mdz|msc|msi|msp|mst|
1139 > # ops|pcd|pif|prg|reg|scr|sct|shb|shs|vb|vbe|vbs|
1140 > # wmf|wsc|wsf|wsh)$'ix, # banned ext - long
1141 >
1142 > # qr'.\.(mim|b64|bhx|hqx|xxe|uu|uue)$'i, # banned extension - WinZip
1143 > vulnerab.
1144 >
1145 > qr'^\.(exe-ms)$', # banned file(1) types
1146 > # qr'^\.(exe|lha|tnef|cab|dll)$', # banned file(1) types
1147 > );
1148 > # See http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262631
1149 > # and http://www.cknow.com/vtutor/vtextensions.htm
1150 >
1151 > # A little trick: a pattern qr'\.exe$' matches both a short type name
1152 > '.exe',
1153 > # as well as any file name which happens to end with .exe. If only matching
1154 > # a file name is desired, but not the short type, a pattern qr'.\.exe$'i
1155 > # or similar may be used, which requires that at least one character
1156 > precedes
1157 > # the '.exe', and so it will never match short file types which always
1158 > start
1159 > # with a dot.
1160 >
1161 >
1162 > # the syntax of these Perl regular expressions is a bit awkward if not
1163 > # familiar with them, so please do follow examples and stick to the idioms:
1164 > # \A ... at the beginning of the first component
1165 > # \z ... at the end of the the last (leaf) component
1166 > # ^ ... at the beginning of each component in the path
1167 > # $ ... at the end of each component in the path
1168 > # (.*\t)? ... at the beginning of a field
1169 > # (\t.*)? ... at the end of a field
1170 > # \t(.*\t)* ... separating fields
1171 > # [^\t\n] ... any single character, but don't escape from this field
1172 > # (.*\n)+ ... one or more levels down
1173 > # (?#...) ... a comment within a regexp
1174 >
1175 > # new-style of banned lookup table
1176 > $banned_namepath_re = new_RE(
1177 >
1178 > # block these MIME types
1179 > qr'(?#NO X-MSDOWNLOAD) ^(.*\t)? M=application/x-msdownload (\t.*)?
1180 > $'xmi,
1181 > qr'(?#NO X-MSDOS-PROGRAM)^(.*\t)? M=application/x-msdos-program(\t.*)?
1182 > $'xmi,
1183 > qr'(?#NO HTA) ^(.*\t)? M=application/hta (\t.*)? $'xmi,
1184 >
1185 > # # block rfc2046 MIME types
1186 > # qr'(?# BLOCK RFC2046 ) ^ (.*\t)? M=message/partial (\t.*)? $'xmi,
1187 > # qr'(?# BLOCK RFC2046 ) ^ (.*\t)? M=message/external-body (\t.*)? $'xmi,
1188 >
1189 > # qr'(?#No Metafile MIME) ^(.*\t)? M=application/x-msmetafile (\t.*)?
1190 > $'xmi,
1191 > # qr'(?#No Metafile MIME) ^(.*\t)? M=image/x-wmf (\t.*)?
1192 > $'xmi,
1193 > # qr'(?#No Metafile file) ^(.*\t)? T=wmf (\t.*)? $'xm,
1194 >
1195 > # # within traditional Unix compressions allow any name and type
1196 > # [ qr'(?#rule-3) ^ (.*\t)? T=(Z|gz|bz2) (\t.*)? $'xmi => 0 ], # allow
1197 >
1198 > # within traditional Unix archives allow any name and type
1199 > [ qr'(?#rule-4) ^ (.*\t)? T=(tar|rpm|cpio) (\t.*)? $'xmi => 0 ], # allow
1200 >
1201 > # # block anything within a zip
1202 > # qr'(?#rule-5) ^ (.*\t)? T=zip (\t.*)? (.*\n)+ .* $'xmi,
1203 >
1204 > # block certain double extensions in filenames
1205 > qr'(?# BLOCK DOUBLE-EXTENSIONS )
1206 > ^ (.*\t)? N= [^\t\n]* \. [^./\t\n]* [A-Za-z] [^./\t\n]* \.
1207 > (exe|vbs|pif|scr|bat|cmd|com|cpl|dll) \.? (\t.*)? $'xmi,
1208 >
1209 > # # block Class ID (CLSID) extensions in filenames
1210 > # qr'(?# BLOCK CLSID-EXTENSIONS )
1211 > # ^ (.*\t)? N= [^\t\n]* \{[0-9a-z]{4,}(-[0-9a-z]{4,}){0,7}\}?
1212 > [^\t\n]* (\t.*)? $'xmi,
1213 >
1214 > # # banned declared names with three or more consecutive spaces
1215 > # qr'(?# BLOCK NAMES WITH SPACES )
1216 > # ^ (.*\t)? N= [^\t\n]* [ ]{3,} 'xmi,
1217 >
1218 > # # within PC archives allow any types or names at any depth
1219 > # [ qr'(?#rule-7) ^ (.*\t)? T=(zip|rar|arc|arj|zoo) (\t.*)? $'xmi => 0
1220 > ], # ok
1221 >
1222 > # # within certain archives allow leaf members at any depth if crypted
1223 > # [ qr'(?# ALLOW ENCRYPTED )
1224 > # ^ (.*\t)? T=(zip|rar|arj) (.*\n)+ (.*\t)? A=C (\t.*)? \z'xmi => 0 ],
1225 >
1226 > # # allow crypted leaf members regardless of their name or type
1227 > # [ qr'(?# ALLOW IF ENCRYPTED ) ^ (.*\t)? A=C (\t.*)? \z'xmi => 0 ],
1228 >
1229 > # # block if any component can not be decoded (is encrypted or bad archive)
1230 > # qr'(?# BLOCK IF UNDECIPHERABLE ) ^ (.*\t)? A=U (\t.*)? \z'xmi,
1231 >
1232 > # [ qr'(?# SPECIAL ALLOWANCES - MAGIC NAMES)
1233 > # \A (.*\t)? T=(rpm|cpio|tar|zip|rar|arc|arj|zoo|Z|gz|bz2)
1234 > # \t(.*\t)* N=example\d+[^\t\n]*
1235 > # (\t.*)? $'xmi => 0 ],
1236 >
1237 > # banned filename extensions (in declared names) anywhere - basic
1238 > qr'(?# BLOCK COMMON NAME EXENSIONS )
1239 > ^ (.*\t)? N= [^\t\n]* \. (exe|vbs|pif|scr|bat|com|cpl) (\t.*)? $'xmi,
1240 >
1241 > # # banned filename extensions (in declared names) anywhere - long
1242 > # qr'(?# BLOCK MORE NAME EXTENSIONS )
1243 > # ^ (.*\t)? N= [^\t\n]* \. (
1244 > # ade|adp|app|bas|bat|chm|cmd|com|cpl|crt|emf|exe|fxp|grp|hlp|hta|
1245 > # inf|ins|isp|js|jse|lnk|mda|mdb|mde|mdw|mdt|mdz|msc|msi|msp|mst|
1246 > # ops|pcd|pif|prg|reg|scr|sct|shb|shs|vb|vbe|vbs|
1247 > # wmf|wsc|wsf|wsh) (\t.*)? $'xmi,
1248 >
1249 > # # banned filename extensions anywhere - WinZip vulnerability (pre-V9)
1250 > # qr'(?# BLOCK WinZip VULNERABILITY EXENSIONS )
1251 > # ^ (.*\t)? N= [^\t\n]* \. (mim|b64|bhx|hqx|xxe|uu|uue) (\t.*)? $'xmi,
1252 >
1253 > [ qr'(?# BLOCK EMPTY MIME PART APPLICATION/OCTET-STREAM )
1254 > ^ (.*\t)? M=application/octet-stream \t(.*\t)* T=empty (\t.*)? $'xmi
1255 > => 'DISCARD' ],
1256 >
1257 > # [ qr'(?# BLOCK EMPTY MIME PARTS )
1258 > # ^ (.*\t)? M= [^\t\n]+ \t(.*\t)* T=empty (\t.*)? $'xmi =>
1259 > 'DISCARD' ],
1260 >
1261 > qr'(?# BLOCK Microsoft EXECUTABLES )
1262 > ^ (.*\t)? T=exe-ms (\t.*)? $'xm, # banned file(1) type
1263 >
1264 > # qr'(?# BLOCK ANY EXECUTABLE )
1265 > # ^ (.*\t)? T=exe (\t.*)? $'xm, # banned file(1) type
1266 >
1267 > # qr'(?# BLOCK THESE TYPES )
1268 > # ^ (.*\t)? T=(exe|lha|tnef|cab|dll) (\t.*)? $'xm, # banned file(1)
1269 > types
1270 >
1271 > );
1272 >
1273 > # use old or new style of banned lookup table; not both to avoid confusion
1274 > #
1275 > # @banned_filename_maps = (); # to disable old-style
1276 > $banned_namepath_re = undef; # to disable new-style
1277 >
1278 >
1279 > %banned_rules = (
1280 > 'MYNETS-DEFAULT' => new_RE( # permissive set of rules for internal
1281 > hosts
1282 > [ qr'^\.(rpm|cpio|tar)$' => 0 ], # allow any name/type in Unix
1283 > archives
1284 > qr'.\.(vbs|pif|scr)$'i, # banned extension - rudimentary
1285 > ),
1286 > 'DEFAULT' => $banned_filename_re,
1287 > );
1288 >
1289 >
1290 > #
1291 > # Section V - Per-recipient and per-sender handling, whitelisting, etc.
1292 > #
1293 >
1294 > # @virus_lovers_maps list of lookup tables:
1295 > # (this should be considered a policy option, is does not disable checks,
1296 > # see bypass*checks for that!)
1297 > #
1298 > # Exclude certain RECIPIENTS from virus filtering by adding their
1299 > (lower-cased)
1300 > # envelope e-mail address (or domain only) to one of the lookup tables in
1301 > # the @virus_lovers_maps list - see README.lookups and examples.
1302 > # Make sure the appropriate form (e.g. external/internal) of address
1303 > # is used in case of virtual domains, or when mapping external to internal
1304 > # addresses, etc. - this is MTA-specific.
1305 > #
1306 > # Notifications would still be generated however (see the overall
1307 > # picture above), and infected mail (if passed) gets additional header:
1308 > # X-AMaViS-Alert: INFECTED, message contains virus: ...
1309 > # (header not inserted with Courier or milter interface!)
1310 > #
1311 > # Setting $final_*_destiny=D_PASS is functionally equivalent to having
1312 > # all recipients match the @*_lovers_maps.
1313 > #
1314 > # NOTE (milter interface only): in case of multiple recipients,
1315 > # it is only possible to drop or accept the message in its entirety -
1316 > for all
1317 > # recipients. If all of them are virus lovers, we'll accept mail, but if
1318 > # at least one recipient is not a virus lover, we'll discard the message.
1319 >
1320 >
1321 > # @bypass_virus_checks_maps list of lookup tables:
1322 > # (this is mainly a time-saving option, unlike virus_lovers* !)
1323 > #
1324 > # Similar in concept to @virus_lovers_maps, a @bypass_virus_checks_maps
1325 > # is used to skip entirely the decoding, unpacking and virus checking,
1326 > # but only if ALL recipients match the lookup.
1327 > #
1328 > # @bypass_virus_checks_maps does NOT GUARANTEE the message will NOT be
1329 > checked
1330 > # for viruses - this may still happen when there is more than one recipient
1331 > # for a message and not all of them match these lookup tables, or when
1332 > # check result was cached (i.e. the same contents was recently sent to
1333 > other
1334 > # recipients). To guarantee virus delivery, a recipient must also match
1335 > # @virus_lovers_maps lookups (but see milter limitations above),
1336 > #
1337 > # The following table summarizes the possible combinations:
1338 > # bypass lover
1339 > # 0 0 useful, check for malware and block it
1340 > # 0 1 useful, check but deliver nevertheless, possibly tagged
1341 > # 1 0 not too useful, free riding on cached or other-people's
1342 > checks
1343 > # 1 1 useful, no checks if possible, and no effects
1344 >
1345 > # NOTE: it would not be clever to base enabling of virus checks on SENDER
1346 > # address, since there are no guarantees that it is genuine. Many viruses
1347 > # and spam messages fake sender address. To achieve selective filtering
1348 > # based on the source of the mail (e.g. IP address, MTA port number, ...),
1349 > # use mechanisms provided by MTA if available, possibly combined with
1350 > policy
1351 > # banks feature.
1352 >
1353 > # Similar to lists of lookup tables controlling virus checking, there are
1354 > # counterparts for spam scanning, banned names/types, and headers_checks
1355 > # control:
1356 > # @spam_lovers_maps,
1357 > # @banned_files_lovers_maps,
1358 > # @bad_header_lovers_maps
1359 > # and:
1360 > # @bypass_spam_checks_maps,
1361 > # @bypass_banned_checks_maps,
1362 > # @bypass_header_checks_maps
1363 >
1364 > # Example:
1365 > # @bypass_header_checks_maps = ( [qw( user@×××××××.com )] );
1366 > # @bad_header_lovers_maps = ( [qw( user@×××××××.com )] );
1367 >
1368 > # The following example disables spam checking altogether,
1369 > # since it matches any recipient e-mail address.
1370 > # @bypass_spam_checks_maps = (1);
1371 >
1372 >
1373 > # See README.lookups for further detail, and examples below.
1374 >
1375 > # In the following example a list of lookup tables @virus_lovers_maps
1376 > # contains three elements, the first is a reference to an ACL lookup table
1377 > # (brackets in Perl indicate a ref to a list), the second is a reference
1378 > # to a hash lookup table (curly braces in Perl indicate a ref to a hash),
1379 > # the third is a regexp lookup table, indicated by the type of object
1380 > # created by new_RE() :
1381 > #
1382 > #@virus_lovers_maps = (
1383 > # [ qw( me@×××××××.com !lab.xxx.com .xxx.com yyy.org ) ],
1384 > # { "postmaster\@$mydomain" => 1, # double quotes permit variable
1385 > evaluation
1386 > # 'postmaster@×××××××.com'=> 1, # in single quotes the '@' need not be
1387 > quoted
1388 > # 'abuse@×××××××.com'=> 1,
1389 > # 'some.user@' => 1, # this recipient, regardless of domain
1390 > # 'boss@×××××××.com' => 0, # never, even if domain matches
1391 > # 'example.com' => 1, # this domain, but not its subdomains
1392 > # '.example.com' => 1, # this domain, including its subdomains
1393 > # },
1394 > # new_RE( qr'^(helpdesk|postmaster)@example\.com$'i ),
1395 > #);
1396 >
1397 > #@spam_lovers_maps = (
1398 > # ["postmaster\@$mydomain", 'postmaster@×××××××.com', 'abuse@×××××××.com'],
1399 > #);
1400 >
1401 > #@bad_header_lovers_maps = (
1402 > # ["postmaster\@", "abuse\@$mydomain"],
1403 > #);
1404 >
1405 >
1406 > # as an alternative to fiddling with @_lovers_maps and similar _maps, here
1407 > # is an illustration of using a more general *_by_ccat associative array,
1408 > # introduced with 2.4.0, like %lovers_maps_by_ccat in this example:
1409 > #
1410 > #$lovers_maps_by_ccat{CC_SPAM} = [
1411 > # read_hash("$MYHOME/etc/spam_lovers.txt"),
1412 > # [qw(postmaster@×××××××.com abuse@×××××××.com)],
1413 > #];
1414 > #
1415 > #$lovers_maps_by_ccat{CC_BANNED} = [
1416 > # { map {lc $_ => 1} # construct a hash lookup table from a list
1417 > # qw(user1@×××××××.com user2.example.com)
1418 > # },
1419 > #];
1420 >
1421 >
1422 > # to save some typing of quotes and commas, a Perl operator qw can be used
1423 > # to split its argument on whitespace and to quote resulting elements:
1424 > #@bypass_spam_checks_maps = (
1425 > # [ qw( some.ddd !butnot.example.com .example.com ) ],
1426 > #);
1427 >
1428 >
1429 > # don't run spam check for these RECIPIENT domains:
1430 > # @bypass_spam_checks_maps = ( [qw( d1.com .d2.com a.d3.com )] );
1431 > # or the other way around (bypass check for all BUT these):
1432 > # @bypass_spam_checks_maps = ( [qw( !d1.com !.d2.com !a.d3.com . )] );
1433 > # a practical application: don't check outgoing mail for spam:
1434 > # @bypass_spam_checks_maps = ( [ "!.$mydomain", "." ] );
1435 > # or calculated (negated) from the %local_domains:
1436 > # @bypass_spam_checks_maps =
1437 > # ( {map {$_ => !$local_domains{$_}} keys %local_domains}, 1);
1438 > # (a downside of which is that such mail will not count as ham in SA
1439 > bayes db)
1440 > #
1441 > # Note that 'outgoing' is not the same as 'originating from inside'.
1442 > # The internal-to-internal mail is not outgoing, but is originating from
1443 > # inside. To base rules on 'originating from inside', the use of policy
1444 > bank
1445 > # MYNETS is needed, in conjunction with XFORWARD Postfix extension to SMTP.
1446 >
1447 > # Where to find SQL server(s) and database to support SQL lookups?
1448 > # A list of triples: (dsn,user,passw). (dsn = data source name)
1449 > # More than one entry may be specified for multiple (backup) SQL servers.
1450 > # See 'man DBI', 'man DBD::mysql', 'man DBD::Pg', ... for details.
1451 > # When chroot-ed, accessing SQL server over inet socket may be more
1452 > convenient.
1453 > #
1454 > # @lookup_sql_dsn =
1455 > # ( ['DBI:mysql:database=mail;host=127.0.0.1;port=3306', 'user1',
1456 > 'passwd1'],
1457 > # ['DBI:mysql:database=mail;host=host2', 'username2', 'password2'],
1458 > # ["DBI:SQLite:dbname=$MYHOME/sql/mail_prefs.sqlite", '', ''] );
1459 > # @storage_sql_dsn = @lookup_sql_dsn; # none, same, or separate database
1460 > #
1461 > @lookup_sql_dsn =
1462 > (
1463 > ['DBI:mysql:database=amavis;host=192.168.10.35;port=3306','amavis','db4me!']
1464 > );
1465 > # ('mail' in the example is the database name, choose what you like)
1466 > # With PostgreSQL the dsn (first element of the triple) may look like:
1467 > # 'DBI:Pg:dbname=mail;host=host1'
1468 >
1469 > # The SQL select clause to fetch per-recipient policy settings.
1470 > # The %k will be replaced by a comma-separated list of query addresses
1471 > # (e.g. full address, domain only (stripped level by level), and a
1472 > catchall).
1473 > # Use ORDER if there is a chance that multiple records will match - the
1474 > first
1475 > # match wins. If field names are not unique (e.g. 'id'), the later field
1476 > # overwrites the earlier in a hash returned by lookup, which is why we use
1477 > # '*,users.id' instead of just '*'. No need to uncomment the following
1478 > # assignment if the default is ok.
1479 > # $sql_select_policy = 'SELECT *,users.id FROM users,policy'.
1480 > # ' WHERE (users.policy_id=policy.id) AND (users.email IN (%k))'.
1481 > # ' ORDER BY users.priority DESC';
1482 > #
1483 > # The SQL select clause to check sender in per-recipient
1484 > whitelist/blacklist
1485 > # The first SELECT argument '?' will be users.id from recipient SQL lookup,
1486 > # the %k will be sender addresses (e.g. full address, domain only,
1487 > catchall).
1488 > # The default value is:
1489 > # $sql_select_white_black_list = 'SELECT wb FROM wblist,mailaddr'.
1490 > # ' WHERE (wblist.rid=?) AND (wblist.sid=mailaddr.id)'.
1491 > # ' AND (mailaddr.email IN (%k))'.
1492 > # ' ORDER BY mailaddr.priority DESC';
1493 > #
1494 > # To disable SQL white/black list, set to undef (otherwise comment-out
1495 > # the following statement, leaving it at the default value):
1496 > #$sql_select_white_black_list = undef; # undef disables SQL
1497 > white/blacklisting
1498 >
1499 > $sql_select_white_black_list = 'SELECT wb FROM wblist'.
1500 > ' WHERE (rid=?) AND (wblist.email IN (%k))'.
1501 > ' ORDER BY wblist.priority DESC';
1502 >
1503 > # If passing malware to certain recipients ($final_*_destiny=D_PASS or
1504 > # *_lovers), the recipient-based lookup tables @addr_extension_*_maps may
1505 > # return a string, which (if nonempty) will be added as an address
1506 > extension
1507 > # to the local-part of the recipient's address. This extension may be used
1508 > # by the final local delivery agent (LDA) to place such mail into different
1509 > # subfolders (the extension is usually interpreted as a folder name).
1510 > # This is sometimes known as the 'plus addressing'. Appending address
1511 > # extensions is prevented when:
1512 > # - recipient does not match lookup tables @local_domains_maps;
1513 > # - lookup into corresponding @addr_extension_*_maps results
1514 > # in an empty string or undef;
1515 > # - $recipient_delimiter is empty (see below)
1516 > # LDAs usually default to stripping away address extension if no special
1517 > # handling is specified or if a named subfolder or alias does not exist,
1518 > # so adding address extensions normally does no harm.
1519 >
1520 > # @addr_extension_virus_maps = ('virus'); # defaults to empty
1521 > # @addr_extension_spam_maps = ('spam'); # defaults to empty
1522 > # @addr_extension_banned_maps = ('banned'); # defaults to empty
1523 > # @addr_extension_bad_header_maps = ('badh'); # defaults to empty
1524 > #
1525 > # A more complex example:
1526 > # @addr_extension_virus_maps = (
1527 > # {'sub.example.com'=>'infected', '.example.com'=>'filtered'}, 'virus' );
1528 >
1529 > # Delimiter between local part of the envelope recipient address and
1530 > address
1531 > # extension (which can optionally be added, see @addr_extension_*_maps.
1532 > E.g.
1533 > # recipient address <user@×××××××.com> is changed to
1534 > <user+virus@×××××××.com>.
1535 > #
1536 > # Delimiter must match the equivalent (final) MTA delimiter setting.
1537 > # (e.g. for Postfix add 'recipient_delimiter = +' to main.cf)
1538 > # Setting it to an empty string or to undef disables adding extensions
1539 > # regardless of $addr_extension_*_maps.
1540 >
1541 > # $recipient_delimiter = '+'; # (default is undef, i.e. disabled)
1542 >
1543 > # true: replace extension; false: append extension
1544 > # $replace_existing_extension = 1; # (default is true)
1545 >
1546 > # Affects matching of localpart of e-mail addresses (left of '@')
1547 > # in lookups: true = case sensitive, false = case insensitive
1548 > $localpart_is_case_sensitive = 0; # (default is false)
1549 >
1550 >
1551 > # ENVELOPE SENDER SOFT-WHITELISTING / SOFT-BLACKLISTING
1552 >
1553 > # Instead of hard black- or whitelisting, a softer approach is to add
1554 > # score points (penalties) to the SA score for mail from certain senders.
1555 > # Positive points lean towards blacklisting, negative towards whitelisting.
1556 > # This is much like adding SA rules or using its white/blacklisting, except
1557 > # that here only envelope sender addresses are considered (not addresses
1558 > # in a mail header), and that score points can be assigned per-recipient
1559 > # (or globally), and the assigned penalties are customarily much lower
1560 > # than the default SA white/blacklisting score.
1561 > #
1562 > # The table structure is similar to
1563 > $per_recip_blacklist_sender_lookup_tables
1564 > # i.e. the first level key is recipient, pointing to by-sender lookup
1565 > tables.
1566 > # The essential difference is that scores from _all_ matching by-recipient
1567 > # lookups (not just the first that matches) are summed to give the final
1568 > # score boost. That means that both the site and domain administrators,
1569 > # as well as the recipient can have a say on the final score.
1570 > #
1571 > # NOTE: keep hash keys in lowercase, either manually or by using
1572 > function lc
1573 >
1574 > @score_sender_maps = ({ # a by-recipient hash lookup table
1575 >
1576 > # # per-recipient personal tables (NOTE: positive: black, negative: white)
1577 > # 'user1@×××××××.com' => [{'bla-mobile.press@×××××××.com' => 10.0}],
1578 > # 'user3@×××××××.com' => [{'.ebay.com' => -3.0}],
1579 > # 'user4@×××××××.com' => [{'cleargreen@××××××××××.com' => -7.0,
1580 > # '.cleargreen.com' => -5.0}],
1581 >
1582 > # site-wide opinions about senders (the '.' matches any recipient)
1583 > '.' => [ # the _first_ matching sender determines the score boost
1584 >
1585 > new_RE( # regexp-type lookup table, just happens to be all
1586 > soft-blacklist
1587 > [qr'^(bulkmail|offers|cheapbenefits|earnmoney|foryou)@'i =>
1588 > 5.0],
1589 > [qr'^(greatcasino|investments|lose_weight_today|market\.alert)@'i=>
1590 > 5.0],
1591 > [qr'^(money2you|MyGreenCard|new\.tld\.registry|opt-out|opt-in)@'i=>
1592 > 5.0],
1593 > [qr'^(optin|saveonlsmoking2002k|specialoffer|specialoffers)@'i =>
1594 > 5.0],
1595 > [qr'^(stockalert|stopsnoring|wantsome|workathome|yesitsfree)@'i =>
1596 > 5.0],
1597 > [qr'^(your_friend|greatoffers)@'i =>
1598 > 5.0],
1599 > [qr'^(inkjetplanet|marketopt|MakeMoney)\d*@'i =>
1600 > 5.0],
1601 > ),
1602 >
1603 > # read_hash("/var/amavis/sender_scores_sitewide"),
1604 >
1605 > { # a hash-type lookup table (associative array)
1606 > 'nobody@××××.org' => -3.0,
1607 > 'cert-advisory@×××××××.gov' => -3.0,
1608 > 'owner-alert@×××.net' => -3.0,
1609 > 'slashdot@××××××××.org' => -3.0,
1610 > 'bugtraq@×××××××××××××.com' => -3.0,
1611 > 'ntbugtraq@××××××××××××××××××.com' => -3.0,
1612 > 'security-alerts@×××××××××××××.com' => -3.0,
1613 > 'mailman-announce-admin@××××××.org' => -3.0,
1614 > 'amavis-user-admin@×××××××××××××××××.net'=> -3.0,
1615 > 'spamassassin.apache.org' => -3.0,
1616 > 'notification-return@××××××××××××.com' => -3.0,
1617 > 'owner-postfix-users@×××××××.org' => -3.0,
1618 > 'owner-postfix-announce@×××××××.org' => -3.0,
1619 > 'owner-sendmail-announce@××××××××××××××.org' => -3.0,
1620 > 'sendmail-announce-request@××××××××××××××.org' => -3.0,
1621 > 'donotreply@××××××××.org' => -3.0,
1622 > 'ca+envelope@××××××××.org' => -3.0,
1623 > 'noreply@×××××××××.net' => -3.0,
1624 > 'owner-technews@××××××××××.org' => -3.0,
1625 > 'ietf-123-owner@×××××××××.org' => -3.0,
1626 > 'cvs-commits-list-admin@×××××.org' => -3.0,
1627 > 'rt-users-admin@××××××××××.com' => -3.0,
1628 > 'clp-request@××××××××××××.sg' => -3.0,
1629 > 'surveys-errors@×××××××××.ie' => -3.0,
1630 > 'emailnews@×××××××××.com' => -5.0,
1631 > 'yahoo-dev-null@×××××××××.com' => -3.0,
1632 > 'returns.groups.yahoo.com' => -3.0,
1633 > 'clusternews@××××××××××××.com' => -3.0,
1634 > lc('lvs-users-admin@××××××××××××××××××.org') => -3.0,
1635 > lc('owner-textbreakingnews@××××××××××××××.COM') => -5.0,
1636 >
1637 > # soft-blacklisting (positive score)
1638 > 'sender@×××××××.net' => 3.0,
1639 > '.example.net' => 1.0,
1640 >
1641 > },
1642 > ], # end of site-wide tables
1643 > });
1644 >
1645 >
1646 > # ENVELOPE SENDER WHITELISTING / BLACKLISTING - GLOBAL
1647 > (RECIPIENT-INDEPENDENT)
1648 > # (affects spam checking only, has no effect on virus and other checks)
1649 >
1650 > # WHITELISTING: use ENVELOPE SENDER lookups to ENSURE DELIVERY from
1651 > whitelisted
1652 > # senders even if the message would be recognized as spam. Effectively, for
1653 > # the specified senders, message recipients temporarily become
1654 > 'spam_lovers'.
1655 > # To avoid surprises, whitelisted sender also suppresses inserting/editing
1656 > # the tag2-level header fields (X-Spam-*, Subject), appending spam address
1657 > # extension, and quarantining.
1658 > #
1659 > # BLACKLISTING: messages from specified SENDERS are DECLARED SPAM.
1660 > # Effectively, for messages from blacklisted envelope sender addresses,
1661 > spam
1662 > # level is artificially pushed high, and the normal spam processing
1663 > applies,
1664 > # resulting in 'X-Spam-Flag: YES', high 'X-Spam-Level' bar and other usual
1665 > # reactions to spam, including possible rejection. If the message
1666 > nevertheless
1667 > # still passes (e.g. for spam loving recipients), it is tagged as
1668 > BLACKLISTED
1669 > # in the 'X-Spam-Status' header field, but the reported spam value and
1670 > # set of tests in this report header field (if available from SpamAssassin,
1671 > # which may or may not have been called) is not adjusted.
1672 > #
1673 > # A sender may be both white- and blacklisted at the same time, settings
1674 > # are independent. For example, being both white- and blacklisted, message
1675 > # is delivered to recipients, but is not tagged as spam (X-Spam-Flag: No;
1676 > # X-Spam-Status: No, ...), but the reported spam level (if computed) may
1677 > # still indicate high spam score.
1678 > #
1679 > # If ALL recipients of the message either white- or blacklist the sender,
1680 > # spam scanning (calling the SpamAssassin) is bypassed, saving on time.
1681 > #
1682 > # The following variables (lists of lookup tables) are available,
1683 > # with the semantics and syntax as specified in README.lookups:
1684 > # @whitelist_sender_maps, @blacklist_sender_maps
1685 >
1686 > # SOME EXAMPLES:
1687 > #
1688 > #ACL:
1689 > # @whitelist_sender_maps = ( ['.example.org', '.example.net'] );
1690 > # @whitelist_sender_maps = ( [qw(.example.org .example.net)] ); # same
1691 > thing
1692 > #
1693 > # @whitelist_sender_maps = ( [".$mydomain"] ); # $mydomain and its
1694 > subdomains
1695 > # NOTE: This is not a reliable way of turning off spam checks for
1696 > # locally-originating mail, as sender address can easily be faked.
1697 > # To reliably avoid spam-scanning outgoing mail, use
1698 > @bypass_spam_checks_maps
1699 > # for nonlocal recipients. To reliably avoid spam scanning for locally
1700 > # originating mail (including internal-to-internal mail), recognized by
1701 > # the original SMTP client IP address matching @mynetworks, use policy
1702 > bank
1703 > # MYNETS, adjust @mynetworks, and turn on XFORWARD in the Postfix smtp
1704 > client
1705 > # service feeding amavisd.
1706 >
1707 > #with regexps:
1708 > # @whitelist_sender_maps = ( new_RE(
1709 > # qr'^postmaster@.*\bexample\.com$'i,
1710 > # qr'^owner-[^@]*@'i, qr'-request@'i,
1711 > # qr'\.example\.com$'i
1712 > # ));
1713 >
1714 >
1715 > # illustrates the use of regexp lookup table:
1716 >
1717 > @blacklist_sender_maps = ( new_RE(
1718 > qr'^(bulkmail|offers|cheapbenefits|earnmoney|foryou|greatcasino)@'i,
1719 >
1720 > qr'^(investments|lose_weight_today|market\.alert|money2you|MyGreenCard)@'i,
1721 > qr'^(new\.tld\.registry|opt-out|opt-in|optin|saveonlsmoking2002k)@'i,
1722 > qr'^(specialoffer|specialoffers|stockalert|stopsnoring|wantsome)@'i,
1723 > qr'^(workathome|yesitsfree|your_friend|greatoffers)@'i,
1724 > qr'^(inkjetplanet|marketopt|MakeMoney)\d*@'i,
1725 > ));
1726 >
1727 >
1728 > # NOTE: whitelisting is becoming deprecated because sender address is
1729 > # all too often faked; use @score_sender_maps for soft-whitelisting!
1730 > #
1731 > # Illustrates the use of several lookup tables:
1732 > #
1733 > # @whitelist_sender_maps = (
1734 > #
1735 > # # read_hash("$MYHOME/whitelist_sender"), # a hash table read from a file
1736 > #
1737 > # # and another hash lookup table constructed in-line, with keys
1738 > lowercased:
1739 > # { map {lc $_ => 1} qw(
1740 > # nobody@××××.org
1741 > # cert-advisory@×××××××.gov
1742 > # owner-alert@×××.net
1743 > # slashdot@××××××××.org
1744 > # bugtraq@×××××××××××××.com
1745 > # NTBUGTRAQ@××××××××××××××××××.COM
1746 > # security-alerts@×××××××××××××.com
1747 > # amavis-user-admin@×××××××××××××××××.net
1748 > # notification-return@××××××××××××.com
1749 > # mailman-announce-admin@××××××.org
1750 > # owner-postfix-users@×××××××.org
1751 > # owner-postfix-announce@×××××××.org
1752 > # owner-sendmail-announce@××××××××××××××.org
1753 > # sendmail-announce-request@××××××××××××××.org
1754 > # owner-technews@××××××××××.ORG
1755 > # lvs-users-admin@××××××××××××××××××.org
1756 > # ietf-123-owner@×××××××××.org
1757 > # cvs-commits-list-admin@×××××.org
1758 > # rt-users-admin@××××××××××.com
1759 > # clp-request@××××××××××××.sg
1760 > # surveys-errors@×××××××××.ie
1761 > # emailNews@×××××××××.com
1762 > # owner-textbreakingnews@××××××××××××××.COM
1763 > # yahoo-dev-null@×××××××××.com
1764 > # returns.groups.yahoo.com
1765 > # )},
1766 > #
1767 > # # { '' => 1 }, # and another one, containing just an empty reverse
1768 > path (DSN)
1769 > #
1770 > # );
1771 >
1772 >
1773 > # ENVELOPE SENDER WHITELISTING / BLACKLISTING - PER-RECIPIENT
1774 >
1775 > # The same semantics as for global white/blacklisting applies, but this
1776 > # time each recipient (or its domain, or subdomain, ...) can be given
1777 > # an individual lookup table for matching senders. The per-recipient
1778 > lookups
1779 > # take precedence over the global lookups, which serve as a fallback
1780 > default.
1781 >
1782 > # Specify a two-level lookup table: the key for the outer table is
1783 > recipient,
1784 > # and the result should be an inner lookup table (hash or ACL or RE),
1785 > # where the key used will be the sender. (Note that this structure is
1786 > flatter
1787 > # than @score_sender_maps, where the first level result is a ref to a
1788 > _list_
1789 > # of inner lookup tables, not a ref to a single lookup table.)
1790 > #
1791 > #$per_recip_blacklist_sender_lookup_tables = {
1792 > #
1793 > 'user1@××××××××××.com'=>new_RE(qr'^(inkjetplanet|marketopt|MakeMoney)\d*@'i),
1794 >
1795 > # 'user2@××××××××××.com'=>[qw( spammer@××.example,org .d2.example,org )],
1796 > #};
1797 > #$per_recip_whitelist_sender_lookup_tables = {
1798 > # 'user@××××××××××.com' => [qw( friend@×××××××.org .other.example.org )],
1799 > # '.my1.example.com' => [qw( !foe.other.example,org
1800 > .other.example,org )],
1801 > # '.my2.example.com' => read_hash("$MYHOME/my2-wl.dat"),
1802 > # 'abuse@' => { 'postmaster@'=>1,
1803 > # 'cert-advisory-owner@××××.org'=>1,
1804 > 'owner-alert@×××.net'=>1 },
1805 > #};
1806 >
1807 >
1808 > #
1809 > # Section VI - Resource limits
1810 > #
1811 >
1812 > # Sanity limit to the number of allowed recipients per SMTP transaction
1813 > # $smtpd_recipient_limit = 1100; # (default is 1100)
1814 >
1815 > # Resource limits to protect unpackers, decompressors and virus scanners
1816 > # against mail bombs (e.g. 42.zip)
1817 >
1818 >
1819 > # Maximum recursion level for extraction/decoding (0 or undef disables
1820 > limit)
1821 > $MAXLEVELS = 14; # (default is undef, no limit)
1822 >
1823 > # Maximum number of extracted files (0 or undef disables the limit)
1824 > $MAXFILES = 1500; # (default is undef, no limit)
1825 >
1826 > # For the cumulative total of all decoded mail parts we set max storage
1827 > size
1828 > # to defend against mail bombs. Even though parts may be deleted (replaced
1829 > # by decoded text) during decoding, the size they occupied is _not_
1830 > returned
1831 > # to the quota pool.
1832 > #
1833 > # Parameters to storage quota formula for unpacking/decoding/decompressing
1834 > # Formula:
1835 > # quota = max($MIN_EXPANSION_QUOTA,
1836 > # $mail_size*$MIN_EXPANSION_FACTOR,
1837 > # min($MAX_EXPANSION_QUOTA,
1838 > $mail_size*$MAX_EXPANSION_FACTOR))
1839 > # In plain words (later condition overrules previous ones):
1840 > # allow MAX_EXPANSION_FACTOR times initial mail size,
1841 > # but not more than MAX_EXPANSION_QUOTA,
1842 > # but not less than MIN_EXPANSION_FACTOR times initial mail size,
1843 > # but never less than MIN_EXPANSION_QUOTA
1844 > #
1845 > $MIN_EXPANSION_QUOTA = 100*1024; # bytes (default undef, not
1846 > enforced)
1847 > $MAX_EXPANSION_QUOTA = 300*1024*1024; # bytes (default undef, not
1848 > enforced)
1849 > $MIN_EXPANSION_FACTOR = 5; # times original mail size (default is 5)
1850 > $MAX_EXPANSION_FACTOR = 500; # times original mail size (default is 500)
1851 >
1852 > # expiration time of cached results: time to live in seconds
1853 > # (how long the result of a virus/spam test remains valid)
1854 > $virus_check_negative_ttl= 3*60; # time to remember that mail was not
1855 > infected
1856 > $virus_check_positive_ttl= 30*60; # time to remember that mail was infected
1857 > $spam_check_negative_ttl = 30*60; # time to remember that mail was not spam
1858 > $spam_check_positive_ttl = 30*60; # time to remember that mail was spam
1859 > #
1860 > # NOTE:
1861 > # Cache size will be determined by the largest of the $*_ttl values.
1862 > # Depending on the mail rate, the cache database may grow quite large.
1863 > # Reasonable compromise for the max value is 15 minutes to 2 hours.
1864 >
1865 > #
1866 > # Section VII - External programs, virus scanners
1867 > #
1868 >
1869 > # Specify a path string, which is a colon-separated string of directories
1870 > # (no trailing slashes!) to be assigned to the environment variable PATH
1871 > # and to serve for locating external programs below.
1872 >
1873 > # NOTE: if $daemon_chroot_dir is nonempty, the directories will be
1874 > # relative to the chroot directory specified;
1875 >
1876 > $path =
1877 > '/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin:/opt/bin';
1878 >
1879 > # For external programs specify one string or a search list of strings
1880 > (first
1881 > # match wins). The string (or: each string in a list) may be an absolute
1882 > path,
1883 > # or just a program name, to be located via $path;
1884 > # Empty string or undef (=default) disables the use of that external
1885 > program.
1886 > # Optionally command arguments may be specified - only the first substring
1887 > # up to the whitespace is used for file searching.
1888 >
1889 > $file = 'file'; # file(1) utility; use 3.41 or later to avoid
1890 > vulnerability
1891 > $dspam = 'dspam';
1892 >
1893 > # A list of pairs or n-tuples: [short-type, code_ref, optional-args...].
1894 > # Maps short types to a decoding routine, the first match wins.
1895 > # Arguments beyond the first two can be program path string (or a
1896 > listref of
1897 > # paths to be searched) or a reference to a variable containing such a
1898 > path,
1899 > # which allows for lazy evaluation, making possible to assign values to
1900 > # legacy configuration variables even after the assignment to @decoders.
1901 > #
1902 > @decoders = (
1903 > ['mail', \&do_mime_decode],
1904 > ['asc', \&do_ascii],
1905 > ['uue', \&do_ascii],
1906 > ['hqx', \&do_ascii],
1907 > ['ync', \&do_ascii],
1908 > ['F', \&do_uncompress, ['unfreeze','freeze -d','melt','fcat'] ],
1909 > ['Z', \&do_uncompress, ['uncompress','gzip -d','zcat'] ],
1910 > ['gz', \&do_gunzip],
1911 > ['gz', \&do_uncompress, 'gzip -d'],
1912 > ['bz2', \&do_uncompress, 'bzip2 -d'],
1913 > ['lzo', \&do_uncompress, 'lzop -d'],
1914 > ['rpm', \&do_uncompress, ['rpm2cpio.pl','rpm2cpio'] ],
1915 > ['cpio', \&do_pax_cpio, ['pax','gcpio','cpio'] ],
1916 > ['tar', \&do_pax_cpio, ['pax','gcpio','cpio'] ],
1917 > ['tar', \&do_tar],
1918 > ['deb', \&do_ar, 'ar'],
1919 > # ['a', \&do_ar, 'ar'], # unpacking .a seems an overkill
1920 > ['zip', \&do_unzip],
1921 > ['rar', \&do_unrar, ['rar','unrar'] ],
1922 > ['arj', \&do_unarj, ['arj','unarj'] ],
1923 > ['arc', \&do_arc, ['nomarch','arc'] ],
1924 > ['zoo', \&do_zoo, 'zoo'],
1925 > ['lha', \&do_lha, 'lha'],
1926 > # ['doc', \&do_ole, 'ripole'],
1927 > ['cab', \&do_cabextract, 'cabextract'],
1928 > ['tnef', \&do_tnef_ext, 'tnef'],
1929 > ['tnef', \&do_tnef],
1930 > ['exe', \&do_executable, ['rar','unrar'], 'lha', ['arj','unarj'] ],
1931 > );
1932 >
1933 >
1934 > # SpamAssassin settings
1935 >
1936 > # $sa_local_tests_only is passed to Mail::SpamAssassin::new as a value
1937 > # of the option local_tests_only. See Mail::SpamAssassin man page.
1938 > # If set to 1, no SA tests that require internet access will be performed.
1939 > #
1940 > $sa_local_tests_only = 0; # only tests which do not require internet
1941 > access?
1942 > #$sa_auto_whitelist = 1; # turn on AWL in SA 2.63 or older (irrelevant
1943 > # for SA 3.0, its cf option is
1944 > use_auto_whitelist)
1945 >
1946 > $sa_mail_body_size_limit = 200*1024; # don't waste time on SA if mail is
1947 > larger
1948 > # (less than 1% of spam is > 64k)
1949 > # default: undef, no limitations
1950 >
1951 > # default values, customarily used in the @spam_*_level_maps as the last
1952 > entry
1953 > $sa_tag_level_deflt = -9999; # add spam info headers if at, or above
1954 > that level;
1955 > # undef is interpreted as lower than any spam level
1956 > $sa_tag2_level_deflt = 5;# add 'spam detected' headers at that level to
1957 > # passed mail, adding address extensions;
1958 > $sa_kill_level_deflt = 20; # triggers spam evasive actions
1959 > # at or above that level: bounce/reject/drop,
1960 > # quarantine
1961 > $sa_dsn_cutoff_level = 9; # spam level beyond which a DSN is not sent,
1962 > # effectively turning D_BOUNCE into D_DISCARD;
1963 > # undef disables this feature and is a default;
1964 > # see also $sa_quarantine_cutoff_level above, which only controls
1965 > quarantining
1966 >
1967 > # advanced example specifying per-recipient values using a hash lookup:
1968 > #@spam_tag_level_maps = (\$sa_tag_level_deflt); # this is a default
1969 > #@spam_tag2_level_maps = (
1970 > # { 'user1@×××××××.com' => 8.0, '.example.com' => 6.0 },
1971 > # \$sa_tag2_level_deflt, # catchall default
1972 > #);
1973 > #@spam_kill_level_maps = (
1974 > # { 'user1@×××××××.com' => 8.0, '.example.com' => 6.0 },
1975 > # \$sa_kill_level_deflt, # catchall default
1976 > #);
1977 > #@spam_dsn_cutoff_level_maps = (
1978 > # { 'user1@×××××××.com' => 10, '.example.com' => 15 },
1979 > # \$sa_dsn_cutoff_level, # catchall default
1980 > #);
1981 >
1982 > # a quick reference:
1983 > # tag_level contents category: CC_CLEAN,
1984 > # controls adding the X-Spam-Status and X-Spam-Level headers,
1985 > # tag2_level contents category: CC_SPAMMY,
1986 > # controls adding 'X-Spam-Flag: YES', editing (tagging)
1987 > Subject,
1988 > # and adding address extensions,
1989 > # tag3_level contents category: CC_SPAMMY, minor category 1,
1990 > # like tag2, but may insert different Subject tag
1991 > # e.g. @spam_subject_tag3_maps=('***BLATANT*SPAM*** ');
1992 > # kill_level contents category: CC_SPAM,
1993 > # controls 'evasive actions' (reject, quarantine);
1994 > # it only makes sense to maintain the relationship:
1995 > # tag_level <= tag2_level <= tag3_level <= kill_level <
1996 > # < dsn_cutoff_level <= quarantine_cutoff_level
1997 >
1998 > # string to prepend to Subject header field when message exceeds tag2 level
1999 > $sa_spam_subject_tag = '*SPAM* '; # (defaults to undef, disabled)
2000 > # (only seen when spam is passed and recipient is
2001 > # in local_domains*)
2002 >
2003 > #$sa_spam_modifies_subj = 1; # in @spam_modifies_subj_maps, default is true
2004 >
2005 > # Example: modify Subject for all local recipients except user@×××××××.com
2006 > #@spam_modifies_subj_maps = ( [qw( !user@×××××××.com . )] );
2007 >
2008 > #$sa_spam_level_char = '*'; # char for X-Spam-Level bar, defaults to '*';
2009 > # undef or empty disables inserting X-Spam-Level
2010 > #$sa_spam_report_header = 0; # insert X-Spam-Report header field?
2011 > default false
2012 >
2013 > # stop anti-virus scanning when the first scanner detects a virus?
2014 > #$first_infected_stops_scan = 1; # default is false, all scanners in a
2015 > section
2016 > # are called
2017 >
2018 > # @av_scanners is a list of n-tuples, where fields semantics is:
2019 > # 1. av scanner plain name, to be used in log and reports;
2020 > # 2. scanner program name; this string will be submitted to subroutine
2021 > # find_external_programs(), which will try to find the full program
2022 > path
2023 > # name during startup; if program is not found, this scanner is
2024 > disabled.
2025 > # Besides a simple string (full program path name or just the basename
2026 > # to be looked for in PATH), this may be an array ref of alternative
2027 > # program names or full paths - the first match in the list will be
2028 > used;
2029 > # As a special case for more complex scanners, this field may be
2030 > # a subroutine reference, and the whole n-tuple is passed to it as
2031 > args.
2032 > # 3. command arguments to be given to the scanner program;
2033 > # a substring {} will be replaced by the directory name to be
2034 > scanned, i.e.
2035 > # "$tempdir/parts", a "*" will be replaced by base file names of parts;
2036 > # 4. an array ref of av scanner exit status values, or a regexp (to be
2037 > # matched against scanner output), indicating NO VIRUSES found;
2038 > # a special case is a value undef, which does not claim file to be
2039 > clean
2040 > # (i.e. it never matches, similar to []), but suppresses a failure
2041 > warning;
2042 > # to be used when the result is inconclusive (useful for specialized
2043 > and
2044 > # quick partial scanners such as jpeg checker);
2045 > # 5. an array ref of av scanner exit status values, or a regexp (to be
2046 > # matched against scanner output), indicating VIRUSES WERE FOUND;
2047 > # Note: the virus match prevails over a 'not found' match, so it is
2048 > safe
2049 > # even if the no. 4. matches for viruses too;
2050 > # 6. a regexp (to be matched against scanner output), returning a list
2051 > # of virus names found, or a sub ref, returning such a list when given
2052 > # scanner output as argument;
2053 > # 7. and 8.: (optional) subroutines to be executed before and after
2054 > scanner
2055 > # (e.g. to set environment or current directory);
2056 > # see examples for these at KasperskyLab AVP and NAI uvscan.
2057 >
2058 > # NOTES:
2059 > #
2060 > # - NOT DEFINING @av_scanners (e.g. setting it to empty list, or
2061 > deleting the
2062 > # whole assignment) TURNS OFF LOADING AND COMPILING OF THE ANTIVIRUS CODE
2063 > # (which can be handy if all you want to do is spam scanning);
2064 > #
2065 > # - the order matters: although _all_ available entries from the list
2066 > # are tried regardless of their verdict, scanners are run in the order
2067 > # specified: the report from the first one detecting a virus will be used
2068 > # (providing virus names and scanner output); REARRANGE THE ORDER TO
2069 > WILL;
2070 > # see also $first_infected_stops_scan;
2071 > #
2072 > # - it doesn't hurt to keep an unused command line scanner entry in the
2073 > list
2074 > # if the program can not be found; the path search is only performed once
2075 > # during the program startup;
2076 > #
2077 > # COROLLARY: to disable a scanner that _does_ exist on your system,
2078 > # comment out its entry or use undef or '' as its program name/path
2079 > # (second parameter). An example where this is almost a must: disable
2080 > # Sophos 'sweep' if you have its daemonized version Sophie or SAVI-Perl
2081 > # (same for Trophie/vscan, and clamd/clamscan), or if another unrelated
2082 > # program happens to have a name matching one of the entries ('sweep'
2083 > # again comes to mind);
2084 > #
2085 > # - it DOES HURT to keep unwanted entries which use INTERNAL SUBROUTINES
2086 > # for interfacing (where the second parameter starts with \&).
2087 > # Keeping such entry and not having a corresponding virus scanner daemon
2088 > # causes an unnecessary connection attempt (which eventually times out,
2089 > # but it wastes precious time). For this reason the daemonized entries
2090 > # are commented in the distribution - just remove the '#' where needed.
2091 > #
2092 > # CERT list of av resources: http://www.cert.org/other_sources/viruses.html
2093 >
2094 > @av_scanners = (
2095 >
2096 > # ### http://www.vanja.com/tools/sophie/
2097 > # ['Sophie',
2098 > # \&ask_daemon, ["{}/\n", '/var/run/sophie'],
2099 > # qr/(?x)^ 0+ ( : | [\000\r\n]* $)/, qr/(?x)^ 1 ( : | [\000\r\n]* $)/,
2100 > # qr/(?x)^ [-+]? \d+ : (.*?) [\000\r\n]* $/ ],
2101 >
2102 > # ### http://www.csupomona.edu/~henson/www/projects/SAVI-Perl/
2103 > # ['Sophos SAVI', \&sophos_savi ],
2104 >
2105 > # ### http://www.clamav.net/
2106 > # ['ClamAV-clamd',
2107 > # \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],
2108 > # qr/\bOK$/, qr/\bFOUND$/,
2109 > # qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
2110 > # # NOTE: the easiest is to run clamd under the same user as amavisd;
2111 > match the
2112 > # # socket name (LocalSocket) in clamav.conf to the socket name in this
2113 > entry
2114 > # # When running chrooted one may prefer: ["CONTSCAN
2115 > {}\n","$MYHOME/clamd"],
2116 >
2117 > # ### http://www.clamav.net/ and CPAN (memory-hungry! clamd is preferred)
2118 > # ['Mail::ClamAV', \&ask_clamav, "*", [0], [1], qr/^INFECTED: (.+)/],
2119 >
2120 > # ### http://www.openantivirus.org/
2121 > # ['OpenAntiVirus ScannerDaemon (OAV)',
2122 > # \&ask_daemon, ["SCAN {}\n", '127.0.0.1:8127'],
2123 > # qr/^OK/, qr/^FOUND: /, qr/^FOUND: (.+)/ ],
2124 >
2125 > # ### http://www.vanja.com/tools/trophie/
2126 > # ['Trophie',
2127 > # \&ask_daemon, ["{}/\n", '/var/run/trophie'],
2128 > # qr/(?x)^ 0+ ( : | [\000\r\n]* $)/, qr/(?x)^ 1 ( : | [\000\r\n]* $)/,
2129 > # qr/(?x)^ [-+]? \d+ : (.*?) [\000\r\n]* $/ ],
2130 >
2131 > # ### http://www.grisoft.com/
2132 > # ['AVG Anti-Virus',
2133 > # \&ask_daemon, ["SCAN {}\n", '127.0.0.1:55555'],
2134 > # qr/^200/, qr/^403/, qr/^403 .*?: ([^\r\n]+)/ ],
2135 >
2136 > # ### http://www.f-prot.com/
2137 > # ['FRISK F-Prot Daemon',
2138 > # \&ask_daemon,
2139 > # ["GET {}/*?-dumb%20-archive%20-packed HTTP/1.0\r\n\r\n",
2140 > # ['127.0.0.1:10200','127.0.0.1:10201','127.0.0.1:10202',
2141 > # '127.0.0.1:10203','127.0.0.1:10204'] ],
2142 > # qr/(?i)<summary[^>]*>clean<\/summary>/,
2143 > # qr/(?i)<summary[^>]*>infected<\/summary>/,
2144 > # qr/(?i)<name>(.+)<\/name>/ ],
2145 >
2146 > # ### http://www.sald.com/, http://www.dials.ru/english/,
2147 > http://www.drweb.ru/
2148 > # ['DrWebD', \&ask_daemon, # DrWebD 4.31 or later
2149 > # [pack('N',1). # DRWEBD_SCAN_CMD
2150 > # pack('N',0x00280001). # DONT_CHANGEMAIL, IS_MAIL, RETURN_VIRUSES
2151 > # pack('N', # path length
2152 > # length("$TEMPBASE/amavis-yyyymmddTHHMMSS-xxxxx/parts/pxxx")).
2153 > # '{}/*'. # path
2154 > # pack('N',0). # content size
2155 > # pack('N',0),
2156 > # '/var/drweb/run/drwebd.sock',
2157 > # # '/var/amavis/var/run/drwebd.sock', # suitable for chroot
2158 > # # '/usr/local/drweb/run/drwebd.sock', # FreeBSD drweb ports default
2159 > # # '127.0.0.1:3000', # or over an inet socket
2160 > # ],
2161 > # qr/\A\x00[\x10\x11][\x00\x10]\x00/s, # IS_CLEAN,EVAL_KEY;
2162 > SKIPPED
2163 > # qr/\A\x00[\x00\x01][\x00\x10][\x20\x40\x80]/s, #
2164 > KNOWN_V,UNKNOWN_V,V._MODIF
2165 > # qr/\A.{12}(?:infected with )?([^\x00]+)\x00/s,
2166 > # ],
2167 > # # NOTE: If using amavis-milter, change length to:
2168 > # # length("$TEMPBASE/amavis-milter-xxxxxxxxxxxxxx/parts/pxxx").
2169 >
2170 > ### http://www.kaspersky.com/ (kav4mailservers)
2171 > ['KasperskyLab AVP - aveclient',
2172 > ['/usr/local/kav/bin/aveclient','/usr/local/share/kav/bin/aveclient',
2173 > '/opt/kav/bin/aveclient','aveclient'],
2174 > '-p /var/run/aveserver -s {}/*', [0,3,6,8],
2175 > qr/\b(INFECTED|SUSPICION)\b/,
2176 > qr/(?:INFECTED|SUSPICION) (.+)/,
2177 > ],
2178 >
2179 > ### http://www.kaspersky.com/
2180 > ['KasperskyLab AntiViral Toolkit Pro (AVP)', ['avp'],
2181 > '-* -P -B -Y -O- {}', [0,3,6,8], [2,4], # any use for -A -K ?
2182 > qr/infected: (.+)/,
2183 > sub {chdir('/opt/AVP') or die "Can't chdir to AVP: $!"},
2184 > sub {chdir($TEMPBASE) or die "Can't chdir back to $TEMPBASE $!"},
2185 > ],
2186 >
2187 > ### The kavdaemon and AVPDaemonClient have been removed from Kasperky
2188 > ### products and replaced by aveserver and aveclient
2189 > ['KasperskyLab AVPDaemonClient',
2190 > [ '/opt/AVP/kavdaemon', 'kavdaemon',
2191 > '/opt/AVP/AvpDaemonClient', 'AvpDaemonClient',
2192 > '/opt/AVP/AvpTeamDream', 'AvpTeamDream',
2193 > '/opt/AVP/avpdc', 'avpdc' ],
2194 > "-f=$TEMPBASE {}", [0,8], [3,4,5,6], qr/infected: ([^\r\n]+)/ ],
2195 > # change the startup-script in /etc/init.d/kavd to:
2196 > # DPARMS="-* -Y -dl -f=/var/amavis /var/amavis"
2197 > # (or perhaps: DPARMS="-I0 -Y -* /var/amavis" )
2198 > # adjusting /var/amavis above to match your $TEMPBASE.
2199 > # The '-f=/var/amavis' is needed if not running it as root, so it
2200 > # can find, read, and write its pid file, etc., see 'man kavdaemon'.
2201 > # defUnix.prf: there must be an entry "*/var/amavis" (or whatever
2202 > # directory $TEMPBASE specifies) in the 'Names=' section.
2203 > # cd /opt/AVP/DaemonClients; configure; cd Sample; make
2204 > # cp AvpDaemonClient /opt/AVP/
2205 > # su - vscan -c "${PREFIX}/kavdaemon ${DPARMS}"
2206 >
2207 > ### http://www.centralcommand.com/
2208 > ['CentralCommand Vexira (new) vascan',
2209 > ['vascan','/usr/lib/Vexira/vascan'],
2210 > "-a s --timeout=60 --temp=$TEMPBASE -y $QUARANTINEDIR ".
2211 > "--vdb=/usr/lib/Vexira/vexira8.vdb --log=/var/log/vascan.log {}",
2212 > [0,3], [1,2,5],
2213 > qr/(?x)^\s* (?:virus|iworm|macro|mutant|sequence|trojan)\ found:\ (
2214 > [^\]\s']+ )\ \.\.\.\ / ],
2215 > # Adjust the path of the binary and the virus database as needed.
2216 > # 'vascan' does not allow to have the temp directory to be the same as
2217 > # the quarantine directory, and the quarantine option can not be
2218 > disabled.
2219 > # If $QUARANTINEDIR is not used, then another directory must be
2220 > specified
2221 > # to appease 'vascan'. Move status 3 to the second list if password
2222 > # protected files are to be considered infected.
2223 >
2224 > ### http://www.hbedv.com/
2225 > ['H+BEDV AntiVir or the (old) CentralCommand Vexira Antivirus',
2226 > ['antivir','vexira'],
2227 > '--allfiles -noboot -nombr -rs -s -z {}', [0], qr/ALERT:|VIRUS:/,
2228 > qr/(?x)^\s* (?: ALERT: \s* (?: \[ | [^']* ' ) |
2229 > (?i) VIRUS:\ .*?\ virus\ '?) ( [^\]\s']+ )/ ],
2230 > # NOTE: if you only have a demo version, remove -z and add 214, as in:
2231 > # '--allfiles -noboot -nombr -rs -s {}', [0,214], qr/ALERT:|VIRUS:/,
2232 >
2233 > ### http://www.commandsoftware.com/
2234 > ['Command AntiVirus for Linux', 'csav',
2235 > '-all -archive -packed {}', [50], [51,52,53],
2236 > qr/Infection: (.+)/ ],
2237 >
2238 > ### http://www.symantec.com/
2239 > ['Symantec CarrierScan via Symantec CommandLineScanner',
2240 > 'cscmdline', '-a scan -i 1 -v -s 127.0.0.1:7777 {}',
2241 > qr/^Files Infected:\s+0$/, qr/^Infected\b/,
2242 > qr/^(?:Info|Virus Name):\s+(.+)/ ],
2243 >
2244 > ### http://www.symantec.com/
2245 > ['Symantec AntiVirus Scan Engine',
2246 > 'savsecls', '-server 127.0.0.1:7777 -mode scanrepair -details
2247 > -verbose {}',
2248 > [0], qr/^Infected\b/,
2249 > qr/^(?:Info|Virus Name):\s+(.+)/ ],
2250 > # NOTE: check options and patterns to see which entry better applies
2251 >
2252 > ### http://www.f-secure.com/products/anti-virus/
2253 > ['F-Secure Antivirus', 'fsav',
2254 > '--dumb --mime --archive {}', [0], [3,8],
2255 > qr/(?:infection|Infected|Suspected): (.+)/ ],
2256 >
2257 > # ### http://www.avast.com/
2258 > # ['avast! Antivirus daemon',
2259 > # \&ask_daemon, # greets with 220, terminate with QUIT
2260 > # ["SCAN {}\015\012QUIT\015\012", '/var/run/avast4/mailscanner.sock'],
2261 > # qr/\t\[\+\]/, qr/\t\[L\]\t/, qr/\t\[L\]\t([^[ \t\015\012]+)/ ],
2262 >
2263 > # ### http://www.avast.com/
2264 > # ['avast! Antivirus - Client/Server Version', 'avastlite',
2265 > # '-a /var/run/avast4/mailscanner.sock -n {}', [0], [1],
2266 > # qr/\t\[L\]\t([^[ \t\015\012]+)/ ],
2267 >
2268 > ['CAI InoculateIT', 'inocucmd', # retired product
2269 > '-sec -nex {}', [0], [100],
2270 > qr/was infected by virus (.+)/ ],
2271 > # see: http://www.flatmtn.com/computer/Linux-Antivirus_CAI.html
2272 >
2273 > ### http://www3.ca.com/Solutions/Product.asp?ID=156 (ex InoculateIT)
2274 > ['CAI eTrust Antivirus', 'etrust-wrapper',
2275 > '-arc -nex -spm h {}', [0], [101],
2276 > qr/is infected by virus: (.+)/ ],
2277 > # NOTE: requires suid wrapper around inocmd32; consider flag: -mod
2278 > reviewer
2279 > # see http://marc.theaimsgroup.com/?l=amavis-user&m=109229779912783
2280 >
2281 > ### http://mks.com.pl/english.html
2282 > ['MkS_Vir for Linux (beta)', ['mks32','mks'],
2283 > '-s {}/*', [0], [1,2],
2284 > qr/--[ \t]*(.+)/ ],
2285 >
2286 > ### http://mks.com.pl/english.html
2287 > ['MkS_Vir daemon', 'mksscan',
2288 > '-s -q {}', [0], [1..7],
2289 > qr/^... (\S+)/ ],
2290 >
2291 > ### http://www.nod32.com/
2292 > ['ESET Software NOD32 Command Line Interface v 2.51', 'nod32cli',
2293 > '--subdir {}', [0,3], [1,2], qr/virus="([^"]+)"/ ],
2294 >
2295 > # ### http://www.nod32.com/ old
2296 > # ['ESET Software NOD32 - Client/Server Version', 'nod32cli',
2297 > # '-a -r -d recurse --heur standard {}', [0], [10,11],
2298 > # qr/^\S+\s+infected:\s+(.+)/ ],
2299 >
2300 > # ### http://www.nod32.com/ old
2301 > # ['ESET Software NOD32', 'nod32',
2302 > # '--arch --mail {}', [0], [1,10], qr/^object=.*, virus="(.*?)",/ ],
2303 >
2304 > # Experimental, based on posting from Rado Dibarbora (Dibo) on 2002-05-31
2305 > # ['ESET Software NOD32 Client/Server (NOD32SS)',
2306 > # \&ask_daemon2, # greets with 200, persistent, terminate with QUIT
2307 > # ["SCAN {}/*\r\n", '127.0.0.1:8448' ],
2308 > # qr/^200 File OK/, qr/^201 /, qr/^201 (.+)/ ],
2309 >
2310 > ### http://www.norman.com/products_nvc.shtml
2311 > ['Norman Virus Control v5 / Linux', 'nvcc',
2312 > '-c -l:0 -s -u -temp:$TEMPBASE {}', [0,10,11], [1,2,14],
2313 > qr/(?i).* virus in .* -> \'(.+)\'/ ],
2314 >
2315 > ### http://www.pandasoftware.com/
2316 > ['Panda Antivirus for Linux', ['pavcl'],
2317 > '-aut -aex -heu -cmp -nbr -nor -nso -eng {}',
2318 > qr/Number of files infected[ .]*: 0+(?!\d)/,
2319 > qr/Number of files infected[ .]*: 0*[1-9]/,
2320 > qr/Found virus :\s*(\S+)/ ],
2321 >
2322 > # ### http://www.pandasoftware.com/
2323 > # ['Panda Antivirus for Linux', ['pavcl'],
2324 > # '-TSR -aut -aex -heu -cmp -nbr -nor -nso -eng {}',
2325 > # [0], [0x10, 0x30, 0x50, 0x70, 0x90, 0xB0, 0xD0, 0xF0],
2326 > # qr/Found virus :\s*(\S+)/ ],
2327 >
2328 > # GeCAD AV technology is acquired by Microsoft; RAV has been discontinued.
2329 > # Check your RAV license terms before fiddling with the following two
2330 > lines!
2331 > # ['GeCAD RAV AntiVirus 8', 'ravav',
2332 > # '--all --archive --mail {}', [1], [2,3,4,5], qr/Infected: (.+)/ ],
2333 > # # NOTE: the command line switches changed with scan engine 8.5 !
2334 > # # (btw, assigning stdin to /dev/null causes RAV to fail)
2335 >
2336 > ### http://www.nai.com/
2337 > ['NAI McAfee AntiVirus (uvscan)', 'uvscan',
2338 > '--secure -rv --mime --summary --noboot --mailbox --program
2339 > --timeout 180 - {}', [0], [13],
2340 > qr/(?x) Found (?:
2341 > \ the\ (.+)\ (?:virus|trojan) |
2342 > \ (?:virus|trojan)\ or\ variant\ ([^ ]+) |
2343 > :\ (.+)\ NOT\ a\ virus)/,
2344 > # sub {$ENV{LD_PRELOAD}='/lib/libc.so.6'},
2345 > # sub {delete $ENV{LD_PRELOAD}},
2346 > ],
2347 > # NOTE1: with RH9: force the dynamic linker to look at /lib/libc.so.6
2348 > before
2349 > # anything else by setting environment variable LD_PRELOAD=/lib/libc.so.6
2350 > # and then clear it when finished to avoid confusing anything else.
2351 > # NOTE2: to treat encrypted files as viruses replace the [13] with:
2352 > # qr/^\s{5,}(Found|is password-protected|.*(virus|trojan))/
2353 >
2354 > ### http://www.virusbuster.hu/en/
2355 > ['VirusBuster', ['vbuster', 'vbengcl'],
2356 > "{} -ss -i '*' -log=$MYHOME/vbuster.log", [0], [1],
2357 > qr/: '(.*)' - Virus/ ],
2358 > # VirusBuster Ltd. does not support the daemon version for the
2359 > workstation
2360 > # engine (vbuster-eng-1.12-linux-i386-libc6.tgz) any longer. The names of
2361 > # binaries, some parameters AND return codes have changed (from 3 to 1).
2362 > # See also the new Vexira entry 'vascan' which is possibly related.
2363 >
2364 > # ### http://www.virusbuster.hu/en/
2365 > # ['VirusBuster (Client + Daemon)', 'vbengd',
2366 > # '-f -log scandir {}', [0], [3],
2367 > # qr/Virus found = (.*);/ ],
2368 > # # HINT: for an infected file it always returns 3,
2369 > # # although the man-page tells a different story
2370 >
2371 > ### http://www.cyber.com/
2372 > ['CyberSoft VFind', 'vfind',
2373 > '--vexit {}/*', [0], [23], qr/##==>>>> VIRUS ID: CVDL (.+)/,
2374 > # sub {$ENV{VSTK_HOME}='/usr/lib/vstk'},
2375 > ],
2376 >
2377 > ### http://www.avast.com/
2378 > ['avast! Antivirus', ['/usr/bin/avastcmd','avastcmd'],
2379 > '-a -i -n -t=A {}', [0], [1], qr/\binfected by:\s+([^ \t\n\[\]]+)/ ],
2380 >
2381 > ### http://www.ikarus-software.com/
2382 > ['Ikarus AntiVirus for Linux', 'ikarus',
2383 > '{}', [0], [40], qr/Signature (.+) found/ ],
2384 >
2385 > ### http://www.bitdefender.com/
2386 > ['BitDefender', 'bdc',
2387 > '--arc --mail {}', qr/^Infected files *:0+(?!\d)/,
2388 > qr/^(?:Infected files|Identified viruses|Suspect files) *:0*[1-9]/,
2389 > qr/(?:suspected|infected): (.*)(?:\033|$)/ ],
2390 > # consider also: --all --nowarn --alev=15 --flev=15. The --all
2391 > argument may
2392 > # not apply to your version of bdc, check documentation and see 'bdc
2393 > --help'
2394 >
2395 > # ['File::Scan', sub {Amavis::AV::ask_av(sub{
2396 > # use File::Scan; my($fn)=@_;
2397 > # my($f)=File::Scan->new(max_txt_size=>0, max_bin_size=>0);
2398 > # my($vname) = $f->scan($fn);
2399 > # $f->error ? (2,"Error: ".$f->error)
2400 > # : ($vname ne '') ? (1,"$vname FOUND") : (0,"Clean")}, @_) },
2401 > # ["{}/*"], [0], [1], qr/^(.*) FOUND$/ ],
2402 >
2403 > # ### example: fully-fledged checker for JPEG marker segments of invalid
2404 > length
2405 > # ['check-jpeg',
2406 > # sub { use JpegTester (); Amavis::AV::ask_av(\&JpegTester::test_jpeg,
2407 > @_) },
2408 > # ["{}/*"], undef, [1], qr/^(bad jpeg: .*)$/ ],
2409 > # # NOTE: place file JpegTester.pm somewhere where Perl can find it,
2410 > # # for example in /usr/local/lib/perl5/site_perl
2411 >
2412 > # ### example: simpleminded checker for JPEG marker segments of invalid
2413 > length
2414 > # ### (only checks first 32k, which is not thorough enough)
2415 > # ['check-jpeg-simple',
2416 > # sub { Amavis::AV::ask_av(sub {
2417 > # my($f)=@_; local(*FF,$_,$1,$2); my(@r)=(0,'not jpeg');
2418 > # open(FF,$f) or die "jpeg: open err $f: $!";
2419 > # binmode(FF) or die "jpeg: binmode err $f: $!";
2420 > # defined read(FF,$_,32000) or die "jpeg: read err $f: $!";
2421 > # close(FF) or die "jpeg: close err $f: $!";
2422 > # if (/^\xff\xd8\xff/) {
2423 > # @r=(0,'jpeg ok');
2424 > # while (!/\G(?:\xff\xd9|\z)/gc) { # EOI or eof
2425 > # if (/\G\xff+(?=\xff|\z)/gc) {} # fill-bytes before
2426 > marker
2427 > # elsif (/\G\xff([\x01\xd0-\xd8])/gc) {} # TEM, RSTi, SOI
2428 > # elsif (/\G\xff([^\x00\xff])(..)/gcs) { # marker segment start
2429 > # my($n)=unpack("n",$2)-2;
2430 > # $n=32766 if $n>32766; # Perl regexp limit
2431 > # if ($n<0) {@r=(1,"bad jpeg: len=$n, pos=".pos); last}
2432 > # elsif (/\G.{$n}/gcs) {} # ok
2433 > # elsif (/\G.{0,$n}\z/gcs) {last} # truncated
2434 > # else {@r=(1,"bad jpeg: unexpected, pos=".pos); last}
2435 > # }
2436 > # elsif (/\G[^\xff]+/gc) {} # ECS
2437 > # elsif (/\G(?:\xff\x00)+/gc) {} # ECS
2438 > # else {@r=(2,"bad jpeg: unexpected char, pos=".pos); last}
2439 > # }
2440 > # }; @r}, @_) },
2441 > # ["{}/*"], undef, [1], qr/^(bad jpeg: .*)$/ ],
2442 >
2443 > );
2444 >
2445 >
2446 > # If no virus scanners from the @av_scanners list produce 'clean' nor
2447 > # 'infected' status (i.e. they all fail to run or the list is empty),
2448 > # then _all_ scanners from the @av_scanners_backup list are tried
2449 > # (again, subject to $first_infected_stops_scan). When there are both
2450 > # daemonized and equivalent or similar command-line scanners available,
2451 > # it is customary to place slower command-line scanners in the
2452 > # @av_scanners_backup list. The default choice is somewhat arbitrary,
2453 > # move entries from one list to another as desired, keeping main scanners
2454 > # in the primary list to avoid warnings.
2455 >
2456 > @av_scanners_backup = (
2457 >
2458 > ### http://www.clamav.net/ - backs up clamd or Mail::ClamAV
2459 > ['ClamAV-clamscan', 'clamscan',
2460 > "--stdout --disable-summary -r --tempdir=$TEMPBASE {}",
2461 > [0], qr/:.*\sFOUND$/, qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
2462 >
2463 > ### http://www.f-prot.com/ - backs up F-Prot Daemon
2464 > ['FRISK F-Prot Antivirus', ['f-prot','f-prot.sh'],
2465 > '-dumb -ai -archive -packed -server {}', [0,8], [3,6],
2466 > qr/Infection: (.+)|\s+contains\s+(.+)$/ ],
2467 >
2468 > ### http://www.trendmicro.com/ - backs up Trophie
2469 > ['Trend Micro FileScanner', ['/etc/iscan/vscan','vscan'],
2470 > '-za -a {}', [0], qr/Found virus/, qr/Found virus (.+) in/ ],
2471 >
2472 > ### http://www.sald.com/, http://drweb.imshop.de/ - backs up DrWebD
2473 > ['drweb - DrWeb Antivirus',
2474 > ['/usr/local/drweb/drweb', '/opt/drweb/drweb', 'drweb'],
2475 > '-path={} -al -go -ot -cn -upn -ok-',
2476 > [0,32], [1,9,33], qr' infected (?:with|by)(?: virus)? (.*)$'],
2477 >
2478 > ['KasperskyLab kavscanner', ['/opt/kav/bin/kavscanner','kavscanner'],
2479 > '-i1 -xp {}', [0,10,15], [5,20,21,25],
2480 > qr/(?:CURED|INFECTED|CUREFAILED|WARNING|SUSPICION) (.*)/ ,
2481 > sub {chdir('/opt/kav/bin') or die "Can't chdir to kav: $!"},
2482 > sub {chdir($TEMPBASE) or die "Can't chdir back to $TEMPBASE $!"},
2483 > ],
2484 >
2485 > # Commented out because the name 'sweep' clashes with Debian and FreeBSD
2486 > # package/port of an audio editor. Make sure the correct 'sweep' is found
2487 > # in the path when enabling.
2488 > #
2489 > # ### http://www.sophos.com/ - backs up Sophie or SAVI-Perl
2490 > # ['Sophos Anti Virus (sweep)', 'sweep',
2491 > # '-nb -f -all -rec -ss -sc -archive -cab -tnef --no-reset-atime {}',
2492 > # [0,2], qr/Virus .*? found/,
2493 > # qr/^>>> Virus(?: fragment)? '?(.*?)'? found/,
2494 > # ],
2495 > # # other options to consider: -mime -oe -idedir=/usr/local/sav
2496 >
2497 > # always succeeds (uncomment to consider mail clean if all other
2498 > scanners fail)
2499 > # ['always-clean', sub {0}],
2500 >
2501 > );
2502 >
2503 >
2504 > #
2505 > # Section VIII - Debugging
2506 > #
2507 >
2508 > # The most useful debugging tool is to run amavisd-new non-detached
2509 > # from a terminal window using command: # amavisd debug
2510 >
2511 > # Some more refined approaches:
2512 >
2513 > # If sender matches ACL, turn debugging fully up, just for this one message
2514 > #@debug_sender_maps = ( ["test-sender\@$mydomain"] );
2515 > #@debug_sender_maps = ( [qw( debug@×××××××.com debug@×××××××.net )] );
2516 >
2517 > # May be useful along with @debug_sender_maps:
2518 > # Prevent all decoded originals being deleted (replaced by decoded part)
2519 > #@keep_decoded_original_maps = (1);
2520 >
2521 > # Turn on SpamAssassin debugging (output to STDERR, use with 'amavisd
2522 > debug')
2523 > #$sa_debug = '1,all'; # defaults to false
2524 >
2525 >
2526 > #
2527 > # Section IX - Policy banks (dynamic policy switching)
2528 > #
2529 >
2530 > ## Define some policy banks (sets of settings) and give them
2531 > ## arbitrary names (the names '', 'MYNETS' and 'MYUSERS' have special
2532 > meaning):
2533 > #
2534 > # $policy_bank{'ALT'} = {
2535 > # log_level => 3,
2536 > # syslog_ident => 'alt-amavis',
2537 > # syslog_facility => 'LOCAL3',
2538 > # inet_acl => [qw( 10.0.1.14 )],
2539 > # final_spam_destiny => D_PASS, final_bad_header_destiny => D_PASS,
2540 > # forward_method => 'smtp:*:*',
2541 > # notify_method => 'smtp:[127.0.0.1]:10025',
2542 > # virus_admin_maps => "abuse\@$mydomain",
2543 > # spam_lovers_maps => [@spam_lovers_maps, [qw( abuse@×××××××.com )]],
2544 > # spam_tag_level_maps => 2.1,
2545 > # spam_tag2_level_maps => 6.32,
2546 > # spam_kill_level_maps => 6.72,
2547 > # spam_dsn_cutoff_level_maps => 8,
2548 > # defang_spam => 1,
2549 > # local_client_bind_address => '10.11.12.13',
2550 > # localhost_name => 'amavis.example.com',
2551 > # smtpd_greeting_banner =>
2552 > # '${helo-name} ${protocol} ${product} ${version-id}
2553 > (${version-date}) TEST service ready';
2554 > # auth_mech_avail => [qw(PLAIN LOGIN)],
2555 > # auth_required_inp => 1,
2556 > # auth_required_out => 1,
2557 > # amavis_auth_user => 'amavisd', amavis_auth_pass = 'tOpsecretX',
2558 > # av_scanners => [ # provide only 'free' scanners
2559 > # ['ClamAV-clamd',
2560 > # \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],
2561 > # qr/\bOK$/, qr/\bFOUND$/,
2562 > # qr/^.*?: (?!Infected Archive)(.*) FOUND$/,
2563 > # ],
2564 > # ],
2565 > # av_scanners_backup => [
2566 > # ['ClamAV-clamscan', 'clamscan',
2567 > # "--stdout --disable-summary -r --tempdir=$TEMPBASE {}", [0], [1],
2568 > # qr/^.*?: (?!Infected Archive)(.*) FOUND$/,
2569 > # ],
2570 > # ],
2571 > # };
2572 >
2573 > # NOTE: the use of policy banks for changing protocol on the input
2574 > socket is
2575 > # only needed when different protocols need to be spoken on different
2576 > sockets
2577 > # at the same time. For normal use just set globally e.g.:
2578 > $protocol='AM.PDP';
2579 > #
2580 > #$policy_bank{'AM.PDP-SOCK'} = {
2581 > # protocol => 'AM.PDP', # Amavis policy delegation protocol
2582 > # auth_required_release => 0, # don't require secret_id for
2583 > amavisd-release
2584 > #};
2585 > #
2586 > #$policy_bank{'AM.PDP-INET'} = {
2587 > # protocol => 'AM.PDP', # Amavis policy delegation protocol
2588 > # inet_acl => [qw( 127.0.0.1 [::1] )], # restrict to these IP addresses
2589 > #};
2590 > #
2591 > ## the name 'MYNETS' has special semantics: this policy bank gets loaded
2592 > ## whenever MTA supplies the original SMTP client IP address (Postfix
2593 > XFORWARD
2594 > ## extension or a new AM.PDP protocol) and that address matches
2595 > @mynetworks.
2596 > #
2597 > # $terminate_dsn_on_notify_success = 1;
2598 > # $policy_bank{'MYNETS'} = { # mail originating from @mynetworks
2599 > # terminate_dsn_on_notify_success => 0,
2600 > # spam_kill_level_maps => 6.9,
2601 > # syslog_facility => 'LOCAL4', # tell syslog to log to a separate file
2602 > # spam_admin_maps => ["spamalert\@$mydomain"], # alert of internal spam
2603 > # bypass_spam_checks_maps => [1], # or: don't spam-check internal mail
2604 > # bypass_banned_checks_maps => [1], # don't banned-check internal mail
2605 > # warnbadhsender => 1, # warn local senders about their broken MUA
2606 > # banned_filename_maps => ['MYNETS-DEFAULT'], # more permissive
2607 > banning rules
2608 > # };
2609 >
2610 > ## the name 'MYUSERS' has special semantics: this policy bank gets loaded
2611 > ## whenever the sender matches @local_domains_maps. This only makes sense
2612 > ## if local sender addresses can be trusted -- for example by requiring
2613 > ## authentication before letting users send with their local address.
2614 > #
2615 > # $policy_bank{'MYUSERS'} = {
2616 > # final_virus_destiny => D_BOUNCE, # bounce only to authenticated
2617 > local users
2618 > # final_banned_destiny=> D_BOUNCE,
2619 > # };
2620 >
2621 >
2622 > ## Now we can assign policy banks to amavisd tcp port numbers listed in
2623 > ## $inet_socket_port. Whenever the connection from MTA is received, first
2624 > ## a built-in policy bank $policy_bank{''} gets loaded, which bringings-in
2625 > ## all the global/legacy settings, then it gets overlaid by the bank
2626 > ## named in the $interface_policy{$port} if any, and finally the bank
2627 > ## 'MYNETS' is overlaid if it exists and the SMTP client IP address
2628 > ## is known (by XFORWARD command from MTA) and it matches @mynetworks.
2629 >
2630 > # $interface_policy{'10026'} = 'ALT';
2631 >
2632 > # used by amavisd-release utility of a new AM.PDP-based amavis-milter
2633 > client
2634 > #$interface_policy{'9998'} = 'AM.PDP-INET';
2635 > #$interface_policy{'SOCK'} = 'AM.PDP-SOCK';
2636 >
2637 >
2638 > # Want to execute additional configuration files from some directory?
2639 > #
2640 > #{ my($d) = '/etc/amavis/conf.d'; # do *.cf or *.conf files in this
2641 > directory
2642 > # local(*D); opendir(D,$d) or die "Can't open dir $d: $!";
2643 > # my(@d) = sort grep {/\.(cf|conf)$/ && -f} map {/^(.*)$/,"$d/$1"}
2644 > readdir(D);
2645 > # closedir(D) or die "Can't close $d: $!";
2646 > # for my $f (@d) {
2647 > # printf("Reading config file %s\n", $f); $!=0;
2648 > # if (defined(do $f)) {}
2649 > # elsif ($@ ne '') { die "Error in $f: $@" }
2650 > # elsif ($! != 0) { die "Error reading $f: $!" }
2651 > # }
2652 > #}
2653 >
2654 > #-------------
2655 > 1; # insure a defined return
2656 --
2657 gentoo-server@g.o mailing list

Replies

Subject Author
Re: [gentoo-server] amavisd-new disaster Jonathan Nichols <jnichols@×××.net>