bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "lib.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "str.h"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch#include "array.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "hostpid.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "ioloop.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "istream.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "ostream.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "time-util.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "connection.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "test-common.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "smtp-address.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include "smtp-server.h"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include <sys/types.h>
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include <sys/wait.h>
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include <signal.h>
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#include <unistd.h>
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch#define SERVER_MAX_TIMEOUT_MSECS 10*1000
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Types
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct server_connection {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch void *context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct client_connection {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct connection conn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch pool_t pool;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtypedef void (*test_server_init_t)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (const struct smtp_server_settings *server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtypedef void (*test_client_init_t)(unsigned int index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * State
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* common */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic struct ip_addr bind_ip;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic in_port_t bind_port = 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic struct ioloop *ioloop;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic bool debug = FALSE;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic struct smtp_server *smtp_server = NULL;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic struct io *io_listen;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int fd_listen = -1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic struct smtp_server_callbacks server_callbacks;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic pid_t *client_pids = NULL;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic struct connection_list *client_conn_list;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic unsigned int client_pids_count = 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic unsigned int client_index;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void (*test_client_connected)(struct client_connection *conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void (*test_client_input)(struct client_connection *conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Forward declarations
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_defaults(struct smtp_server_settings *smtp_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_run(const struct smtp_server_settings *smtp_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_run(unsigned int index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test*/
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_run_client_server(
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch const struct smtp_server_settings *server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_init_t server_test,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_init_t client_test,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch unsigned int client_tests_count)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ATTR_NULL(3);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Slow server
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_slow_server_input(struct client_connection *conn ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* do nothing */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch sleep(10);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_slow_server_connected(struct client_connection *conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("CONNECTED");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)o_stream_send_str(conn->conn.output,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "EHLO frop\r\n");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_slow_server(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_input = test_slow_server_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected = test_slow_server_connected;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_run(index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct _slow_server {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct timeout *to_delay;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bool serviced:1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_server_destroyed(struct smtp_server_cmd_ctx *cmd)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _slow_server *ctx = (struct _slow_server *)cmd->context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(ctx->serviced);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch timeout_remove(&ctx->to_delay);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_server_delayed(struct _slow_server *ctx)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_reply *reply;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd = ctx->cmd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch reply = smtp_server_reply_create_ehlo(cmd->cmd);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply_ehlo_add(reply, "FROP");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply_submit(reply);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->serviced = TRUE;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_server_cmd_helo(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_helo *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _slow_server *ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("HELO");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx = i_new(struct _slow_server, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->cmd = cmd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch cmd->hook_destroy = test_server_slow_server_destroyed;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch cmd->context = ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->to_delay = timeout_add(4000,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_slow_server_delayed, ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_server_slow_server
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch(const struct smtp_server_settings *server_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_helo = test_server_slow_server_cmd_helo;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_run(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_slow_server(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_settings smtp_server_set;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_defaults(&smtp_server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_begin("slow server");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run_client_server(&smtp_server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_slow_server,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_slow_server, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_end();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Slow client
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_slow_client_input(struct client_connection *conn ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* nothing */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_slow_client_connected(struct client_connection *conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("CONNECTED");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)o_stream_send_str(conn->conn.output,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "EHLO frop\r\n");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_slow_client(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_input = test_slow_client_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected = test_slow_client_connected;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_run(index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct _slow_client {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct timeout *to_delay;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct timeout *to_disconnect;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bool serviced:1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_client_disconnect_timeout(struct _slow_client *ctx)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(FALSE);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch timeout_remove(&ctx->to_disconnect);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_client_disconnect(void *conn_ctx, const char *reason)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct server_connection *conn = (struct server_connection *)conn_ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _slow_client *ctx = (struct _slow_client *)conn->context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("DISCONNECTED: %s", reason);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch timeout_remove(&ctx->to_disconnect);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_client_cmd_destroyed(struct smtp_server_cmd_ctx *cmd)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _slow_client *ctx = (struct _slow_client *)cmd->context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(ctx->serviced);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch timeout_remove(&ctx->to_delay);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_client_delayed(struct _slow_client *ctx)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_reply *reply;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd = ctx->cmd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch timeout_remove(&ctx->to_delay);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch reply = smtp_server_reply_create_ehlo(cmd->cmd);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply_ehlo_add(reply, "FROP");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->to_disconnect = timeout_add(2000,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_slow_client_disconnect_timeout, ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply_submit(reply);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->serviced = TRUE;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_slow_client_cmd_helo(void *conn_ctx,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_helo *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct server_connection *conn =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (struct server_connection *)conn_ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _slow_client *ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("HELO");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx = i_new(struct _slow_client, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->cmd = cmd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch conn->context = ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch cmd->hook_destroy = test_server_slow_client_cmd_destroyed;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch cmd->context = ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->to_delay = timeout_add_short(500,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_slow_client_delayed, ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_server_slow_client
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch(const struct smtp_server_settings *server_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_disconnect = test_server_slow_client_disconnect;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_helo = test_server_slow_client_cmd_helo;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_run(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_slow_client(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_settings smtp_server_set;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_defaults(&smtp_server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_begin("slow client");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run_client_server(&smtp_server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_slow_client,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_slow_client, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_end();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Hanging command payload
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_hanging_command_payload_connected(struct client_connection *conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)o_stream_send_str(conn->conn.output,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "EHLO frop\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "MAIL FROM:<hangman@example.com>\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "RCPT TO:<jerry@example.com>\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "DATA\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "To be continued... or not");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_hanging_command_payload(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected = test_hanging_command_payload_connected;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_run(index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct _hanging_command_payload {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *payload_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct io *io;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bool serviced:1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_hanging_command_payload_trans_free(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _hanging_command_payload *ctx =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (struct _hanging_command_payload *)trans->context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(!ctx->serviced);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_hanging_command_payload_rcpt(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_rcpt *data)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("RCPT TO:%s",
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_address_encode(data->path));
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_hanging_command_payload_data_begin(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *data_input)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _hanging_command_payload *ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("DATA");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx = i_new(struct _hanging_command_payload, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch trans->context = ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->payload_input = data_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_hanging_command_payload_data_continue(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _hanging_command_payload *ctx =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (struct _hanging_command_payload *)trans->context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch const unsigned char *data;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch size_t size;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch int ret;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("DATA continue");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch while ((ret=i_stream_read_data(ctx->payload_input,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch &data, &size, 0)) > 0) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_stream_skip(ctx->payload_input, size);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (ret == 0)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (ctx->payload_input->stream_errno != 0) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_error("failed to read DATA payload: %s",
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_stream_get_error(ctx->payload_input));
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return -1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_assert(ctx->payload_input->eof);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply(cmd, 250, "2.0.0", "OK");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->serviced = TRUE;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_stream_unref(&ctx->payload_input);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_server_hanging_command_payload
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch(const struct smtp_server_settings *server_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_trans_free =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_hanging_command_payload_trans_free;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_rcpt =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_hanging_command_payload_rcpt;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_data_begin =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_hanging_command_payload_data_begin;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_data_continue =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_hanging_command_payload_data_continue;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_run(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_hanging_command_payload(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_settings smtp_server_set;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_defaults(&smtp_server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_begin("hanging command payload");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run_client_server(&smtp_server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_hanging_command_payload,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_hanging_command_payload, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_end();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Bad command
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_bad_command_connected(struct client_connection *conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)o_stream_send_str(conn->conn.output,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "EHLO\tfrop\r\n");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_bad_command(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected = test_bad_command_connected;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_run(index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct _bad_command {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *payload_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct io *io;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bool serviced:1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_command_disconnect(void *context ATTR_UNUSED, const char *reason)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("Disconnect: %s", reason);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_command_helo(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_helo *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(FALSE);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_command_rcpt(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_rcpt *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_command_data_begin(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *data_input ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply(cmd, 250, "2.0.0", "OK");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_server_bad_command
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch(const struct smtp_server_settings *server_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_disconnect =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_command_disconnect;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_helo =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_command_helo;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_rcpt =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_command_rcpt;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_data_begin =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_command_data_begin;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_run(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_bad_command(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_settings smtp_server_set;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_defaults(&smtp_server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_begin("bad command");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run_client_server(&smtp_server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_command,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_bad_command, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_end();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Long command
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_long_command_connected(struct client_connection *conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)o_stream_send_str(conn->conn.output,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "EHLO some.very.very.very.very.very.long.domain\r\n");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_long_command(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected = test_long_command_connected;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_run(index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct _long_command {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *payload_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct io *io;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bool serviced:1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_long_command_disconnect(void *context ATTR_UNUSED, const char *reason)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("Disconnect: %s", reason);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_long_command_helo(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_helo *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(FALSE);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_long_command_rcpt(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_rcpt *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_long_command_data_begin(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *data_input ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply(cmd, 250, "2.0.0", "OK");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_server_long_command
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch(const struct smtp_server_settings *server_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_disconnect =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_long_command_disconnect;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_helo =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_long_command_helo;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_rcpt =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_long_command_rcpt;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_data_begin =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_long_command_data_begin;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_run(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_long_command(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_settings smtp_server_set;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_defaults(&smtp_server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.command_limits.max_parameters_size = 32;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_begin("long command");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run_client_server(&smtp_server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_long_command,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_long_command, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_end();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Big data
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_big_data_connected(struct client_connection *conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)o_stream_send_str(conn->conn.output,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "EHLO frop\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "MAIL FROM:<sender@example.com>\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "RCPT TO:<recipient@example.com>\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "DATA\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ".\r\n");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_big_data(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected = test_big_data_connected;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_run(index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct _big_data {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *payload_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct io *io;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_big_data_trans_free(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _big_data *ctx =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (struct _big_data *)trans->context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(ctx);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_big_data_rcpt(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_rcpt *data)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("RCPT TO:%s",
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_address_encode(data->path));
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_big_data_data_begin(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *data_input)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _big_data *ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("DATA");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx = i_new(struct _big_data, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch trans->context = ctx;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ctx->payload_input = data_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_big_data_data_continue(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch static const size_t max_size = 32;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct _big_data *ctx =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (struct _big_data *)trans->context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch const unsigned char *data;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch size_t size;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch int ret;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("DATA continue");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch while (ctx->payload_input->v_offset < max_size &&
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (ret=i_stream_read_data(ctx->payload_input,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch &data, &size, 0)) > 0) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (ctx->payload_input->v_offset + size > max_size) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (ctx->payload_input->v_offset >= max_size)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch size = 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch else
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch size = max_size - ctx->payload_input->v_offset;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_stream_skip(ctx->payload_input, size);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (ctx->payload_input->v_offset >= max_size)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch break;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (ctx->payload_input->v_offset >= max_size) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply_early(cmd, 552, "5.3.4",
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "Message too big for system");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return -1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (ret == 0)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(FALSE);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_server_big_data
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch(const struct smtp_server_settings *server_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_trans_free =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_big_data_trans_free;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_rcpt =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_big_data_rcpt;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_data_begin =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_big_data_data_begin;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_data_continue =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_big_data_data_continue;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_run(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_big_data(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_settings smtp_server_set;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_defaults(&smtp_server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.command_limits.max_data_size = 64;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_begin("big_data");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run_client_server(&smtp_server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_big_data,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_big_data, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_end();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Bad EHLO
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_bad_ehlo_connected(struct client_connection *conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)o_stream_send_str(conn->conn.output,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch "EHLO \r\n");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_bad_ehlo(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected = test_bad_ehlo_connected;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_run(index);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstruct _bad_ehlo {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *payload_input;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct io *io;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bool serviced:1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_ehlo_disconnect(void *context ATTR_UNUSED, const char *reason)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("Disconnect: %s", reason);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_stop(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_ehlo_helo(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_helo *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_assert(FALSE);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_ehlo_rcpt(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_rcpt *data ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_bad_ehlo_data_begin(void *conn_ctx ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_cmd_ctx *cmd,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_transaction *trans ATTR_UNUSED,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct istream *data_input ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_reply(cmd, 250, "2.0.0", "OK");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_server_bad_ehlo
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch(const struct smtp_server_settings *server_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_disconnect =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_ehlo_disconnect;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_helo =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_ehlo_helo;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_rcpt =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_ehlo_rcpt;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_cmd_data_begin =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_ehlo_data_begin;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_run(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* test */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_bad_ehlo(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_settings smtp_server_set;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_defaults(&smtp_server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_begin("bad EHLO");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run_client_server(&smtp_server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_bad_ehlo,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_bad_ehlo, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_end();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch/*
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch * Too many recipients
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch */
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch/* client */
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschstatic void
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschtest_too_many_recipients_connected(struct client_connection *conn)
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch{
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch (void)o_stream_send_str(conn->conn.output,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "EHLO frop\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "MAIL FROM:<sender@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient1@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient2@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient3@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient4@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient5@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient6@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient7@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient8@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient9@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient10@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "RCPT TO:<recipient11@example.com>\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "DATA\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch "0123456789ABCDEF0123456789ABCDEF\r\n"
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch ".\r\n");
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch}
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschstatic void test_client_too_many_recipients(unsigned int index)
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch{
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_client_connected = test_too_many_recipients_connected;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_client_run(index);
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch}
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch/* server */
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschstatic void
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschtest_server_too_many_recipients_trans_free(void *conn_ctx ATTR_UNUSED,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct smtp_server_transaction *trans ATTR_UNUSED)
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch{
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch io_loop_stop(ioloop);
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch}
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschstatic int
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschtest_server_too_many_recipients_rcpt(void *conn_ctx ATTR_UNUSED,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct smtp_server_cmd_rcpt *data)
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch{
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch if (debug) {
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch i_debug("RCPT TO:%s",
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch smtp_address_encode(data->path));
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch }
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch return 1;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch}
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschstatic int
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschtest_server_too_many_recipients_data_begin(void *conn_ctx ATTR_UNUSED,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct smtp_server_cmd_ctx *cmd,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct smtp_server_transaction *trans,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct istream *data_input ATTR_UNUSED)
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch{
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_assert(array_count(&trans->rcpt_to) == 10);
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch smtp_server_reply(cmd, 250, "2.0.0", "OK");
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch return 1;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch}
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschstatic void test_server_too_many_recipients
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch(const struct smtp_server_settings *server_set)
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch{
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch server_callbacks.conn_trans_free =
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_server_too_many_recipients_trans_free;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch server_callbacks.conn_cmd_rcpt =
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_server_too_many_recipients_rcpt;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch server_callbacks.conn_cmd_data_begin =
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_server_too_many_recipients_data_begin;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_server_run(server_set);
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch}
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch/* test */
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Boschstatic void test_too_many_recipients(void)
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch{
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct smtp_server_settings smtp_server_set;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_server_defaults(&smtp_server_set);
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch smtp_server_set.max_client_idle_time_msecs = 1000;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch smtp_server_set.max_recipients = 10;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_begin("too many recipients");
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_run_client_server(&smtp_server_set,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_server_too_many_recipients,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_client_too_many_recipients, 1);
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_end();
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch}
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * All tests
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void (*const test_functions[])(void) = {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_slow_server,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_slow_client,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_hanging_command_payload,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_bad_command,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_long_command,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_big_data,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_bad_ehlo,
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch test_too_many_recipients,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch NULL
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Test client
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client connection */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschclient_connection_input(struct connection *_conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct client_connection *conn = (struct client_connection *)_conn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (test_client_input != NULL)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_input(conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschclient_connection_connected(struct connection *_conn, bool success)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct client_connection *conn = (struct client_connection *)_conn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("Client connected");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (success && test_client_connected != NULL)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_connected(conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschclient_connection_init(const struct ip_addr *ip, in_port_t port)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct client_connection *conn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch pool_t pool;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch pool = pool_alloconly_create("client connection", 256);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch conn = p_new(pool, struct client_connection, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch conn->pool = pool;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch connection_init_client_ip(client_conn_list,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch &conn->conn, ip, port);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)connection_client_connect(&conn->conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschserver_connection_deinit(struct client_connection **_conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct client_connection *conn = *_conn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch *_conn = NULL;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch connection_deinit(&conn->conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch pool_unref(&conn->pool);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschclient_connection_destroy(struct connection *_conn)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct client_connection *conn =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (struct client_connection *)_conn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_connection_deinit(&conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic struct connection_settings client_connection_set = {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch .input_max_size = (size_t)-1,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch .output_max_size = (size_t)-1,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch .client = TRUE
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic const struct connection_vfuncs client_connection_vfuncs = {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch .destroy = client_connection_destroy,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch .client_connected = client_connection_connected,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch .input = client_connection_input
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch};
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_client_run(unsigned int index)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_index = index;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("client connecting to %u", bind_port);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_conn_list = connection_list_init
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (&client_connection_set, &client_connection_vfuncs);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_connection_init(&bind_ip, bind_port);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_run(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* close server socket */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_remove(&io_listen);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch connection_list_deinit(&client_conn_list);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Test server
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_defaults(struct smtp_server_settings *smtp_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* server settings */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_zero(smtp_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_set->max_client_idle_time_msecs = 5*1000;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_set->max_pipelined_commands = 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_set->auth_optional = TRUE;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_set->debug = debug;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* client connection */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void server_connection_destroy(void *context)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct server_connection *sconn =
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (struct server_connection *)context;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(sconn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschserver_connection_accept(void *context ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct smtp_server_connection *conn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct server_connection *sconn;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch int fd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* accept new client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch fd = net_accept(fd_listen, NULL, NULL);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (fd == -1)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (fd == -2) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_fatal("test server: accept() failed: %m");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch sconn = i_new(struct server_connection, 1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_callbacks.conn_destroy = server_connection_destroy;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch conn = smtp_server_connection_create(smtp_server, fd, fd,
40a926a1aeae93b3d4944b56eacb013d3059b549Stephan Bosch NULL, 0, FALSE, NULL, &server_callbacks, sconn);
40a926a1aeae93b3d4944b56eacb013d3059b549Stephan Bosch smtp_server_connection_start(conn);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/* */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_timeout(void *context ATTR_UNUSED)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_fatal("Server timed out");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_server_run(const struct smtp_server_settings *smtp_set)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch struct timeout *to;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch to = timeout_add(SERVER_MAX_TIMEOUT_MSECS,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_timeout, NULL);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* open server socket */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_listen = io_add(fd_listen,
677b75f90d81eafe742896d6570a2f63ce501d05Josef 'Jeff' Sipek IO_READ, server_connection_accept, NULL);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server = smtp_server_init(smtp_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_run(ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* close server socket */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_remove(&io_listen);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch timeout_remove(&to);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch smtp_server_deinit(&smtp_server);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Tests
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic int test_open_server_fd(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch int fd = net_listen(&bind_ip, &bind_port, 128);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("server listening on %u", bind_port);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (fd == -1) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_fatal("listen(%s:%u) failed: %m",
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch net_ip2addr(&bind_ip), bind_port);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch return fd;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_clients_kill_all(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch unsigned int i;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (client_pids_count > 0) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch for (i = 0; i < client_pids_count; i++) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (client_pids[i] != (pid_t)-1) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)kill(client_pids[i], SIGKILL);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)waitpid(client_pids[i], NULL, 0);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids[i] = -1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids_count = 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_run_client_server(
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch const struct smtp_server_settings *server_set,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_server_init_t server_test,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_client_init_t client_test,
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch unsigned int client_tests_count)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch unsigned int i;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids = NULL;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids_count = 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch fd_listen = test_open_server_fd();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (client_tests_count > 0) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids = i_new(pid_t, client_tests_count);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch for (i = 0; i < client_tests_count; i++)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids[i] = (pid_t)-1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids_count = client_tests_count;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch for (i = 0; i < client_tests_count; i++) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if ((client_pids[i] = fork()) == (pid_t)-1)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_fatal("fork() failed: %m");
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (client_pids[i] == 0) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids[i] = (pid_t)-1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_pids_count = 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch hostpid_init();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("client[%d]: PID=%s", i+1, my_pid);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* child: client */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch usleep(100000); /* wait a little for server setup */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_close_fd(&fd_listen);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ioloop = io_loop_create();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch client_test(i);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_destroy(&ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(client_pids);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* wait for it to be killed; this way, valgrind
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch will not object to this process going away
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch inelegantly. */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch sleep(60);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch exit(1);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (debug)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_debug("server: PID=%s", my_pid);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* parent: server */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_zero(&server_callbacks);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch ioloop = io_loop_create();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch server_test(server_set);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch io_loop_destroy(&ioloop);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_close_fd(&fd_listen);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_clients_kill_all();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_free(client_pids);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch/*
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch * Main
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschvolatile sig_atomic_t terminating = 0;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschtest_signal_handler(int signo)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch if (terminating != 0)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch raise(signo);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch terminating = 1;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* make sure we don't leave any pesky children alive */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_clients_kill_all();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)signal(signo, SIG_DFL);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch raise(signo);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschstatic void test_atexit(void)
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_clients_kill_all();
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Boschint main(int argc, char *argv[])
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch{
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch int c;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch atexit(test_atexit);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)signal(SIGCHLD, SIG_IGN);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)signal(SIGTERM, test_signal_handler);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)signal(SIGQUIT, test_signal_handler);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)signal(SIGINT, test_signal_handler);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)signal(SIGSEGV, test_signal_handler);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch (void)signal(SIGABRT, test_signal_handler);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch while ((c = getopt(argc, argv, "D")) > 0) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch switch (c) {
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch case 'D':
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch debug = TRUE;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch break;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch default:
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_fatal("Usage: %s [-D]", argv[0]);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch }
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch /* listen on localhost */
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch i_zero(&bind_ip);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bind_ip.family = AF_INET;
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch bind_ip.u.ip4.s_addr = htonl(INADDR_LOOPBACK);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch test_run(test_functions);
b85d7b8561dba4072a61f6df26443896072efae9Stephan Bosch}