summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorzhuzhenjun <[email protected]>2024-11-27 08:26:41 +0000
committerzhuzhenjun <[email protected]>2024-11-27 08:26:41 +0000
commit3694c142d974ab35f55bde4a8519525b9afcbc84 (patch)
treece92ad91f08e6ec8c81e2899d6ff93327ef7bff1 /test
parentd0a868591470a4a9d71a65a5d540058e72c8d92c (diff)
tmp
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt9
-rw-r--r--test/decoders/mail/CMakeLists.txt94
-rw-r--r--test/decoders/mail/conf/spec.toml9
-rw-r--r--test/decoders/mail/mail_test_main.cpp80
-rw-r--r--test/decoders/mail/mail_test_md5.cpp156
-rw-r--r--test/decoders/mail/mail_test_md5.h56
-rw-r--r--test/decoders/mail/mail_test_module.cpp608
-rw-r--r--test/decoders/mail/pcap/01-imap-mail-account-in-command-with-base64.pcapbin0 -> 17486 bytes
-rw-r--r--test/decoders/mail/pcap/02-imap-starttls.pcapbin0 -> 555955 bytes
-rw-r--r--test/decoders/mail/pcap/03-smtp-s2c-mail.pcapbin0 -> 1618 bytes
-rw-r--r--test/decoders/mail/pcap/04-smtp-attachment-charset-unknown.pcapbin0 -> 4013 bytes
-rw-r--r--test/decoders/mail/pcap/05-smtp-curl-mails.pcapbin0 -> 7456 bytes
-rw-r--r--test/decoders/mail/pcap/06-smtp-starttls.pcapbin0 -> 4220 bytes
-rw-r--r--test/decoders/mail/pcap/07-smtp-auth-xoauth2.pcapbin0 -> 4866 bytes
-rw-r--r--test/decoders/mail/pcap/08-smtp-mime-header-rfc2047.pcapbin0 -> 3063 bytes
-rw-r--r--test/decoders/mail/pcap/09-pop3-c2s-55325-1100.pcapbin0 -> 2767 bytes
-rw-r--r--test/decoders/mail/pcap/10-pop3-s2c-1100-55325.pcapbin0 -> 18034 bytes
-rw-r--r--test/decoders/mail/pcap/11-pop3-c2s.pcapbin0 -> 2767 bytes
-rw-r--r--test/decoders/mail/pcap/12-pop3-s2c.pcapbin0 -> 18034 bytes
-rw-r--r--test/decoders/mail/pcap/13-pop3-mail.pcapbin0 -> 14121 bytes
-rw-r--r--test/decoders/mail/pcap/14-pop3-starttls.pcapbin0 -> 9400 bytes
-rw-r--r--test/decoders/mail/pcap/15-pop3-capa.pcapbin0 -> 1656785 bytes
-rw-r--r--test/decoders/mail/pcap/16-ftp-c2s-8569-8021.pcapbin0 -> 1565 bytes
-rw-r--r--test/decoders/mail/pcap/17-ftp-c2s-8569-8080.pcapbin0 -> 1565 bytes
-rw-r--r--test/decoders/mail/pcap/18-http-delete.pcapbin0 -> 1642 bytes
-rw-r--r--test/decoders/mail/result/01-imap-mail-account-in-command-with-base64.json8
-rw-r--r--test/decoders/mail/result/03-smtp-s2c-mail.json7
-rw-r--r--test/decoders/mail/result/04-smtp-attachment-charset-unknown.json14
-rw-r--r--test/decoders/mail/result/05-smtp-curl-mails.json29
-rw-r--r--test/decoders/mail/result/08-smtp-mime-header-rfc2047.json13
30 files changed, 1079 insertions, 4 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 11d1abc..1bd35ec 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,9 +1,10 @@
#add_subdirectory(packet_inject)
-add_subdirectory(packet_tool)
-add_subdirectory(session_debugger)
-add_subdirectory(lpi_plus)
+#add_subdirectory(packet_tool)
+#add_subdirectory(session_debugger)
+#add_subdirectory(lpi_plus)
#add_subdirectory(decoders/http)
#add_subdirectory(decoders/socks)
#add_subdirectory(decoders/stratum)
#add_subdirectory(decoders/session_flags)
-add_subdirectory(monitor) \ No newline at end of file
+#add_subdirectory(monitor)
+add_subdirectory(decoders/mail)
diff --git a/test/decoders/mail/CMakeLists.txt b/test/decoders/mail/CMakeLists.txt
new file mode 100644
index 0000000..4d2c706
--- /dev/null
+++ b/test/decoders/mail/CMakeLists.txt
@@ -0,0 +1,94 @@
+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}.03-smtp-s2c-mail
+ COMMAND sh -c "
+ cat ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all | grep '03-smtp-s2c-mail.pcap' > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.txt &&
+ ${TEST_MAIN} -m -c ./conf/stellar.toml -f ${CMAKE_CURRENT_BINARY_DIR}/result/03-smtp-s2c-mail.json
+ "
+)
+
+add_test(
+ NAME ${TEST_NAME}.04-smtp-attachment-charset-unknown
+ COMMAND sh -c "
+ cat ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all | grep '04-smtp-attachment-charset-unknown.pcap' > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.txt &&
+ ${TEST_MAIN} -m -c ./conf/stellar.toml -f ${CMAKE_CURRENT_BINARY_DIR}/result/04-smtp-attachment-charset-unknown.json
+ "
+)
+
+add_test(
+ NAME ${TEST_NAME}.05-smtp-curl-mails
+ COMMAND sh -c "
+ cat ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all | grep '05-smtp-curl-mails.pcap' > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.txt &&
+ ${TEST_MAIN} -m -c ./conf/stellar.toml -f ${CMAKE_CURRENT_BINARY_DIR}/result/05-smtp-curl-mails.json
+ "
+)
+
+add_test(
+ NAME ${TEST_NAME}.06-smtp-starttls
+ COMMAND sh -c "
+ cat ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all | grep '06-smtp-starttls.pcap' > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.txt &&
+ ${TEST_MAIN} -m -c ./conf/stellar.toml -f ${CMAKE_CURRENT_BINARY_DIR}/result/06-smtp-starttls.json
+ "
+)
+
+add_test(
+ NAME ${TEST_NAME}.07-smtp-auth-xoauth2
+ COMMAND sh -c "
+ cat ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all | grep '07-smtp-auth-xoauth2.pcap' > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.txt &&
+ ${TEST_MAIN} -m -c ./conf/stellar.toml -f ${CMAKE_CURRENT_BINARY_DIR}/result/07-smtp-auth-xoauth2.json
+ "
+)
+
+add_test(
+ NAME ${TEST_NAME}.08-smtp-mime-header-rfc2047
+ COMMAND sh -c "
+ cat ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.all | grep '08-smtp-mime-header-rfc2047.pcap' > ${CMAKE_CURRENT_BINARY_DIR}/pcaplist.txt &&
+ ${TEST_MAIN} -m -c ./conf/stellar.toml -f ${CMAKE_CURRENT_BINARY_DIR}/result/08-smtp-mime-header-rfc2047.json
+ "
+)
+
+set_tests_properties(
+ ${TEST_NAME}.03-smtp-s2c-mail
+ PROPERTIES
+ FIXTURES_REQUIRED ${TEST_NAME}.SETUP
+)
diff --git a/test/decoders/mail/conf/spec.toml b/test/decoders/mail/conf/spec.toml
new file mode 100644
index 0000000..32aded2
--- /dev/null
+++ b/test/decoders/mail/conf/spec.toml
@@ -0,0 +1,9 @@
+[[module]]
+ path = ""
+ init = "mail_init"
+ exit = "mail_exit"
+
+[[module]]
+ path = ""
+ init = "mail_test_init"
+ exit = "mail_test_exit"
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_md5.cpp b/test/decoders/mail/mail_test_md5.cpp
new file mode 100644
index 0000000..a5e8ec3
--- /dev/null
+++ b/test/decoders/mail/mail_test_md5.cpp
@@ -0,0 +1,156 @@
+#include <memory.h>
+#include "mail_test_md5.h"
+
+unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+void MD5Init(MD5_CTX *context)
+{
+ context->count[0] = 0;
+ context->count[1] = 0;
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+}
+void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)
+{
+ unsigned int i = 0,index = 0,partlen = 0;
+ index = (context->count[0] >> 3) & 0x3F;
+ partlen = 64 - index;
+ context->count[0] += inputlen << 3;
+ if(context->count[0] < (inputlen << 3))
+ context->count[1]++;
+ context->count[1] += inputlen >> 29;
+ if(inputlen >= partlen)
+ {
+ memcpy(&context->buffer[index],input,partlen);
+ MD5Transform(context->state,context->buffer);
+ for(i = partlen;i+64 <= inputlen;i+=64)
+ MD5Transform(context->state,&input[i]);
+ index = 0;
+ }
+ else
+ {
+ i = 0;
+ }
+ memcpy(&context->buffer[index],&input[i],inputlen-i);
+}
+void MD5Final(MD5_CTX *context,unsigned char digest[16])
+{
+ unsigned int index = 0,padlen = 0;
+ unsigned char bits[8];
+ index = (context->count[0] >> 3) & 0x3F;
+ padlen = (index < 56)?(56-index):(120-index);
+ MD5Encode(bits,context->count,8);
+ MD5Update(context,PADDING,padlen);
+ MD5Update(context,bits,8);
+ MD5Encode(digest,context->state,16);
+}
+void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)
+{
+ unsigned int i = 0,j = 0;
+ while(j < len)
+ {
+ output[j] = input[i] & 0xFF;
+ output[j+1] = (input[i] >> 8) & 0xFF;
+ output[j+2] = (input[i] >> 16) & 0xFF;
+ output[j+3] = (input[i] >> 24) & 0xFF;
+ i++;
+ j+=4;
+ }
+}
+void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)
+{
+ unsigned int i = 0,j = 0;
+ while(j < len)
+ {
+ output[i] = (input[j]) |
+ (input[j+1] << 8) |
+ (input[j+2] << 16) |
+ (input[j+3] << 24);
+ i++;
+ j+=4;
+ }
+}
+void MD5Transform(unsigned int state[4],unsigned char block[64])
+{
+ unsigned int a = state[0];
+ unsigned int b = state[1];
+ unsigned int c = state[2];
+ unsigned int d = state[3];
+ unsigned int x[64];
+ MD5Decode(x,block,64);
+ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
+ /* Round 2 */
+ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
+ /* Round 3 */
+ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
+ /* Round 4 */
+ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+}
diff --git a/test/decoders/mail/mail_test_md5.h b/test/decoders/mail/mail_test_md5.h
new file mode 100644
index 0000000..d423e4f
--- /dev/null
+++ b/test/decoders/mail/mail_test_md5.h
@@ -0,0 +1,56 @@
+#ifndef MD5_H
+#define MD5_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct
+{
+ unsigned int count[2];
+ unsigned int state[4];
+ unsigned char buffer[64];
+}MD5_CTX;
+#define F(x,y,z) ((x & y) | (~x & z))
+#define G(x,y,z) ((x & z) | (y & ~z))
+#define H(x,y,z) (x^y^z)
+#define I(x,y,z) (y ^ (x | ~z))
+#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
+#define FF(a,b,c,d,x,s,ac) \
+ { \
+ a += F(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+ }
+#define GG(a,b,c,d,x,s,ac) \
+ { \
+ a += G(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+ }
+#define HH(a,b,c,d,x,s,ac) \
+ { \
+ a += H(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+ }
+#define II(a,b,c,d,x,s,ac) \
+ { \
+ a += I(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+ }
+void MD5Init(MD5_CTX *context);
+void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
+void MD5Final(MD5_CTX *context,unsigned char digest[16]);
+void MD5Transform(unsigned int state[4],unsigned char block[64]);
+void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
+void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/test/decoders/mail/mail_test_module.cpp b/test/decoders/mail/mail_test_module.cpp
new file mode 100644
index 0000000..fab6961
--- /dev/null
+++ b/test/decoders/mail/mail_test_module.cpp
@@ -0,0 +1,608 @@
+#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 <uthash/uthash.h>
+#include "cjson/cJSON.h"
+#include "mail_test_md5.h"
+
+#include <gtest/gtest.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 {
+ cJSON *json;
+ int mail_size;
+ char *mailbuf;
+ char *to_cmd;
+ char *to;
+ char *cc;
+ char *bcc;
+
+ int result_seq;
+ 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"};
+int g_attatch_count = 1;
+
+static void get_md5(char *buf, int len, char *md5_buf)
+{
+ unsigned char md[16] = {0};
+ int i = 0;
+
+ MD5_CTX md5;
+ MD5Init(&md5);
+ MD5Update(&md5,(unsigned char *)buf,len);
+ MD5Final(&md5,md);
+
+ for(i=0;i<16;i++)
+ {
+ sprintf(md5_buf + i*2,"%02x",md[i]);
+ }
+}
+
+void account_string_strcat(char **dest,const char *src, int s_len, char split)
+{
+ if(src==NULL || s_len<=0)
+ {
+ return ;
+ }
+
+ if(*dest==NULL)
+ {
+ *dest=(char *)calloc(1, s_len+1);
+ memcpy(*dest, src, s_len);
+ }
+ else
+ {
+ int d_len=strlen(*dest);
+ *dest=(char *)realloc(*dest, d_len+s_len+2);
+ (*dest)[d_len++]=split;
+ memcpy(*dest+d_len, src, s_len);
+ (*dest)[d_len+s_len]='\0';
+ }
+}
+
+static void mail_test_result_commit(struct mail_test_result *result, cJSON *json, int result_seq)
+{
+ cJSON_AddNumberToObject(json, "test_result", result_seq);
+ 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) {
+ if (exdata->mailbuf) {
+ free(exdata->mailbuf);
+ }
+ if (exdata->to_cmd) {
+ free(exdata->to_cmd);
+ }
+ if (exdata->to) {
+ free(exdata->to);
+ }
+ if (exdata->cc) {
+ free(exdata->cc);
+ }
+ if (exdata->bcc) {
+ free(exdata->bcc);
+ }
+ if (exdata->json) {
+ cJSON_Delete(exdata->json);
+ }
+ 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,
+ const char *cmd_arg, size_t cmd_arg_len,
+ const char *cmd_line, size_t cmd_line_len,
+ void *arg)
+{
+ char buf[1024] = {0};
+ 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);
+ }
+
+ if (exdata->json == NULL) {
+ exdata->json = cJSON_CreateObject();
+ cJSON_AddStringToObject(exdata->json, "Tuple4", session_get_readable_addr(sess));
+ cJSON_AddStringToObject(exdata->json, "Mail_proto", mail_protocol_name[(int)mail_protocol]);
+ }
+
+ switch (command) {
+ case MAIL_CMD_USERNAME:
+ memcpy(buf, cmd_arg, cmd_arg_len);
+ cJSON_AddStringToObject(exdata->json, "MAIL_USERNAME", buf);
+ break;
+ case MAIL_CMD_MAIL_FROM:
+ memcpy(buf, cmd_arg, cmd_arg_len);
+ cJSON_AddStringToObject(exdata->json, "MAIL_FROM_CMD", buf);
+ break;
+ case MAIL_CMD_RCPT_TO:
+ account_string_strcat(&exdata->to_cmd, (char *)cmd_arg, cmd_arg_len, ';');
+ break;
+ case MAIL_CMD_STARTTLS:
+ cJSON_AddStringToObject(exdata->json, "MAIL_STARTTLS_CMD", "1");
+ break;
+ default:
+ break;
+ }
+}
+
+void mail_test_header_callback(struct session *sess,
+ enum MAIL_PROTOCOL mail_protocol, size_t mail_seq,
+ const struct mail_header *header,
+ void *arg)
+{
+ char buf[1024] = {0};
+ 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);
+ }
+
+ if (exdata->json == NULL) {
+ exdata->json = cJSON_CreateObject();
+ cJSON_AddStringToObject(exdata->json, "Tuple4", session_get_readable_addr(sess));
+ cJSON_AddStringToObject(exdata->json, "Mail_proto", mail_protocol_name[(int)mail_protocol]);
+ }
+
+ if (header->from) {
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, header->from->field_value, header->from->field_value_len);
+ cJSON_AddStringToObject(exdata->json, "MAIL_FROM", buf);
+ }
+ if (header->to) {
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, header->to->field_value, header->to->field_value_len);
+ cJSON_AddStringToObject(exdata->json, "MAIL_TO", buf);
+ }
+ if (header->cc) {
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, header->cc->field_value, header->cc->field_value_len);
+ cJSON_AddStringToObject(exdata->json, "MAIL_CC", buf);
+ }
+ if (header->bcc) {
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, header->bcc->field_value, header->bcc->field_value_len);
+ cJSON_AddStringToObject(exdata->json, "MAIL_BCC", buf);
+ }
+ if (header->subject) {
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, header->subject->field_value, header->subject->field_value_len);
+ cJSON_AddStringToObject(exdata->json, "MAIL_SUBJECT", buf);
+ }
+}
+
+void mail_test_body_callback(struct session *sess,
+ enum MAIL_PROTOCOL mail_protocol, size_t mail_seq,
+ const 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,
+ const char *name, size_t name_len,
+ const char *attachment, size_t attachment_len, size_t offset, int is_finish,
+ void *arg)
+{
+ char buf[1024] = {0};
+ char namebuf[1024] = {0};
+ 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);
+ }
+
+ if (exdata->json == NULL) {
+ exdata->json = cJSON_CreateObject();
+ cJSON_AddStringToObject(exdata->json, "Tuple4", session_get_readable_addr(sess));
+ cJSON_AddStringToObject(exdata->json, "Mail_proto", mail_protocol_name[(int)mail_protocol]);
+ }
+
+ if (is_finish) {
+ sprintf(buf, "MAIL_ATTACH_NAME_%d", g_attatch_count);
+ g_attatch_count+=1;
+
+ memcpy(namebuf, name, name_len);
+ cJSON_AddStringToObject(exdata->json, buf, namebuf);
+ }
+}
+
+void mail_test_eml_callback(struct session *sess,
+ enum MAIL_PROTOCOL mail_protocol,
+ const 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);
+ }
+
+ if (exdata->json == NULL) {
+ exdata->json = cJSON_CreateObject();
+ cJSON_AddStringToObject(exdata->json, "Tuple4", session_get_readable_addr(sess));
+ cJSON_AddStringToObject(exdata->json, "Mail_proto", mail_protocol_name[(int)mail_protocol]);
+ }
+
+ if (eml && eml_len > 0) {
+ if(exdata->mail_size == 0) {
+ exdata->mail_size += eml_len;
+ exdata->mailbuf = (char *)malloc(exdata->mail_size);
+ } else {
+ exdata->mail_size += eml_len;
+ exdata->mailbuf = (char *)realloc(exdata->mailbuf, exdata->mail_size);
+ }
+ memcpy(exdata->mailbuf + exdata->mail_size - eml_len, eml, eml_len);
+ }
+
+ if(is_finish) {
+ if (exdata->mail_size > 0) {
+ char md5_buf[33] = {0};
+
+ char file_name[256] = {0};
+ sprintf(file_name, "%s_%s_MAIL_RESULT_%d.eml",
+ session_get_readable_addr(sess),
+ mail_protocol_name[(int)mail_protocol],
+ exdata->result_seq);
+ FILE *fp = fopen(file_name, "wb");
+ if(fp != NULL)
+ {
+ fwrite(exdata->mailbuf, exdata->mail_size, 1, fp);
+ fclose(fp);
+ }
+
+ get_md5(exdata->mailbuf, exdata->mail_size, md5_buf);
+
+ cJSON_AddNumberToObject(exdata->json, "MAIL_FILE_SIZE", exdata->mail_size);
+ cJSON_AddStringToObject(exdata->json, "MAIL_FILE_MD5", md5_buf);
+ }
+
+ if(exdata->to_cmd!=NULL)
+ {
+ cJSON_AddStringToObject(exdata->json, "MAIL_TO_CMD", exdata->to_cmd);
+ free(exdata->to_cmd);
+ exdata->to_cmd = NULL;
+ }
+
+ if(exdata->to!=NULL)
+ {
+ cJSON_AddStringToObject(exdata->json, "MAIL_TO", exdata->to);
+ free(exdata->to);
+ exdata->to = NULL;
+ }
+
+ if(exdata->cc!=NULL)
+ {
+ cJSON_AddStringToObject(exdata->json, "MAIL_CC", exdata->cc);
+ free(exdata->cc);
+ exdata->cc = NULL;
+ }
+
+ if(exdata->bcc!=NULL)
+ {
+ cJSON_AddStringToObject(exdata->json, "MAIL_BCC", exdata->bcc);
+ free(exdata->bcc);
+ exdata->bcc = NULL;
+ }
+
+ mail_test_result_commit(mod_ctx->result, exdata->json, exdata->result_seq++);
+ exdata->json = NULL;
+ }
+}
+
+void mail_test_on_exdata_free(int idx, void *ex_ptr, void *arg)
+{
+ (void)(idx);
+ struct mail_test_exdata *exdata = (struct mail_test_exdata *)ex_ptr;
+ struct mail_test_module_ctx *mod_ctx = (struct mail_test_module_ctx *)arg;
+
+ if (exdata) {
+ if (exdata->json) {
+ if(exdata->to_cmd!=NULL)
+ {
+ cJSON_AddStringToObject(exdata->json, "MAIL_TO_CMD", exdata->to_cmd);
+ free(exdata->to_cmd);
+ exdata->to_cmd = NULL;
+ }
+ mail_test_result_commit(mod_ctx->result, exdata->json, exdata->result_seq++);
+ exdata->json = NULL;
+ }
+ 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_env *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
new file mode 100644
index 0000000..d4344c7
--- /dev/null
+++ b/test/decoders/mail/pcap/01-imap-mail-account-in-command-with-base64.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/02-imap-starttls.pcap b/test/decoders/mail/pcap/02-imap-starttls.pcap
new file mode 100644
index 0000000..2fd3bf8
--- /dev/null
+++ b/test/decoders/mail/pcap/02-imap-starttls.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/03-smtp-s2c-mail.pcap b/test/decoders/mail/pcap/03-smtp-s2c-mail.pcap
new file mode 100644
index 0000000..3549c0d
--- /dev/null
+++ b/test/decoders/mail/pcap/03-smtp-s2c-mail.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/04-smtp-attachment-charset-unknown.pcap b/test/decoders/mail/pcap/04-smtp-attachment-charset-unknown.pcap
new file mode 100644
index 0000000..1cd8cfc
--- /dev/null
+++ b/test/decoders/mail/pcap/04-smtp-attachment-charset-unknown.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/05-smtp-curl-mails.pcap b/test/decoders/mail/pcap/05-smtp-curl-mails.pcap
new file mode 100644
index 0000000..b452fd7
--- /dev/null
+++ b/test/decoders/mail/pcap/05-smtp-curl-mails.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/06-smtp-starttls.pcap b/test/decoders/mail/pcap/06-smtp-starttls.pcap
new file mode 100644
index 0000000..c26ec62
--- /dev/null
+++ b/test/decoders/mail/pcap/06-smtp-starttls.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/07-smtp-auth-xoauth2.pcap b/test/decoders/mail/pcap/07-smtp-auth-xoauth2.pcap
new file mode 100644
index 0000000..b6e3bf8
--- /dev/null
+++ b/test/decoders/mail/pcap/07-smtp-auth-xoauth2.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/08-smtp-mime-header-rfc2047.pcap b/test/decoders/mail/pcap/08-smtp-mime-header-rfc2047.pcap
new file mode 100644
index 0000000..c7754e0
--- /dev/null
+++ b/test/decoders/mail/pcap/08-smtp-mime-header-rfc2047.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/09-pop3-c2s-55325-1100.pcap b/test/decoders/mail/pcap/09-pop3-c2s-55325-1100.pcap
new file mode 100644
index 0000000..3b54a68
--- /dev/null
+++ b/test/decoders/mail/pcap/09-pop3-c2s-55325-1100.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/10-pop3-s2c-1100-55325.pcap b/test/decoders/mail/pcap/10-pop3-s2c-1100-55325.pcap
new file mode 100644
index 0000000..f018536
--- /dev/null
+++ b/test/decoders/mail/pcap/10-pop3-s2c-1100-55325.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/11-pop3-c2s.pcap b/test/decoders/mail/pcap/11-pop3-c2s.pcap
new file mode 100644
index 0000000..dc1c679
--- /dev/null
+++ b/test/decoders/mail/pcap/11-pop3-c2s.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/12-pop3-s2c.pcap b/test/decoders/mail/pcap/12-pop3-s2c.pcap
new file mode 100644
index 0000000..810d885
--- /dev/null
+++ b/test/decoders/mail/pcap/12-pop3-s2c.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/13-pop3-mail.pcap b/test/decoders/mail/pcap/13-pop3-mail.pcap
new file mode 100644
index 0000000..6663699
--- /dev/null
+++ b/test/decoders/mail/pcap/13-pop3-mail.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/14-pop3-starttls.pcap b/test/decoders/mail/pcap/14-pop3-starttls.pcap
new file mode 100644
index 0000000..faae843
--- /dev/null
+++ b/test/decoders/mail/pcap/14-pop3-starttls.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/15-pop3-capa.pcap b/test/decoders/mail/pcap/15-pop3-capa.pcap
new file mode 100644
index 0000000..a2eabc5
--- /dev/null
+++ b/test/decoders/mail/pcap/15-pop3-capa.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/16-ftp-c2s-8569-8021.pcap b/test/decoders/mail/pcap/16-ftp-c2s-8569-8021.pcap
new file mode 100644
index 0000000..f6cbb48
--- /dev/null
+++ b/test/decoders/mail/pcap/16-ftp-c2s-8569-8021.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/17-ftp-c2s-8569-8080.pcap b/test/decoders/mail/pcap/17-ftp-c2s-8569-8080.pcap
new file mode 100644
index 0000000..75dc205
--- /dev/null
+++ b/test/decoders/mail/pcap/17-ftp-c2s-8569-8080.pcap
Binary files differ
diff --git a/test/decoders/mail/pcap/18-http-delete.pcap b/test/decoders/mail/pcap/18-http-delete.pcap
new file mode 100644
index 0000000..08f04bd
--- /dev/null
+++ b/test/decoders/mail/pcap/18-http-delete.pcap
Binary files differ
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"
+ }
+]
diff --git a/test/decoders/mail/result/03-smtp-s2c-mail.json b/test/decoders/mail/result/03-smtp-s2c-mail.json
new file mode 100644
index 0000000..6362b9e
--- /dev/null
+++ b/test/decoders/mail/result/03-smtp-s2c-mail.json
@@ -0,0 +1,7 @@
+[{
+ "Tuple4": "172.17.107.32:18867-218.229.99.73:25-6-0",
+ "Mail_proto": "SMTP",
+ "MAIL_FROM_CMD": "<[email protected]>",
+ "MAIL_TO_CMD": "<[email protected]>",
+ "test_result": 0
+}]
diff --git a/test/decoders/mail/result/04-smtp-attachment-charset-unknown.json b/test/decoders/mail/result/04-smtp-attachment-charset-unknown.json
new file mode 100644
index 0000000..3db67c4
--- /dev/null
+++ b/test/decoders/mail/result/04-smtp-attachment-charset-unknown.json
@@ -0,0 +1,14 @@
+[{
+ "Tuple4": "192.168.56.6:58952-183.47.101.192:25-6-0",
+ "Mail_proto": "SMTP",
+ "MAIL_FROM_CMD": "<[email protected]>",
+ "MAIL_FROM": "[email protected]",
+ "MAIL_TO": "[email protected]",
+ "MAIL_CC": "[email protected]",
+ "MAIL_SUBJECT": "后天周末",
+ "MAIL_ATTACH_NAME_1": "何冰凝测试文件.txt",
+ "MAIL_FILE_SIZE": 754,
+ "MAIL_FILE_MD5": "1fc353229c92fbc292020434918070dd",
+ "test_result": 0
+}]
diff --git a/test/decoders/mail/result/05-smtp-curl-mails.json b/test/decoders/mail/result/05-smtp-curl-mails.json
new file mode 100644
index 0000000..68b15fe
--- /dev/null
+++ b/test/decoders/mail/result/05-smtp-curl-mails.json
@@ -0,0 +1,29 @@
+[{
+ "Tuple4": "192.168.56.20:48202-192.168.90.158:25-6-0",
+ "Mail_proto": "SMTP",
+ "MAIL_FROM_CMD": "<[email protected]>",
+ "MAIL_FROM": "[email protected]",
+ "MAIL_TO": "[email protected]",
+ "MAIL_CC": "[email protected]",
+ "MAIL_BCC": "[email protected]",
+ "MAIL_SUBJECT": "curlSubject",
+ "MAIL_ATTACH_NAME_1": "mail_test_english.txt",
+ "MAIL_FILE_SIZE": 950,
+ "MAIL_FILE_MD5": "31e58ffd6ed69a86cddd0450b1831e99",
+ "MAIL_TO_CMD": "<[email protected]>",
+ "test_result": 0
+ }, {
+ "Tuple4": "192.168.56.20:48204-192.168.90.158:25-6-0",
+ "Mail_proto": "SMTP",
+ "MAIL_FROM_CMD": "<[email protected]>",
+ "MAIL_FROM": "[email protected]",
+ "MAIL_TO": "[email protected]",
+ "MAIL_CC": "[email protected]",
+ "MAIL_BCC": "[email protected]",
+ "MAIL_SUBJECT": "curlSubject",
+ "MAIL_ATTACH_NAME_2": "mail_test_english.txt",
+ "MAIL_FILE_SIZE": 950,
+ "MAIL_FILE_MD5": "4bdd5ee31f540f78b10cdcd779b753f0",
+ "MAIL_TO_CMD": "<[email protected]>",
+ "test_result": 0
+ }]
diff --git a/test/decoders/mail/result/08-smtp-mime-header-rfc2047.json b/test/decoders/mail/result/08-smtp-mime-header-rfc2047.json
new file mode 100644
index 0000000..b31ff75
--- /dev/null
+++ b/test/decoders/mail/result/08-smtp-mime-header-rfc2047.json
@@ -0,0 +1,13 @@
+[{
+ "Tuple4": "192.168.64.25:59012-192.168.40.206:25-6-0",
+ "Mail_proto": "SMTP",
+ "MAIL_FROM_CMD": "<[email protected]>",
+ "MAIL_FROM": "[email protected]",
+ "MAIL_TO": "[email protected]",
+ "MAIL_SUBJECT": "aaa",
+ "MAIL_ATTACH_NAME_1": "E:/Chrome_download/interval.txt",
+ "MAIL_FILE_SIZE": 700,
+ "MAIL_FILE_MD5": "0e562dbb020a96bd3aa3b72183ef5d4c",
+ "MAIL_TO_CMD": "<[email protected]>",
+ "test_result": 0
+ }]