summaryrefslogtreecommitdiff
path: root/conf.d/020_acl.conf
blob: a909910be1ad6b35b4b186cd716d4001caeac6a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
######################################################################
#                       ACL CONFIGURATION                            #
#         Specifies access control lists for incoming SMTP mail      #
######################################################################

begin acl


######################
# GENERAL CHECK ACLs #
######################

# Ensures that the remote host has introduced itself.
acl_check_rcpt_introduction:

  # Insist that a HELO/EHLO was accepted.
  require  condition     = ${if def:sender_helo_name}
           set acl_m_msg = HELO/EHLO command required.

  accept


# Syntactic validation of fields.
acl_check_rcpt_syntax:

  # Deny if the local parts is malformed.
  deny     local_parts   = ^[.] : ^.*[@%!/|]
           set acl_m_msg = Invalid local part.

  accept


# Checks the link between a given mail alias and a given user.
# $acl_arg1: alias to check
# $acl_arg2: user
acl_check_alias:

  # Accept if the alias belongs to the user.
  accept   condition     = ${lookup{$acl_arg1}lsearch{ALIASMAP} \
                             {${if eq{$value}{$acl_arg2} {yes}{no}}} {no}}

  # Deny otherwise
  deny


# Checks if the host is allowed to send messages according to the local whitelist, DNS blocklists and SPF policy.
acl_check_rcpt_host_policy:

  # Accept all messages from trusted hosts and relays.
  accept   hosts         = +redirected_from_hosts

  # Deny messages from hosts known to be bad.
  deny     dnslists      = sbl-xbl.spamhaus.org : bl.spamcop.net
           set acl_m_msg = Rejected: $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text

  # Accept if the host is an authorized sender according to the SPF policy for the domain (SPF pass).
  accept   set acl_m_spf = ${run{/usr/bin/spfquery.mail-spf-perl \
                             --ip ${quote:$sender_host_address} \
                             --identity ${if def:sender_address_domain \
                               {--scope mfrom --identity ${quote:$sender_address}} \
                               {--scope helo --identity ${quote:$sender_helo_name}}}}}
           condition     = ${if eq {$acl_m_spf}{0}{yes}{no}}

  # Deny if the host is explicitely not an authorized sender according to the SPF policy for the domain (SPF fail).
  deny     condition     = ${if eq {$acl_m_spf}{1}{yes}{no}}
           set acl_m_msg = [SPF] $sender_host_address is not allowed to send mail from \
                           ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}}. \
                           Please see http://www.openspf.org/Why?scope=${if def:sender_address_domain \
                             {mfrom}{helo}};identity=${if def:sender_address_domain \
                             {$sender_address}{$sender_helo_name}};ip=$sender_host_address

  # Deny messages from hosts listed as non-MTA in the PBL, for which SPF couldn't determine a policy.
  deny     dnslists      = pbl.spamhaus.org
           set acl_m_msg = Rejected: $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text

  # Accept otherwise
  accept


#########################
# MUA ACLs (submission) #
#########################

acl_mua_rcpt:

  require  encrypted     = *
           message       = Encryption required.

  require  acl           = acl_check_rcpt_introduction
           message       = Courtesy protocol violation: $acl_m_msg

  require  authenticated = *
           control       = submission
           control       = dkim_disable_verify
           message       = Authentication required.

  require  acl           = acl_check_rcpt_syntax
           message       = Syntactic validation failed: $acl_m_msg

  require  verify        = sender
           message       = Sender verification failed.

  accept


acl_mua_mail:

  require  acl           = acl_check_alias $sender_address $authenticated_id
           message       = Envelope address mismatch: $authenticated_id is not authorized to use $sender_address.

  accept


acl_mua_data:

  require  acl           = acl_check_alias ${address:$h_from:} $authenticated_id
           message       = Header address mismatch: $authenticated_id is not authorized to use ${address:$h_from:}.

  accept


############
# MTA ACLs #
############

acl_mta_rcpt:

  require  acl           = acl_check_rcpt_introduction
           message       = Courtesy protocol violation: $acl_m_msg

  require  acl           = acl_check_rcpt_host_policy
           message       = $acl_m_msg

  require  acl           = acl_check_rcpt_syntax
           message       = Syntactic validation failed: $acl_m_msg

  require  verify        = sender
           message       = Sender verification failed.

  require  domains       = +local_domains : +relay_to_domains
           message       = Unhandled destination.

  require  verify        = recipient
           message       = Recipient verification failed.

  accept


acl_mta_data:

  # Deny if the message contains an overlong line. Per the standards we should never receive one such via SMTP.
  deny     condition     = ${if > {$max_received_linelength}{998}}
           set acl_m_msg = Maximum allowed line length is 998 octets, got $max_received_linelength.

  accept


# Checks the validity of each signatures in the message, and the presence of a required signature for the sender domain.
# Global var to enable mandatory signature check: dkim_verify_signers = $sender_address_domain:$dkim_signers
acl_mta_dkim:

  # Deny messages with invalid signatures.
  deny     dkim_status   = fail
           message       = [DKIM] invalid signature ($dkim_verify_reason).

  # Deny messages with no signature for domains which are explicitely requiring one.
  deny     dkim_status   = none
           condition     = ${if match \
                             {${run{/usr/bin/dig +short TXT ${quote:_domainkey.$sender_host_address}}}}{/o=-/} \
                             {yes}{no}}
           message       = [DKIM] required signature is missing.

  accept