Home | History | Annotate | Line # | Download | only in smtpd
      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