bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "lib.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "array.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "ioloop.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "smtp-parser.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "smtp-syntax.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "smtp-address.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "smtp-server-private.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* MAIL command */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic bool
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschcmd_mail_check_state(struct smtp_server_cmd_ctx *cmd)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_connection *conn = cmd->conn;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_command *command = cmd->cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (conn->state.trans != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (command->hook_replied != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch conn->state.pending_mail_cmds--;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch command->hook_replied = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_reply(cmd, 503, "5.5.0", "MAIL already given");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return TRUE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void cmd_mail_replied(struct smtp_server_cmd_ctx *cmd)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_connection *conn = cmd->conn;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_command *command = cmd->cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_mail *data =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch (struct smtp_server_cmd_mail *)command->data;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch conn->state.pending_mail_cmds--;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(smtp_server_command_is_replied(command));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!smtp_server_command_replied_success(command)) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* failure; substitute our own error if predictable */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch (void)cmd_mail_check_state(cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* success */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch conn->state.trans = smtp_server_transaction_create(conn,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch data->path, &data->params, &data->timestamp);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void cmd_mail_recheck(struct smtp_server_cmd_ctx *cmd)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_connection *conn = cmd->conn;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* all preceeding commands have finished and now the transaction state
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch is clear. This provides the opportunity to re-check the transaction
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch state */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!cmd_mail_check_state(cmd))
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Advance state */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_MAIL_FROM);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_cmd_mail(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *params)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_connection *conn = cmd->conn;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct smtp_server_settings *set = &conn->set;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum smtp_capability caps = set->capabilities;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct smtp_server_callbacks *callbacks = conn->callbacks;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_command *command = cmd->cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_mail *mail_data;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_address *path;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum smtp_param_parse_error pperror;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *error;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* mail = "MAIL FROM:" Reverse-path [SP Mail-parameters] CRLF
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch Reverse-path = Path / "<>"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* check transaction state as far as possible */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!cmd_mail_check_state(cmd))
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Reverse-path */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (params == NULL || strncasecmp(params, "FROM:", 5) != 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4", "Invalid parameters");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (smtp_address_parse_path_full(pool_datastack_create(), params + 5,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &path, &error, &params) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4", "Invalid FROM: %s", error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (*params == ' ')
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch params++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else if (*params != '\0') {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch "Invalid FROM: Invalid character in path");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (conn->pending_helo == NULL && conn->helo.domain == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* no EHLO executed post-login, use pre-login value instead */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch conn->helo_domain = conn->helo_login;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch conn->helo_login = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch conn->helo.domain = conn->helo_domain;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_data = p_new(cmd->pool, struct smtp_server_cmd_mail, 1);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* [SP Mail-parameters] */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (smtp_params_mail_parse(cmd->pool, params, caps,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch set->param_extensions, &mail_data->params,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &pperror, &error) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch switch (pperror) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case SMTP_PARAM_PARSE_ERROR_BAD_SYNTAX:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4", "%s", error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case SMTP_PARAM_PARSE_ERROR_NOT_SUPPORTED:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_reply(cmd, 555, "5.5.4", "%s", error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch default:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_unreached();
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_data->path = smtp_address_clone(cmd->pool, path);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_data->timestamp = ioloop_timeval;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch command->data = mail_data;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch command->hook_next = cmd_mail_recheck;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch command->hook_replied = cmd_mail_replied;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_MAIL_FROM);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch conn->state.pending_mail_cmds++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_command_ref(command);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (callbacks != NULL && callbacks->conn_cmd_mail != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* specific implementation of MAIL command */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if ((ret=callbacks->conn_cmd_mail(conn->context,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd, mail_data)) <= 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(ret == 0 ||
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_command_is_replied(command));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* command is waiting for external event or it failed */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_command_unref(&command);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!smtp_server_command_is_replied(command)) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* set generic MAIL success reply if none is provided */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_reply(cmd, 250, "2.1.0", "OK");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_command_unref(&command);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}