bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "lib.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "array.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "base64.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "str.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "llist.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "iostream.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "istream.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "ostream.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "hostpid.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "process-title.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "var-expand.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "settings-parser.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "smtp-server.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "master-service.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "master-service-ssl.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "master-service-settings.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "iostream-ssl.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "mail-namespace.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "mail-storage.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "mail-storage-service.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "raw-storage.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "main.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "lda-settings.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "lmtp-settings.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "lmtp-local.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "lmtp-proxy.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "commands.h"
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina#include "client.h"
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina#include <unistd.h>
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina#define CLIENT_IDLE_TIMEOUT_MSECS (1000*60*5)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic struct client *clients = NULL;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic unsigned int clients_count = 0;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic bool verbose_proctitle = FALSE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic const struct smtp_server_callbacks lmtp_callbacks;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic const char *client_remote_id(struct client *client)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const char *addr;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina addr = net_ip2addr(&client->remote_ip);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (addr[0] == '\0')
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina addr = "local";
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return addr;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic void refresh_proctitle(void)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct client *client;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina string_t *title;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (!verbose_proctitle)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina title = t_str_new(128);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina str_append_c(title, '[');
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina switch (clients_count) {
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina case 0:
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina str_append(title, "idling");
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina break;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina case 1:
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client = clients;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina str_append(title, client_remote_id(client));
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina str_append_c(title, ' ');
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina str_append(title, client_state_get_name(client));
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina break;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina default:
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina str_printfa(title, "%u connections", clients_count);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina break;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina }
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina str_append_c(title, ']');
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina process_title_set(str_c(title));
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic void client_raw_user_create(struct client *client)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina void **sets;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina sets = master_service_settings_get_others(master_service);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->raw_mail_user =
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina raw_storage_create_from_set(client->user_set_info, sets[0]);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic void client_read_settings(struct client *client, bool ssl)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct mail_storage_service_input input;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const struct setting_parser_context *set_parser;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct lmtp_settings *lmtp_set;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct lda_settings *lda_set;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const char *error;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_zero(&input);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.module = input.service = "lmtp";
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.local_ip = client->local_ip;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.remote_ip = client->remote_ip;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.local_port = client->local_port;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.remote_port = client->remote_port;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.conn_secured = ssl;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.conn_ssl_secured = ssl;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina input.username = "";
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (mail_storage_service_read_settings(storage_service, &input,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->pool,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina &client->user_set_info,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina &set_parser, &error) < 0)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_fatal("%s", error);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina lmtp_settings_dup(set_parser, client->pool, &lmtp_set, &lda_set);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const struct var_expand_table *tab =
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina mail_storage_service_get_var_expand_table(storage_service, &input);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (settings_var_expand(&lmtp_setting_parser_info, lmtp_set,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->pool, tab, &error) <= 0)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_fatal("Failed to expand settings: %s", error);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->service_set = master_service_settings_get(master_service);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->lmtp_set = lmtp_set;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->unexpanded_lda_set = lda_set;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastruct client *client_create(int fd_in, int fd_out,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const struct master_service_connection *conn)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct smtp_server_settings lmtp_set;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct client *client;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina pool_t pool;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina pool = pool_alloconly_create("lmtp client", 2048);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client = p_new(pool, struct client, 1);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->pool = pool;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->remote_ip = conn->remote_ip;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->remote_port = conn->remote_port;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->local_ip = conn->local_ip;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->local_port = conn->local_port;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->state_pool = pool_alloconly_create("client state", 4096);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client_read_settings(client, conn->ssl);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client_raw_user_create(client);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->my_domain = client->unexpanded_lda_set->hostname;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (client->service_set->verbose_proctitle)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina verbose_proctitle = TRUE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_zero(&lmtp_set);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina lmtp_set.capabilities =
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina SMTP_CAPABILITY_PIPELINING |
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina SMTP_CAPABILITY_ENHANCEDSTATUSCODES |
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina SMTP_CAPABILITY_8BITMIME |
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina SMTP_CAPABILITY_CHUNKING |
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina SMTP_CAPABILITY_XCLIENT;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (!conn->ssl && master_service_ssl_is_enabled(master_service))
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina lmtp_set.capabilities |= SMTP_CAPABILITY_STARTTLS;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina lmtp_set.hostname = client->unexpanded_lda_set->hostname;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina lmtp_set.rcpt_domain_optional = TRUE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina lmtp_set.max_client_idle_time_msecs = CLIENT_IDLE_TIMEOUT_MSECS;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->conn = smtp_server_connection_create
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina (lmtp_server, fd_in, fd_out,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina &conn->remote_ip, conn->remote_port,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina conn->ssl, &lmtp_set, &lmtp_callbacks, client);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina DLLIST_PREPEND(&clients, client);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina clients_count++;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina smtp_server_connection_start(client->conn);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_info("Connect from %s", client_remote_id(client));
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina refresh_proctitle();
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return client;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinavoid client_state_reset(struct client *client)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (client->local != NULL)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina lmtp_local_deinit(&client->local);
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina if (client->proxy != NULL)
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina lmtp_proxy_deinit(&client->proxy);
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina o_stream_unref(&client->state.mail_data_output);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_zero(&client->state);
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina p_clear(client->state_pool);
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina}
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březinavoid client_destroy(struct client *client, const char *enh_code,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const char *reason)
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina{
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina if (client->destroyed)
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina return;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->destroyed = TRUE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client_disconnect(client, enh_code, reason);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina clients_count--;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina DLLIST_REMOVE(&clients, client);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (client->raw_mail_user != NULL)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina mail_user_unref(&client->raw_mail_user);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client_state_reset(client);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina pool_unref(&client->state_pool);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina pool_unref(&client->pool);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina master_service_client_connection_destroyed(master_service);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinaconst char *client_state_get_name(struct client *client)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina enum smtp_server_state state;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (client->conn == NULL)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina state = client->last_state;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina else
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina state = smtp_server_connection_get_state(client->conn);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return smtp_server_state_names[state];
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinavoid client_disconnect(struct client *client, const char *enh_code,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const char *reason)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina struct smtp_server_connection *conn = client->conn;
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina if (client->disconnected)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->disconnected = TRUE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (reason == NULL)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina reason = "Connection closed";
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_info("Disconnect from %s: %s (state = %s)", client_remote_id(client),
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina reason, client_state_get_name(client));
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina if (conn != NULL) {
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina client->last_state = smtp_server_connection_get_state(conn);
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina smtp_server_connection_terminate(&conn,
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina (enh_code == NULL ? "4.0.0" : enh_code), reason);
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina }
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic void
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinaclient_connection_trans_free(void *context,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct smtp_server_transaction *trans ATTR_UNUSED)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct client *client = (struct client *)context;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client_state_reset(client);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic void
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinaclient_connection_state_changed(void *context ATTR_UNUSED,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina enum smtp_server_state newstate ATTR_UNUSED)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (clients_count == 1)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina refresh_proctitle();
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic void
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinaclient_connection_proxy_data_updated(void *context,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const struct smtp_proxy_data *data)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct client *client = (struct client *)context;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->remote_ip = data->source_ip;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->remote_port = data->source_port;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (clients_count == 1)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina refresh_proctitle();
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic void client_connection_disconnect(void *context, const char *reason)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct client *client = (struct client *)context;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct smtp_server_connection *conn = client->conn;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (conn != NULL)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client->last_state = smtp_server_connection_get_state(conn);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client_disconnect(client, NULL, reason);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březinastatic void client_connection_destroy(void *context)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct client *client = (struct client *)context;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina client_destroy(client, NULL, NULL);
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina}
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic bool client_connection_is_trusted(void *context)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct client *client = (struct client *)context;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina const char *const *net;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina struct ip_addr net_ip;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina unsigned int bits;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (client->lmtp_set->login_trusted_networks == NULL)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return FALSE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina net = t_strsplit_spaces(client->lmtp_set->login_trusted_networks, ", ");
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina for (; *net != NULL; net++) {
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (net_parse_range(*net, &net_ip, &bits) < 0) {
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina i_error("login_trusted_networks: "
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina "Invalid network '%s'", *net);
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina break;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina }
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina if (net_is_in_network(&client->remote_ip, &net_ip, bits))
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return TRUE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina }
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina return FALSE;
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinavoid clients_destroy(void)
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina{
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina while (clients != NULL) {
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina client_destroy(clients, "4.3.2", "Shutting down");
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina }
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina}
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březinastatic const struct smtp_server_callbacks lmtp_callbacks = {
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_cmd_mail = cmd_mail,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_cmd_rcpt = cmd_rcpt,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_cmd_data_begin = cmd_data_begin,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_cmd_data_continue = cmd_data_continue,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_trans_free = client_connection_trans_free,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_state_changed = client_connection_state_changed,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_proxy_data_updated = client_connection_proxy_data_updated,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_disconnect = client_connection_disconnect,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_destroy = client_connection_destroy,
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina .conn_is_trusted = client_connection_is_trusted
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina};
bd4c2ed5aec7f57ea04500f0e43f151eedfdde45Pavel Březina