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 "str-sanitize.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "istream.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "istream-concat.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "istream-seekable.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "mail-storage.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "imap-url.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "imap-msgpart.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "imap-msgpart-url.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "imap-urlauth.h"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch#include "imap-urlauth-fetch.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 * DATA/BDAT commands
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstruct cmd_data_context {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct client *client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_transaction *trans;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_client_command *cmd_proxied;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch};
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic void cmd_data_proxy_cb(const struct smtp_reply *proxy_reply,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct cmd_data_context *data_ctx)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd = data_ctx->cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_transaction *trans = data_ctx->trans;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct client *client = data_ctx->client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_reply reply;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* finished proxying message to relay server */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* check for fatal problems */
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 i_info("Successfully relayed message: "
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "from=<%s>, size=%"PRIuUOFF_T", "
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "id=%s, nrcpt=%u, reply=`%s'",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_address_encode(trans->mail_from),
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->state.data_size, trans->id,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch array_count(&trans->rcpt_to),
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch str_sanitize(smtp_reply_log(proxy_reply), 128));
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch } else {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_info("Failed to relay message: "
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "from=<%s>, size=%"PRIuUOFF_T", nrcpt=%u, reply=`%s'",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_address_encode(trans->mail_from),
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->state.data_size, array_count(&trans->rcpt_to),
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch str_sanitize(smtp_reply_log(proxy_reply), 128));
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply_forward(cmd, &reply);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschint cmd_data_continue(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_transaction *trans)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct client *client = conn_ctx;
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct cmd_data_context *data_ctx = trans->context;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct istream *data_input = client->state.data_input;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct istream *inputs[3];
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch string_t *added_headers;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch const unsigned char *data;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch size_t size;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch int ret;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch while ((ret = i_stream_read_more(data_input, &data, &size)) > 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_stream_skip(data_input, size);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (ret == 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (ret < 0 && data_input->stream_errno != 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* Done reading DATA stream; remove it from state and continue with
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch local variable. */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->state.data_input = NULL;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = i_stream_get_size(data_input, TRUE,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch &client->state.data_size);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_assert(ret > 0); // FIXME
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* prepend our own headers */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch added_headers = t_str_new(200);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_transaction_write_trace_record(added_headers, trans);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_stream_seek(data_input, 0);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch inputs[0] = i_stream_create_copy_from_data(
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch str_data(added_headers), str_len(added_headers));
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch inputs[1] = data_input;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch inputs[2] = NULL;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch data_ctx->cmd = cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch data_input = i_stream_create_concat(inputs);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_stream_unref(&inputs[0]);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_stream_unref(&inputs[1]);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* start proxying to relay server */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch data_ctx->cmd_proxied = smtp_client_command_data_submit(
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->proxy_conn, 0, data_input,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch cmd_data_proxy_cb, data_ctx);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_stream_unref(&data_input);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschint cmd_data_begin(void *conn_ctx,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_transaction *trans,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct istream *data_input)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct client *client = conn_ctx;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct cmd_data_context *data_ctx;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct istream *inputs[2];
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch string_t *path;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch data_ctx = p_new(trans->pool, struct cmd_data_context, 1);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch data_ctx->client = client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch data_ctx->trans = trans;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch trans->context = (void*)data_ctx;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch inputs[0] = data_input;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch inputs[1] = NULL;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch path = t_str_new(256);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch mail_user_set_get_temp_prefix(path, client->user->set);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch client->state.data_input = i_stream_create_seekable_path(inputs,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch SUBMISSION_MAIL_DATA_MAX_INMEMORY_SIZE, str_c(path));
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch/*
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch * BURL command
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch/* FIXME: RFC 4468
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch If the URL argument to BURL refers to binary data, then the submit server
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch MAY refuse the command or down convert as described in Binary SMTP.
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstruct cmd_burl_context {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct client *client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct imap_urlauth_fetch *urlauth_fetch;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct imap_msgpart_url *url_fetch;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch bool chunk_last:1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch};
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic void
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschcmd_burl_destroy(struct smtp_server_cmd_ctx *cmd)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct cmd_burl_context *burl_cmd = cmd->context;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (burl_cmd->urlauth_fetch != NULL)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch imap_urlauth_fetch_deinit(&burl_cmd->urlauth_fetch);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (burl_cmd->url_fetch != NULL)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch imap_msgpart_url_free(&burl_cmd->url_fetch);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic int
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschcmd_burl_fetch_cb(struct imap_urlauth_fetch_reply *reply,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch bool last, void *context)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct cmd_burl_context *burl_cmd = context;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd = burl_cmd->cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch int ret;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch i_assert(last);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (reply == NULL) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* fatal failure */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch // FIXME: make this an internal error
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 554, "5.6.6",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "IMAP URLAUTH resolution failed");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (!reply->succeeded) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* URL fetch failed */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (reply->error != NULL) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 554, "5.6.6",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "IMAP URLAUTH resolution failed: %s",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch reply->error);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch } else {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 554, "5.6.6",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "IMAP URLAUTH resolution failed");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* URL fetch succeeded */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = smtp_server_connection_data_chunk_add(cmd,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch reply->input, reply->size, burl_cmd->chunk_last, FALSE);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (ret < 0)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* Command is likely not yet complete at this point, so return 0 */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic int
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschcmd_burl_fetch_trusted(struct cmd_burl_context *burl_cmd,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct imap_url *imap_url)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd = burl_cmd->cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct client *client = burl_cmd->client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch const char *host_name = client->set->imap_urlauth_host;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch in_port_t host_port = client->set->imap_urlauth_port;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct imap_msgpart_open_result result;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch const char *error;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* validate host */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (imap_url->host.name == NULL ||
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch (strcmp(host_name, URL_HOST_ALLOW_ANY) != 0 &&
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch strcmp(imap_url->host.name, host_name) != 0)) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 554, "5.6.6",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "IMAP URL resolution failed: "
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "Inappropriate or missing host name");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* validate port */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if ((imap_url->port == 0 && host_port != 143) ||
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch (imap_url->port != 0 && host_port != imap_url->port)) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 554, "5.6.6",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "IMAP URL resolution failed: "
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "Inappropriate server port");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* retrieve URL */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (imap_msgpart_url_create
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch (client->user, imap_url, &burl_cmd->url_fetch, &error) < 0) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 554, "5.6.6",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "IMAP URL resolution failed: %s", error);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (imap_msgpart_url_read_part(burl_cmd->url_fetch,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch &result, &error) <= 0) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 554, "5.6.6",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "IMAP URL resolution failed: %s", error);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return smtp_server_connection_data_chunk_add(cmd,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch result.input, result.size, burl_cmd->chunk_last, FALSE);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschstatic int
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschcmd_burl_fetch(struct cmd_burl_context *burl_cmd, const char *url,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct imap_url *imap_url)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_cmd_ctx *cmd = burl_cmd->cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct client *client = burl_cmd->client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (client->urlauth_ctx == NULL) {
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch /* RFC5248, Section 2.4:
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch 554 5.7.14 Trust relationship required
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch The submission server requires a configured trust
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch relationship with a third-party server in order to access
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch the message content. This value replaces the prior use of
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch X.7.8 for this error condition, thereby updating [RFC4468].
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch */
00cdcc993df1a468b6b16d2e580cb394a022c244Stephan Bosch smtp_server_reply(cmd, 554, "5.7.14",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "No IMAP URLAUTH access available");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* urlauth */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch burl_cmd->urlauth_fetch =
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch imap_urlauth_fetch_init(client->urlauth_ctx,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch cmd_burl_fetch_cb, burl_cmd);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (imap_urlauth_fetch_url_parsed(burl_cmd->urlauth_fetch,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch url, imap_url, IMAP_URLAUTH_FETCH_FLAG_BODY) == 0) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* wait for URL fetch */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 0;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return 1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Boschvoid cmd_burl(struct smtp_server_cmd_ctx *cmd, const char *params)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch{
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct smtp_server_connection *conn = cmd->conn;
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek struct client *client = smtp_server_connection_get_context(conn);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct cmd_burl_context *burl_cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch const char *const *argv;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch enum imap_url_parse_flags url_parse_flags =
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch IMAP_URL_PARSE_ALLOW_URLAUTH;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch struct imap_url *imap_url;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch const char *url, *error;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch bool chunk_last = FALSE;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch int ret = 1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_connection_data_chunk_init(cmd);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* burl-cmd = "BURL" SP absolute-URI [SP end-marker] CRLF
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch end-marker = "LAST"
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch argv = t_strsplit(params, " ");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch url = argv[0];
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (url == NULL) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "Missing chunk URL parameter");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch } else if (imap_url_parse(url, NULL, url_parse_flags,
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch &imap_url, &error) < 0) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "Invalid chunk URL: %s", error);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch } else if (argv[1] != NULL) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (strcasecmp(argv[1], "LAST") != 0) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "Invalid end marker parameter");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch } else if (argv[2] != NULL) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_reply(cmd, 501, "5.5.4",
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch "Invalid parameters");
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = -1;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch } else {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch chunk_last = TRUE;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (ret < 0 || !smtp_server_connection_data_check_state(cmd))
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch return;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch burl_cmd = p_new(cmd->pool, struct cmd_burl_context, 1);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch burl_cmd->client = client;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch burl_cmd->cmd = cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch burl_cmd->chunk_last = chunk_last;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
0cce67356125083a0affed3ca9cb4f278258e5beJosef 'Jeff' Sipek cmd->context = burl_cmd;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch cmd->hook_destroy = cmd_burl_destroy;
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (imap_url->uauth_rumpurl == NULL) {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch /* direct local url */
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = cmd_burl_fetch_trusted(burl_cmd, imap_url);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch } else {
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch ret = cmd_burl_fetch(burl_cmd, url, imap_url);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch }
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch if (ret == 0 && chunk_last)
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch smtp_server_command_input_lock(cmd);
2cbbe9b4829adb184c83dbf780316f4144559054Stephan Bosch}