diff options
Diffstat (limited to 'test')
22 files changed, 508 insertions, 0 deletions
diff --git a/test/decoders/mail/CMakeLists.txt b/test/decoders/mail/CMakeLists.txt new file mode 100644 index 0000000..378f401 --- /dev/null +++ b/test/decoders/mail/CMakeLists.txt @@ -0,0 +1,53 @@ +set(TEST_NAME mail_test) +set(TEST_MAIN ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}) + +file(GLOB TEST_SRC "${TEST_NAME}*.cpp") + +add_executable( + ${TEST_NAME} + ${TEST_SRC} +) + +target_include_directories( + ${TEST_NAME} PRIVATE + ${CMAKE_SOURCE_DIR}/deps/ + ${CMAKE_SOURCE_DIR}/decoders/ +) + +target_link_libraries( + ${TEST_NAME} + mail + stellar_lib + cjson-static + dl "-rdynamic" + gtest + gmock +) + +add_test( NAME ${TEST_NAME}.SETUP + COMMAND sh -c " + mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/result/ && + mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/log/ && + mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/conf/ && + cat ${CMAKE_SOURCE_DIR}/conf/stellar.toml > ${CMAKE_CURRENT_BINARY_DIR}/conf/stellar.toml && + cat ${CMAKE_CURRENT_SOURCE_DIR}/conf/spec.toml >> ${CMAKE_CURRENT_BINARY_DIR}/conf/stellar.toml && + sed -i 's/mode = \"pcapfile\"/mode = \"pcaplist\"/g' ${CMAKE_CURRENT_BINARY_DIR}/conf/stellar.toml && + sed -i 's/pcap_path = \"\\\/tmp\\\/test.pcap\"/pcap_path = \"pcaplist.txt\"/g' ${CMAKE_CURRENT_BINARY_DIR}/conf/stellar.toml && + find ${CMAKE_CURRENT_SOURCE_DIR}/result/ -type f | xargs -i cp {} ${CMAKE_CURRENT_BINARY_DIR}/result/ && + find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/ -type f > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all + " +) + +add_test( + NAME ${TEST_NAME}.imap + COMMAND sh -c " + cat ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all | grep '01-imap-mail-account-in-command-with-base64' > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.txt && + ${TEST_MAIN} -m -c ./conf/stellar.toml -f ${CMAKE_CURRENT_BINARY_DIR}/result/01-imap-mail-account-in-command-with-base64.json + " +) + +set_tests_properties( + ${TEST_NAME}.imap + PROPERTIES + FIXTURES_REQUIRED ${TEST_NAME}.SETUP +) diff --git a/test/decoders/mail/mail_test_main.cpp b/test/decoders/mail/mail_test_main.cpp new file mode 100644 index 0000000..8cbaa1b --- /dev/null +++ b/test/decoders/mail/mail_test_main.cpp @@ -0,0 +1,80 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "stellar/stellar.h" + +#include <gtest/gtest.h> + +const char *usage = "Usage: %s [-m] [-u test_filter] [-c config_file] [-f result_file]\n"; + +int main(int argc, char **argv) { + int opt; + int run_unittest = 0; + int run_stellar = 0; + const char *test_filter = NULL; + const char *result_filename = NULL; + const char *conf_filename = NULL; + + if (argc == 1) { + fprintf(stderr, usage, argv[0]); + exit(-1); + } + + while ((opt = getopt(argc, argv, "hmu:c:f:")) != -1) { + switch (opt) { + case 'u': + run_unittest = 1; + test_filter = optarg; + break; + case 'm': + run_stellar = 1; + break; + case 'f': + result_filename = optarg; + break; + case 'c': + conf_filename = optarg; + break; + case 'h': + default: + fprintf(stderr, usage, argv[0]); + exit(-1); + } + } + + ::testing::InitGoogleTest(&argc, argv); + + if (run_unittest) { + testing::GTEST_FLAG(filter) = test_filter ? test_filter : ""; + int test_ret = RUN_ALL_TESTS(); + if (test_ret != 0) { + fprintf(stderr, "Tests failed with return code %d\n", test_ret); + return test_ret; + } + } + + if (run_stellar) { + if (result_filename == NULL) { + result_filename = "./mail_result.json"; + } + // setenv for mail test module + setenv("MAIL_TEST_RESULT_EXPECT", result_filename, 1); + + if (conf_filename == NULL) { + conf_filename = "./conf/stellar.toml"; + } + + struct stellar *st = stellar_new(conf_filename); + if (st == NULL) { + fprintf(stderr, "Failed to create stellar instance.\n"); + return -1; + } + + stellar_run(st); + stellar_free(st); + } + + return ::testing::Test::HasFailure() ? -1 : 0; +} + diff --git a/test/decoders/mail/mail_test_module.cpp b/test/decoders/mail/mail_test_module.cpp new file mode 100644 index 0000000..827d273 --- /dev/null +++ b/test/decoders/mail/mail_test_module.cpp @@ -0,0 +1,367 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> + +#include "stellar/stellar.h" +#include "stellar/module.h" +#include "stellar/session.h" +#include "stellar/utils.h" +#include "stellar/mail.h" + +#include <gtest/gtest.h> +#include <uthash/uthash.h> +#include "cjson/cJSON.h" + +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-function" + +#define MAIL_TEST_MODULE_NAME "MAIL_TEST_MODULE" +#define MAIL_TEST_RESULT_EXPECT_ENV "MAIL_TEST_RESULT_EXPECT" +#define MAIL_TEST_EXDATA_NAME "MAIL_TEST_EXDATA" + +#define MAIL_TEST_TRANSACTION_SEQ_MAX 64 + +#define timeval_delta_ms(start, end) (((end).tv_sec-(start).tv_sec)*1000 + ((end).tv_usec-(start).tv_usec)/1000) +#define timeval_delta_us(start, end) (((end).tv_sec-(start).tv_sec)*1000*1000 + ((end).tv_usec-(start).tv_usec)) +#define timeval_to_ms(t) ((t).tv_sec*1000+(t).tv_usec/1000) + +struct mail_test_sockaddr_in { + int family; + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } sockaddr; +}; + +struct mail_test_exdata { + int callback_times; + struct mail_test_module_ctx *mod_ctx_ref; +}; + +struct mail_test_result { + cJSON *test_json; + cJSON *expect_json; + int count; +}; + +struct mail_test_module_ctx { + int exdata_id; + struct mail_test_result *result; + + // depends a single session pcap + int callback_times; + struct module_manager *mod_mgr_ref; +}; + +const char *mail_protocol_name[]={"SMTP", "POP3", "IMAP"}; + +static void mail_test_result_commit(struct mail_test_result *result, cJSON *json) +{ + cJSON_AddNumberToObject(json, "test_result", ++result->count); + cJSON_AddItemToArray(result->test_json, json); +} + +static void mail_test_result_compare(struct mail_test_result *result) +{ + EXPECT_TRUE(result->expect_json != NULL); + EXPECT_TRUE(result->test_json != NULL); + + int i, json_compare; + int test_result_count, expect_result_count; + char *test_str, *expect_str; + cJSON *tmp_test, *tmp_expect; + + //expect_str = cJSON_Print(result->expect_json); + //test_str = cJSON_Print(result->test_json); + //printf("LOAD Raw:\n%s\n", expect_str); + //printf("TEST Raw:\n%s\n", test_str); + + test_result_count = cJSON_GetArraySize(result->test_json); + expect_result_count = cJSON_GetArraySize(result->expect_json); + + EXPECT_EQ(test_result_count, expect_result_count); + + for (i = 0; i < MIN(test_result_count, expect_result_count); i++) { + tmp_test = cJSON_GetArrayItem(result->test_json, i); + tmp_expect = cJSON_GetArrayItem(result->expect_json, i); + expect_str = cJSON_Print(tmp_expect); + test_str = cJSON_Print(tmp_test); + + json_compare = cJSON_Compare(tmp_expect, tmp_test, 0); + if (json_compare != 1) { + printf("LOAD Diff:\n%s\n", expect_str); + printf("TEST Diff:\n%s\n", test_str); + } + + free(expect_str); + free(test_str); + + EXPECT_EQ(json_compare, 1); + break; + } +} + +static void mail_test_result_exit(struct mail_test_result *result) +{ + if (result->expect_json) { + cJSON_Delete(result->expect_json); + } + if (result->test_json) { + cJSON_Delete(result->test_json); + } + free(result); +} + +static struct mail_test_result * mail_test_result_init(const char *filename) +{ + long filesize; + char *buffer; + FILE *file; + struct mail_test_result *result; + + result = (struct mail_test_result *)calloc(1, sizeof(struct mail_test_result)); + + file = fopen(filename, "rb"); + if (file) { + fseek(file, 0, SEEK_END); + filesize = ftell(file); + rewind(file); + buffer = (char *)calloc(filesize + 1, 1); + fread(buffer, 1, filesize, file); + + result->expect_json = cJSON_Parse(buffer); + + free(buffer); + fclose(file); + } + + result->test_json = cJSON_CreateArray(); + + printf("mail test result expect: %s\n", filename); + return result; +} + +static void mail_test_store_packet_dst(struct mail_test_sockaddr_in *sockaddr, const struct packet *pkt) { + const struct layer *layer; + + if (sockaddr == NULL) { + return; + } + + memset(sockaddr, 0, sizeof(struct mail_test_sockaddr_in)); + + layer = packet_get_layer_by_idx(pkt, packet_get_layer_count(pkt) - 2); + if (layer->proto == LAYER_PROTO_IPV4) { + sockaddr->family = AF_INET; + sockaddr->sockaddr.ipv4.sin_family = AF_INET; + sockaddr->sockaddr.ipv4.sin_addr = layer->hdr.ip4->ip_dst; + + layer = packet_get_layer_by_idx(pkt, packet_get_layer_count(pkt) - 1); + if (layer->proto == LAYER_PROTO_TCP) { + sockaddr->sockaddr.ipv4.sin_port = htons(layer->hdr.tcp->dest); + } + if (layer->proto == LAYER_PROTO_UDP) { + sockaddr->sockaddr.ipv4.sin_port = htons(layer->hdr.udp->dest); + } + } + if (layer->proto == LAYER_PROTO_IPV6) { + sockaddr->family = AF_INET6; + sockaddr->sockaddr.ipv6.sin6_family = AF_INET6; + memcpy(&sockaddr->sockaddr.ipv6.sin6_addr, &layer->hdr.ip6->ip6_dst, sizeof(struct in6_addr)); + + layer = packet_get_layer_by_idx(pkt, packet_get_layer_count(pkt) - 2); + if (layer->proto == LAYER_PROTO_TCP) { + sockaddr->sockaddr.ipv6.sin6_port = htons(layer->hdr.tcp->dest); + } + if (layer->proto == LAYER_PROTO_UDP) { + sockaddr->sockaddr.ipv6.sin6_port = htons(layer->hdr.udp->dest); + } + } +} + +static void mail_test_store_packet_src(struct mail_test_sockaddr_in *sockaddr, const struct packet *pkt) { + const struct layer *layer; + + if (sockaddr == NULL) { + return; + } + + memset(sockaddr, 0, sizeof(struct mail_test_sockaddr_in)); + + layer = packet_get_layer_by_idx(pkt, packet_get_layer_count(pkt) - 2); + if (layer->proto == LAYER_PROTO_IPV4) { + sockaddr->family = AF_INET; + sockaddr->sockaddr.ipv4.sin_family = AF_INET; + sockaddr->sockaddr.ipv4.sin_addr = layer->hdr.ip4->ip_src; + + layer = packet_get_layer_by_idx(pkt, packet_get_layer_count(pkt) - 1); + if (layer->proto == LAYER_PROTO_TCP) { + sockaddr->sockaddr.ipv4.sin_port = htons(layer->hdr.tcp->source); + } + if (layer->proto == LAYER_PROTO_UDP) { + sockaddr->sockaddr.ipv4.sin_port = htons(layer->hdr.udp->source); + } + } + if (layer->proto == LAYER_PROTO_IPV6) { + sockaddr->family = AF_INET6; + sockaddr->sockaddr.ipv6.sin6_family = AF_INET6; + memcpy(&sockaddr->sockaddr.ipv6.sin6_addr, &layer->hdr.ip6->ip6_src, sizeof(struct in6_addr)); + + layer = packet_get_layer_by_idx(pkt, packet_get_layer_count(pkt) - 2); + if (layer->proto == LAYER_PROTO_TCP) { + sockaddr->sockaddr.ipv6.sin6_port = htons(layer->hdr.tcp->source); + } + if (layer->proto == LAYER_PROTO_UDP) { + sockaddr->sockaddr.ipv6.sin6_port = htons(layer->hdr.udp->source); + } + } +} + +static int mail_test_compare_packet_src(struct mail_test_sockaddr_in *sockaddr, const struct packet *pkt) +{ + struct mail_test_sockaddr_in pkt_src; + mail_test_store_packet_src(&pkt_src, pkt); + return 0 == memcmp(sockaddr, &pkt_src, sizeof(pkt_src)); +} + +void mail_test_exdata_free(struct mail_test_exdata *exdata) +{ + if (exdata) { + free(exdata); + } +} + +struct mail_test_exdata * mail_test_exdata_new(void) +{ + struct mail_test_exdata *exdata; + exdata = (struct mail_test_exdata *)calloc(1, sizeof(struct mail_test_exdata)); + return exdata; +} + +void mail_test_command_callback(struct session *sess, + enum MAIL_PROTOCOL mail_protocol, size_t mail_seq, + enum MAIL_COMMAND command, + char *cmd_param, size_t cmd_param_len, + char *cmd_line, size_t cmd_line_len, + void *arg) +{ + printf("mail command callback\n"); + printf("%.*s\n", cmd_line_len, cmd_line); +} + +void mail_test_header_callback(struct session *sess, + enum MAIL_PROTOCOL mail_protocol, size_t mail_seq, + struct mail_header *header, + void *arg) +{ + printf("mail header callback\n"); +} + +void mail_test_body_callback(struct session *sess, + enum MAIL_PROTOCOL mail_protocol, size_t mail_seq, + char *body, size_t body_len, size_t offset, int is_finish, + void *arg) +{ + printf("mail body callback\n"); +} + +void mail_test_attachment_callback(struct session *sess, + enum MAIL_PROTOCOL mail_protocol, size_t mail_seq, + char *name, size_t name_len, + char *attachment, size_t attachment_len, size_t offset, int is_finish, + void *arg) +{ + printf("mail attachment callback\n"); +} + +void mail_test_eml_callback(struct session *sess, + enum MAIL_PROTOCOL mail_protocol, + char *eml, size_t eml_len, size_t offset, int is_finish, + void *arg) +{ + struct mail_test_exdata *exdata; + struct mail_test_module_ctx *mod_ctx = (struct mail_test_module_ctx *)arg; + + exdata = (struct mail_test_exdata *)session_get_exdata(sess, mod_ctx->exdata_id); + if (exdata == NULL) { + exdata = (struct mail_test_exdata *)calloc(1, sizeof(struct mail_test_exdata)); + session_set_exdata(sess, mod_ctx->exdata_id, exdata); + } + + printf("mail eml callback: %s\n", mail_protocol_name[mail_protocol]); + +} + +void mail_test_on_exdata_free(int idx, void *ex_ptr, void *arg) +{ + (void)(idx); + (void)(arg); + struct mail_test_exdata *exdata = (struct mail_test_exdata *)ex_ptr; + + if (exdata) { + mail_test_exdata_free(exdata); + } +} + +extern "C" void mail_test_exit(struct module_manager *mod_mgr, struct module *mod) +{ + (void)(mod_mgr); + struct mail_test_module_ctx *mod_ctx; + + if (mod) { + mod_ctx = (struct mail_test_module_ctx *)module_get_ctx(mod); + if (mod_ctx) { + mail_test_result_compare(mod_ctx->result); + mail_test_result_exit(mod_ctx->result); + free(mod_ctx); + } + module_free(mod); + } +} + +extern "C" struct module *mail_test_init(struct module_manager *mod_mgr) +{ + int ret; + struct module *mod; + struct mail_test_module_ctx *mod_ctx; + struct session_manager *sess_mgr; + struct mail_decoder *decoder; + + mod_ctx = (struct mail_test_module_ctx *)calloc(1, sizeof(struct mail_test_module_ctx)); + mod_ctx->mod_mgr_ref = mod_mgr; + mod = module_new(MAIL_TEST_MODULE_NAME, mod_ctx); + sess_mgr = module_to_session_manager(module_manager_get_module(mod_mgr, SESSION_MANAGER_MODULE_NAME)); + + if (mod_mgr == NULL || sess_mgr == NULL) { + goto exit; + } + + mod_ctx->exdata_id = session_manager_new_session_exdata_index(sess_mgr, MAIL_TEST_EXDATA_NAME, mail_test_on_exdata_free, mod_ctx); + if (mod_ctx->exdata_id < 0) { + goto exit; + } + + mod_ctx->result = mail_test_result_init(getenv(MAIL_TEST_RESULT_EXPECT_ENV)); + if (mod_ctx->result == NULL) { + goto exit; + } + + decoder = module_to_mail_decoder(module_manager_get_module(mod_mgr, MAIL_MODULE_NAME)); + ret = mail_subscribe(decoder, + mail_test_command_callback, + mail_test_header_callback, + mail_test_body_callback, + mail_test_attachment_callback, + mail_test_eml_callback, + mod_ctx); + if (ret < 0) { + goto exit; + } + + return mod; +exit: + printf("mail_test module init failed!\n"); + mail_test_exit(mod_mgr, mod); + return NULL; +} + diff --git a/test/decoders/mail/pcap/01-imap-mail-account-in-command-with-base64.pcap b/test/decoders/mail/pcap/01-imap-mail-account-in-command-with-base64.pcap Binary files differnew file mode 100644 index 0000000..d4344c7 --- /dev/null +++ b/test/decoders/mail/pcap/01-imap-mail-account-in-command-with-base64.pcap diff --git a/test/decoders/mail/pcap/02-imap-starttls.pcap b/test/decoders/mail/pcap/02-imap-starttls.pcap Binary files differnew file mode 100644 index 0000000..2fd3bf8 --- /dev/null +++ b/test/decoders/mail/pcap/02-imap-starttls.pcap diff --git a/test/decoders/mail/pcap/03-smtp-s2c-mail.pcap b/test/decoders/mail/pcap/03-smtp-s2c-mail.pcap Binary files differnew file mode 100644 index 0000000..3549c0d --- /dev/null +++ b/test/decoders/mail/pcap/03-smtp-s2c-mail.pcap diff --git a/test/decoders/mail/pcap/04-smtp-attachment-charset-unknown.pcap b/test/decoders/mail/pcap/04-smtp-attachment-charset-unknown.pcap Binary files differnew file mode 100644 index 0000000..1cd8cfc --- /dev/null +++ b/test/decoders/mail/pcap/04-smtp-attachment-charset-unknown.pcap diff --git a/test/decoders/mail/pcap/05-smtp-curl-mails.pcap b/test/decoders/mail/pcap/05-smtp-curl-mails.pcap Binary files differnew file mode 100644 index 0000000..b452fd7 --- /dev/null +++ b/test/decoders/mail/pcap/05-smtp-curl-mails.pcap diff --git a/test/decoders/mail/pcap/06-smtp-starttls.pcap b/test/decoders/mail/pcap/06-smtp-starttls.pcap Binary files differnew file mode 100644 index 0000000..c26ec62 --- /dev/null +++ b/test/decoders/mail/pcap/06-smtp-starttls.pcap diff --git a/test/decoders/mail/pcap/07-smtp-auth-xoauth2.pcap b/test/decoders/mail/pcap/07-smtp-auth-xoauth2.pcap Binary files differnew file mode 100644 index 0000000..b6e3bf8 --- /dev/null +++ b/test/decoders/mail/pcap/07-smtp-auth-xoauth2.pcap diff --git a/test/decoders/mail/pcap/08-smtp-mime-header-rfc2047.pcap b/test/decoders/mail/pcap/08-smtp-mime-header-rfc2047.pcap Binary files differnew file mode 100644 index 0000000..c7754e0 --- /dev/null +++ b/test/decoders/mail/pcap/08-smtp-mime-header-rfc2047.pcap diff --git a/test/decoders/mail/pcap/09-pop3-c2s-55325-1100.pcap b/test/decoders/mail/pcap/09-pop3-c2s-55325-1100.pcap Binary files differnew file mode 100644 index 0000000..3b54a68 --- /dev/null +++ b/test/decoders/mail/pcap/09-pop3-c2s-55325-1100.pcap diff --git a/test/decoders/mail/pcap/10-pop3-s2c-1100-55325.pcap b/test/decoders/mail/pcap/10-pop3-s2c-1100-55325.pcap Binary files differnew file mode 100644 index 0000000..f018536 --- /dev/null +++ b/test/decoders/mail/pcap/10-pop3-s2c-1100-55325.pcap diff --git a/test/decoders/mail/pcap/11-pop3-c2s.pcap b/test/decoders/mail/pcap/11-pop3-c2s.pcap Binary files differnew file mode 100644 index 0000000..dc1c679 --- /dev/null +++ b/test/decoders/mail/pcap/11-pop3-c2s.pcap diff --git a/test/decoders/mail/pcap/12-pop3-s2c.pcap b/test/decoders/mail/pcap/12-pop3-s2c.pcap Binary files differnew file mode 100644 index 0000000..810d885 --- /dev/null +++ b/test/decoders/mail/pcap/12-pop3-s2c.pcap diff --git a/test/decoders/mail/pcap/13-pop3-mail.pcap b/test/decoders/mail/pcap/13-pop3-mail.pcap Binary files differnew file mode 100644 index 0000000..6663699 --- /dev/null +++ b/test/decoders/mail/pcap/13-pop3-mail.pcap diff --git a/test/decoders/mail/pcap/14-pop3-starttls.pcap b/test/decoders/mail/pcap/14-pop3-starttls.pcap Binary files differnew file mode 100644 index 0000000..faae843 --- /dev/null +++ b/test/decoders/mail/pcap/14-pop3-starttls.pcap diff --git a/test/decoders/mail/pcap/15-pop3-capa.pcap b/test/decoders/mail/pcap/15-pop3-capa.pcap Binary files differnew file mode 100644 index 0000000..a2eabc5 --- /dev/null +++ b/test/decoders/mail/pcap/15-pop3-capa.pcap diff --git a/test/decoders/mail/pcap/16-ftp-c2s-8569-8021.pcap b/test/decoders/mail/pcap/16-ftp-c2s-8569-8021.pcap Binary files differnew file mode 100644 index 0000000..f6cbb48 --- /dev/null +++ b/test/decoders/mail/pcap/16-ftp-c2s-8569-8021.pcap diff --git a/test/decoders/mail/pcap/17-ftp-c2s-8569-8080.pcap b/test/decoders/mail/pcap/17-ftp-c2s-8569-8080.pcap Binary files differnew file mode 100644 index 0000000..75dc205 --- /dev/null +++ b/test/decoders/mail/pcap/17-ftp-c2s-8569-8080.pcap diff --git a/test/decoders/mail/pcap/18-http-delete.pcap b/test/decoders/mail/pcap/18-http-delete.pcap Binary files differnew file mode 100644 index 0000000..08f04bd --- /dev/null +++ b/test/decoders/mail/pcap/18-http-delete.pcap diff --git a/test/decoders/mail/result/01-imap-mail-account-in-command-with-base64.json b/test/decoders/mail/result/01-imap-mail-account-in-command-with-base64.json new file mode 100644 index 0000000..4eea170 --- /dev/null +++ b/test/decoders/mail/result/01-imap-mail-account-in-command-with-base64.json @@ -0,0 +1,8 @@ +[ + { + "MAIL_STARTTLS_CMD": "1", + "Mail_proto": "IMAP", + "Tuple4": "192.168.32.123.54643>159.226.251.13.143", + "name": "MAIL_RESULT_1" + } +] |
