summaryrefslogtreecommitdiffstats
path: root/src/smtpd/smtpd.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/smtpd/smtpd.h441
1 files changed, 441 insertions, 0 deletions
diff --git a/src/smtpd/smtpd.h b/src/smtpd/smtpd.h
new file mode 100644
index 0000000..490cda2
--- /dev/null
+++ b/src/smtpd/smtpd.h
@@ -0,0 +1,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
+/*--*/