summaryrefslogtreecommitdiff
path: root/conf.d/020_acl.conf
blob: 1ff3d1e32f980a96337f52bf7cd0edaf7bb947f3 (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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
######################################################################
#                       ACL CONFIGURATION                            #
#         Specifies access control lists for incoming SMTP mail      #
######################################################################

begin acl


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

acl_check_mail_introduction:
  require  condition     = ${if def:sender_helo_name}
           set acl_m_msg = HELO/EHLO command required.

  require  verify        = reverse_host_lookup/defer_ok
           set acl_m_msg = HELO/EHLO lookup yielded mismatch.

  accept


acl_check_rcpt_syntax:
  deny     local_parts   = ^[.] : ^.*[@%!/|]
           set acl_m_msg = Invalid local part.

  accept


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

# Checks the link between a given mail alias and a given user.
# $acl_arg1: alias to check
# $acl_arg2: user
acl_check_alias:
  require  condition     = ${lookup{$acl_arg1}lsearch{ALIASMAP} {${if eq{$value}{$acl_arg2} {yes}{no}}} {no}}

  accept


acl_mua_mail:
  require  acl           = acl_check_mail_introduction
           message       = Courtesy protocol violation: $acl_m_msg

  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_rcpt:
  require  encrypted     = *
           message       = Encrypted session required for message submission.

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

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

  require  verify        = sender
           message       = Sender verification failed.

  accept


acl_mua_data:
  require  verify        = header_names_ascii
           message       = Invalid character in header name.

  require  verify        = header_syntax
           message       = Syntax error in header.

  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_connect:
  accept   hosts         = +trusted_relay_hosts

  # Deny messages from hosts known to be bad.
  drop     dnslists      = sbl-xbl.spamhaus.org : bl.spamcop.net
           message       = [RBL] $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text

  accept


acl_mta_mail:
  require  acl           = acl_check_mail_introduction
           message       = Courtesy protocol violation: $acl_m_msg

  accept   hosts         = +trusted_relay_hosts

  defer    spf           = temperror
           message       = [SPF] Could not proceed through validation. Please try again later.

  drop     spf           = permerror
           message       = [SPF] Syntax error in the SPF record of \
                           ${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

  drop     spf           = fail
           message       = [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 end-user IP address ranges listed in the PBL, for which SPF didn't explicitly pass.
  # It is safe to assume that legitimate home-hosted MTAs have an associated SPF record, that zombie machines would lack.
  drop     !spf          = pass
           dnslists      = pbl.spamhaus.org
           message       = [RBL] $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text

  accept


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

  require  verify        = sender
           message       = Sender verification failed.

  accept   hosts         = +relay_from_hosts

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

  require  verify        = recipient
           message       = Recipient verification failed.

  accept


.ifdef SPAMD_ADDRESS
SCAN_SPAM = yes
.else
SCAN_SPAM = no
.endif

acl_mta_data:
  deny     condition     = ${if > {$max_received_linelength}{998}}
           set acl_m_msg = Maximum allowed line length is 998 octets, got $max_received_linelength.

  require  verify        = header_syntax
           message       = Syntax error in header.

  warn     condition     = SCAN_SPAM
           spam          = nobody:true/defer_ok
           remove_header = x-spam-bar : x-spam-score : x-spam-report : x-spam-status
           add_header    = X-Spam-Score: $spam_score ($spam_bar)
           add_header    = X-Spam-Report: $spam_report
           add_header    = X-Spam-Status: ${if eq{$spam_action}{reject} {Yes}{No}}

  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:
  defer    dkim_status   = invalid
           message       = [DKIM] Could not proceed through validation ($dkim_verify_reason). \
                           Please try again later.

  deny     dkim_status   = fail
           message       = [DKIM] invalid signature ($dkim_verify_reason).

  deny     dkim_status   = none
           set acl_m_ddk = ${run{DIG_QUERY_COMMAND +short TXT ${quote:_domainkey.$sender_host_address}}}
           condition     = ${if match {$acl_m_ddk}{/o=-/} {yes}{no}}
           message       = [DKIM] required signature for $sender_host_address is missing.

  accept