1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
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;
}
|