X-Git-Url: https://git.distorted.org.uk/~mdw/exim-config/blobdiff_plain/8f6af4ae7d9ef046f28c5625f58efa4e5e128ff7..beb15dae3f15ff993556b44897bed035d543c683:/base.m4 diff --git a/base.m4 b/base.m4 index 75b1c4c..4a925df 100644 --- a/base.m4 +++ b/base.m4 @@ -25,7 +25,7 @@ ### Global settings. SECTION(global, priv)m4_dnl -admin_groups = root : adm +admin_groups = CONF_admin_groups prod_requires_admin = false SECTION(global, logging)m4_dnl @@ -59,18 +59,18 @@ gecos_pattern = ([^,:]*) SECTION(global, incoming)m4_dnl received_header_text = Received: \ - ${if def:sender_rcvhost {from $sender_rcvhost\n\t} \ + ${if def:sender_rcvhost \ + {from $sender_rcvhost\n\t} \ {${if def:sender_ident \ - {from ${quote_local_part:$sender_ident} }}\ - ${if def:sender_helo_name \ - {(helo=$sender_helo_name)\n\t}}}}\ + {from ${quote_local_part:$sender_ident} }}}}\ by $primary_hostname \ + (Exim $version_number)\ + ${if def:tls_cipher {\n\t} { }}\ ${if def:received_protocol \ {with $received_protocol \ - ${if def:tls_cipher {(cipher=$tls_cipher)\n\t}}}}\ - (Exim $version_number)\n\t\ + ${if def:tls_cipher {(cipher=$tls_cipher)}}}}\n\t\ ${if def:sender_address \ - {(envelope-from <$sender_address>\ + {(envelope-from $sender_address\ ${if def:authenticated_id \ {; auth=$authenticated_id}})\n\t}}\ id $message_exim_id\ @@ -88,6 +88,18 @@ qualify_domain = CONF_master_domain SECTION(global, bounce)m4_dnl delay_warning = 1h : 24h : 2d +SECTION(global, tls)m4_dnl +tls_certificate = CONF_sysconf_dir/server.cert +tls_privatekey = CONF_sysconf_dir/server.key +tls_advertise_hosts = ${if exists {CONF_sysconf_dir/server.key} {*}{}} +tls_dhparam = CONF_ca_dir/dh-param-2048.pem +tls_require_ciphers = ${if or {{={$received_port}{CONF_submission_port}} \ + {match_ip {$sender_host_address}{+trusted}}} \ + {CONF_good_ciphers} \ + {CONF_acceptable_ciphers}} +tls_verify_certificates = CONF_ca_dir/ca.cert +tls_verify_hosts = ${if eq{$acl_c_mode}{submission} {} {+allnets}} + DIVERT(null) ###-------------------------------------------------------------------------- ### Access control lists. @@ -97,9 +109,39 @@ SECTION(global, acl)m4_dnl acl_smtp_helo = helo SECTION(acl, misc)m4_dnl helo: - require message = The other one has bells on - verify = helo + ## Check that the caller's claimed identity is actually plausible. + ## This seems like it's a fairly effective filter on spamminess, but + ## it's too blunt a tool. Rather than reject, add a warning header. + ## Only we can't do this the easy way, so save it up for use in MAIL. + ## Also, we're liable to get a subsequent HELO (e.g., after STARTTLS) + ## and we should only care about the most recent one. + warn set acl_c_helo_warning = false + !condition = \ + ${if and {{match_ip {$sender_host_address} \ + {<; 127.0.0.0/8 ; ::1}} \ + {match_domain {$sender_helo_name} \ + {localhost : +thishost}}}} + !condition = \ + ${if exists {CONF_sysconf_dir/helo.conf} \ + {${lookup {$sender_helo_name} \ + partial0-lsearch \ + {CONF_sysconf_dir/helo.conf} \ + {${if match_ip \ + {$sender_host_address} \ + {$value}}}}}} + !verify = helo + set acl_c_helo_warning = true + + accept + +SECTION(global, acl)m4_dnl +acl_not_smtp_start = not_smtp_start +SECTION(acl, misc)m4_dnl +not_smtp_start: + ## Record the user's name. + warn set acl_c_user = $sender_ident + ## Done. accept SECTION(global, acl)m4_dnl @@ -107,6 +149,15 @@ acl_smtp_mail = mail SECTION(acl, mail)m4_dnl mail: + ## If we stashed a warning header about HELO from earlier, we should + ## add it now. + warn condition = $acl_c_helo_warning + add_header = :after_received:X-Distorted-Warning: \ + BADHELO \ + Client's HELO doesn't match its IP address.\n\t\ + helo-name=$sender_helo_name \ + address=$sender_host_address + ## Always allow the empty sender, so that we can receive bounces. accept senders = : @@ -120,6 +171,15 @@ mail: warn condition = ${if eq{$acl_c_mode}{submission}} control = submission + ## Insist that a local client connect through TLS. + deny message = Hosts within CONF_master_domain must use TLS + !condition = ${if eq{$acl_c_mode}{submission}} + hosts = +allnets + !encrypted = * + + ## Check that a submitted message's sender address is allowable. + require acl = mail_check_auth + SECTION(acl, mail-tail)m4_dnl ## And we're done. accept @@ -137,7 +197,7 @@ SECTION(acl, connect-tail)m4_dnl check_submission: ## See whether this message needs hacking on. - accept !hosts = +localnet + accept !hosts = +thishost !condition = ${if ={$received_port}{CONF_submission_port}} set acl_c_mode = relay @@ -186,6 +246,51 @@ expn_vrfy: DIVERT(null) ###-------------------------------------------------------------------------- +### Verification of sender address. + +SECTION(acl, misc)m4_dnl +mail_check_auth: + + ## If this isn't a submission then it doesn't need checking. + accept condition = ${if !eq{$acl_c_mode}{submission}} + + ## If the caller hasn't formally authenticated, but this is a + ## loopback connection, then we can trust identd to tell us the right + ## answer. So we should stash the right name somewhere consistent. + warn set acl_c_user = $authenticated_id + hosts = +thishost + !authenticated = * + set acl_c_user = $sender_ident + + ## User must be authenticated. + deny message = Sender not authenticated + !hosts = +thishost + !authenticated = * + + ## Make sure that the local part is one that the authenticated sender + ## is allowed to claim. + deny message = Sender address forbidden to calling user + !condition = ${LOOKUP_DOMAIN($sender_address_domain, + {${if and {{match_local_part \ + {$acl_c_user} \ + {+dom_users}} \ + {match_local_part \ + {$sender_address_local_part} \ + {+dom_locals}}}}}, + {${if and {{match_local_part \ + {$sender_address_local_part} \ + {+user_extaddr}} \ + {or {{eq {$sender_address_domain} \ + {}} \ + {match_domain \ + {$sender_address_domain} \ + {+public}}}}}}})} + + ## All done. + accept + +DIVERT(null) +###-------------------------------------------------------------------------- ### Common options for forwarding routers. ## We're pretty permissive here. @@ -221,6 +326,15 @@ m4_define(<:FILTER_TRANSPORTS:>, pipe_transport = pipe reply_transport = reply:>) +m4_define(<:FILTER_ROUTER:>, +<:$1_vrf: + $2 + FILTER_VERIFY<::>$3 +$1: + $2 + verify = no + FILTER_TRANSPORTS<::>$4:>) + DIVERT(null) ###-------------------------------------------------------------------------- ### Some standard transports. @@ -231,14 +345,37 @@ m4_define(<:USER_DELIVERY:>, return_path_add = true:>) SECTION(transports)m4_dnl -## A standard transport for remote delivery. Try to do TLS, and don't worry -## too much if it's not very secure: the alternative is sending in plaintext -## anyway. +## A standard transport for remote delivery. By default, try to do TLS, and +## don't worry too much if it's not very secure: the alternative is sending +## in plaintext anyway. But all of this can be overridden from the +## `domains.conf' file. Annoyingly, the `tls_dh_min_bits' setting isn't +## expanded before use, so we can't set it the obvious way. Instead, encode +## it into the transport name. This is very unpleasant, of course. +m4_define(<:SMTP_TRANS_DHBITS:>, + <:driver = smtp + hosts_try_auth = * + hosts_require_tls = DOMKV(tls-peer-ca, {*}{}) + hosts_require_auth = \ + ${if bool {DOMKV(require-auth, {$value}{false})} {*}{}} + tls_certificate = DOMKV(tls-certificate, {${expand:$value}}fail) + tls_privatekey = DOMKV(tls-private-key, {${expand:$value}}fail) + tls_verify_certificates = DOMKV(tls-peer-ca, {${expand:$value}}fail) + tls_require_ciphers = \ + DOMKV(tls-ciphers, + {${extract {${expand:$value}} \ + { good = CONF_good_ciphers \ + any = CONF_acceptable_ciphers } \ + {$value} \ + {${expand:$value}}}} \ + {CONF_acceptable_ciphers}) + tls_dh_min_bits = $1 + tls_tempfail_tryclear = true:>)m4_dnl smtp: - driver = smtp - tls_require_ciphers = CONF_acceptable_ciphers - tls_dh_min_bits = 1020 - tls_tempfail_tryclear = true + SMTP_TRANS_DHBITS(1020) +smtp_dhbits_1024: + SMTP_TRANS_DHBITS(1020) +smtp_dhbits_2048: + SMTP_TRANS_DHBITS(2046) ## Transport to a local SMTP server; use TLS and perform client ## authentication. @@ -249,10 +386,10 @@ smtp_local: tls_privatekey = CONF_sysconf_dir/client.key tls_verify_certificates = CONF_ca_dir/ca.cert tls_require_ciphers = CONF_good_ciphers - tls_dh_min_bits = 3070 + tls_dh_min_bits = 2046 tls_tempfail_tryclear = false authenticated_sender = ${if def:authenticated_id \ - ${authenticated_id@CONF_master_domain} \ + {$authenticated_id@CONF_master_domain} \ fail} ## A standard transport for local delivery.