diff options
Diffstat (limited to 'src/lib-smtp/smtp-server-private.h')
-rw-r--r-- | src/lib-smtp/smtp-server-private.h | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/src/lib-smtp/smtp-server-private.h b/src/lib-smtp/smtp-server-private.h new file mode 100644 index 0000000..7a92336 --- /dev/null +++ b/src/lib-smtp/smtp-server-private.h @@ -0,0 +1,404 @@ +#ifndef SMTP_SERVER_PRIVATE_H +#define SMTP_SERVER_PRIVATE_H + +#include "connection.h" + +#include "smtp-server.h" + +#define SMTP_SERVER_COMMAND_POOL_MAX (8 * 1024) + +#define SMTP_SERVER_DEFAULT_MAX_COMMAND_LINE (4 * 1024) +#define SMTP_SERVER_DEFAULT_MAX_BAD_COMMANDS 10 +#define SMTP_SERVER_DEFAULT_MAX_SIZE_EXCESS_LIMIT (1024*1024) + +#define SMTP_SERVER_DEFAULT_CAPABILITIES \ + (SMTP_CAPABILITY_SIZE | SMTP_CAPABILITY_ENHANCEDSTATUSCODES | \ + SMTP_CAPABILITY_8BITMIME | SMTP_CAPABILITY_CHUNKING) + +struct smtp_server_cmd_hook; +struct smtp_server_reply; +struct smtp_server_command; +struct smtp_server_connection; + +ARRAY_DEFINE_TYPE(smtp_server_reply, struct smtp_server_reply); +ARRAY_DEFINE_TYPE(smtp_server_cmd_hook, struct smtp_server_cmd_hook); + +enum smtp_server_command_state { + /* New command; callback to command start handler executing. */ + SMTP_SERVER_COMMAND_STATE_NEW = 0, + /* This command is being processed; command data is fully read, but no + reply is yet submitted */ + SMTP_SERVER_COMMAND_STATE_PROCESSING, + /* A reply is submitted for this command. If not all command data was + read by the handler, it is first skipped on the input. If this is a + multi-reply command (LMTP->DATA), not all replies may be submitted + yet. */ + SMTP_SERVER_COMMAND_STATE_SUBMITTED_REPLY, + /* Request is ready for sending reply; a reply is submitted and the + command payload is fully read. If this is a multi-reply command + (LMTP->DATA), not all replies may be submitted yet. In that case the + command state goes back to PROCESSING once the all submitted replies + are sent. */ + SMTP_SERVER_COMMAND_STATE_READY_TO_REPLY, + /* The reply for the command is sent */ + SMTP_SERVER_COMMAND_STATE_FINISHED, + /* Request is aborted; still lingering due to references */ + SMTP_SERVER_COMMAND_STATE_ABORTED +}; + +struct smtp_server_command_hook { + enum smtp_server_command_hook_type type; + struct smtp_server_command_hook *prev, *next; + + smtp_server_cmd_func_t *func; + void *context; +}; + +struct smtp_server_recipient_hook { + enum smtp_server_recipient_hook_type type; + struct smtp_server_recipient_hook *prev, *next; + + smtp_server_rcpt_func_t *func; + void *context; +}; + +struct smtp_server_reply_content { + unsigned int status; + const char *enhanced_code; + const char *status_prefix; + + string_t *text; + size_t last_line; +}; + +struct smtp_server_reply { + struct smtp_server_command *command; + unsigned int index; + struct event *event; + + /* Replies may share content */ + struct smtp_server_reply_content *content; + + bool submitted:1; + bool sent:1; + bool forwarded:1; +}; + +struct smtp_server_command_reg { + const char *name; + enum smtp_server_command_flags flags; + smtp_server_cmd_start_func_t *func; +}; + +struct smtp_server_command { + struct smtp_server_cmd_ctx context; + const struct smtp_server_command_reg *reg; + int refcount; + + enum smtp_server_command_state state; + + struct smtp_server_command *prev, *next; + + struct smtp_server_command_hook *hooks_head, *hooks_tail; + void *data; + + ARRAY_TYPE(smtp_server_reply) replies; + unsigned int replies_expected; + unsigned int replies_submitted; + + bool input_locked:1; + bool input_captured:1; + bool pipeline_blocked:1; + bool reply_early:1; + bool destroying:1; +}; + +struct smtp_server_recipient_private { + struct smtp_server_recipient rcpt; + int refcount; + + struct smtp_server_recipient_hook *hooks_head, *hooks_tail; + + bool destroying:1; +}; + +struct smtp_server_state_data { + enum smtp_server_state state; + char *args; + time_t timestamp; + + unsigned int pending_mail_cmds; + unsigned int pending_rcpt_cmds, denied_rcpt_cmds; + unsigned int pending_data_cmds; + + struct smtp_server_transaction *trans; + struct istream *data_input, *data_chain_input; + struct istream_chain *data_chain; + unsigned int data_chunks; + uoff_t data_size; + + bool data_failed:1; +}; + +struct smtp_server_connection { + struct connection conn; + struct smtp_server *server; + pool_t pool; + int refcount; + struct event *event, *next_trans_event; + + struct smtp_server_settings set; + + ARRAY(struct smtp_capability_extra) extra_capabilities; + ARRAY_TYPE(const_string) mail_param_extensions; /* NULL-terminated */ + ARRAY_TYPE(const_string) rcpt_param_extensions; /* NULL-terminated */ + + const struct smtp_server_callbacks *callbacks; + void *context; + + enum smtp_proxy_protocol proxy_proto; + unsigned int proxy_ttl_plus_1; + unsigned int proxy_timeout_secs; + char *proxy_helo; + + struct smtp_server_helo_data helo, *pending_helo; + char *helo_domain, *username; + + char *session_id; + unsigned int transaction_seq; + + struct timeout *to_idle; + struct istream *raw_input; + struct ostream *raw_output; + struct ssl_iostream_context *ssl_ctx; + struct ssl_iostream *ssl_iostream; + struct smtp_command_parser *smtp_parser; + + struct smtp_server_command *command_queue_head, *command_queue_tail; + unsigned int command_queue_count; + unsigned int bad_counter; + + struct smtp_server_state_data state; + + struct smtp_server_stats stats; + + bool started:1; + bool halted:1; + bool ssl_start:1; + bool ssl_secured:1; + bool authenticated:1; + bool created_from_streams:1; + bool corked:1; + bool disconnected:1; + bool closing:1; + bool closed:1; + bool input_broken:1; + bool input_locked:1; + bool handling_input:1; + bool rawlog_checked:1; + bool rawlog_enabled:1; +}; + +struct smtp_server { + pool_t pool; + + struct smtp_server_settings set; + + struct event *event; + struct ssl_iostream_context *ssl_ctx; + + ARRAY(struct smtp_server_command_reg) commands_reg; + + struct connection_list *conn_list; + + bool commands_unsorted:1; +}; + +bool smtp_server_connection_pending_command_data( + struct smtp_server_connection *conn); + +/* + * Reply + */ + +void smtp_server_reply_free(struct smtp_server_command *cmd); + +int smtp_server_reply_send(struct smtp_server_reply *resp); + +const char * +smtp_server_reply_get_one_line(const struct smtp_server_reply *reply); +const char * +smtp_server_reply_get_message(const struct smtp_server_reply *reply); + +void smtp_server_reply_add_to_event(const struct smtp_server_reply *reply, + struct event_passthrough *e); + +/* + * Command + */ + +void smtp_server_commands_init(struct smtp_server *server); + +void smtp_server_command_debug(struct smtp_server_cmd_ctx *cmd, + const char *format, ...) ATTR_FORMAT(2, 3); + +struct smtp_server_command * +smtp_server_command_new_invalid(struct smtp_server_connection *conn); +struct smtp_server_command * +smtp_server_command_new(struct smtp_server_connection *conn, const char *name); + +void smtp_server_command_execute(struct smtp_server_command *cmd, + const char *params); + +void smtp_server_command_ref(struct smtp_server_command *cmd); +bool smtp_server_command_unref(struct smtp_server_command **_cmd); +void smtp_server_command_abort(struct smtp_server_command **_cmd); + +bool smtp_server_command_call_hooks(struct smtp_server_command **_cmd, + enum smtp_server_command_hook_type type, + bool remove); +void smtp_server_command_remove_hooks(struct smtp_server_command *cmd, + enum smtp_server_command_hook_type type); + +void smtp_server_command_submit_reply(struct smtp_server_command *cmd); + +int smtp_server_connection_flush(struct smtp_server_connection *conn); + +void smtp_server_command_ready_to_reply(struct smtp_server_command *cmd); +bool smtp_server_command_send_replies(struct smtp_server_command *cmd); +void smtp_server_command_finished(struct smtp_server_command *cmd); + +bool smtp_server_command_next_to_reply(struct smtp_server_command **_cmd); +bool smtp_server_command_completed(struct smtp_server_command **_cmd); + +static inline bool +smtp_server_command_is_complete(struct smtp_server_command *cmd) +{ + struct smtp_server_connection *conn = cmd->context.conn; + + return (conn->input_broken || (cmd->next != NULL) || cmd->reply_early || + !smtp_server_connection_pending_command_data(conn)); +} + +/* + * Connection + */ + +typedef void smtp_server_input_callback_t(void *context); + +void smtp_server_connection_debug(struct smtp_server_connection *conn, + const char *format, ...) ATTR_FORMAT(2, 3); + +struct connection_list *smtp_server_connection_list_init(void); + +struct event_reason * +smtp_server_connection_reason_begin(struct smtp_server_connection *conn, + const char *name); + +void smtp_server_connection_switch_ioloop(struct smtp_server_connection *conn); + +void smtp_server_connection_handle_output_error( + struct smtp_server_connection *conn); +void smtp_server_connection_trigger_output(struct smtp_server_connection *conn); +bool smtp_server_connection_pending_payload(struct smtp_server_connection *conn); + +void smtp_server_connection_cork(struct smtp_server_connection *conn); +void smtp_server_connection_uncork(struct smtp_server_connection *conn); + +void smtp_server_connection_input_halt(struct smtp_server_connection *conn); +void smtp_server_connection_input_resume(struct smtp_server_connection *conn); +void smtp_server_connection_input_capture( + struct smtp_server_connection *conn, + smtp_server_input_callback_t *callback, void *context); +#define smtp_server_connection_input_capture(conn, callback, context) \ + smtp_server_connection_input_capture(conn - \ + CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \ + (smtp_server_input_callback_t *)callback, context) + +void smtp_server_connection_timeout_stop(struct smtp_server_connection *conn); +void smtp_server_connection_timeout_start(struct smtp_server_connection *conn); +void smtp_server_connection_timeout_reset(struct smtp_server_connection *conn); + +void smtp_server_connection_send_line(struct smtp_server_connection *conn, + const char *fmt, ...) ATTR_FORMAT(2, 3); +void smtp_server_connection_reply_lines(struct smtp_server_connection *conn, + unsigned int status, + const char *enh_code, + const char *const *text_lines); +void smtp_server_connection_reply_immediate( + struct smtp_server_connection *conn, unsigned int status, + const char *fmt, ...) ATTR_FORMAT(3, 4); + +void smtp_server_connection_reset_state(struct smtp_server_connection *conn); +void smtp_server_connection_set_state(struct smtp_server_connection *conn, + enum smtp_server_state state, + const char *args) ATTR_NULL(3); + +int smtp_server_connection_ssl_init(struct smtp_server_connection *conn); + +void smtp_server_connection_clear(struct smtp_server_connection *conn); + +struct smtp_server_transaction * +smtp_server_connection_get_transaction(struct smtp_server_connection *conn); + +/* + * Recipient + */ + +struct smtp_server_recipient * +smtp_server_recipient_create(struct smtp_server_cmd_ctx *cmd, + const struct smtp_address *rcpt_to, + const struct smtp_params_rcpt *params); +void smtp_server_recipient_ref(struct smtp_server_recipient *rcpt); +bool smtp_server_recipient_unref(struct smtp_server_recipient **_rcpt); +void smtp_server_recipient_destroy(struct smtp_server_recipient **_rcpt); + +bool smtp_server_recipient_approved(struct smtp_server_recipient **_rcpt); +void smtp_server_recipient_denied(struct smtp_server_recipient *rcpt, + const struct smtp_server_reply *reply); + +void smtp_server_recipient_data_command(struct smtp_server_recipient *rcpt, + struct smtp_server_cmd_ctx *cmd); +void smtp_server_recipient_data_replied(struct smtp_server_recipient *rcpt); + +void smtp_server_recipient_reset(struct smtp_server_recipient *rcpt); +void smtp_server_recipient_finished(struct smtp_server_recipient *rcpt, + const struct smtp_server_reply *reply); + +bool smtp_server_recipient_call_hooks( + struct smtp_server_recipient **_rcpt, + enum smtp_server_recipient_hook_type type); + +/* + * Transaction + */ + +struct smtp_server_transaction * +smtp_server_transaction_create(struct smtp_server_connection *conn, + const struct smtp_server_cmd_mail *mail_data); +void smtp_server_transaction_free(struct smtp_server_transaction **_trans); + +void smtp_server_transaction_add_rcpt(struct smtp_server_transaction *trans, + struct smtp_server_recipient *rcpt); +bool smtp_server_transaction_has_rcpt(struct smtp_server_transaction *trans); +unsigned int +smtp_server_transaction_rcpt_count(struct smtp_server_transaction *trans); + +void smtp_server_transaction_data_command(struct smtp_server_transaction *trans, + struct smtp_server_cmd_ctx *cmd); + +void smtp_server_transaction_received(struct smtp_server_transaction *trans, + uoff_t data_size); + +void smtp_server_transaction_reset(struct smtp_server_transaction *trans); +void smtp_server_transaction_finished(struct smtp_server_transaction *trans, + struct smtp_server_cmd_ctx *cmd); + +/* + * Server + */ + +void smtp_server_event_init(struct smtp_server *server, struct event *event); +int smtp_server_init_ssl_ctx(struct smtp_server *server, const char **error_r); + +#endif |