From: Stephan Bosch Date: Fri, 29 Oct 2021 17:37:16 +0000 (+0200) Subject: lib-smtp: test-smtp-server-errors - Add tests for very long AUTH response lines. X-Git-Tag: 2.3.18~169 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12eb20fc0d1cbd7dbbf594666a2eb1ff33fbd738;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: test-smtp-server-errors - Add tests for very long AUTH response lines. --- diff --git a/src/lib-smtp/test-smtp-server-errors.c b/src/lib-smtp/test-smtp-server-errors.c index d82e0d39db..314bde2643 100644 --- a/src/lib-smtp/test-smtp-server-errors.c +++ b/src/lib-smtp/test-smtp-server-errors.c @@ -821,6 +821,313 @@ static void test_long_command(void) test_end(); } +/* + * Long auth line + */ + +/* client */ + +#define _LONG_AUTH_LINE_DATA \ + "dXNlcj10ZXN0dXNlcjEBYXV0aD1CZWFyZXIgZXlKaGJHY2lPaUpTVXpJMU5pSXNJ" \ + "blI1Y0NJZ09pQWlTbGRVSWl3aWEybGtJaUE2SUNKdVRIRlVlRnBXWVhKSlgwWndS" \ + "a0Z3Umt3MloyUnhiak4xV1VSS2R6WnNWVjlMYVZoa2JWazJialpSSW4wLmV5Smxl" \ + "SEFpT2pFMk16UTJNemMyTlRFc0ltbGhkQ0k2TVRZek5EWXpOek0xTVN3aWFuUnBJ" \ + "am9pT1RFM1lUYzFaalF0WTJZME9DMDBOVEEyTFRnNVpXSXRNRE13WldaaU5tSTVO" \ + "MlZrSWl3aWFYTnpJam9pYUhSMGNEb3ZMekU1TWk0eE5qZ3VNUzR5TVRveE9EQTRN" \ + "QzloZFhSb0wzSmxZV3h0Y3k5eVpXeDBaWE4wSWl3aVlYVmtJam9pWVdOamIzVnVk" \ + "Q0lzSW5OMVlpSTZJamhsWVRRME1UWTNMVGN6TTJVdE5EVTBZeTFpT0dJMUxXTmpa" \ + "bVl3WkRnek1URTVaQ0lzSW5SNWNDSTZJa0psWVhKbGNpSXNJbUY2Y0NJNkltUnZk" \ + "bVZqYjNRaUxDSnpaWE56YVc5dVgzTjBZWFJsSWpvaU1tTTNPVEUzWldJdE16QTFO" \ + "UzAwTkRZeExXSXdZell0WTJVeFlUbGlNVEZoTWpReklpd2lZV055SWpvaU1TSXNJ" \ + "bkpsWVd4dFgyRmpZMlZ6Y3lJNmV5SnliMnhsY3lJNld5SnZabVpzYVc1bFgyRmpZ" \ + "MlZ6Y3lJc0luVnRZVjloZFhSb2IzSnBlbUYwYVc5dUlsMTlMQ0p5WlhOdmRYSmpa" \ + "VjloWTJObGMzTWlPbnNpWVdOamIzVnVkQ0k2ZXlKeWIyeGxjeUk2V3lKdFlXNWha" \ + "MlV0WVdOamIzVnVkQ0lzSW0xaGJtRm5aUzFoWTJOdmRXNTBMV3hwYm10eklpd2lk" \ + "bWxsZHkxd2NtOW1hV3hsSWwxOWZTd2ljMk52Y0dVaU9pSndjbTltYVd4bElHVnRZ" \ + "V2xzSWl3aVpXMWhhV3hmZG1WeWFXWnBaV1FpT21aaGJITmxMQ0p1WVcxbElqb2lk" \ + "R1Z6ZEhWelpYSXhJRUYxZEc5SFpXNWxjbUYwWldRaUxDSndjbVZtWlhKeVpXUmZk" \ + "WE5sY201aGJXVWlPaUowWlhOMGRYTmxjakVpTENKbmFYWmxibDl1WVcxbElqb2lk" \ + "R1Z6ZEhWelpYSXhJaXdpWm1GdGFXeDVYMjVoYldVaU9pSkJkWFJ2UjJWdVpYSmhk" \ + "R1ZrSWl3aVpXMWhhV3dpT2lKMFpYTjBkWE5sY2pGQWJYbGtiMjFoYVc0dWIzZ2lm" \ + "US5ta2JGSURpT0FhbENCcVMwODRhVHJURjBIdDk1c1Z4cGlSbTFqZnhJd0JiN1hM" \ + "M2gzWUJkdXVrVXlZdDJqX1pqUFlhMDhDcVVYNWFrLVBOSjdSVWRTUXNmUlgwM1Zi" \ + "cXA4MHFZZjNGYzJpcDR0YmhHLXFEV0R6NzdhZDhWcEFNei16YWlSamZCclZ2R3hB" \ + "T3ZsZnFDVWhaZTJDR3ZqWjZ1Q3RKTlFaS0dyazZHOXoxX2pqekZkTjBXWjUxbEZs" \ + "US1JdE5LREpoTjNIekJ5SW93M19qQU9kWEI0R0w4R3JHM1hqU09rSFVRam5GTEQw" \ + "QUF1QXY4SkxmTXY1NGc1a2tKaklxRFgxZlgyWVo0Y2JQOWV3TUp6UV84ZWdLeW5T" \ + "VV9XSk8xRU9Qa1NVZjlMX19RX3FwY0dNbzFtTkxuTURKUlU2dmZFY3JrM2k0cVNz" \ + "MXRPdHdLaHcBAQ" + +struct _long_auth_line_client { + struct smtp_reply_parser *parser; + unsigned int reply; + + bool replied:1; +}; + +static void test_long_auth_line_client_input(struct client_connection *conn) +{ + struct _long_auth_line_client *ctx = conn->context; + struct smtp_reply *reply; + const char *error; + int ret; + + while ((ret = smtp_reply_parse_next(ctx->parser, FALSE, + &reply, &error)) > 0) { + if (debug) + i_debug("REPLY: %s", smtp_reply_log(reply)); + + switch (ctx->reply++) { + case 0: /* greeting */ + i_assert(reply->status == 220); + break; + case 1: /* EHLO reply */ + i_assert(reply->status == 250); + break; + case 2: /* AUTH continue */ + i_assert(reply->status == 334); + break; + case 3: /* AUTH reply */ + switch (client_index) { + case 0: + i_assert(reply->status == 235); + break; + case 1: + i_assert(reply->status == 235); + break; + case 2: + i_assert(reply->status == 500); + ctx->replied = TRUE; + io_loop_stop(ioloop); + connection_disconnect(&conn->conn); + return; + default: + i_unreached(); + } + break; + case 4: /* MAIL reply */ + i_assert(client_index < 2); + i_assert(reply->status == 250); + break; + case 5: /* RCPT reply */ + i_assert(client_index < 2); + i_assert(reply->status == 250); + break; + case 6: /* DATA initial reply */ + i_assert(client_index < 2); + i_assert(reply->status == 354); + break; + case 7: /* DATA reply */ + i_assert(client_index < 2); + i_assert(reply->status == 250); + break; + case 8: /* QUIT reply */ + i_assert(client_index < 2); + i_assert(reply->status == 221); + ctx->replied = TRUE; + io_loop_stop(ioloop); + connection_disconnect(&conn->conn); + return; + default: + i_unreached(); + } + } + + i_assert(ret >= 0); +} + +static void test_long_auth_line_client_connected(struct client_connection *conn) +{ + struct _long_auth_line_client *ctx; + unsigned int i; + + ctx = p_new(conn->pool, struct _long_auth_line_client, 1); + ctx->parser = smtp_reply_parser_init(conn->conn.input, SIZE_MAX); + conn->context = ctx; + + o_stream_nsend_str( + conn->conn.output, + "EHLO frop\r\n" + "AUTH XOAUTH2\r\n"); + for (i = 0; i < (client_index > 1 ? 6 : 1); i++) + o_stream_nsend_str(conn->conn.output, _LONG_AUTH_LINE_DATA); + o_stream_nsend_str( + conn->conn.output, + "=="); + if (client_index == 1) { + o_stream_nsend_str( + conn->conn.output, + " "); + } + o_stream_nsend_str( + conn->conn.output, + "\r\n" + "MAIL FROM:\r\n" + "RCPT TO:\r\n" + "DATA\r\n" + "frop\r\n" + ".\r\n" + "QUIT\r\n"); +} + +static void test_long_auth_line_client_deinit(struct client_connection *conn) +{ + struct _long_auth_line_client *ctx = conn->context; + + i_assert(ctx->replied); + smtp_reply_parser_deinit(&ctx->parser); +} + +static void test_client_long_auth_line(unsigned int index) +{ + test_client_input = test_long_auth_line_client_input; + test_client_connected = test_long_auth_line_client_connected; + test_client_deinit = test_long_auth_line_client_deinit; + test_client_run(index); +} + +/* server */ + +struct _long_auth_line { + struct istream *payload_input; +}; + +static void +test_server_long_auth_line_disconnect(void *context ATTR_UNUSED, + const char *reason) +{ + if (debug) + i_debug("Disconnect: %s", reason); +} + +static int +test_server_long_auth_line_helo(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, + struct smtp_server_cmd_helo *data ATTR_UNUSED) +{ + return 1; +} + +static int +test_server_long_auth_line_auth(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_auth *data ATTR_UNUSED) +{ + smtp_server_cmd_auth_send_challenge(cmd, ""); + return 0; +} + +static int +test_server_long_auth_line_auth_continue(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd, + const char *response) +{ + if (strcmp(response, _LONG_AUTH_LINE_DATA"==") == 0) + smtp_server_cmd_auth_success(cmd, "user", NULL); + else { + smtp_server_reply(cmd, 535, "5.7.8", + "Authentication credentials invalid"); + } + return 1; +} + +static int +test_server_long_auth_line_rcpt(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, + struct smtp_server_recipient *rcpt ATTR_UNUSED) +{ + if (debug) + i_debug("RCPT"); + return 1; +} + +static int +test_server_long_auth_line_data_begin(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, + struct smtp_server_transaction *trans, + struct istream *data_input) +{ + struct _long_auth_line *ctx; + + if (debug) + i_debug("DATA"); + + ctx = p_new(trans->pool, struct _long_auth_line, 1); + trans->context = ctx; + + ctx->payload_input = data_input; + return 0; +} + +static int +test_server_long_auth_line_data_continue(void *conn_ctx ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_transaction *trans) +{ + struct _long_auth_line *ctx = (struct _long_auth_line *)trans->context; + struct istream *data_input = ctx->payload_input; + size_t size; + ssize_t ret; + + if (debug) + i_debug("DATA continue"); + + while ((ret = i_stream_read(data_input)) > 0 || ret == -2) { + (void)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 void +test_server_long_auth_line(const struct smtp_server_settings *server_set) +{ + server_callbacks.conn_disconnect = + test_server_long_auth_line_disconnect; + + server_callbacks.conn_cmd_helo = + test_server_long_auth_line_helo; + server_callbacks.conn_cmd_auth = + test_server_long_auth_line_auth; + server_callbacks.conn_cmd_auth_continue = + test_server_long_auth_line_auth_continue; + server_callbacks.conn_cmd_rcpt = + test_server_long_auth_line_rcpt; + server_callbacks.conn_cmd_data_begin = + test_server_long_auth_line_data_begin; + server_callbacks.conn_cmd_data_continue = + test_server_long_auth_line_data_continue; + test_server_run(server_set); +} + +/* test */ + +static void test_long_auth_line(void) +{ + struct smtp_server_settings smtp_server_set; + + test_server_defaults(&smtp_server_set); + smtp_server_set.capabilities = SMTP_CAPABILITY_AUTH; + smtp_server_set.max_client_idle_time_msecs = 1000; + + test_begin("long auth line"); + test_run_client_server(&smtp_server_set, + test_server_long_auth_line, + test_client_long_auth_line, 3); + test_end(); +} + /* * Big data */ @@ -3174,6 +3481,7 @@ static void (*const test_functions[])(void) = { test_bad_command, test_many_bad_commands, test_long_command, + test_long_auth_line, test_big_data, test_bad_helo, test_bad_mail,