1 /* $NetBSD: smtpd.h,v 1.7 2026/05/09 18:49:20 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 #define SMTPD_FLAG_REQTLS (1<<5) /* RFC 8689 */ 215 216 #define SMTPD_NOTE_BARE_LF (1<<0) /* saw at least one bare LF */ 217 218 /* Flags that apply to only one MAIL transaction. */ 219 #define SMTPD_FLAGS_PER_MESSAGE (SMTPD_FLAG_SMTPUTF8 | SMTPD_FLAG_REQTLS) 220 221 /* Security: don't reset SMTPD_FLAG_AUTH_USED. */ 222 #define SMTPD_MASK_MAIL_KEEP \ 223 ~(SMTPD_FLAG_SMTPUTF8) /* Fix 20140706 */ 224 225 #define SMTPD_STATE_XFORWARD_INIT (1<<0) /* xforward preset done */ 226 #define SMTPD_STATE_XFORWARD_NAME (1<<1) /* client name received */ 227 #define SMTPD_STATE_XFORWARD_ADDR (1<<2) /* client address received */ 228 #define SMTPD_STATE_XFORWARD_PROTO (1<<3) /* protocol received */ 229 #define SMTPD_STATE_XFORWARD_HELO (1<<4) /* client helo received */ 230 #define SMTPD_STATE_XFORWARD_IDENT (1<<5) /* message identifier */ 231 #define SMTPD_STATE_XFORWARD_DOMAIN (1<<6) /* address context */ 232 #define SMTPD_STATE_XFORWARD_PORT (1<<7) /* client port received */ 233 234 #define SMTPD_STATE_XFORWARD_CLIENT_MASK \ 235 (SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR \ 236 | SMTPD_STATE_XFORWARD_PROTO | SMTPD_STATE_XFORWARD_HELO \ 237 | SMTPD_STATE_XFORWARD_PORT) 238 239 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *, const char *); 240 extern void smtpd_state_reset(SMTPD_STATE *); 241 242 /* 243 * Conversation stages. This is used for "lost connection after XXX" 244 * diagnostics. 245 */ 246 #define SMTPD_AFTER_CONNECT "CONNECT" 247 #define SMTPD_AFTER_DATA "DATA content" 248 #define SMTPD_AFTER_BDAT "BDAT content" 249 #define SMTPD_AFTER_EOM "END-OF-MESSAGE" 250 251 /* 252 * Other stages. These are sometimes used to change the way information is 253 * logged or what information will be available for access control. 254 */ 255 #define SMTPD_CMD_HELO "HELO" 256 #define SMTPD_CMD_EHLO "EHLO" 257 #define SMTPD_CMD_STARTTLS "STARTTLS" 258 #define SMTPD_CMD_AUTH "AUTH" 259 #define SMTPD_CMD_MAIL "MAIL" 260 #define SMTPD_CMD_RCPT "RCPT" 261 #define SMTPD_CMD_DATA "DATA" 262 #define SMTPD_CMD_BDAT "BDAT" 263 #define SMTPD_CMD_EOD SMTPD_AFTER_EOM /* XXX Was: END-OF-DATA */ 264 #define SMTPD_CMD_RSET "RSET" 265 #define SMTPD_CMD_NOOP "NOOP" 266 #define SMTPD_CMD_VRFY "VRFY" 267 #define SMTPD_CMD_ETRN "ETRN" 268 #define SMTPD_CMD_QUIT "QUIT" 269 #define SMTPD_CMD_XCLIENT "XCLIENT" 270 #define SMTPD_CMD_XFORWARD "XFORWARD" 271 #define SMTPD_CMD_UNKNOWN "UNKNOWN" 272 #define SMTPD_CMD_HELP "HELP" 273 274 /* 275 * Representation of unknown and non-existent client information. Throughout 276 * Postfix, we use the "unknown" string value for unknown client information 277 * (e.g., unknown remote client hostname), and we use the empty string, null 278 * pointer or "no queue file record" for non-existent client information 279 * (e.g., no HELO command, or local submission). 280 * 281 * Inside the SMTP server, unknown real client attributes are represented by 282 * the string "unknown", and non-existent HELO is represented as a null 283 * pointer. The SMTP server uses this same representation internally for 284 * forwarded client attributes; the XFORWARD syntax makes no distinction 285 * between unknown (remote submission) and non-existent (local submission). 286 * 287 * The SMTP client sends forwarded client attributes only when upstream client 288 * attributes exist (i.e. remote submission). Thus, local submissions will 289 * appear to come from an SMTP-based content filter, which is acceptable. 290 * 291 * Known/unknown client attribute values use the SMTP server's internal 292 * representation in queue files, in queue manager delivery requests, and in 293 * delivery agent $name expansions. 294 * 295 * Non-existent attribute values are never present in queue files. Non-existent 296 * information is represented as empty strings in queue manager delivery 297 * requests and in delivery agent $name expansions. 298 */ 299 #define CLIENT_ATTR_UNKNOWN "unknown" 300 301 #define CLIENT_NAME_UNKNOWN CLIENT_ATTR_UNKNOWN 302 #define CLIENT_ADDR_UNKNOWN CLIENT_ATTR_UNKNOWN 303 #define CLIENT_PORT_UNKNOWN CLIENT_ATTR_UNKNOWN 304 #define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN 305 #define CLIENT_HELO_UNKNOWN 0 306 #define CLIENT_PROTO_UNKNOWN CLIENT_ATTR_UNKNOWN 307 #define CLIENT_IDENT_UNKNOWN 0 308 #define CLIENT_DOMAIN_UNKNOWN 0 309 #define CLIENT_LOGIN_UNKNOWN 0 310 311 #define SERVER_ATTR_UNKNOWN "unknown" 312 313 #define SERVER_ADDR_UNKNOWN SERVER_ATTR_UNKNOWN 314 #define SERVER_PORT_UNKNOWN SERVER_ATTR_UNKNOWN 315 316 #define IS_AVAIL_CLIENT_ATTR(v) ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN)) 317 318 #define IS_AVAIL_CLIENT_NAME(v) IS_AVAIL_CLIENT_ATTR(v) 319 #define IS_AVAIL_CLIENT_ADDR(v) IS_AVAIL_CLIENT_ATTR(v) 320 #define IS_AVAIL_CLIENT_PORT(v) IS_AVAIL_CLIENT_ATTR(v) 321 #define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v) 322 #define IS_AVAIL_CLIENT_HELO(v) ((v) != 0) 323 #define IS_AVAIL_CLIENT_PROTO(v) IS_AVAIL_CLIENT_ATTR(v) 324 #define IS_AVAIL_CLIENT_IDENT(v) ((v) != 0) 325 #define IS_AVAIL_CLIENT_DOMAIN(v) ((v) != 0) 326 327 /* 328 * If running in stand-alone mode, do not try to talk to Postfix daemons but 329 * write to queue file instead. 330 */ 331 #define SMTPD_STAND_ALONE_STREAM(stream) \ 332 (stream == VSTREAM_IN && getuid() != var_owner_uid) 333 334 #define SMTPD_STAND_ALONE(state) \ 335 (state->client == VSTREAM_IN && getuid() != var_owner_uid) 336 337 /* 338 * If running as proxy front-end, disable actions that require communication 339 * with the cleanup server. 340 */ 341 #define USE_SMTPD_PROXY(state) \ 342 (SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt) 343 344 /* 345 * Are we in a MAIL transaction? 346 */ 347 #define SMTPD_IN_MAIL_TRANSACTION(state) ((state)->sender != 0) 348 349 /* 350 * Are we processing BDAT requests? 351 */ 352 #define SMTPD_PROCESSING_BDAT(state) \ 353 ((state)->bdat_state != SMTPD_BDAT_STAT_NONE) 354 355 /* 356 * SMTPD peer information lookup. 357 */ 358 extern void smtpd_peer_init(SMTPD_STATE *state); 359 extern void smtpd_peer_reset(SMTPD_STATE *state); 360 extern void smtpd_peer_from_default(SMTPD_STATE *); 361 extern int smtpd_peer_from_haproxy(SMTPD_STATE *); 362 363 #define SMTPD_PEER_CODE_OK 2 364 #define SMTPD_PEER_CODE_TEMP 4 365 #define SMTPD_PEER_CODE_PERM 5 366 #define SMTPD_PEER_CODE_FORGED 6 367 368 /* 369 * Construct name[addr] or name[addr]:port as appropriate 370 */ 371 #define SMTPD_BUILD_NAMADDRPORT(name, addr, port) \ 372 concatenate((name), "[", (addr), "]", \ 373 var_smtpd_client_port_log ? ":" : (char *) 0, \ 374 (port), (char *) 0) 375 376 /* 377 * Don't mix information from the current SMTP session with forwarded 378 * information from an up-stream session. 379 */ 380 #define HAVE_FORWARDED_CLIENT_ATTR(s) \ 381 ((s)->xforward.flags & SMTPD_STATE_XFORWARD_CLIENT_MASK) 382 383 #define FORWARD_CLIENT_ATTR(s, a) \ 384 (HAVE_FORWARDED_CLIENT_ATTR(s) ? \ 385 (s)->xforward.a : (s)->a) 386 387 #define FORWARD_ADDR(s) FORWARD_CLIENT_ATTR((s), rfc_addr) 388 #define FORWARD_NAME(s) FORWARD_CLIENT_ATTR((s), name) 389 #define FORWARD_NAMADDR(s) FORWARD_CLIENT_ATTR((s), namaddr) 390 #define FORWARD_PROTO(s) FORWARD_CLIENT_ATTR((s), protocol) 391 #define FORWARD_HELO(s) FORWARD_CLIENT_ATTR((s), helo_name) 392 #define FORWARD_PORT(s) FORWARD_CLIENT_ATTR((s), port) 393 394 /* 395 * Mixing is not a problem with forwarded local message identifiers. 396 */ 397 #define HAVE_FORWARDED_IDENT(s) \ 398 ((s)->xforward.ident != 0) 399 400 #define FORWARD_IDENT(s) \ 401 (HAVE_FORWARDED_IDENT(s) ? \ 402 (s)->xforward.ident : (s)->queue_id) 403 404 /* 405 * Mixing is not a problem with forwarded address rewriting contexts. 406 */ 407 #define FORWARD_DOMAIN(s) \ 408 (((s)->xforward.flags & SMTPD_STATE_XFORWARD_DOMAIN) ? \ 409 (s)->xforward.domain : (s)->rewrite_context) 410 411 extern void smtpd_xforward_init(SMTPD_STATE *); 412 extern void smtpd_xforward_preset(SMTPD_STATE *); 413 extern void smtpd_xforward_reset(SMTPD_STATE *); 414 415 /* 416 * Transparency: before mail is queued, do we check for unknown recipients, 417 * do we allow address mapping, automatic bcc, header/body checks? 418 */ 419 extern int smtpd_input_transp_mask; 420 421 /* 422 * More Milter support. 423 */ 424 extern MILTERS *smtpd_milters; 425 426 /* 427 * Message size multiplication factor for free space check. 428 */ 429 extern double smtpd_space_multf; 430 431 /* 432 * header_from_format support. 433 */ 434 extern int smtpd_hfrom_format; 435 436 /* LICENSE 437 /* .ad 438 /* .fi 439 /* The Secure Mailer license must be distributed with this software. 440 /* AUTHOR(S) 441 /* Wietse Venema 442 /* IBM T.J. Watson Research 443 /* P.O. Box 704 444 /* Yorktown Heights, NY 10598, USA 445 /* 446 /* Wietse Venema 447 /* Google, Inc. 448 /* 111 8th Avenue 449 /* New York, NY 10011, USA 450 /* 451 /* TLS support originally by: 452 /* Lutz Jaenicke 453 /* BTU Cottbus 454 /* Allgemeine Elektrotechnik 455 /* Universitaetsplatz 3-4 456 /* D-03044 Cottbus, Germany 457 /*--*/ 458