test-smtp-server-errors.c revision 4dd460cf19f1df3b51090427fea87e9c4b73c6d4
/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "array.h"
#include "hostpid.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "time-util.h"
#include "connection.h"
#include "test-common.h"
#include "smtp-address.h"
#include "smtp-server.h"
#include <signal.h>
#include <unistd.h>
/*
* Types
*/
struct server_connection {
void *context;
};
struct client_connection {
struct connection conn;
};
typedef void (*test_server_init_t)
(const struct smtp_server_settings *server_set);
typedef void (*test_client_init_t)(unsigned int index);
/*
* State
*/
/* common */
/* server */
static int fd_listen = -1;
static struct smtp_server_callbacks server_callbacks;
/* client */
static struct connection_list *client_conn_list;
static unsigned int client_pids_count = 0;
static unsigned int client_index;
/*
* Forward declarations
*/
/* server */
static void
static void
/* client */
static void test_client_run(unsigned int index);
/* test*/
static void test_run_client_server(
const struct smtp_server_settings *server_set,
unsigned int client_tests_count)
ATTR_NULL(3);
/*
* Slow server
*/
/* client */
static void
{
/* do nothing */
sleep(10);
}
static void
{
if (debug)
i_debug("CONNECTED");
"EHLO frop\r\n");
}
static void test_client_slow_server(unsigned int index)
{
}
/* server */
struct _slow_server {
struct smtp_server_cmd_ctx *cmd;
bool serviced:1;
};
static void
{
}
static void
{
struct smtp_server_reply *reply;
}
static int
struct smtp_server_cmd_ctx *cmd,
{
struct _slow_server *ctx;
if (debug)
i_debug("HELO");
return 0;
}
static void test_server_slow_server
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_slow_server(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("slow server");
test_end();
}
/*
* Slow client
*/
/* client */
static void
{
/* nothing */
}
static void
{
if (debug)
i_debug("CONNECTED");
"EHLO frop\r\n");
}
static void test_client_slow_client(unsigned int index)
{
}
/* server */
struct _slow_client {
struct smtp_server_cmd_ctx *cmd;
struct timeout *to_disconnect;
bool serviced:1;
};
static void
{
}
static void
{
if (debug)
}
static void
{
}
static void
{
struct smtp_server_reply *reply;
}
static int
struct smtp_server_cmd_ctx *cmd,
{
struct server_connection *conn =
(struct server_connection *)conn_ctx;
struct _slow_client *ctx;
if (debug)
i_debug("HELO");
return 0;
}
static void test_server_slow_client
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_slow_client(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("slow client");
test_end();
}
/*
* Hanging command payload
*/
/* client */
static void
{
"EHLO frop\r\n"
"MAIL FROM:<hangman@example.com>\r\n"
"RCPT TO:<jerry@example.com>\r\n"
"DATA\r\n"
"To be continued... or not");
}
static void test_client_hanging_command_payload(unsigned int index)
{
}
/* server */
struct _hanging_command_payload {
struct istream *payload_input;
bool serviced:1;
};
static void
struct smtp_server_transaction *trans)
{
struct _hanging_command_payload *ctx =
}
static int
struct smtp_server_cmd_rcpt *data)
{
if (debug) {
i_debug("RCPT TO:%s",
}
return 1;
}
static int
struct smtp_server_transaction *trans,
struct istream *data_input)
{
struct _hanging_command_payload *ctx;
if (debug)
i_debug("DATA");
return 0;
}
static int
struct smtp_server_cmd_ctx *cmd,
struct smtp_server_transaction *trans)
{
struct _hanging_command_payload *ctx =
const unsigned char *data;
int ret;
if (debug)
i_debug("DATA continue");
}
if (ret == 0)
return 0;
i_error("failed to read DATA payload: %s",
return -1;
}
return 1;
}
static void test_server_hanging_command_payload
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_hanging_command_payload(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("hanging command payload");
test_end();
}
/*
* Bad command
*/
/* client */
static void
{
"EHLO\tfrop\r\n");
}
static void test_client_bad_command(unsigned int index)
{
}
/* server */
struct _bad_command {
struct istream *payload_input;
bool serviced:1;
};
static void
{
if (debug)
}
static int
{
return 1;
}
static int
{
return 1;
}
static int
struct smtp_server_cmd_ctx *cmd,
{
return 1;
}
static void test_server_bad_command
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_bad_command(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("bad command");
test_end();
}
/*
* Long command
*/
/* client */
static void
{
"EHLO some.very.very.very.very.very.long.domain\r\n");
}
static void test_client_long_command(unsigned int index)
{
}
/* server */
struct _long_command {
struct istream *payload_input;
bool serviced:1;
};
static void
{
if (debug)
}
static int
{
return 1;
}
static int
{
return 1;
}
static int
struct smtp_server_cmd_ctx *cmd,
{
return 1;
}
static void test_server_long_command
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_long_command(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("long command");
test_end();
}
/*
* Big data
*/
/* client */
static void
{
"EHLO frop\r\n"
"MAIL FROM:<sender@example.com>\r\n"
"RCPT TO:<recipient@example.com>\r\n"
"DATA\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
".\r\n");
}
static void test_client_big_data(unsigned int index)
{
}
/* server */
struct _big_data {
struct istream *payload_input;
};
static void
struct smtp_server_transaction *trans)
{
}
static int
struct smtp_server_cmd_rcpt *data)
{
if (debug) {
i_debug("RCPT TO:%s",
}
return 1;
}
static int
struct smtp_server_transaction *trans,
struct istream *data_input)
{
if (debug)
i_debug("DATA");
return 0;
}
static int
struct smtp_server_cmd_ctx *cmd,
struct smtp_server_transaction *trans)
{
const unsigned char *data;
int ret;
if (debug)
i_debug("DATA continue");
size = 0;
else
}
break;
}
"Message too big for system");
return -1;
}
if (ret == 0)
return 0;
return 1;
}
static void test_server_big_data
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_big_data(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("big_data");
test_client_big_data, 1);
test_end();
}
/*
* Bad EHLO
*/
/* client */
static void
{
"EHLO \r\n");
}
static void test_client_bad_ehlo(unsigned int index)
{
}
/* server */
struct _bad_ehlo {
struct istream *payload_input;
bool serviced:1;
};
static void
{
if (debug)
}
static int
{
return 1;
}
static int
{
return 1;
}
static int
struct smtp_server_cmd_ctx *cmd,
{
return 1;
}
static void test_server_bad_ehlo
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_bad_ehlo(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("bad EHLO");
test_client_bad_ehlo, 1);
test_end();
}
/*
* Too many recipients
*/
/* client */
static void
{
"EHLO frop\r\n"
"MAIL FROM:<sender@example.com>\r\n"
"RCPT TO:<recipient1@example.com>\r\n"
"RCPT TO:<recipient2@example.com>\r\n"
"RCPT TO:<recipient3@example.com>\r\n"
"RCPT TO:<recipient4@example.com>\r\n"
"RCPT TO:<recipient5@example.com>\r\n"
"RCPT TO:<recipient6@example.com>\r\n"
"RCPT TO:<recipient7@example.com>\r\n"
"RCPT TO:<recipient8@example.com>\r\n"
"RCPT TO:<recipient9@example.com>\r\n"
"RCPT TO:<recipient10@example.com>\r\n"
"RCPT TO:<recipient11@example.com>\r\n"
"DATA\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
"0123456789ABCDEF0123456789ABCDEF\r\n"
".\r\n");
}
static void test_client_too_many_recipients(unsigned int index)
{
}
/* server */
static void
{
}
static int
struct smtp_server_cmd_rcpt *data)
{
if (debug) {
i_debug("RCPT TO:%s",
}
return 1;
}
static int
struct smtp_server_cmd_ctx *cmd,
struct smtp_server_transaction *trans,
{
return 1;
}
static void test_server_too_many_recipients
(const struct smtp_server_settings *server_set)
{
}
/* test */
static void test_too_many_recipients(void)
{
struct smtp_server_settings smtp_server_set;
test_begin("too many recipients");
test_end();
}
/*
* All tests
*/
static void (*const test_functions[])(void) = {
};
/*
* Test client
*/
/* client connection */
static void
{
if (test_client_input != NULL)
}
static void
{
if (debug)
i_debug("Client connected");
}
static void
{
struct client_connection *conn;
}
static void
{
}
static void
{
struct client_connection *conn =
(struct client_connection *)_conn;
}
/* */
static struct connection_settings client_connection_set = {
};
static const struct connection_vfuncs client_connection_vfuncs = {
};
static void test_client_run(unsigned int index)
{
if (debug)
/* close server socket */
}
/*
* Test server
*/
static void
{
/* server settings */
}
/* client connection */
static void server_connection_destroy(void *context)
{
struct server_connection *sconn =
(struct server_connection *)context;
}
static void
{
struct smtp_server_connection *conn;
struct server_connection *sconn;
int fd;
/* accept new client */
if (fd == -1)
return;
if (fd == -2) {
i_fatal("test server: accept() failed: %m");
}
}
/* */
static void
{
i_fatal("Server timed out");
}
static void
{
/* open server socket */
/* close server socket */
timeout_remove(&to);
}
/*
* Tests
*/
static int test_open_server_fd(void)
{
if (debug)
if (fd == -1) {
i_fatal("listen(%s:%u) failed: %m",
}
return fd;
}
static void test_clients_kill_all(void)
{
unsigned int i;
if (client_pids_count > 0) {
for (i = 0; i < client_pids_count; i++) {
client_pids[i] = -1;
}
}
}
client_pids_count = 0;
}
static void test_run_client_server(
const struct smtp_server_settings *server_set,
unsigned int client_tests_count)
{
unsigned int i;
client_pids = NULL;
client_pids_count = 0;
if (client_tests_count > 0) {
for (i = 0; i < client_tests_count; i++)
for (i = 0; i < client_tests_count; i++) {
i_fatal("fork() failed: %m");
if (client_pids[i] == 0) {
client_pids_count = 0;
hostpid_init();
if (debug)
/* child: client */
ioloop = io_loop_create();
client_test(i);
/* wait for it to be killed; this way, valgrind
will not object to this process going away
inelegantly. */
sleep(60);
exit(1);
}
}
if (debug)
}
/* parent: server */
ioloop = io_loop_create();
}
/*
* Main
*/
volatile sig_atomic_t terminating = 0;
static void
test_signal_handler(int signo)
{
if (terminating != 0)
terminating = 1;
/* make sure we don't leave any pesky children alive */
}
static void test_atexit(void)
{
}
{
int c;
switch (c) {
case 'D':
break;
default:
}
}
/* listen on localhost */
}