summaryrefslogtreecommitdiff
path: root/KEP-0010.txt
blob: ccdf430d7a17fbbca3c3af288636a0bf11e9f7e6 (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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
{{kep
 |number=10
 |ticketnumber=
 |title=Kolab SMTP Access Policy
 |author=Jeroen van Meeuwen
 |author_email=vanmeeuwen@kolabsys.com
 |status=draft
 |type=informational
 |creation_date=2011-07-01
 |obsoletes=
 |obsoleted_by=
 |related=
}}

== Abstract ==

The Kolab SMTP Access Policy rejects, allows or defers policy requests from the Postfix mail transfer agent using policy configuration and recipient's and sender's LDAP attributes. To offer guidance in the exact policy request handling, configuration and deployment, this KEP outlines how the Kolab SMTP Access Policy works.

The following access policies exist:

* [[#Sender_Access_Policy | Sender Access Policy]]
* [[#Recipient_Access_Policy | Recipient Access Policy]]

== Postfix Configuration ==

=== Restriction Checking Order ===

It is important to remember in which order the restrictions are checked in Postfix. Suffice it to say between 'sender' and 'recipient' restrictions, they are executed in reverse alphabetical order; The sender restrictions are applied before the recipient restrictions.

=== PERMIT, REJECT and OTHER ===

It is also important to remember how Postfix determines the result of a set of restrictions in combination with the exact position of the Kolab SMTP Access Policy, and the policy result used (configured for) the Kolab SMTP Access Policy. For more information on possible actions the Kolab SMTP Access Policy could return to Postfix, please see [http://www.postfix.org/access.5.html access(5)].

=== Caching ===

In order to reduce the load on LDAP, the Kolab SMTP Access Policy employs a form of volatile caching, storing a tuple of sender, recipient, sasl_username, sasl_sender, function, result and expire.

== Access Policies ==

A typical Postfix MTA listens on multiple ports;

# '''smtp''', 25/tcp,
# '''smtps''', 465/tcp,
# '''submission''', 587/tcp

Different rules apply to each of these services. For example, '''submission''' is often specifically enabled to force authentication to take place, and thus offers opportunity to thoroughly check the sender's authenticity and apply sender policies. Thinking of Kolab Delegate users for example, the sender's policy for the target 'sender' should be applied rather then the sender policy associated with the 'sasl_username'.

However, receiving incoming mail from the Internet over port 25, without exception, no authentication information is available. The sender can still be matched against recipient policies, but since the actual sender cannot be authenticated, complying with the sender policies becomes more difficult and behaves subtly differently compared to sender policies applied to '''submission'''.

== Timing, not 42, is Everything ==

For internal mail exchangers, with external mail exchangers doing content filtering, and additional, non-Kolab, groupware environments, may find themselves forced to using one single load-balanced IP address with little to no opportunity for verification of the sending host's IP address.

As such, in combining restrictions such as ''permit_mynetworks'' (in combination with which networks are listed), ''reject_unlisted_sender'' and the Kolab SMTP Access Policy, which check is performed after and before another is crucially important.

== Recipient Access Policy ==

A recipient access policy is used to determine whether a sender may send email to a recipient, using the recipient's policy (using the multi-valued '''kolabAllowSMTPSender''' attribute). That is to say, when a policy request comes in, the Kolab SMTP Access Policy searches for the recipient's LDAP object, and checks whether the recipient allows the sender to send to said recipient.

The recipient access policy is checked at two points in the transmission;

# When receiving '''incoming''' email, from unauthenticated mail exchangers,
# When receiving '''submitted''' email, from authenticated users.

=== Example Implementation ===

An example implementation would be as follows:

'''Example LDAP Objects'''

 dn: uid=john.doe,ou=People,dc=kolab,dc=org
 ...
 mail: john.doe@kolab.org
 kolabAllowSMTPSender: -recruiter@kolabsys.com
 ...
 
 dn: uid=jane.doe,ou=People,dc=kolab,dc=org
 ...
 mail: jane.doe@kolab.org
 kolabAllowSMTPSender: -john.doe@kolab.org
 ...

'''Example Postfix Configuration (main.cf)'''

 smtpd_recipient_restrictions = permit_mynetworks
     reject_unauth_pipelining
     reject_rbl_client zen.spamhaus.org
     reject_non_fqdn_recipient
     reject_invalid_helo_hostname
     reject_unknown_recipient_domain
     reject_unauth_destination
     check_policy_service unix:private/recipient_policy_incoming
     permit
 
 smtpd_sender_restrictions = permit_mynetworks
     check_policy_service unix:private/sender_policy_incoming
 
 submission_recipient_restrictions = check_policy_service unix:private/recipient_policy
     permit_sasl_authenticated
     reject
 
 submission_sender_restrictions = reject_non_fqdn_sender
     reject_unlisted_sender
     check_policy_service unix:private/sender_policy
     reject

'''Example Postfix Configuration (master.cf)'''

 recipient_policy unix    -   n   n   -       -   spawn
     user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-recipient
 
 recipient_policy_incoming unix - n n -       -   spawn
     user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-recipient --allow-unauthenticated

=== Example Process #1 ===

; '''Sender'''
: recruiter@kolabsys.com
; '''Recipient(s)'''
: john.doe@kolab.org, jane.doe@kolab.org;

# The email arrives at the internal (Kolab) mail exchanger
# The Postfix MTA is configured to check the recipient policy

{{note|Mail from External|Please note the aforementioned example is supposed to illustrate incoming email from an external source, through the Internet, and as such, the sender is (by definition) not authenticated. Naturally, exceptions to this rule apply, such as would be the case with Trusted Third Parties.}}

The Kolab SMTP Access Policy is executed provided with the following information:

 request=smtpd_access_policy
 protocol_state=RCPT
 protocol_name=ESMTP
 helo_name=ext-mx01.kolabsys.com
 queue_id=8045F2AB23
 sender=recruiter@kolabsys.com
 recipient=john.doe@kolab.org
 client_address=1.2.3.4
 client_name=ext-mx01.kolabsys.com
 instance=123.456.7
 sasl_method=
 sasl_username=
 sasl_sender=
 size=12345
 ''[empty line]''

{{note|Kolab SMTP Access Policy Executed per Recipient|The Kolab SMTP Access Policy is executed once for every recipient. If one of the access policies denies the request, a NDR should be returned [/needs-investigation].}}

Because this is the '''recipient''' checking, the Kolab SMTP Access Policy will now attempt to determine whether the LDAP object that has the '''recipient address''' associated with it also has an LDAP attribute '''kolabAllowSMTPSender'''.

If no such LDAP attribute exists for the recipient, the delivery is allowed.

If the LDAP attribute '''kolabAllowSMTPSender''' does exist, the Kolab SMTP Access Policy attempts to match the sender address (''recruiter@kolabsys.com'') to the value(s) of the LDAP attribute for the LDAP object (for John Doe, this is ''-recruiter@kolabsys.com'').

For matching policies, please see [[#Matching_Policies|the section on Matching Policies]].

In this example, suffice to say the mail from ''recruiter@kolabsys.com'' to ''john.doe@kolab.org'' is rejected, and the copy sent to ''jane.doe@kolab.org'' is accepted (subject to other smtpd_recipient_policies).

=== Example Process #2 ===

; '''Sender'''
: john.doe@kolab.org
; '''Recipient(s)'''
: jane.doe@kolab.org;

# The email is submitted to the Postfix MTA,
# The Postfix MTA is configured to check the recipient policy

{{note|Mail from Internal|Please note the aforementioned example is supposed to illustrate email being sent internally, and as such, the sender could be authenticated.}}

The Kolab SMTP Access Policy is executed provided with the following information:

 request=smtpd_access_policy
 protocol_state=RCPT
 protocol_name=ESMTP
 helo_name=webmail.kolab.org
 queue_id=8045F2AB23
 sender=john.doe@kolab.org
 recipient=jane.doe@kolab.org
 client_address=1.2.3.4
 client_name=webmail.kolab.org
 instance=123.456.7
 sasl_method=
 sasl_username=<does not matter>
 sasl_sender=
 size=12345
 ''[empty line]''

Because this is the '''recipient''' checking, the Kolab SMTP Access Policy will now attempt to determine whether the LDAP object that has the '''recipient address''' associated with it also has an LDAP attribute '''kolabAllowSMTPSender'''.

If no such LDAP attribute exists for the recipient, the delivery is allowed.

If the LDAP attribute '''kolabAllowSMTPSender''' does exist, the Kolab SMTP Access Policy attempts to match the sender address (''john.doe@kolab.org'') to the value(s) of the LDAP attribute for the LDAP object (for Jane Doe, this is ''-john.doe@kolab.org'').

For matching policies, please see [[#Matching_Policies|the section on Matching Policies]].

In this example, suffice to say the mail from ''john.doe@kolab.org'' to ''jane.doe@kolab.org'' is rejected.

== Sender Access Policy ==

The sender access policy is used to determine whether or not;

* an authenticated sender is allowed to use the envelope address used,
* the sender is allowed to send to these recipient(s) using the sender's policy.

{{important|Postfix Submission Daemon|For email to a domain name space for which the Postfix instance executing the policy is also a delivery destination (i.e. the domain name space for the recipient is among the domain name spaces listed in ''$relay_domains'' or ''$mydestination''), the sender access policy could immediately verify the recipient address(es) as well.}}

=== Example Implementation ===

An example implementation would be as follows:

'''Example LDAP Objects'''

 dn: uid=john.doe,ou=People,dc=kolab,dc=org
 ...
 mail: john.doe@kolab.org
 kolabAllowSMTPRecipient: -recruiter@kolabsys.com
 ...
 
 dn: uid=jane.doe,ou=People,dc=kolab,dc=org
 ...
 mail: jane.doe@kolab.org
 kolabAllowSMTPRecipient: -john.doe@kolab.org
 ...

'''Example Postfix Configuration (main.cf)'''

 smtpd_recipient_restrictions = permit_mynetworks
     reject_unauth_pipelining
     reject_rbl_client zen.spamhaus.org
     reject_non_fqdn_recipient
     reject_invalid_helo_hostname
     reject_unknown_recipient_domain
     reject_unauth_destination
     check_policy_service unix:private/recipient_policy_incoming
     permit
 
 smtpd_sender_restrictions = permit_mynetworks
     check_policy_service unix:private/sender_policy_incoming
 
 submission_recipient_restrictions = check_policy_service unix:private/recipient_policy
     permit_sasl_authenticated
     reject
 
 submission_sender_restrictions = reject_non_fqdn_sender
     reject_unlisted_sender
     check_policy_service unix:private/sender_policy
     reject

'''Example Postfix Configuration (master.cf)'''

 sender_policy    unix    -   n   n   -       -   spawn
     user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-sender
 
 sender_policy_incoming unix - n  n   -       -   spawn
     user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-sender --allow-unauthenticated

=== The Process ===

== Matching Policies ==

An example implementation of parsing the policies attributed to '''kolabAllowSMTPRecipient''' and '''kolabAllowSMTPSender''' attributes can be found [http://git.kolab.org/pykolab/tree/bin/kolab_smtp_access_policy.py?id=68422fedfe7d5db35bbb12a6ac765a7507fd6ff5#n133 here].

== References ==

{{Reflist}}