add socks_decoder, stratum_decoder and session_flags
This commit is contained in:
38
test/decoders/socks/CMakeLists.txt
Normal file
38
test/decoders/socks/CMakeLists.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
set(DECODER_NAME socks)
|
||||
|
||||
add_library(${DECODER_NAME}_test SHARED socks_decoder_test_plugin.cpp)
|
||||
add_dependencies(${DECODER_NAME}_test ${DECODER_NAME})
|
||||
set_target_properties(${DECODER_NAME}_test PROPERTIES PREFIX "")
|
||||
|
||||
set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/testing)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||
include_directories(${CMAKE_BINARY_DIR}/vendors/cjson/src/cjson/include)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/decoders/socks)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include/stellar)
|
||||
|
||||
add_executable(gtest_pcap_socks socks_decoder_pcap_gtest.cpp dummy.c ${PROJECT_SOURCE_DIR}/decoders/socks/socks_decoder.cpp)
|
||||
target_link_libraries(gtest_pcap_socks gtest logger pcap)
|
||||
|
||||
add_executable(socks_test_main plugin_test_main.cpp)
|
||||
set_target_properties(socks_test_main
|
||||
PROPERTIES
|
||||
LINK_OPTIONS
|
||||
"-rdynamic"
|
||||
)
|
||||
set_target_properties(socks_test_main
|
||||
PROPERTIES
|
||||
LINK_FLAGS
|
||||
"-rdynamic"
|
||||
)
|
||||
set(LINK_FLAGS "-rdynamic")
|
||||
target_link_libraries(socks_test_main gtest cjson-static stellar_lib)
|
||||
|
||||
add_subdirectory(test_based_on_stellar)
|
||||
|
||||
#copy pcap file folder to build directory
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/pcap DESTINATION ${CMAKE_BINARY_DIR}/test/decoders/socks)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(gtest_pcap_socks)
|
||||
151
test/decoders/socks/dummy.c
Normal file
151
test/decoders/socks/dummy.c
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "dummy.h"
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
int direction;
|
||||
|
||||
void session_set_current_state(struct session *sess, enum session_state sess_state)
|
||||
{
|
||||
sess->sess_state = sess_state;
|
||||
|
||||
return;
|
||||
}
|
||||
enum session_state session_get_current_state(const struct session *sess)
|
||||
{
|
||||
return sess->sess_state;
|
||||
}
|
||||
|
||||
void dummy_set_direction(int dir)
|
||||
{
|
||||
direction = dir;
|
||||
}
|
||||
|
||||
struct logger *stellar_get_logger(struct stellar *st)
|
||||
{
|
||||
UNUSED(st);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum flow_type session_get_flow_type(const struct session *sess)
|
||||
{
|
||||
UNUSED(sess);
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
const struct packet *session_get0_current_packet(const struct session *sess)
|
||||
{
|
||||
UNUSED(sess);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *packet_get_payload(const struct packet *pkt)
|
||||
{
|
||||
UNUSED(pkt);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t packet_get_payload_len(const struct packet *pkt)
|
||||
{
|
||||
UNUSED(pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int session_mq_ignore_message(struct session *sess, int topic_id, int plugin_id)
|
||||
{
|
||||
UNUSED(sess);
|
||||
UNUSED(topic_id);
|
||||
UNUSED(plugin_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int session_exdata_set(struct session *sess, int idx, void *ex_ptr)
|
||||
{
|
||||
UNUSED(sess);
|
||||
UNUSED(idx);
|
||||
UNUSED(ex_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *session_exdata_get(struct session *sess, int idx)
|
||||
{
|
||||
UNUSED(sess);
|
||||
UNUSED(idx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void stellar_session_plugin_dettach_current_session(struct session *sess)
|
||||
{
|
||||
UNUSED(sess);
|
||||
}
|
||||
|
||||
int session_mq_publish_message(struct session *sess, int topic_id, void *msg)
|
||||
{
|
||||
UNUSED(sess);
|
||||
UNUSED(topic_id);
|
||||
UNUSED(msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *session_get0_readable_addr(const struct session *sess)
|
||||
{
|
||||
UNUSED(sess);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int stellar_exdata_new_index(struct stellar *st, const char *name, stellar_exdata_free *free_func,void *arg)
|
||||
{
|
||||
UNUSED(st);
|
||||
UNUSED(name);
|
||||
UNUSED(free_func);
|
||||
UNUSED(arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stellar_mq_create_topic(struct stellar *st, const char *topic_name, stellar_msg_free_cb_func *msg_free_cb, void *msg_free_arg)
|
||||
{
|
||||
UNUSED(st);
|
||||
UNUSED(topic_name);
|
||||
UNUSED(msg_free_cb);
|
||||
UNUSED(msg_free_arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stellar_mq_get_topic_id(struct stellar *st, const char *topic_name)
|
||||
{
|
||||
UNUSED(st);
|
||||
UNUSED(topic_name);
|
||||
|
||||
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)
|
||||
{
|
||||
UNUSED(st);
|
||||
UNUSED(topic_id);
|
||||
UNUSED(plugin_on_msg_cb);
|
||||
UNUSED(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)
|
||||
{
|
||||
UNUSED(st);
|
||||
UNUSED(session_ctx_new);
|
||||
UNUSED(session_ctx_free);
|
||||
UNUSED(plugin_env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
14
test/decoders/socks/dummy.h
Normal file
14
test/decoders/socks/dummy.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "stellar/stellar.h"
|
||||
#include "stellar/session.h"
|
||||
#include "stellar/stellar_mq.h"
|
||||
#include "stellar/stellar_exdata.h"
|
||||
|
||||
struct session //stub just for test
|
||||
{
|
||||
enum session_state sess_state;
|
||||
int payload_len;
|
||||
char *payload;
|
||||
};
|
||||
|
||||
void session_set_current_state(struct session *sess, enum session_state sess_state);
|
||||
void dummy_set_direction(int dir);
|
||||
7
test/decoders/socks/pcap/result.json
Normal file
7
test/decoders/socks/pcap/result.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[{
|
||||
"socks_info": {
|
||||
"version": "SOCKS4",
|
||||
"dst_addr": "127.0.0.1",
|
||||
"dst_port": 8888
|
||||
}
|
||||
}]
|
||||
BIN
test/decoders/socks/pcap/socks4.pcap
Normal file
BIN
test/decoders/socks/pcap/socks4.pcap
Normal file
Binary file not shown.
BIN
test/decoders/socks/pcap/socks4_nest_socks4a.pcap
Normal file
BIN
test/decoders/socks/pcap/socks4_nest_socks4a.pcap
Normal file
Binary file not shown.
BIN
test/decoders/socks/pcap/socks4a_domain.pcap
Normal file
BIN
test/decoders/socks/pcap/socks4a_domain.pcap
Normal file
Binary file not shown.
BIN
test/decoders/socks/pcap/socks5_auth_failed.pcap
Normal file
BIN
test/decoders/socks/pcap/socks5_auth_failed.pcap
Normal file
Binary file not shown.
BIN
test/decoders/socks/pcap/socks5_auth_success.pcap
Normal file
BIN
test/decoders/socks/pcap/socks5_auth_success.pcap
Normal file
Binary file not shown.
BIN
test/decoders/socks/pcap/socks5_no_auth.pcap
Normal file
BIN
test/decoders/socks/pcap/socks5_no_auth.pcap
Normal file
Binary file not shown.
135
test/decoders/socks/plugin_test_main.cpp
Normal file
135
test/decoders/socks/plugin_test_main.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "cJSON.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include "stellar/stellar.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// #define IGNORE_PRINTF
|
||||
#ifdef IGNORE_PRINTF
|
||||
#define printf(fmt, ...) (0)
|
||||
#endif
|
||||
static cJSON *g_test_result_root = NULL;
|
||||
static cJSON *g_load_result_root = NULL;
|
||||
static const char *result_json_path = NULL;
|
||||
|
||||
extern "C" int commit_test_result_json(cJSON *node, const char *name)
|
||||
{
|
||||
(void)name;
|
||||
if (g_test_result_root)
|
||||
{
|
||||
// cJSON_AddItemToObject(g_test_result_root, name, node);
|
||||
// cJSON_AddStringToObject(node, "name", name);
|
||||
cJSON_AddItemToArray(g_test_result_root, node);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static cJSON *load_result_from_jsonfile(const char *json_path)
|
||||
{
|
||||
if (json_path == NULL)
|
||||
return NULL;
|
||||
|
||||
long file_len = 0;
|
||||
char *file_content = NULL;
|
||||
FILE *fp = NULL;
|
||||
|
||||
fp = fopen(json_path, "r+");
|
||||
if (NULL == fp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END);
|
||||
file_len = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
if (file_len == 0)
|
||||
{
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
file_content = (char *)malloc(file_len + 1);
|
||||
fread(file_content, file_len, 1, fp);
|
||||
file_content[file_len] = '\0';
|
||||
cJSON *load = cJSON_Parse(file_content);
|
||||
free(file_content);
|
||||
fclose(fp);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
TEST(PROTOCOL, compare_result_json)
|
||||
{
|
||||
EXPECT_EQ(cJSON_GetArraySize(g_test_result_root), cJSON_GetArraySize(g_load_result_root));
|
||||
int ret = cJSON_Compare(g_test_result_root, g_load_result_root, 0);
|
||||
EXPECT_EQ(1, ret);
|
||||
|
||||
if (ret != 1)
|
||||
{
|
||||
char *load_json_str = cJSON_Print(g_load_result_root);
|
||||
printf("LOAD Raw:\n%s\n", load_json_str);
|
||||
free(load_json_str);
|
||||
char *result_json_str = cJSON_Print(g_test_result_root);
|
||||
printf("TEST Raw:\n%s\n", result_json_str);
|
||||
free(result_json_str);
|
||||
|
||||
cJSON *t_load = g_load_result_root->child, *t_test = g_test_result_root->child;
|
||||
while (t_load != NULL)
|
||||
{
|
||||
ret = cJSON_Compare(t_load, t_test, 0);
|
||||
if (ret != 1)
|
||||
{
|
||||
load_json_str = cJSON_Print(t_load);
|
||||
printf("LOAD Diff:\n%s\n", load_json_str);
|
||||
free(load_json_str);
|
||||
result_json_str = cJSON_Print(t_test);
|
||||
printf("TEST Diff:\n%s\n", result_json_str);
|
||||
free(result_json_str);
|
||||
goto fail;
|
||||
}
|
||||
t_load = t_load->next;
|
||||
t_test = t_test->next;
|
||||
}
|
||||
}
|
||||
cJSON_Delete(g_load_result_root);
|
||||
cJSON_Delete(g_test_result_root);
|
||||
return;
|
||||
fail:
|
||||
cJSON_Delete(g_load_result_root);
|
||||
cJSON_Delete(g_test_result_root);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Usage: %s <result_json_path>\n", argv[0]);
|
||||
result_json_path = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_json_path = argv[1];
|
||||
g_test_result_root = cJSON_CreateArray();
|
||||
g_load_result_root = load_result_from_jsonfile(result_json_path);
|
||||
assert(g_load_result_root != NULL && g_test_result_root != NULL);
|
||||
}
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
struct stellar *st = stellar_new("./conf/stellar.toml", "./plugin/spec.toml", "./conf/log.toml");
|
||||
stellar_run(st);
|
||||
if (result_json_path != NULL)
|
||||
{
|
||||
ret = RUN_ALL_TESTS();
|
||||
}
|
||||
stellar_free(st);
|
||||
return ret;
|
||||
}
|
||||
246
test/decoders/socks/socks_decoder_pcap_gtest.cpp
Normal file
246
test/decoders/socks/socks_decoder_pcap_gtest.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <pcap/sll.h>
|
||||
#include <pcap/pcap.h>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "socks_decoder_internal.h"
|
||||
extern "C" {
|
||||
#include "stellar/session.h"
|
||||
#include "dummy.h"
|
||||
}
|
||||
|
||||
#define LINUX_COOKED_CAPTURE 20
|
||||
|
||||
extern int socks_process(struct socks_decoder_info *socks_decoder_info, struct session *sess, struct socks_tunnel_stream *stream, const char *payload, size_t payload_len);
|
||||
struct pcap_loop_arg
|
||||
{
|
||||
pcap_t *pcap_handle;
|
||||
struct socks_tunnel_stream *stream;
|
||||
};
|
||||
|
||||
struct socks_decoder_info *socks_decoder_info = NULL;
|
||||
|
||||
static void pcap_handle_cb(pcap_loop_arg *userarg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
|
||||
{
|
||||
struct pcap_loop_arg *arg = (struct pcap_loop_arg *)userarg;
|
||||
struct session sess;
|
||||
int payload_len = 0;
|
||||
char *payload = NULL;
|
||||
unsigned short sport, dport;
|
||||
unsigned short eth_proto_type;
|
||||
unsigned char *ip_header;
|
||||
|
||||
memset(&sess, 0, sizeof(sess));
|
||||
|
||||
int data_link_type = pcap_datalink(arg->pcap_handle);
|
||||
switch (data_link_type) {
|
||||
case DLT_EN10MB:
|
||||
eth_proto_type = ntohs(*(unsigned short *)(packet + 12));
|
||||
ip_header = (unsigned char *)(packet + sizeof(struct ethhdr));
|
||||
break;
|
||||
case 276://DLT_LINUX_SLL2
|
||||
eth_proto_type = ntohs(*(unsigned short *)packet);
|
||||
ip_header = (unsigned char *)(packet + LINUX_COOKED_CAPTURE);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (eth_proto_type == ETH_P_IP) {
|
||||
int l4_proto = *(unsigned char *)(ip_header + 9);
|
||||
if (l4_proto == IPPROTO_TCP) {
|
||||
int ip_total_len = ntohs(*(unsigned short *)(ip_header + 2));
|
||||
int ip_header_len = (*(unsigned char *)ip_header & 0x0f) * 4;
|
||||
int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(iphdr) + 12) & 0xf0) >> 4);
|
||||
payload_len = ip_total_len - ip_header_len - tcp_header_len;
|
||||
payload = (char *)ip_header + ip_header_len + tcp_header_len;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
sport = ntohs(*(unsigned short *)(ip_header + sizeof(iphdr) + 0));
|
||||
dport = ntohs(*(unsigned short *)(ip_header + sizeof(iphdr) + 2));
|
||||
|
||||
} else if (eth_proto_type == ETH_P_IPV6) {
|
||||
int l4_proto = *(unsigned char *)(ip_header + 6);
|
||||
if (l4_proto == IPPROTO_TCP) {
|
||||
int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(struct ip6_hdr) + 12) & 0xf0) >> 4);
|
||||
payload_len = pkthdr->caplen - (ip_header - packet) - sizeof(struct ip6_hdr) - tcp_header_len;
|
||||
payload = (char *)ip_header + sizeof(struct ip6_hdr) + tcp_header_len;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
sport = ntohs(*(unsigned short *)(ip_header + sizeof(struct ip6_hdr) + 0));
|
||||
dport = ntohs(*(unsigned short *)(ip_header + sizeof(struct ip6_hdr) + 2));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
session_set_current_state(&sess, SESSION_STATE_ACTIVE);
|
||||
|
||||
if (sport > dport)
|
||||
{
|
||||
dummy_set_direction(FLOW_TYPE_C2S);
|
||||
} else {
|
||||
dummy_set_direction(FLOW_TYPE_S2C);
|
||||
}
|
||||
socks_process(socks_decoder_info, &sess, arg->stream, payload, payload_len);
|
||||
|
||||
}
|
||||
|
||||
TEST(socks_decoder, socks4)
|
||||
{
|
||||
char error[100];
|
||||
struct pcap_loop_arg arg;
|
||||
struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream));
|
||||
pcap_t * handle = pcap_open_offline("pcap/socks4.pcap", error);
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.stream = stream;
|
||||
arg.pcap_handle = handle;
|
||||
|
||||
pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg);
|
||||
|
||||
EXPECT_EQ(stream->info.version, SOCKS_VERSION_4);
|
||||
EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_IPV4);
|
||||
EXPECT_EQ(stream->info.dst_addr.ipv4, inet_addr("93.184.216.119"));
|
||||
EXPECT_EQ(stream->info.dst_addr.port, htons(80));
|
||||
EXPECT_EQ(stream->info.user_name.iov_len, 0);
|
||||
EXPECT_EQ(stream->info.password.iov_len, 0);
|
||||
EXPECT_EQ(stream->client_state, SS_END);
|
||||
EXPECT_EQ(stream->server_state, SS_END);
|
||||
|
||||
pcap_close(handle);
|
||||
free(stream);
|
||||
}
|
||||
|
||||
TEST(socks_decoder, socks4a_domain)
|
||||
{
|
||||
char error[100];
|
||||
struct pcap_loop_arg arg;
|
||||
struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream));
|
||||
pcap_t * handle = pcap_open_offline("pcap/socks4a_domain.pcap", error);
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.stream = stream;
|
||||
arg.pcap_handle = handle;
|
||||
|
||||
pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg);
|
||||
|
||||
EXPECT_EQ(stream->info.version, SOCKS_VERSION_4);
|
||||
EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_FQDN);
|
||||
EXPECT_EQ(stream->info.dst_addr.fqdn.iov_len, strlen("www.example.com"));
|
||||
EXPECT_STREQ("www.example.com", (char *)stream->info.dst_addr.fqdn.iov_base);
|
||||
EXPECT_EQ(stream->info.dst_addr.port, htons(80));
|
||||
EXPECT_EQ(stream->info.user_name.iov_len, 0);
|
||||
EXPECT_EQ(stream->info.password.iov_len, 0);
|
||||
EXPECT_EQ(stream->client_state, SS_END);
|
||||
EXPECT_EQ(stream->server_state, SS_END);
|
||||
|
||||
pcap_close(handle);
|
||||
free(stream->info.dst_addr.fqdn.iov_base);
|
||||
free(stream);
|
||||
}
|
||||
|
||||
TEST(socks_decoder, socks5_no_auth)
|
||||
{
|
||||
char error[100];
|
||||
struct pcap_loop_arg arg;
|
||||
struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream));
|
||||
pcap_t * handle = pcap_open_offline("pcap/socks5_no_auth.pcap", error);
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.stream = stream;
|
||||
arg.pcap_handle = handle;
|
||||
|
||||
pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg);
|
||||
|
||||
EXPECT_EQ(stream->info.version, SOCKS_VERSION_5);
|
||||
EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_IPV4);
|
||||
EXPECT_EQ(stream->info.dst_addr.ipv4, inet_addr("93.184.216.119"));
|
||||
EXPECT_EQ(stream->info.dst_addr.port, htons(80));
|
||||
EXPECT_EQ(stream->info.user_name.iov_len, 0);
|
||||
EXPECT_EQ(stream->info.password.iov_len, 0);
|
||||
EXPECT_EQ(stream->client_state, SS_END);
|
||||
EXPECT_EQ(stream->server_state, SS_END);
|
||||
|
||||
pcap_close(handle);
|
||||
free(stream);
|
||||
}
|
||||
|
||||
TEST(socks_decoder, socks5_auth_success)
|
||||
{
|
||||
char error[100];
|
||||
struct pcap_loop_arg arg;
|
||||
struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream));
|
||||
pcap_t * handle = pcap_open_offline("pcap/socks5_auth_success.pcap", error);
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.stream = stream;
|
||||
arg.pcap_handle = handle;
|
||||
|
||||
pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg);
|
||||
|
||||
EXPECT_EQ(stream->info.version, SOCKS_VERSION_5);
|
||||
EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_IPV4);
|
||||
EXPECT_EQ(stream->info.dst_addr.ipv4, inet_addr("93.184.216.119"));
|
||||
EXPECT_EQ(stream->info.dst_addr.port, htons(80));
|
||||
EXPECT_EQ(stream->info.user_name.iov_len, strlen("testuser"));
|
||||
EXPECT_STREQ("testuser", (char *)stream->info.user_name.iov_base);
|
||||
EXPECT_EQ(stream->info.password.iov_len, strlen("testuser"));
|
||||
EXPECT_STREQ("testuser", (char *)stream->info.password.iov_base);
|
||||
EXPECT_EQ(stream->client_state, SS_END);
|
||||
EXPECT_EQ(stream->server_state, SS_END);
|
||||
|
||||
pcap_close(handle);
|
||||
free(stream->info.user_name.iov_base);
|
||||
free(stream->info.password.iov_base);
|
||||
free(stream);
|
||||
}
|
||||
|
||||
TEST(socks_decoder, socks5_auth_fail)
|
||||
{
|
||||
char error[100];
|
||||
struct pcap_loop_arg arg;
|
||||
struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream));
|
||||
pcap_t * handle = pcap_open_offline("pcap/socks5_auth_failed.pcap", error);
|
||||
ASSERT_NE(handle, nullptr);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.stream = stream;
|
||||
arg.pcap_handle = handle;
|
||||
|
||||
pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg);
|
||||
|
||||
EXPECT_EQ(stream->client_state, SS_SUB);
|
||||
EXPECT_EQ(stream->server_state, SS_FAILED);
|
||||
|
||||
pcap_close(handle);
|
||||
free(stream->info.user_name.iov_base);
|
||||
free(stream->info.password.iov_base);
|
||||
free(stream);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
socks_decoder_info = (struct socks_decoder_info *)calloc(1, sizeof(struct socks_decoder_info));
|
||||
|
||||
int result = RUN_ALL_TESTS();
|
||||
|
||||
free(socks_decoder_info);
|
||||
|
||||
return result;
|
||||
}
|
||||
88
test/decoders/socks/socks_decoder_test_plugin.cpp
Normal file
88
test/decoders/socks/socks_decoder_test_plugin.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
extern "C" {
|
||||
#include "stellar/stellar.h"
|
||||
#include "stellar/session.h"
|
||||
#include "stellar/stellar_mq.h"
|
||||
#include "stellar/stellar_exdata.h"
|
||||
}
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "socks_decoder.h"
|
||||
|
||||
extern "C" int commit_test_result_json(cJSON *node, const char *name);
|
||||
#define unused(x) ((void)(x))
|
||||
|
||||
|
||||
int g_test_socks_decoder_plugin_id = 0;
|
||||
int g_socks_message_topic_id = 0;
|
||||
|
||||
void *ctx_new(struct session *session, void *plugin_env)
|
||||
{
|
||||
unused(plugin_env);
|
||||
unused(session);
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
return (void *)root;
|
||||
}
|
||||
|
||||
void ctx_free(struct session *sess, void *session_ctx, void *plugin_env)
|
||||
{
|
||||
unused(sess);
|
||||
unused(plugin_env);
|
||||
|
||||
commit_test_result_json((cJSON *)session_ctx, "socks_decoder_test");
|
||||
}
|
||||
|
||||
static void append_json(cJSON *root, struct socks_info *info)
|
||||
{
|
||||
cJSON *json_stream = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddStringToObject(json_stream, "version", info->version == SOCKS_VERSION_4 ? "SOCKS4" : "SOCKS5");
|
||||
|
||||
char ip_str[INET6_ADDRSTRLEN] = {0};
|
||||
if (info->dst_addr.type == SOCKS_ADDR_IPV4) {
|
||||
inet_ntop(AF_INET, &info->dst_addr.ipv4, ip_str, INET_ADDRSTRLEN);
|
||||
} else if (info->dst_addr.type == SOCKS_ADDR_IPV6) {
|
||||
inet_ntop(AF_INET6, info->dst_addr.ipv6, ip_str, INET6_ADDRSTRLEN);
|
||||
} else {
|
||||
memcpy(ip_str, info->dst_addr.fqdn.iov_base, info->dst_addr.fqdn.iov_len);
|
||||
}
|
||||
cJSON_AddStringToObject(json_stream, "dst_addr", ip_str);
|
||||
cJSON_AddNumberToObject(json_stream, "dst_port", ntohs(info->dst_addr.port));
|
||||
cJSON_AddStringToObject(json_stream, "user_name", (char *)info->user_name.iov_base);
|
||||
cJSON_AddStringToObject(json_stream, "password", (char *)info->password.iov_base);
|
||||
|
||||
cJSON_AddItemToObject(root, "socks_info", json_stream);
|
||||
}
|
||||
|
||||
void test_socks_decoder_on_message(struct session *session, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env)
|
||||
{
|
||||
unused(plugin_env);
|
||||
unused(session);
|
||||
unused(topic_id);
|
||||
|
||||
struct socks_info *info = (struct socks_info *)msg;
|
||||
cJSON *json_root = (cJSON *)per_session_ctx;
|
||||
|
||||
append_json(json_root, info);
|
||||
}
|
||||
|
||||
extern "C" void *SOCKS_DECODER_TEST_PLUG_INIT(struct stellar *st)
|
||||
{
|
||||
g_test_socks_decoder_plugin_id = stellar_session_plugin_register(st, ctx_new, ctx_free, NULL);
|
||||
g_socks_message_topic_id = stellar_mq_get_topic_id(st, SOCKS_MESSAGE_TOPIC);
|
||||
|
||||
stellar_session_mq_subscribe(st, g_socks_message_topic_id, test_socks_decoder_on_message, g_test_socks_decoder_plugin_id);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C" void SOCKS_DECODER_TEST_PLUG_DESTROY(void *plugin_env)
|
||||
{
|
||||
unused(plugin_env);
|
||||
}
|
||||
37
test/decoders/socks/test_based_on_stellar/CMakeLists.txt
Normal file
37
test/decoders/socks/test_based_on_stellar/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
set(DECODER_NAME socks)
|
||||
|
||||
set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/test/decoders/socks)
|
||||
set(SAPP_DEVEL_DIR ${TEST_RUN_DIR}/lib)
|
||||
set(TEST_MAIN socks_test_main)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/test)
|
||||
include_directories(/usr/local/include/cjson)
|
||||
include_directories(/opt/tsg/framework/include/stellar)
|
||||
include_directories(/opt/MESA/include/MESA)
|
||||
include_directories(/opt/tsg/stellar/include/)
|
||||
|
||||
#various ways to add -rdynamic for centos7, centos8, and different cmake version
|
||||
add_definitions(-rdynamic)
|
||||
link_directories(${SAPP_DEVEL_DIR})
|
||||
|
||||
# assemble test env
|
||||
add_test(NAME SOCKS_MKDIR_METRIC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/metrics; mkdir -p ${TEST_RUN_DIR}/plugin; mkdir -p ${TEST_RUN_DIR}/log; mkdir -p ${TEST_RUN_DIR}/pcap")
|
||||
add_test(NAME SOCKS_COPY_SPEC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plugin/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/spec.toml ${TEST_RUN_DIR}/plugin/spec.toml")
|
||||
add_test(NAME SOCKS_COPY_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/stellar.toml ${TEST_RUN_DIR}/conf/stellar.toml")
|
||||
add_test(NAME SOCKS_COPY_LOG_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/log.toml ${TEST_RUN_DIR}/conf/log.toml")
|
||||
|
||||
# update plugin to be tested
|
||||
add_test(NAME SOCKS_CP_DECODER_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/decoders/socks/socks_dyn.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}.so")
|
||||
add_test(NAME SOCKS_CP_DECODER_GTEST_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/decoders/socks/${DECODER_NAME}_test.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}_test.so")
|
||||
|
||||
set_tests_properties(SOCKS_MKDIR_METRIC SOCKS_COPY_SPEC
|
||||
SOCKS_COPY_CONF SOCKS_COPY_LOG_CONF
|
||||
SOCKS_CP_DECODER_SO SOCKS_CP_DECODER_GTEST_SO
|
||||
PROPERTIES FIXTURES_SETUP TestFixture)
|
||||
|
||||
set(TEST_PCAP_DIR ${PROJECT_SOURCE_DIR}/test/decoders/socks/pcap)
|
||||
|
||||
# run tests
|
||||
add_test(NAME SOCKS_DECODER_PLUGIN_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/socks4_nest_socks4a.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_PCAP_DIR}/result.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
|
||||
|
||||
4
test/decoders/socks/test_based_on_stellar/env/log.toml
vendored
Normal file
4
test/decoders/socks/test_based_on_stellar/env/log.toml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[log]
|
||||
output = "stderr" # stderr, file
|
||||
file = "log/stellar.log"
|
||||
level = "ERROR" # TRACE, DEBUG, INFO, WARN, ERROR, FATAL
|
||||
9
test/decoders/socks/test_based_on_stellar/env/spec.toml
vendored
Normal file
9
test/decoders/socks/test_based_on_stellar/env/spec.toml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
[[plugin]]
|
||||
path = "./plugin/socks.so"
|
||||
init = "socks_decoder_init"
|
||||
exit = "socks_decoder_exit"
|
||||
|
||||
[[plugin]]
|
||||
path = "./plugin/socks_test.so"
|
||||
init = "SOCKS_DECODER_TEST_PLUG_INIT"
|
||||
exit = "SOCKS_DECODER_TEST_PLUG_DESTROY"
|
||||
64
test/decoders/socks/test_based_on_stellar/env/stellar.toml
vendored
Normal file
64
test/decoders/socks/test_based_on_stellar/env/stellar.toml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
[instance]
|
||||
id = 1 # range: [0, 4095] (20 bit)
|
||||
|
||||
[packet_io]
|
||||
mode = "pcapfile" # pcapfile, pcaplist, marsio
|
||||
app_symbol = "stellar"
|
||||
dev_symbol = "nf_0_fw"
|
||||
pcap_path = "./pcap/test.pcap"
|
||||
nr_worker_thread = 1 # range: [1, 256]
|
||||
cpu_mask = [5, 6, 7, 8, 9, 10, 11, 12]
|
||||
idle_yield_interval_ms = 90 # range: [0, 60000] (ms)
|
||||
|
||||
[ip_reassembly]
|
||||
enable = 1
|
||||
bucket_entries = 32 # range: [1, 4294967295] (must be power of 2)
|
||||
bucket_num = 1024 # range: [1, 4294967295]
|
||||
|
||||
ip_frag_timeout_ms = 1000 # range: [1, 60000] (ms)
|
||||
ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms)
|
||||
ip_frag_expire_polling_limit = 1024 # range: [1, 1024]
|
||||
|
||||
[session_manager]
|
||||
tcp_session_max = 500
|
||||
udp_session_max = 500
|
||||
|
||||
evict_old_on_tcp_table_limit = 1 # range: [0, 1]
|
||||
evict_old_on_udp_table_limit = 1 # range: [0, 1]
|
||||
|
||||
expire_period_ms = 0 # range: [0, 60000] (ms)
|
||||
expire_batch_max = 1024 # range: [1, 1024]
|
||||
|
||||
[session_manager.tcp_timeout_ms]
|
||||
init = 500 # range: [1, 60000] (ms)
|
||||
handshake = 500 # range: [1, 60000] (ms)
|
||||
data = 500 # range: [1, 15999999000] (ms)
|
||||
half_closed = 500 # range: [1, 604800000] (ms)
|
||||
time_wait = 500 # range: [1, 600000] (ms)
|
||||
discard_default = 1000 # range: [1, 15999999000] (ms)
|
||||
unverified_rst = 500 # range: [1, 600000] (ms)
|
||||
|
||||
[session_manager.udp_timeout_ms]
|
||||
data = 500 # range: [1, 15999999000] (ms)
|
||||
discard_default = 500 # range: [1, 15999999000] (ms)
|
||||
|
||||
[session_manager.duplicated_packet_bloom_filter]
|
||||
enable = 0
|
||||
capacity = 1000000 # range: [1, 4294967295]
|
||||
time_window_ms = 10000 # range: [1, 60000] (ms)
|
||||
error_rate = 0.00001 # range: [0.0, 1.0]
|
||||
|
||||
[session_manager.evicted_session_bloom_filter]
|
||||
enable = 0 # range: [0, 1]
|
||||
capacity = 1000000 # range: [1, 4294967295]
|
||||
time_window_ms = 10000 # range: [1, 60000] (ms)
|
||||
error_rate = 0.00001 # range: [0.0, 1.0]
|
||||
|
||||
[session_manager.tcp_reassembly]
|
||||
enable = 1 # range: [0, 1]
|
||||
timeout_ms = 100 # range: [1, 60000] (ms)
|
||||
buffered_segments_max = 256 # range: [2, 4096] per flow
|
||||
|
||||
[stat]
|
||||
merge_interval_ms = 500 # range: [0, 60000] (ms)
|
||||
output_interval_ms = 1000 # range: [0, 60000] (ms)
|
||||
Reference in New Issue
Block a user