summaryrefslogtreecommitdiff
path: root/test/gtest_ftp_decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/gtest_ftp_decoder.cpp')
-rw-r--r--test/gtest_ftp_decoder.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/test/gtest_ftp_decoder.cpp b/test/gtest_ftp_decoder.cpp
new file mode 100644
index 0000000..4ea20e3
--- /dev/null
+++ b/test/gtest_ftp_decoder.cpp
@@ -0,0 +1,251 @@
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <arpa/inet.h>
+#include "ftp_decoder.h"
+#include "ftp_decoder_inner.h"
+#include "ftp_decoder_util.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <stellar/session.h>
+#include <stellar/session_exdata.h>
+#include <stellar/session_mq.h>
+#include <stellar/stellar.h>
+#ifdef __cplusplus
+}
+#endif
+/********************* Stellar Mock ********************/
+int stellar_get_worker_thread_num(struct stellar *st) { return 1; }
+int stellar_get_current_thread_id(struct stellar *st) { return 0; }
+int session_get_current_thread_id(struct session *sess) { return 0; }
+const char *session_get0_readable_addr(struct session *sess) { return "TODO"; }
+struct session_addr *session_get0_addr(struct session *sess, enum session_addr_type *addr_type)
+{
+ *addr_type = SESSION_ADDR_TYPE_UNKNOWN;
+ return NULL;
+}
+int session_mq_publish_message(struct session *sess, int topic_id, void *msg) { return 0; }
+const char *session_get0_current_payload(struct session *sess, size_t *payload_len)
+{
+ *payload_len = 0;
+ return "TODO";
+}
+void stellar_session_plugin_dettach_current_session(struct session *sess) { return; }
+enum session_state session_get_current_state(struct session *sess) { return SESSION_STATE_INVALID; }
+int stellar_session_mq_create_topic(struct stellar *st, const char *topic_name, session_msg_free_cb_func *msg_free_cb, void *msg_free_arg) { return 0; }
+int stellar_session_mq_subscribe(struct stellar *st, int topic_id, on_session_msg_cb_func *plugin_on_msg_cb, int plugin_id) { return 0; }
+int stellar_session_plugin_register(struct stellar *st, session_ctx_new_func session_ctx_new, session_ctx_free_func session_ctx_free, void *plugin_env) { return 0; }
+int stellar_session_mq_get_topic_id(struct stellar *st, const char *topic_name) { return 0; }
+const struct packet *session_get0_current_packet(struct session *sess) { return NULL; }
+int packet_get_direction(const struct packet *pkt) { return PACKET_DIRECTION_UNKNOWN; }
+/********************* Stellar Mock End ********************/
+
+TEST(ftp_decoder, identify_by_payload)
+{
+ // true
+ ASSERT_TRUE(ftp_ctrl_identify_by_payload("USER", 4, PACKET_DIRECTION_C2S));
+ ASSERT_TRUE(ftp_ctrl_identify_by_payload("USER test", 9, PACKET_DIRECTION_C2S));
+ ASSERT_TRUE(ftp_ctrl_identify_by_payload("220 (vsFTPd 3.0.1)", strlen("220 (vsFTPd 3.0.1)"), PACKET_DIRECTION_S2C));
+ ASSERT_TRUE(ftp_ctrl_identify_by_payload("220 (vsFTPD 3.0.2)", strlen("220 (vsFTPD 3.0.2)"), PACKET_DIRECTION_S2C));
+ ASSERT_TRUE(ftp_ctrl_identify_by_payload("220 (ftpd 3.0.3)", strlen("220 (ftpd 3.0.3)"), PACKET_DIRECTION_S2C));
+ ASSERT_TRUE(ftp_ctrl_identify_by_payload("220-Microsoft FTP Service", strlen("220-Microsoft FTP Service"), PACKET_DIRECTION_S2C));
+
+ // false
+ ASSERT_FALSE(ftp_ctrl_identify_by_payload("USR", 3, PACKET_DIRECTION_C2S));
+ ASSERT_FALSE(ftp_ctrl_identify_by_payload("USRxx", 5, PACKET_DIRECTION_C2S));
+ ASSERT_FALSE(ftp_ctrl_identify_by_payload("PASS", 4, PACKET_DIRECTION_C2S));
+ ASSERT_FALSE(ftp_ctrl_identify_by_payload("200 OK", 6, PACKET_DIRECTION_S2C));
+ ASSERT_FALSE(ftp_ctrl_identify_by_payload("220 (xxx 3.0.3)", strlen("220 (xxx 3.0.3)"), PACKET_DIRECTION_S2C));
+}
+
+TEST(ftp_decoder, ftp_cmd_readline)
+{
+ struct ftp_interact_line line;
+ ftp_cmd_readline(&line, "USER test", strlen("USER test"));
+ ASSERT_EQ(line.cmd_refer.iov_len, 4);
+ ASSERT_EQ(line.arg_refer.iov_len, 4);
+ ASSERT_EQ(0, strncmp("USER", (char *)line.cmd_refer.iov_base, 4));
+ ASSERT_EQ(0, strncmp("test", (char *)line.arg_refer.iov_base, 4));
+
+ ftp_cmd_readline(&line, "CUSTOM xx1 xx2 xx3", strlen("CUSTOM xx1 xx2 xx3"));
+ ASSERT_EQ(line.cmd_refer.iov_len, 6);
+ ASSERT_EQ(line.arg_refer.iov_len, 11);
+ ASSERT_EQ(0, strncmp("CUSTOM", (char *)line.cmd_refer.iov_base, 6));
+ ASSERT_EQ(0, strncmp("xx1 xx2 xx3", (char *)line.arg_refer.iov_base, 11));
+}
+
+TEST(ftp_decoder, ftp_skip_tail_crlf)
+{
+ ASSERT_EQ(ftp_skip_tail_crlf("", 0), 0);
+ ASSERT_EQ(ftp_skip_tail_crlf("\r", 1), 0);
+ ASSERT_EQ(ftp_skip_tail_crlf("\n", 1), 0);
+ ASSERT_EQ(ftp_skip_tail_crlf("\r\n", 2), 0);
+ ASSERT_EQ(ftp_skip_tail_crlf("a\r\n", 3), 1);
+ ASSERT_EQ(ftp_skip_tail_crlf("abcdefg\r\n", 9), 7);
+}
+
+TEST(ftp_decoder, ipv4_port_style)
+{
+ int ret;
+ uint32_t ipv4_net;
+ uint16_t port_net;
+ fstring ip_port_style;
+ // normal
+ ip_port_style.iov_base = (void *)"192,168,38,2,202,95";
+ ip_port_style.iov_len = strlen("192,168,38,2,202,95");
+ ret = ftp_parse_ipv4_port_style(&ip_port_style, &ipv4_net, &port_net);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(ipv4_net, htonl(0xC0A82602));
+ ASSERT_EQ(port_net, htons(51807));
+
+ // add tab and blank
+ ip_port_style.iov_base = (void *)" 192,168,38,2,202,95 ";
+ ip_port_style.iov_len = strlen(" 192,168,38,2,202,95 ");
+ ret = ftp_parse_ipv4_port_style(&ip_port_style, &ipv4_net, &port_net);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(ipv4_net, htonl(0xC0A82602));
+ ASSERT_EQ(port_net, htons(51807));
+
+ // add bracket
+ ip_port_style.iov_base = (void *)"(192,168,38,2,202,95)";
+ ip_port_style.iov_len = strlen("(192,168,38,2,202,95)");
+ ret = ftp_parse_ipv4_port_style(&ip_port_style, &ipv4_net, &port_net);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(ipv4_net, htonl(0xC0A82602));
+ ASSERT_EQ(port_net, htons(51807));
+
+ // PASV response
+ ip_port_style.iov_base = (void *)"Entering Passive Mode(192,168,38,2,202,95)";
+ ip_port_style.iov_len = strlen("Entering Passive Mode(192,168,38,2,202,95)");
+ ret = ftp_parse_ipv4_port_style(&ip_port_style, &ipv4_net, &port_net);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(ipv4_net, htonl(0xC0A82602));
+ ASSERT_EQ(port_net, htons(51807));
+
+ // PASV response with blank
+ ip_port_style.iov_base = (void *)"Entering Passive Mode ( 192,168,38,2,202,95 )";
+ ip_port_style.iov_len = strlen("Entering Passive Mode ( 192,168,38,2,202,95 )");
+ ret = ftp_parse_ipv4_port_style(&ip_port_style, &ipv4_net, &port_net);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(ipv4_net, htonl(0xC0A82602));
+ ASSERT_EQ(port_net, htons(51807));
+}
+
+TEST(ftp_decoder, ipv6_port_style)
+{
+ int ret;
+ uint16_t port_net;
+ fstring ip_port_style;
+ // normal
+ ip_port_style.iov_base = (void *)"Entering Extended Passive Mode (|||12345|)";
+ ip_port_style.iov_len = strlen("Entering Extended Passive Mode (|||12345|)");
+ ret = ftp_parse_ipv6_port_style(&ip_port_style, &port_net);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(port_net, htons(12345));
+
+ // add blank
+ ip_port_style.iov_base = (void *)"Entering Extended Passive Mode ( |||12345| )";
+ ip_port_style.iov_len = strlen("Entering Extended Passive Mode ( |||12345| )");
+ ret = ftp_parse_ipv6_port_style(&ip_port_style, &port_net);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(port_net, htons(12345));
+}
+
+TEST(ftp_decoder, ipv6_eprt_style)
+{
+ int ret;
+ uint16_t port_net = 0;
+ fstring eprt_style;
+ struct in6_addr ipv6addr = {};
+ // normal
+ eprt_style.iov_base = (void *)"|2|1234::abcd|12345|";
+ eprt_style.iov_len = strlen("|2|1234::abcd|12345|");
+ ret = ftp_parse_eprt_ipport_style(&eprt_style, &ipv6addr, &port_net);
+ ASSERT_EQ(ret, 0);
+ struct in6_addr tmpaddr;
+ inet_pton(AF_INET6, "1234::abcd", &tmpaddr);
+ ASSERT_EQ(0, memcmp(&tmpaddr, &ipv6addr, sizeof(struct in6_addr)));
+ ASSERT_EQ(port_net, htons(12345));
+
+ // loopback address
+ eprt_style.iov_base = (void *)"|2|::1|12345|";
+ eprt_style.iov_len = strlen("|2|::1|12345|");
+ ret = ftp_parse_eprt_ipport_style(&eprt_style, &ipv6addr, &port_net);
+ ASSERT_EQ(ret, 0);
+ inet_pton(AF_INET6, "::1", &tmpaddr);
+ ASSERT_EQ(0, memcmp(&tmpaddr, &ipv6addr, sizeof(struct in6_addr)));
+ ASSERT_EQ(port_net, htons(12345));
+
+ // add blank
+ eprt_style.iov_base = (void *)" |2|1234:4321::abcd|12345| ";
+ eprt_style.iov_len = strlen(" |2|1234:4321::abcd|12345| ");
+ ret = ftp_parse_eprt_ipport_style(&eprt_style, &ipv6addr, &port_net);
+ ASSERT_EQ(ret, 0);
+ inet_pton(AF_INET6, "1234:4321::abcd", &tmpaddr);
+ ASSERT_EQ(0, memcmp(&tmpaddr, &ipv6addr, sizeof(struct in6_addr)));
+ ASSERT_EQ(port_net, htons(12345));
+}
+
+static const char *gtest_cla_short_options = "hLf:";
+static const struct option gtest_cla_long_options[] =
+ {
+ {"help", no_argument, NULL, 'h'},
+ {"gtest_list_tests", no_argument, NULL, 'L'},
+ {"gtest_filter", required_argument, NULL, 'f'},
+ {NULL, 0, NULL, 0}};
+
+static void usage(int argc, char *argv[])
+{
+ printf("args example:\n");
+ printf("\t%s short-arg long-arg\n", argv[0]);
+ printf("\t%s -v \t--version\n", argv[0]);
+ printf("\t%s -L \t--gtest_list_tests\n", argv[0]);
+ printf("\t%s -f \t--gtest_filter=ftp_decoder*\n", argv[0]);
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ int to_gtest_argc = 1;
+ char *to_gtest_args[4] = {(char *)"ftp_gtest", NULL, NULL, NULL};
+ char temp_string[1024] = {};
+ while (1)
+ {
+ c = getopt_long(argc, argv, gtest_cla_short_options, gtest_cla_long_options, NULL);
+ if (c == -1)
+ {
+ break;
+ }
+
+ switch (c)
+ {
+
+ case 'h':
+ usage(argc, argv);
+ break;
+
+ case 'L':
+ to_gtest_args[1] = (char *)"--gtest_list_tests";
+ to_gtest_argc++;
+ break;
+
+ case 'f':
+ strncpy(temp_string, "--gtest_filter=", strlen("--gtest_filter=") + 1);
+ strcat(temp_string, optarg);
+ to_gtest_argc++;
+ to_gtest_args[1] = temp_string;
+ break;
+
+ case '?': /* invalid or unknown option */
+ return -1;
+ break;
+ }
+ }
+
+ testing::InitGoogleTest(&to_gtest_argc, to_gtest_args);
+ int ret = RUN_ALL_TESTS();
+ return ret;
+}