diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib-smtp/fuzz-smtp-server.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/lib-smtp/fuzz-smtp-server.c b/src/lib-smtp/fuzz-smtp-server.c new file mode 100644 index 0000000..4b5d21d --- /dev/null +++ b/src/lib-smtp/fuzz-smtp-server.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "fuzzer.h" +#include "istream.h" +#include "ioloop.h" +#include "smtp-server.h" + +static struct { + struct istream *data_input; +} state = { + .data_input = NULL, +}; + +static int +server_cmd_rcpt(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, + struct smtp_server_recipient *rcpt ATTR_UNUSED) +{ + return 1; +} + +static int +server_cmd_data_continue(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_transaction *trans ATTR_UNUSED) +{ + struct istream *data_input = state.data_input; + const unsigned char *data; + size_t size; + ssize_t ret; + + while ((ret = i_stream_read(data_input)) > 0 || ret == -2) { + data = i_stream_get_data(data_input, &size); + i_stream_skip(data_input, size); + if (!smtp_server_cmd_data_check_size(cmd)) + return -1; + } + + if (ret == 0) + return 0; + if (ret < 0 && data_input->stream_errno != 0) { + /* Client probably disconnected */ + return -1; + } + + smtp_server_reply_all(cmd, 250, "2.0.0", "Accepted"); + return 1; +} + +static int +server_cmd_data_begin(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, + struct smtp_server_transaction *trans ATTR_UNUSED, + struct istream *data_input) +{ + state.data_input = data_input; + return 0; +} + +static void server_connection_free(void *context) +{ + struct fuzzer_context *ctx = context; + io_loop_stop(ctx->ioloop); +} + +static void test_server_continue(struct fuzzer_context *ctx) +{ + //instead of simple io_loop_stop so as to free input io + io_loop_stop_delayed(ctx->ioloop); +} + +FUZZ_BEGIN_FD +{ + struct smtp_server_connection *conn; + struct smtp_server_settings smtp_server_set = { + .max_client_idle_time_msecs = 500, + .max_pipelined_commands = 16, + .auth_optional = TRUE, + }; + struct smtp_server_callbacks server_callbacks = { + .conn_cmd_rcpt = server_cmd_rcpt, + .conn_cmd_data_begin = server_cmd_data_begin, + .conn_cmd_data_continue = server_cmd_data_continue, + .conn_free = server_connection_free, + }; + struct smtp_server *smtp_server = NULL; + struct timeout *to; + + to = timeout_add_short(10, test_server_continue, &fuzz_ctx); + smtp_server = smtp_server_init(&smtp_server_set); + + conn = smtp_server_connection_create(smtp_server, fuzz_ctx.fd, fuzz_ctx.fd, NULL, 0, + FALSE, NULL, &server_callbacks, &fuzz_ctx); + smtp_server_connection_start(conn); + + io_loop_run(fuzz_ctx.ioloop); + + smtp_server_deinit(&smtp_server); + timeout_remove(&to); +} +FUZZ_END |