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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
|
/*++
/* NAME
/* smtpd 3h
/* SUMMARY
/* smtp server
/* SYNOPSIS
/* include "smtpd.h"
/* DESCRIPTION
/* .nf
/*
* System library.
*/
#include <sys/time.h>
#include <unistd.h>
/*
* Utility library.
*/
#include <vstream.h>
#include <vstring.h>
#include <argv.h>
#include <myaddrinfo.h>
/*
* Global library.
*/
#include <mail_stream.h>
/*
* Postfix TLS library.
*/
#include <tls.h>
/*
* Milter library.
*/
#include <milter.h>
/*
* Variables that keep track of conversation state. There is only one SMTP
* conversation at a time, so the state variables can be made global. And
* some of this has to be global anyway, so that the run-time error handler
* can clean up in case of a fatal error deep down in some library routine.
*/
typedef struct SMTPD_DEFER {
int active; /* is this active */
VSTRING *reason; /* reason for deferral */
VSTRING *dsn; /* DSN detail */
int code; /* SMTP reply code */
int class; /* error notification class */
} SMTPD_DEFER;
typedef struct {
int flags; /* XFORWARD server state */
char *name; /* name for access control */
char *addr; /* address for access control */
char *port; /* port for logging */
char *namaddr; /* name[address]:port */
char *rfc_addr; /* address for RFC 2821 */
char *protocol; /* email protocol */
char *helo_name; /* helo/ehlo parameter */
char *ident; /* local message identifier */
char *domain; /* rewrite context */
} SMTPD_XFORWARD_ATTR;
typedef struct {
int flags; /* see below */
int err; /* cleanup server/queue file errors */
VSTREAM *client; /* SMTP client handle */
VSTRING *buffer; /* SMTP client buffer */
VSTRING *addr_buf; /* internalized address buffer */
char *service; /* for event rate control */
struct timeval arrival_time; /* start of MAIL FROM transaction */
char *name; /* verified client hostname */
char *reverse_name; /* unverified client hostname */
char *addr; /* client host address string */
char *port; /* port for logging */
char *namaddr; /* name[address]:port */
char *rfc_addr; /* address for RFC 2821 */
int addr_family; /* address family */
char *dest_addr; /* Dovecot AUTH, Milter {daemon_addr} */
char *dest_port; /* Milter {daemon_port} */
struct sockaddr_storage sockaddr; /* binary client endpoint */
SOCKADDR_SIZE sockaddr_len; /* binary client endpoint */
struct sockaddr_storage dest_sockaddr; /* binary local endpoint */
SOCKADDR_SIZE dest_sockaddr_len; /* binary local endpoint */
int name_status; /* 2=ok 4=soft 5=hard 6=forged */
int reverse_name_status; /* 2=ok 4=soft 5=hard */
int conn_count; /* connections from this client */
int conn_rate; /* connection rate for this client */
int error_count; /* reset after DOT */
int error_mask; /* client errors */
int notify_mask; /* what to report to postmaster */
char *helo_name; /* client HELO/EHLO argument */
char *queue_id; /* from cleanup server/queue file */
VSTREAM *cleanup; /* cleanup server/queue file handle */
MAIL_STREAM *dest; /* another server/file handle */
int rcpt_count; /* number of accepted recipients */
char *access_denied; /* fixme */
ARGV *history; /* protocol transcript */
char *reason; /* cause of connection loss */
char *sender; /* sender address */
char *encoding; /* owned by mail_cmd() */
char *verp_delims; /* owned by mail_cmd() */
char *recipient; /* recipient address */
char *etrn_name; /* client ETRN argument */
char *protocol; /* SMTP or ESMTP */
char *where; /* protocol stage */
int recursion; /* Kellerspeicherpegelanzeiger */
off_t msg_size; /* MAIL FROM message size */
off_t act_size; /* END-OF-DATA message size */
int junk_cmds; /* counter */
int rcpt_overshoot; /* counter */
char *rewrite_context; /* address rewriting context */
/*
* SASL specific.
*/
#ifdef USE_SASL_AUTH
struct XSASL_SERVER *sasl_server;
VSTRING *sasl_reply;
char *sasl_mechanism_list;
char *sasl_method;
char *sasl_username;
char *sasl_sender;
#endif
/*
* Specific to smtpd access checks.
*/
int sender_rcptmap_checked; /* sender validated against maps */
int recipient_rcptmap_checked; /* recipient validated against maps */
int warn_if_reject; /* force reject into warning */
SMTPD_DEFER defer_if_reject; /* force reject into deferral */
SMTPD_DEFER defer_if_permit; /* force permit into deferral */
int defer_if_permit_client; /* force permit into warning */
int defer_if_permit_helo; /* force permit into warning */
int defer_if_permit_sender; /* force permit into warning */
int discard; /* discard message */
char *saved_filter; /* postponed filter action */
char *saved_redirect; /* postponed redirect action */
ARGV *saved_bcc; /* postponed bcc action */
int saved_flags; /* postponed hold/discard */
#ifdef DELAY_ACTION
int saved_delay; /* postponed deferred delay */
#endif
VSTRING *expand_buf; /* scratch space for $name expansion */
ARGV *prepend; /* prepended headers */
VSTRING *instance; /* policy query correlation */
int seqno; /* policy query correlation */
int ehlo_discard_mask; /* suppressed EHLO features */
char *dsn_envid; /* temporary MAIL FROM state */
int dsn_ret; /* temporary MAIL FROM state */
VSTRING *dsn_buf; /* scratch space for xtext expansion */
VSTRING *dsn_orcpt_buf; /* scratch space for ORCPT parsing */
/*
* Pass-through proxy client.
*/
struct SMTPD_PROXY *proxy;
char *proxy_mail; /* owned by mail_cmd() */
/*
* XFORWARD server state.
*/
SMTPD_XFORWARD_ATTR xforward; /* up-stream logging info */
/*
* TLS related state.
*/
#ifdef USE_TLS
#ifdef USE_TLSPROXY
VSTREAM *tlsproxy; /* tlsproxy(8) temp. handle */
#endif
TLS_SESS_STATE *tls_context; /* TLS session state */
#endif
/*
* Milter support.
*/
const char **milter_argv; /* SMTP command vector */
ssize_t milter_argc; /* SMTP command vector */
const char *milter_reject_text; /* input to call-back from Milter */
MILTERS *milters; /* Milter initialization status. */
/*
* EHLO temporary space.
*/
VSTRING *ehlo_buf;
ARGV *ehlo_argv;
/*
* BDAT processing state.
*/
#define SMTPD_BDAT_STAT_NONE 0 /* not processing BDAT */
#define SMTPD_BDAT_STAT_OK 1 /* accepting BDAT chunks */
#define SMTPD_BDAT_STAT_ERROR 2 /* skipping BDAT chunks */
int bdat_state; /* see above */
VSTREAM *bdat_get_stream; /* memory stream from BDAT chunk */
VSTRING *bdat_get_buffer; /* read from memory stream */
int bdat_prev_rec_type;
} SMTPD_STATE;
#define SMTPD_FLAG_HANGUP (1<<0) /* 421/521 disconnect */
#define SMTPD_FLAG_ILL_PIPELINING (1<<1) /* inappropriate pipelining */
#define SMTPD_FLAG_AUTH_USED (1<<2) /* don't reuse SASL state */
#define SMTPD_FLAG_SMTPUTF8 (1<<3) /* RFC 6531/2 transaction */
#define SMTPD_FLAG_NEED_MILTER_ABORT (1<<4) /* undo milter_mail_event() */
/* Security: don't reset SMTPD_FLAG_AUTH_USED. */
#define SMTPD_MASK_MAIL_KEEP \
~(SMTPD_FLAG_SMTPUTF8) /* Fix 20140706 */
#define SMTPD_STATE_XFORWARD_INIT (1<<0) /* xforward preset done */
#define SMTPD_STATE_XFORWARD_NAME (1<<1) /* client name received */
#define SMTPD_STATE_XFORWARD_ADDR (1<<2) /* client address received */
#define SMTPD_STATE_XFORWARD_PROTO (1<<3) /* protocol received */
#define SMTPD_STATE_XFORWARD_HELO (1<<4) /* client helo received */
#define SMTPD_STATE_XFORWARD_IDENT (1<<5) /* message identifier */
#define SMTPD_STATE_XFORWARD_DOMAIN (1<<6) /* address context */
#define SMTPD_STATE_XFORWARD_PORT (1<<7) /* client port received */
#define SMTPD_STATE_XFORWARD_CLIENT_MASK \
(SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR \
| SMTPD_STATE_XFORWARD_PROTO | SMTPD_STATE_XFORWARD_HELO \
| SMTPD_STATE_XFORWARD_PORT)
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *, const char *);
extern void smtpd_state_reset(SMTPD_STATE *);
/*
* Conversation stages. This is used for "lost connection after XXX"
* diagnostics.
*/
#define SMTPD_AFTER_CONNECT "CONNECT"
#define SMTPD_AFTER_DATA "DATA content"
#define SMTPD_AFTER_BDAT "BDAT content"
#define SMTPD_AFTER_EOM "END-OF-MESSAGE"
/*
* Other stages. These are sometimes used to change the way information is
* logged or what information will be available for access control.
*/
#define SMTPD_CMD_HELO "HELO"
#define SMTPD_CMD_EHLO "EHLO"
#define SMTPD_CMD_STARTTLS "STARTTLS"
#define SMTPD_CMD_AUTH "AUTH"
#define SMTPD_CMD_MAIL "MAIL"
#define SMTPD_CMD_RCPT "RCPT"
#define SMTPD_CMD_DATA "DATA"
#define SMTPD_CMD_BDAT "BDAT"
#define SMTPD_CMD_EOD SMTPD_AFTER_EOM /* XXX Was: END-OF-DATA */
#define SMTPD_CMD_RSET "RSET"
#define SMTPD_CMD_NOOP "NOOP"
#define SMTPD_CMD_VRFY "VRFY"
#define SMTPD_CMD_ETRN "ETRN"
#define SMTPD_CMD_QUIT "QUIT"
#define SMTPD_CMD_XCLIENT "XCLIENT"
#define SMTPD_CMD_XFORWARD "XFORWARD"
#define SMTPD_CMD_UNKNOWN "UNKNOWN"
/*
* Representation of unknown and non-existent client information. Throughout
* Postfix, we use the "unknown" string value for unknown client information
* (e.g., unknown remote client hostname), and we use the empty string, null
* pointer or "no queue file record" for non-existent client information
* (e.g., no HELO command, or local submission).
*
* Inside the SMTP server, unknown real client attributes are represented by
* the string "unknown", and non-existent HELO is represented as a null
* pointer. The SMTP server uses this same representation internally for
* forwarded client attributes; the XFORWARD syntax makes no distinction
* between unknown (remote submission) and non-existent (local submission).
*
* The SMTP client sends forwarded client attributes only when upstream client
* attributes exist (i.e. remote submission). Thus, local submissions will
* appear to come from an SMTP-based content filter, which is acceptable.
*
* Known/unknown client attribute values use the SMTP server's internal
* representation in queue files, in queue manager delivery requests, and in
* delivery agent $name expansions.
*
* Non-existent attribute values are never present in queue files. Non-existent
* information is represented as empty strings in queue manager delivery
* requests and in delivery agent $name expansions.
*/
#define CLIENT_ATTR_UNKNOWN "unknown"
#define CLIENT_NAME_UNKNOWN CLIENT_ATTR_UNKNOWN
#define CLIENT_ADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
#define CLIENT_PORT_UNKNOWN CLIENT_ATTR_UNKNOWN
#define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
#define CLIENT_HELO_UNKNOWN 0
#define CLIENT_PROTO_UNKNOWN CLIENT_ATTR_UNKNOWN
#define CLIENT_IDENT_UNKNOWN 0
#define CLIENT_DOMAIN_UNKNOWN 0
#define CLIENT_LOGIN_UNKNOWN 0
#define SERVER_ATTR_UNKNOWN "unknown"
#define SERVER_ADDR_UNKNOWN SERVER_ATTR_UNKNOWN
#define SERVER_PORT_UNKNOWN SERVER_ATTR_UNKNOWN
#define IS_AVAIL_CLIENT_ATTR(v) ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN))
#define IS_AVAIL_CLIENT_NAME(v) IS_AVAIL_CLIENT_ATTR(v)
#define IS_AVAIL_CLIENT_ADDR(v) IS_AVAIL_CLIENT_ATTR(v)
#define IS_AVAIL_CLIENT_PORT(v) IS_AVAIL_CLIENT_ATTR(v)
#define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v)
#define IS_AVAIL_CLIENT_HELO(v) ((v) != 0)
#define IS_AVAIL_CLIENT_PROTO(v) IS_AVAIL_CLIENT_ATTR(v)
#define IS_AVAIL_CLIENT_IDENT(v) ((v) != 0)
#define IS_AVAIL_CLIENT_DOMAIN(v) ((v) != 0)
/*
* If running in stand-alone mode, do not try to talk to Postfix daemons but
* write to queue file instead.
*/
#define SMTPD_STAND_ALONE_STREAM(stream) \
(stream == VSTREAM_IN && getuid() != var_owner_uid)
#define SMTPD_STAND_ALONE(state) \
(state->client == VSTREAM_IN && getuid() != var_owner_uid)
/*
* If running as proxy front-end, disable actions that require communication
* with the cleanup server.
*/
#define USE_SMTPD_PROXY(state) \
(SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt)
/*
* Are we in a MAIL transaction?
*/
#define SMTPD_IN_MAIL_TRANSACTION(state) ((state)->sender != 0)
/*
* Are we processing BDAT requests?
*/
#define SMTPD_PROCESSING_BDAT(state) \
((state)->bdat_state != SMTPD_BDAT_STAT_NONE)
/*
* SMTPD peer information lookup.
*/
extern void smtpd_peer_init(SMTPD_STATE *state);
extern void smtpd_peer_reset(SMTPD_STATE *state);
extern void smtpd_peer_from_default(SMTPD_STATE *);
extern int smtpd_peer_from_haproxy(SMTPD_STATE *);
#define SMTPD_PEER_CODE_OK 2
#define SMTPD_PEER_CODE_TEMP 4
#define SMTPD_PEER_CODE_PERM 5
#define SMTPD_PEER_CODE_FORGED 6
/*
* Construct name[addr] or name[addr]:port as appropriate
*/
#define SMTPD_BUILD_NAMADDRPORT(name, addr, port) \
concatenate((name), "[", (addr), "]", \
var_smtpd_client_port_log ? ":" : (char *) 0, \
(port), (char *) 0)
/*
* Don't mix information from the current SMTP session with forwarded
* information from an up-stream session.
*/
#define HAVE_FORWARDED_CLIENT_ATTR(s) \
((s)->xforward.flags & SMTPD_STATE_XFORWARD_CLIENT_MASK)
#define FORWARD_CLIENT_ATTR(s, a) \
(HAVE_FORWARDED_CLIENT_ATTR(s) ? \
(s)->xforward.a : (s)->a)
#define FORWARD_ADDR(s) FORWARD_CLIENT_ATTR((s), rfc_addr)
#define FORWARD_NAME(s) FORWARD_CLIENT_ATTR((s), name)
#define FORWARD_NAMADDR(s) FORWARD_CLIENT_ATTR((s), namaddr)
#define FORWARD_PROTO(s) FORWARD_CLIENT_ATTR((s), protocol)
#define FORWARD_HELO(s) FORWARD_CLIENT_ATTR((s), helo_name)
#define FORWARD_PORT(s) FORWARD_CLIENT_ATTR((s), port)
/*
* Mixing is not a problem with forwarded local message identifiers.
*/
#define HAVE_FORWARDED_IDENT(s) \
((s)->xforward.ident != 0)
#define FORWARD_IDENT(s) \
(HAVE_FORWARDED_IDENT(s) ? \
(s)->xforward.ident : (s)->queue_id)
/*
* Mixing is not a problem with forwarded address rewriting contexts.
*/
#define FORWARD_DOMAIN(s) \
(((s)->xforward.flags & SMTPD_STATE_XFORWARD_DOMAIN) ? \
(s)->xforward.domain : (s)->rewrite_context)
extern void smtpd_xforward_init(SMTPD_STATE *);
extern void smtpd_xforward_preset(SMTPD_STATE *);
extern void smtpd_xforward_reset(SMTPD_STATE *);
/*
* Transparency: before mail is queued, do we check for unknown recipients,
* do we allow address mapping, automatic bcc, header/body checks?
*/
extern int smtpd_input_transp_mask;
/*
* More Milter support.
*/
extern MILTERS *smtpd_milters;
/*
* Message size multiplication factor for free space check.
*/
extern double smtpd_space_multf;
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*
/* TLS support originally by:
/* Lutz Jaenicke
/* BTU Cottbus
/* Allgemeine Elektrotechnik
/* Universitaetsplatz 3-4
/* D-03044 Cottbus, Germany
/*--*/
|