bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "submission-common.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "str.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "mail-user.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "smtp-syntax.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "smtp-address.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "smtp-client.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "smtp-client-connection.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "submission-commands.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch/*
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch * MAIL command
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstruct cmd_mail_context {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct client *client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_mail *data;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_client_command *cmd_proxied;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch};
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic void cmd_mail_update_xclient(struct client *client)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_proxy_data proxy_data;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_helo_data *helo_data =
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_connection_get_helo_data(client->conn);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (client->xclient_sent)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (!client->set->submission_relay_trusted)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (helo_data->domain == NULL)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_zero(&proxy_data);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch proxy_data.helo = helo_data->domain;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch proxy_data.proto = SMTP_PROXY_PROTOCOL_ESMTP;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch (void)smtp_client_connection_send_xclient(
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->proxy_conn, &proxy_data);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->xclient_sent = TRUE;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic void cmd_mail_replied(struct smtp_server_cmd_ctx *cmd)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct cmd_mail_context *mail_cmd = cmd->context;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (mail_cmd->cmd_proxied != NULL)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_client_command_abort(&mail_cmd->cmd_proxied);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic void cmd_mail_proxy_cb(const struct smtp_reply *proxy_reply,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct cmd_mail_context *mail_cmd)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd = mail_cmd->cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct client *client = mail_cmd->client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_reply reply;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* finished proxying MAIL command to relay server */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_assert(mail_cmd != NULL);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch mail_cmd->cmd_proxied = NULL;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (!client_command_handle_proxy_reply(client, proxy_reply, &reply))
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if ((proxy_reply->status / 100) == 2) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* if relay accepts it, we accept it too */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* the default 2.0.0 code won't do */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (!smtp_reply_has_enhanced_code(proxy_reply))
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch reply.enhanced_code = SMTP_REPLY_ENH_CODE(2, 1, 0);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* forward reply */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply_forward(cmd, &reply);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic int
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschcmd_mail_parameter_auth(struct client *client,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch enum smtp_capability proxy_caps,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_mail *data)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_params_mail *params = &data->params;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_address *auth_addr;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch const char *error;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if ((proxy_caps & SMTP_CAPABILITY_AUTH) == 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch auth_addr = NULL;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (smtp_address_parse_username(cmd->pool,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->user->username,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch &auth_addr, &error) < 0) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_warning("Username `%s' is not a valid SMTP address: %s",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->user->username, error);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch params->auth = auth_addr;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic int
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschcmd_mail_parameter_size(struct client *client,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch enum smtp_capability proxy_caps,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_mail *data)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch uoff_t max_size;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* SIZE=<size-value>: RFC 1870 */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (data->params.size == 0 || (proxy_caps & SMTP_CAPABILITY_SIZE) == 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* determine actual size limit (account for our additions) */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch max_size = client_get_max_mail_size(client);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (max_size > 0 && data->params.size > max_size) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 552, "5.3.4",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "Message size exceeds fixed maximum message size");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* proxy the SIZE parameter (account for additional size) */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch data->params.size += SUBMISSION_MAX_ADDITIONAL_MAIL_SIZE;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschint cmd_mail(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_mail *data)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct client *client = conn_ctx;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct cmd_mail_context *mail_cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch enum smtp_capability proxy_caps =
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_client_connection_get_capabilities(client->proxy_conn);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* check and adjust parameters where necessary */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (cmd_mail_parameter_auth(client, cmd, proxy_caps, data) < 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (cmd_mail_parameter_size(client, cmd, proxy_caps, data) < 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch cmd_mail_update_xclient(client);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* queue command (pipeline) */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch mail_cmd = p_new(cmd->pool, struct cmd_mail_context, 1);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch mail_cmd->cmd = cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch mail_cmd->data = data;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch mail_cmd->client = client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek cmd->context = mail_cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch cmd->hook_replied = cmd_mail_replied;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch mail_cmd->cmd_proxied = smtp_client_command_mail_submit(
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->proxy_conn, 0, data->path, &data->params,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch cmd_mail_proxy_cb, mail_cmd);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}