chiark / gitweb /
defs.m4: New macros for inserting separators into lists.
[exim-config] / base.m4
1 ### -*-m4-*-
2 ###
3 ### Basic settings for distorted.org.uk Exim configuration
4 ###
5 ### (c) 2012 Mark Wooding
6 ###
7
8 ###----- Licensing notice ---------------------------------------------------
9 ###
10 ### This program is free software; you can redistribute it and/or modify
11 ### it under the terms of the GNU General Public License as published by
12 ### the Free Software Foundation; either version 2 of the License, or
13 ### (at your option) any later version.
14 ###
15 ### This program is distributed in the hope that it will be useful,
16 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ### GNU General Public License for more details.
19 ###
20 ### You should have received a copy of the GNU General Public License
21 ### along with this program; if not, write to the Free Software Foundation,
22 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 ###--------------------------------------------------------------------------
25 ### Global settings.
26
27 SECTION(global, priv)m4_dnl
28 admin_groups = CONF_admin_groups
29 trusted_groups = CONF_trusted_groups
30 prod_requires_admin = false
31
32 SECTION(global, logging)m4_dnl
33 log_file_path = : syslog
34 log_selector = \
35         +smtp_confirmation \
36         +tls_peerdn
37 log_timezone = true
38 syslog_duplication = false
39 syslog_timestamp = false
40
41 SECTION(global, daemon)m4_dnl
42 local_interfaces = <; CONF_interfaces
43 extra_local_interfaces = <; 0.0.0.0 ; ::0
44
45 SECTION(global, resource)m4_dnl
46 deliver_queue_load_max = 8
47 queue_only_load = 12
48 smtp_accept_max = 16
49 smtp_accept_queue = 32
50 smtp_accept_reserve = 4
51 smtp_load_reserve = 10
52 smtp_reserve_hosts = +trusted
53
54 SECTION(global, policy)m4_dnl
55 host_lookup = *
56
57 SECTION(global, users)m4_dnl
58 gecos_name = $1
59 gecos_pattern = ([^,:]*)
60
61 SECTION(global, incoming)m4_dnl
62 received_header_text = Received: \
63         ${if def:sender_rcvhost \
64              {from $sender_rcvhost\n\t} \
65              {${if def:sender_ident \
66                    {from ${quote_local_part:$sender_ident} }}}}\
67         by $primary_hostname \
68         (Exim $version_number)\
69         ${if def:tls_cipher {\n\t} { }}\
70         ${if def:received_protocol \
71              {with $received_protocol \
72               ${if def:tls_cipher {(cipher=$tls_cipher)}}}}\n\t\
73         ${if def:sender_address \
74              {(envelope-from $sender_address\
75               ${if def:authenticated_id \
76                    {; auth=$authenticated_id}})\n\t}}\
77         id $message_exim_id\
78         ${if def:received_for {\n\tfor $received_for}}
79
80 SECTION(global, smtp)m4_dnl
81 smtp_return_error_details = true
82 accept_8bitmime = true
83
84 SECTION(global, process)m4_dnl
85 extract_addresses_remove_arguments = false
86 headers_charset = utf-8
87 qualify_domain = CONF_master_domain
88
89 SECTION(global, bounce)m4_dnl
90 delay_warning = 1h : 24h : 2d
91
92 SECTION(global, tls)m4_dnl
93 tls_certificate = CONF_sysconf_dir/server.certlist
94 tls_privatekey = CONF_sysconf_dir/server.key
95 tls_advertise_hosts = ${if exists {CONF_sysconf_dir/server.key} {*}{}}
96 tls_dhparam = CONF_ca_dir/dh-param-2048.pem
97 tls_require_ciphers = ${if or {{={$received_port}{CONF_submission_port}} \
98                                {match_ip {$sender_host_address}{+trusted}}} \
99                            {CONF_good_ciphers} \
100                            {CONF_acceptable_ciphers}}
101 tls_verify_certificates = CONF_ca_dir/ca.cert
102 tls_verify_hosts = ${if eq{$acl_c_mode}{submission} {} {+allnets}}
103
104 DIVERT(null)
105 ###--------------------------------------------------------------------------
106 ### Access control lists.
107
108 SECTION(global, acl-after)
109 SECTION(global, acl)m4_dnl
110 acl_smtp_helo = helo
111 SECTION(acl, misc)m4_dnl
112 helo:
113         ## Check that the caller's claimed identity is actually plausible.
114         ## This seems like it's a fairly effective filter on spamminess, but
115         ## it's too blunt a tool.  Rather than reject, add a warning header.
116         ## Only we can't do this the easy way, so save it up for use in MAIL.
117         ## Also, we're liable to get a subsequent HELO (e.g., after STARTTLS)
118         ## and we should only care about the most recent one.
119         warn     set acl_c_helo_warning = false
120                 !condition = \
121                         ${if and {{match_ip {$sender_host_address} \
122                                             {<; 127.0.0.0/8 ; ::1}} \
123                                   {match_domain {$sender_helo_name} \
124                                                 {localhost : +thishost}}}}
125                 !condition = \
126                         ${if exists {CONF_sysconf_dir/helo.conf} \
127                              {${lookup {$sender_helo_name} \
128                                        partial0-lsearch \
129                                        {CONF_sysconf_dir/helo.conf} \
130                                        {${if match_ip \
131                                              {$sender_host_address} \
132                                              {<; $value}}}}}}
133                 !verify = helo
134                  set acl_c_helo_warning = true
135
136         accept
137
138 SECTION(global, acl)m4_dnl
139 acl_not_smtp_start = not_smtp_start
140 SECTION(acl, misc)m4_dnl
141 not_smtp_start:
142         ## Record the user's name.
143         warn     set acl_c_user = $sender_ident
144
145         ## Done.
146         accept
147
148 SECTION(global, acl)m4_dnl
149 acl_smtp_mail = mail
150 SECTION(acl, mail)m4_dnl
151 mail:
152
153         ## If we stashed a warning header about HELO from earlier, we should
154         ## add it now.
155         warn     condition = $acl_c_helo_warning
156                  add_header = :after_received:X-Distorted-Warning: \
157                         BADHELO \
158                         Client's HELO doesn't match its IP address.\n\t\
159                         helo-name=$sender_helo_name \
160                         address=$sender_host_address
161
162         ## Always allow the empty sender, so that we can receive bounces.
163         accept   senders = :
164
165         ## Ensure that the sender looks valid.
166         require  acl = mail_check_sender
167
168         ## If this is directly from a client then hack on it for a while.
169         warn     condition = ${if eq{$acl_c_mode}{submission}}
170                  control = submission
171
172         ## Insist that a local client connect through TLS.
173         deny     message = Hosts within CONF_master_domain must use TLS
174                 !condition = ${if eq{$acl_c_mode}{submission}}
175                  hosts = +allnets
176                 !encrypted = *
177
178         ## Check that a submitted message's sender address is allowable.
179         require  acl = mail_check_auth
180
181 SECTION(acl, mail-tail)m4_dnl
182         ## And we're done.
183         accept
184
185 SECTION(acl, misc)m4_dnl
186 mail_check_sender:
187
188         ## See whether there's a special exception for this sender domain.
189         accept   senders = ${LOOKUP_DOMAIN($sender_address_domain,
190                              {KV(senders, {$value}{})},
191                              {})}
192
193         ## Ensure that the sender is routable.  This is important to prevent
194         ## undeliverable bounces.
195         require  message = Invalid sender; \
196                         ($sender_verify_failure; $acl_verify_message)
197                  verify = sender
198
199         ## We're good, then.
200         accept
201
202 SECTION(global, acl)m4_dnl
203 acl_smtp_connect = connect
204 SECTION(acl, connect)m4_dnl
205 connect:
206 SECTION(acl, connect-tail)m4_dnl
207         ## Configure variables according to the submission mode.
208         warn     acl = check_submission
209
210         ## Done.
211         accept
212
213 check_submission:
214         ## See whether this message needs hacking on.
215         accept  !hosts = +thishost
216                 !condition = ${if ={$received_port}{CONF_submission_port}}
217                  set acl_c_mode = relay
218
219         ## Remember to apply submission controls.
220         warn     set acl_c_mode = submission
221
222         ## Done.
223         accept
224
225 SECTION(global, acl)m4_dnl
226 acl_smtp_rcpt = rcpt
227 SECTION(acl, rcpt)m4_dnl
228 rcpt:
229
230         ## Reject if the client isn't allowed to relay and the recipient
231         ## isn't in one of our known domains.
232         require  message = Relaying not permitted
233                  acl = check_relay
234
235         ## Ensure that the recipient is routable.
236         require  message = Invalid recipient \
237                         ($recipient_verify_failure; $acl_verify_message)
238                  verify = recipient
239
240 SECTION(acl, misc)m4_dnl
241 check_relay:
242         ## Accept either if the client is allowed to relay through us, or if
243         ## we're the correct place to send this mail.
244
245         ## Known clients and authenticated users are OK.
246         accept    hosts = CONF_relay_clients
247         accept    authenticated = *
248
249         ## Known domains are OK.
250         accept    domains = +public
251
252         ## Finally, domains in our table are OK, unless they say they aren't.
253         accept    domains = \
254                 ${if exists{CONF_sysconf_dir/domains.conf} \
255                      {partial0-lsearch; CONF_sysconf_dir/domains.conf}}
256                   condition = DOMKV(service, {$value}{true})
257
258         ## Nope, that's not allowed.
259         deny
260
261 SECTION(acl, rcpt-tail)m4_dnl
262         ## Everything checks out OK: let this one go through.
263         accept
264
265 SECTION(global, acl)m4_dnl
266 acl_smtp_data = data
267 SECTION(acl, data)m4_dnl
268 data:
269
270 SECTION(acl, data-tail)m4_dnl
271         accept
272
273 SECTION(global, acl)m4_dnl
274 acl_smtp_expn = expn_vrfy
275 acl_smtp_vrfy = expn_vrfy
276 SECTION(acl, misc)m4_dnl
277 expn_vrfy:
278         accept   hosts = +trusted
279         deny     message = Suck it and see
280
281 DIVERT(null)
282 ###--------------------------------------------------------------------------
283 ### Verification of sender address.
284
285 SECTION(acl, misc)m4_dnl
286 mail_check_auth:
287
288         ## If this isn't a submission then it doesn't need checking.
289         accept   condition = ${if !eq{$acl_c_mode}{submission}}
290
291         ## If the caller hasn't formally authenticated, but this is a
292         ## loopback connection, then we can trust identd to tell us the right
293         ## answer.  So we should stash the right name somewhere consistent.
294         warn     set acl_c_user = $authenticated_id
295                  hosts = +thishost
296                 !authenticated = *
297                  condition = ${if def:sender_ident}
298                  set acl_c_user = $sender_ident
299
300         ## User must be authenticated by now.
301         deny     message = Sender not authenticated
302                  condition = ${if !def:acl_c_user}
303
304         ## Make sure that the local part is one that the authenticated sender
305         ## is allowed to claim.
306         deny     message = Sender address forbidden to calling user
307                 !condition = \
308                         ${if exists {CONF_sysconf_dir/auth-sender.conf} \
309                              {${lookup {$acl_c_user} \
310                                        lsearch \
311                                        {CONF_sysconf_dir/auth-sender.conf} \
312                                        {${if match_address \
313                                              {$sender_address} \
314                                              {+value}}} \
315                                        {false}}}}
316                 !condition = ${LOOKUP_DOMAIN($sender_address_domain,
317                                {${if and {{match_local_part \
318                                             {$acl_c_user} \
319                                             {+dom_users}} \
320                                           {match_local_part \
321                                             {$sender_address_local_part} \
322                                             {+dom_locals}}}}},
323                                {${if and {{match_local_part \
324                                             {$sender_address_local_part} \
325                                             {+user_extaddr}} \
326                                           {or {{eq {$sender_address_domain} \
327                                                    {}} \
328                                                {match_domain \
329                                                  {$sender_address_domain} \
330                                                  {+public}}}}}}})}
331
332         ## All done.
333         accept
334
335 DIVERT(null)
336 ###--------------------------------------------------------------------------
337 ### Common options for forwarding routers.
338
339 ## We're pretty permissive here.
340 m4_define(<:FILTER_BASE:>,
341         <:driver = redirect
342         modemask = 002
343         check_owner = false
344         check_group = false
345         allow_filter = true
346         allow_defer = true
347         allow_fail = true
348         forbid_blackhole = false
349         check_ancestor = true:>)
350
351 ## Common options for forwarding routers at verification time.
352 m4_define(<:FILTER_VERIFY:>,
353         <:verify_only = true
354         user = CONF_filter_user
355         forbid_filter_dlfunc = true
356         forbid_filter_logwrite = true
357         forbid_filter_perl = true
358         forbid_filter_readsocket = true
359         forbid_filter_run = true
360         file_transport = dummy
361         directory_transport = dummy
362         pipe_transport = dummy
363         reply_transport = dummy:>)
364
365 ## Transports for redirection filters.
366 m4_define(<:FILTER_TRANSPORTS:>,
367         <:file_transport = mailbox
368         directory_transport = maildir
369         pipe_transport = pipe
370         reply_transport = reply:>)
371
372 m4_define(<:FILTER_ROUTER:>,
373 <:$1_vrf:
374         $2
375         FILTER_VERIFY<::>$3
376 $1:
377         $2
378         verify = no
379         FILTER_TRANSPORTS<::>$4:>)
380
381 DIVERT(null)
382 ###--------------------------------------------------------------------------
383 ### Some standard transports.
384
385 m4_define(<:USER_DELIVERY:>,
386         <:delivery_date_add = true
387         envelope_to_add = true
388         return_path_add = true:>)
389
390 SECTION(transports)m4_dnl
391 ## A standard transport for remote delivery.  By default, try to do TLS, and
392 ## don't worry too much if it's not very secure: the alternative is sending
393 ## in plaintext anyway.  But all of this can be overridden from the
394 ## `domains.conf' file.  Annoyingly, the `tls_dh_min_bits' setting isn't
395 ## expanded before use, so we can't set it the obvious way.  Instead, encode
396 ## it into the transport name.  This is very unpleasant, of course.
397 smtp:
398         driver = smtp
399         tls_require_ciphers = CONF_acceptable_ciphers
400         tls_dh_min_bits = 1020
401         tls_tempfail_tryclear = true
402
403 m4_define(<:SMTP_TRANS_DHBITS:>,
404         <:driver = smtp
405         hosts_try_auth = *
406         hosts_require_tls = DOMKV(tls-peer-ca, {*}{})
407         hosts_require_auth = \
408                 ${if bool {DOMKV(require-auth, {$value}{false})} {*}{}}
409         tls_certificate = DOMKV(tls-certificate, {${expand:$value}}fail)
410         tls_privatekey = DOMKV(tls-private-key, {${expand:$value}}fail)
411         tls_verify_certificates = DOMKV(tls-peer-ca, {${expand:$value}}fail)
412         tls_require_ciphers = \
413                 DOMKV(tls-ciphers,
414                       {${extract {${expand:$value}} \
415                                  { good = CONF_good_ciphers \
416                                    any = CONF_acceptable_ciphers } \
417                                  {$value} \
418                                  {${expand:$value}}}} \
419                       {CONF_acceptable_ciphers})
420         tls_dh_min_bits = $1
421         tls_tempfail_tryclear = true:>)m4_dnl
422 smtp_dhbits_1024:
423         SMTP_TRANS_DHBITS(1020)
424 smtp_dhbits_2048:
425         SMTP_TRANS_DHBITS(2046)
426
427 ## Transport to a local SMTP server; use TLS and perform client
428 ## authentication.
429 smtp_local:
430         driver = smtp
431         hosts_require_tls = *
432         tls_certificate = CONF_sysconf_dir/client.certlist
433         tls_privatekey = CONF_sysconf_dir/client.key
434         tls_verify_certificates = CONF_ca_dir/ca.cert
435         tls_require_ciphers = CONF_good_ciphers
436         tls_dh_min_bits = 2046
437         tls_tempfail_tryclear = false
438         authenticated_sender = ${if def:authenticated_id \
439                                     {$authenticated_id@CONF_master_domain} \
440                                     fail}
441
442 ## A standard transport for local delivery.
443 deliver:
444         driver = appendfile
445         file = /var/mail/$local_part
446         group = mail
447         mode = 0600
448         mode_fail_narrower = false
449         USER_DELIVERY
450
451 ## Transports for user filters.
452 mailbox:
453         driver = appendfile
454         initgroups = true
455         USER_DELIVERY
456
457 maildir:
458         driver = appendfile
459         maildir_format = true
460         initgroups = true
461         USER_DELIVERY
462
463 pipe:
464         driver = pipe
465         path = ${if and {{def:home} {exists{$home/bin}}} {$home/bin:} {}}\
466                 /usr/local/bin:/usr/local/sbin:\
467                 /usr/bin:/usr/sbin:/bin:/sbin
468         initgroups = true
469         umask = 002
470         return_fail_output = true
471         log_output = true
472
473 ## A special dummy transport for use during address verification.
474 dummy:
475         driver = appendfile
476         file = /dev/null
477
478 DIVERT(null)
479 ###--------------------------------------------------------------------------
480 ### Retry configuration.
481
482 SECTION(retry, default)m4_dnl
483 ## Default.
484 *                                       * \
485         F,2h,15m; G,16h,2h,1.5; F,4d,6h
486
487 DIVERT(null)
488 ###----- That's all, folks --------------------------------------------------