1 /*        $NetBSD: smtpd.h,v 1.6 2025/02/25 19:15:50 christos Exp $   */
2 
3 /*++
4 /* NAME
5 /*        smtpd 3h
6 /* SUMMARY
7 /*        smtp server
8 /* SYNOPSIS
9 /*        include "smtpd.h"
10 /* DESCRIPTION
11 /* .nf
12 
13  /*
14   * System library.
15   */
16 #include <sys/time.h>
17 #include <unistd.h>
18 
19  /*
20   * Utility library.
21   */
22 #include <vstream.h>
23 #include <vstring.h>
24 #include <argv.h>
25 #include <myaddrinfo.h>
26 
27  /*
28   * Global library.
29   */
30 #include <mail_stream.h>
31 
32  /*
33   * Postfix TLS library.
34   */
35 #include <tls.h>
36 
37  /*
38   * Milter library.
39   */
40 #include <milter.h>
41 
42  /*
43   * Variables that keep track of conversation state. There is only one SMTP
44   * conversation at a time, so the state variables can be made global. And
45   * some of this has to be global anyway, so that the run-time error handler
46   * can clean up in case of a fatal error deep down in some library routine.
47   */
48 typedef struct SMTPD_DEFER {
49     int     active;                     /* is this active */
50     VSTRING *reason;                              /* reason for deferral */
51     VSTRING *dsn;                       /* DSN detail */
52     int     code;                       /* SMTP reply code */
53     int     class;                      /* error notification class */
54 } SMTPD_DEFER;
55 
56 typedef struct {
57     int     flags;                      /* XFORWARD server state */
58     char   *name;                       /* name for access control */
59     char   *addr;                       /* address for access control */
60     char   *port;                       /* port for logging */
61     char   *namaddr;                              /* name[address]:port */
62     char   *rfc_addr;                             /* address for RFC 2821 */
63     char   *protocol;                             /* email protocol */
64     char   *helo_name;                            /* helo/ehlo parameter */
65     char   *ident;                      /* local message identifier */
66     char   *domain;                     /* rewrite context */
67 } SMTPD_XFORWARD_ATTR;
68 
69 typedef struct {
70     int     flags;                      /* see below */
71     int     err;                        /* cleanup server/queue file errors */
72     VSTREAM *client;                              /* SMTP client handle */
73     VSTRING *buffer;                              /* SMTP client buffer */
74     VSTRING *addr_buf;                            /* internalized address buffer */
75     char   *service;                              /* for event rate control */
76     struct timeval arrival_time;        /* start of MAIL FROM transaction */
77     char   *name;                       /* verified client hostname */
78     char   *reverse_name;               /* unverified client hostname */
79     char   *addr;                       /* client host address string */
80     char   *port;                       /* port for logging */
81     char   *namaddr;                              /* name[address]:port */
82     char   *anvil_range;                /* client address or network/length */
83     char   *rfc_addr;                             /* address for RFC 2821 */
84     int     addr_family;                /* address family */
85     char   *dest_addr;                            /* Dovecot AUTH, Milter {daemon_addr} */
86     char   *dest_port;                            /* Milter {daemon_port} */
87     struct sockaddr_storage sockaddr;   /* binary client endpoint */
88     SOCKADDR_SIZE sockaddr_len;                   /* binary client endpoint */
89     struct sockaddr_storage dest_sockaddr;        /* binary local endpoint */
90     SOCKADDR_SIZE dest_sockaddr_len;    /* binary local endpoint */
91     int     name_status;                /* 2=ok 4=soft 5=hard 6=forged */
92     int     reverse_name_status;        /* 2=ok 4=soft 5=hard */
93     int     conn_count;                           /* connections from this client */
94     int     conn_rate;                            /* connection rate for this client */
95     int     error_count;                /* reset after DOT */
96     int     error_mask;                           /* client errors */
97     int     notify_mask;                /* what to report to postmaster */
98     char   *helo_name;                            /* client HELO/EHLO argument */
99     char   *queue_id;                             /* from cleanup server/queue file */
100     VSTREAM *cleanup;                             /* cleanup server/queue file handle */
101     MAIL_STREAM *dest;                            /* another server/file handle */
102     int     rcpt_count;                           /* number of accepted recipients */
103     char   *access_denied;              /* fixme */
104     ARGV   *history;                              /* protocol transcript */
105     char   *reason;                     /* cause of connection loss */
106     char   *sender;                     /* sender address */
107     char   *encoding;                             /* owned by mail_cmd() */
108     char   *verp_delims;                /* owned by mail_cmd() */
109     char   *recipient;                            /* recipient address */
110     char   *etrn_name;                            /* client ETRN argument */
111     char   *protocol;                             /* SMTP or ESMTP */
112     char   *where;                      /* protocol stage */
113     int     recursion;                            /* Kellerspeicherpegelanzeiger */
114     off_t   msg_size;                             /* MAIL FROM message size */
115     off_t   act_size;                             /* END-OF-DATA message size */
116     int     junk_cmds;                            /* counter */
117     int     rcpt_overshoot;             /* counter */
118     char   *rewrite_context;            /* address rewriting context */
119     int     notes;                      /* notes aggregator */
120 
121     /*
122      * SASL specific.
123      */
124 #ifdef USE_SASL_AUTH
125     struct XSASL_SERVER *sasl_server;
126     VSTRING *sasl_reply;
127     char   *sasl_mechanism_list;
128     char   *sasl_method;
129     char   *sasl_username;
130     char   *sasl_sender;
131 #endif
132 
133     /*
134      * Specific to smtpd access checks.
135      */
136     int     sender_rcptmap_checked;     /* sender validated against maps */
137     int     recipient_rcptmap_checked;  /* recipient validated against maps */
138     int     warn_if_reject;             /* force reject into warning */
139     SMTPD_DEFER defer_if_reject;        /* force reject into deferral */
140     SMTPD_DEFER defer_if_permit;        /* force permit into deferral */
141     int     defer_if_permit_client;     /* force permit into warning */
142     int     defer_if_permit_helo;       /* force permit into warning */
143     int     defer_if_permit_sender;     /* force permit into warning */
144     int     discard;                              /* discard message */
145     char   *saved_filter;               /* postponed filter action */
146     char   *saved_redirect;             /* postponed redirect action */
147     ARGV   *saved_bcc;                            /* postponed bcc action */
148     int     saved_flags;                /* postponed hold/discard */
149 #ifdef DELAY_ACTION
150     int     saved_delay;                /* postponed deferred delay */
151 #endif
152     VSTRING *expand_buf;                /* scratch space for $name expansion */
153     ARGV   *prepend;                              /* prepended headers */
154     VSTRING *instance;                            /* policy query correlation */
155     int     seqno;                      /* policy query correlation */
156     int     ehlo_discard_mask;                    /* suppressed EHLO features */
157     char   *dsn_envid;                            /* temporary MAIL FROM state */
158     int     dsn_ret;                              /* temporary MAIL FROM state */
159     VSTRING *dsn_buf;                             /* scratch space for xtext expansion */
160     VSTRING *dsn_orcpt_buf;             /* scratch space for ORCPT parsing */
161 
162     /*
163      * Pass-through proxy client.
164      */
165     struct SMTPD_PROXY *proxy;
166     char   *proxy_mail;                           /* owned by mail_cmd() */
167 
168     /*
169      * XFORWARD server state.
170      */
171     SMTPD_XFORWARD_ATTR xforward;       /* up-stream logging info */
172 
173     /*
174      * TLS related state.
175      */
176 #ifdef USE_TLS
177 #ifdef USE_TLSPROXY
178     VSTREAM *tlsproxy;                            /* tlsproxy(8) temp. handle */
179 #endif
180     TLS_SESS_STATE *tls_context;        /* TLS session state */
181 #endif
182 
183     /*
184      * Milter support.
185      */
186     const char **milter_argv;           /* SMTP command vector */
187     ssize_t milter_argc;                /* SMTP command vector */
188     const char *milter_reject_text;     /* input to call-back from Milter */
189     MILTERS *milters;                             /* Milter initialization status. */
190 
191     /*
192      * EHLO temporary space.
193      */
194     VSTRING *ehlo_buf;
195     ARGV   *ehlo_argv;
196 
197     /*
198      * BDAT processing state.
199      */
200 #define SMTPD_BDAT_STAT_NONE  0         /* not processing BDAT */
201 #define SMTPD_BDAT_STAT_OK    1         /* accepting BDAT chunks */
202 #define SMTPD_BDAT_STAT_ERROR 2         /* skipping BDAT chunks */
203     int     bdat_state;                           /* see above */
204     VSTREAM *bdat_get_stream;           /* memory stream from BDAT chunk */
205     VSTRING *bdat_get_buffer;           /* read from memory stream */
206     int     bdat_prev_rec_type;
207 } SMTPD_STATE;
208 
209 #define SMTPD_FLAG_HANGUP        (1<<0) /* 421/521 disconnect */
210 #define SMTPD_FLAG_ILL_PIPELINING  (1<<1)         /* inappropriate pipelining */
211 #define SMTPD_FLAG_AUTH_USED     (1<<2) /* don't reuse SASL state */
212 #define SMTPD_FLAG_SMTPUTF8      (1<<3) /* RFC 6531/2 transaction */
213 #define SMTPD_FLAG_NEED_MILTER_ABORT (1<<4)       /* undo milter_mail_event() */
214 
215 #define SMTPD_NOTE_BARE_LF       (1<<0) /* saw at least one bare LF */
216 
217  /* Security: don't reset SMTPD_FLAG_AUTH_USED. */
218 #define SMTPD_MASK_MAIL_KEEP \
219               ~(SMTPD_FLAG_SMTPUTF8)    /* Fix 20140706 */
220 
221 #define SMTPD_STATE_XFORWARD_INIT  (1<<0)         /* xforward preset done */
222 #define SMTPD_STATE_XFORWARD_NAME  (1<<1)         /* client name received */
223 #define SMTPD_STATE_XFORWARD_ADDR  (1<<2)         /* client address received */
224 #define SMTPD_STATE_XFORWARD_PROTO (1<<3)         /* protocol received */
225 #define SMTPD_STATE_XFORWARD_HELO  (1<<4)         /* client helo received */
226 #define SMTPD_STATE_XFORWARD_IDENT (1<<5)         /* message identifier */
227 #define SMTPD_STATE_XFORWARD_DOMAIN (1<<6)        /* address context */
228 #define SMTPD_STATE_XFORWARD_PORT  (1<<7)         /* client port received */
229 
230 #define SMTPD_STATE_XFORWARD_CLIENT_MASK \
231           (SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR \
232           | SMTPD_STATE_XFORWARD_PROTO | SMTPD_STATE_XFORWARD_HELO \
233           | SMTPD_STATE_XFORWARD_PORT)
234 
235 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *, const char *);
236 extern void smtpd_state_reset(SMTPD_STATE *);
237 
238  /*
239   * Conversation stages.  This is used for "lost connection after XXX"
240   * diagnostics.
241   */
242 #define SMTPD_AFTER_CONNECT   "CONNECT"
243 #define SMTPD_AFTER_DATA      "DATA content"
244 #define SMTPD_AFTER_BDAT      "BDAT content"
245 #define SMTPD_AFTER_EOM                 "END-OF-MESSAGE"
246 
247  /*
248   * Other stages. These are sometimes used to change the way information is
249   * logged or what information will be available for access control.
250   */
251 #define SMTPD_CMD_HELO                  "HELO"
252 #define SMTPD_CMD_EHLO                  "EHLO"
253 #define SMTPD_CMD_STARTTLS    "STARTTLS"
254 #define SMTPD_CMD_AUTH                  "AUTH"
255 #define SMTPD_CMD_MAIL                  "MAIL"
256 #define SMTPD_CMD_RCPT                  "RCPT"
257 #define SMTPD_CMD_DATA                  "DATA"
258 #define SMTPD_CMD_BDAT                  "BDAT"
259 #define SMTPD_CMD_EOD                   SMTPD_AFTER_EOM     /* XXX Was: END-OF-DATA */
260 #define SMTPD_CMD_RSET                  "RSET"
261 #define SMTPD_CMD_NOOP                  "NOOP"
262 #define SMTPD_CMD_VRFY                  "VRFY"
263 #define SMTPD_CMD_ETRN                  "ETRN"
264 #define SMTPD_CMD_QUIT                  "QUIT"
265 #define SMTPD_CMD_XCLIENT     "XCLIENT"
266 #define SMTPD_CMD_XFORWARD    "XFORWARD"
267 #define SMTPD_CMD_UNKNOWN     "UNKNOWN"
268 #define SMTPD_CMD_HELP                  "HELP"
269 
270  /*
271   * Representation of unknown and non-existent client information. Throughout
272   * Postfix, we use the "unknown" string value for unknown client information
273   * (e.g., unknown remote client hostname), and we use the empty string, null
274   * pointer or "no queue file record" for non-existent client information
275   * (e.g., no HELO command, or local submission).
276   *
277   * Inside the SMTP server, unknown real client attributes are represented by
278   * the string "unknown", and non-existent HELO is represented as a null
279   * pointer. The SMTP server uses this same representation internally for
280   * forwarded client attributes; the XFORWARD syntax makes no distinction
281   * between unknown (remote submission) and non-existent (local submission).
282   *
283   * The SMTP client sends forwarded client attributes only when upstream client
284   * attributes exist (i.e. remote submission). Thus, local submissions will
285   * appear to come from an SMTP-based content filter, which is acceptable.
286   *
287   * Known/unknown client attribute values use the SMTP server's internal
288   * representation in queue files, in queue manager delivery requests, and in
289   * delivery agent $name expansions.
290   *
291   * Non-existent attribute values are never present in queue files. Non-existent
292   * information is represented as empty strings in queue manager delivery
293   * requests and in delivery agent $name expansions.
294   */
295 #define CLIENT_ATTR_UNKNOWN   "unknown"
296 
297 #define CLIENT_NAME_UNKNOWN   CLIENT_ATTR_UNKNOWN
298 #define CLIENT_ADDR_UNKNOWN   CLIENT_ATTR_UNKNOWN
299 #define CLIENT_PORT_UNKNOWN   CLIENT_ATTR_UNKNOWN
300 #define CLIENT_NAMADDR_UNKNOWN          CLIENT_ATTR_UNKNOWN
301 #define CLIENT_HELO_UNKNOWN   0
302 #define CLIENT_PROTO_UNKNOWN  CLIENT_ATTR_UNKNOWN
303 #define CLIENT_IDENT_UNKNOWN  0
304 #define CLIENT_DOMAIN_UNKNOWN 0
305 #define CLIENT_LOGIN_UNKNOWN  0
306 
307 #define SERVER_ATTR_UNKNOWN   "unknown"
308 
309 #define SERVER_ADDR_UNKNOWN   SERVER_ATTR_UNKNOWN
310 #define SERVER_PORT_UNKNOWN   SERVER_ATTR_UNKNOWN
311 
312 #define IS_AVAIL_CLIENT_ATTR(v)         ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN))
313 
314 #define IS_AVAIL_CLIENT_NAME(v)         IS_AVAIL_CLIENT_ATTR(v)
315 #define IS_AVAIL_CLIENT_ADDR(v)         IS_AVAIL_CLIENT_ATTR(v)
316 #define IS_AVAIL_CLIENT_PORT(v)         IS_AVAIL_CLIENT_ATTR(v)
317 #define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v)
318 #define IS_AVAIL_CLIENT_HELO(v)         ((v) != 0)
319 #define IS_AVAIL_CLIENT_PROTO(v) IS_AVAIL_CLIENT_ATTR(v)
320 #define IS_AVAIL_CLIENT_IDENT(v) ((v) != 0)
321 #define IS_AVAIL_CLIENT_DOMAIN(v) ((v) != 0)
322 
323  /*
324   * If running in stand-alone mode, do not try to talk to Postfix daemons but
325   * write to queue file instead.
326   */
327 #define SMTPD_STAND_ALONE_STREAM(stream) \
328           (stream == VSTREAM_IN && getuid() != var_owner_uid)
329 
330 #define SMTPD_STAND_ALONE(state) \
331           (state->client == VSTREAM_IN && getuid() != var_owner_uid)
332 
333  /*
334   * If running as proxy front-end, disable actions that require communication
335   * with the cleanup server.
336   */
337 #define USE_SMTPD_PROXY(state) \
338           (SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt)
339 
340  /*
341   * Are we in a MAIL transaction?
342   */
343 #define SMTPD_IN_MAIL_TRANSACTION(state) ((state)->sender != 0)
344 
345  /*
346   * Are we processing BDAT requests?
347   */
348 #define SMTPD_PROCESSING_BDAT(state) \
349           ((state)->bdat_state != SMTPD_BDAT_STAT_NONE)
350 
351  /*
352   * SMTPD peer information lookup.
353   */
354 extern void smtpd_peer_init(SMTPD_STATE *state);
355 extern void smtpd_peer_reset(SMTPD_STATE *state);
356 extern void smtpd_peer_from_default(SMTPD_STATE *);
357 extern int smtpd_peer_from_haproxy(SMTPD_STATE *);
358 
359 #define   SMTPD_PEER_CODE_OK  2
360 #define SMTPD_PEER_CODE_TEMP  4
361 #define SMTPD_PEER_CODE_PERM  5
362 #define SMTPD_PEER_CODE_FORGED          6
363 
364  /*
365   * Construct name[addr] or name[addr]:port as appropriate
366   */
367 #define SMTPD_BUILD_NAMADDRPORT(name, addr, port) \
368           concatenate((name), "[", (addr), "]", \
369                         var_smtpd_client_port_log ? ":" : (char *) 0, \
370                         (port), (char *) 0)
371 
372  /*
373   * Don't mix information from the current SMTP session with forwarded
374   * information from an up-stream session.
375   */
376 #define HAVE_FORWARDED_CLIENT_ATTR(s) \
377           ((s)->xforward.flags & SMTPD_STATE_XFORWARD_CLIENT_MASK)
378 
379 #define FORWARD_CLIENT_ATTR(s, a) \
380           (HAVE_FORWARDED_CLIENT_ATTR(s) ? \
381               (s)->xforward.a : (s)->a)
382 
383 #define FORWARD_ADDR(s)                 FORWARD_CLIENT_ATTR((s), rfc_addr)
384 #define FORWARD_NAME(s)                 FORWARD_CLIENT_ATTR((s), name)
385 #define FORWARD_NAMADDR(s)    FORWARD_CLIENT_ATTR((s), namaddr)
386 #define FORWARD_PROTO(s)      FORWARD_CLIENT_ATTR((s), protocol)
387 #define FORWARD_HELO(s)                 FORWARD_CLIENT_ATTR((s), helo_name)
388 #define FORWARD_PORT(s)                 FORWARD_CLIENT_ATTR((s), port)
389 
390  /*
391   * Mixing is not a problem with forwarded local message identifiers.
392   */
393 #define HAVE_FORWARDED_IDENT(s) \
394           ((s)->xforward.ident != 0)
395 
396 #define FORWARD_IDENT(s) \
397           (HAVE_FORWARDED_IDENT(s) ? \
398               (s)->xforward.ident : (s)->queue_id)
399 
400  /*
401   * Mixing is not a problem with forwarded address rewriting contexts.
402   */
403 #define FORWARD_DOMAIN(s) \
404           (((s)->xforward.flags & SMTPD_STATE_XFORWARD_DOMAIN) ? \
405               (s)->xforward.domain : (s)->rewrite_context)
406 
407 extern void smtpd_xforward_init(SMTPD_STATE *);
408 extern void smtpd_xforward_preset(SMTPD_STATE *);
409 extern void smtpd_xforward_reset(SMTPD_STATE *);
410 
411  /*
412   * Transparency: before mail is queued, do we check for unknown recipients,
413   * do we allow address mapping, automatic bcc, header/body checks?
414   */
415 extern int smtpd_input_transp_mask;
416 
417  /*
418   * More Milter support.
419   */
420 extern MILTERS *smtpd_milters;
421 
422  /*
423   * Message size multiplication factor for free space check.
424   */
425 extern double smtpd_space_multf;
426 
427  /*
428   * header_from_format support.
429   */
430 extern int smtpd_hfrom_format;
431 
432 /* LICENSE
433 /* .ad
434 /* .fi
435 /*        The Secure Mailer license must be distributed with this software.
436 /* AUTHOR(S)
437 /*        Wietse Venema
438 /*        IBM T.J. Watson Research
439 /*        P.O. Box 704
440 /*        Yorktown Heights, NY 10598, USA
441 /*
442 /*        Wietse Venema
443 /*        Google, Inc.
444 /*        111 8th Avenue
445 /*        New York, NY 10011, USA
446 /*
447 /*        TLS support originally by:
448 /*        Lutz Jaenicke
449 /*        BTU Cottbus
450 /*        Allgemeine Elektrotechnik
451 /*        Universitaetsplatz 3-4
452 /*        D-03044 Cottbus, Germany
453 /*--*/
454