1、将dynamic bypass 从tsg_entry.cpp 拆分出来 2、使用ja3信息代替chello信息做bypass ssl信息 3、增加获取ja3流标签,通过cmsg发送给tfe 4、增加dynamic bypass 配置文件开关
This commit is contained in:
@@ -74,6 +74,8 @@ enum tfe_cmsg_tlv_type
|
|||||||
TFE_CMSG_DST_IP_LOCATION_PROVINE, // string max size 256
|
TFE_CMSG_DST_IP_LOCATION_PROVINE, // string max size 256
|
||||||
TFE_CMSG_SRC_IP_LOCATION_CITY, // string max size 256
|
TFE_CMSG_SRC_IP_LOCATION_CITY, // string max size 256
|
||||||
TFE_CMSG_DST_IP_LOCATION_CITY, // string max size 256
|
TFE_CMSG_DST_IP_LOCATION_CITY, // string max size 256
|
||||||
|
//ja3 fingerprint
|
||||||
|
TFE_CMSG_SSL_CLIENT_JA3_FINGERPRINT,
|
||||||
//cmsg tlv max
|
//cmsg tlv max
|
||||||
KNI_CMSG_TLV_NR_MAX,
|
KNI_CMSG_TLV_NR_MAX,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,7 +75,11 @@ print_mode = 1
|
|||||||
#self test Shunt rules security policy id
|
#self test Shunt rules security policy id
|
||||||
[tsg_diagnose]
|
[tsg_diagnose]
|
||||||
enabled = 1
|
enabled = 1
|
||||||
security_policy_id = 3
|
security_policy_id = 3,10
|
||||||
|
|
||||||
|
|
||||||
|
[ssl_dynamic_bypass]
|
||||||
|
enabled = 1
|
||||||
|
|
||||||
#kni dynamic bypass
|
#kni dynamic bypass
|
||||||
[traceid2sslinfo_htable]
|
[traceid2sslinfo_htable]
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
add_library(kni SHARED src/kni_entry.cpp src/tfe_mgr.cpp src/ssl_utils.cpp src/kni_tun.cpp src/kni_pxy_tcp_option.cpp)
|
add_library(kni SHARED src/kni_entry.cpp src/tfe_mgr.cpp src/kni_tun.cpp src/kni_pxy_tcp_option.cpp src/kni_dynamic_bypass.cpp)
|
||||||
target_include_directories(kni PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
target_include_directories(kni PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
target_link_libraries(kni common MESA_prof_load MESA_htable MESA_field_stat maatframe mrzcpd dabloom)
|
target_link_libraries(kni common MESA_prof_load MESA_htable MESA_field_stat maatframe mrzcpd dabloom)
|
||||||
12
entry/include/kni_dynamic_bypass.h
Normal file
12
entry/include/kni_dynamic_bypass.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef __KNI_DYNAMIC_BYPASS_H__
|
||||||
|
#define __KNI_DYNAMIC_BYPASS_H__
|
||||||
|
|
||||||
|
#include "kni_entry.h"
|
||||||
|
|
||||||
|
int first_data_ssl_dynamic_bypass(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq);
|
||||||
|
void next_data_ssl_dynamic_bypass(struct pkt_info *pktinfo);
|
||||||
|
int ssl_dynamic_bypass_htable_add(struct pme_info *pmeinfo);
|
||||||
|
int ssl_dynamic_bypass_htable_init(const char *profile,void * local_logger);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
#define CALLER_SAPP 0
|
#define CALLER_SAPP 0
|
||||||
#define CALLER_TFE 1
|
#define CALLER_TFE 1
|
||||||
|
|
||||||
#define SSL_INFO_LEN 2048
|
|
||||||
#define _MAX_MAAT_TABLE_NAME_LEN 64
|
#define _MAX_MAAT_TABLE_NAME_LEN 64
|
||||||
|
|
||||||
#define MAX_STRING_LEN 32
|
#define MAX_STRING_LEN 32
|
||||||
@@ -217,6 +216,7 @@ struct kni_handle{
|
|||||||
int tsg_diagnose_enable;
|
int tsg_diagnose_enable;
|
||||||
int *arr_last_tfe_dispatch_index;
|
int *arr_last_tfe_dispatch_index;
|
||||||
struct security_policy_shunt_tsg_diagnose secpolicyid_shunt_tsg_diagnose;
|
struct security_policy_shunt_tsg_diagnose secpolicyid_shunt_tsg_diagnose;
|
||||||
|
int ssl_dynamic_bypass_enable;
|
||||||
MESA_htable_handle sslinfo2bypass_htable;
|
MESA_htable_handle sslinfo2bypass_htable;
|
||||||
int pxy_tcp_option_enable; //for proxy tcp option enable
|
int pxy_tcp_option_enable; //for proxy tcp option enable
|
||||||
int pxy_tcp_option_enable_override;
|
int pxy_tcp_option_enable_override;
|
||||||
@@ -231,10 +231,7 @@ struct traceid2pme_search_cb_args{
|
|||||||
void *logger;
|
void *logger;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dynamic_bypass_ssl_feature{
|
|
||||||
char value[SSL_INFO_LEN];
|
|
||||||
size_t vlen;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
enum chello_parse_result
|
|
||||||
{
|
|
||||||
CHELLO_PARSE_SUCCESS = 0,
|
|
||||||
CHELLO_PARSE_INVALID_FORMAT = -1,
|
|
||||||
CHELLO_PARSE_NOT_ENOUGH_BUFF = -2
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssl_version
|
|
||||||
{
|
|
||||||
uint8_t minor;
|
|
||||||
uint8_t major;
|
|
||||||
uint16_t ossl_format;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssl_chello
|
|
||||||
{
|
|
||||||
struct ssl_version min_version;
|
|
||||||
struct ssl_version max_version;
|
|
||||||
|
|
||||||
char *sni;
|
|
||||||
char *alpn;
|
|
||||||
char *sign_algos;
|
|
||||||
uint16_t sign_algos_len;
|
|
||||||
char *supported_groups;
|
|
||||||
uint16_t supported_groups_len;
|
|
||||||
char *cipher_suites;
|
|
||||||
uint16_t cipher_suites_len;
|
|
||||||
};
|
|
||||||
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result);
|
|
||||||
|
|
||||||
void ssl_chello_free(struct ssl_chello* chello);
|
|
||||||
|
|
||||||
void ssl_cipher_suites_to_name(const char *source, int source_len, char *result_common, size_t sz_common, char *result_tls13, size_t sz_tls13);
|
|
||||||
|
|
||||||
368
entry/src/kni_dynamic_bypass.cpp
Normal file
368
entry/src/kni_dynamic_bypass.cpp
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
#include "kni_dynamic_bypass.h"
|
||||||
|
|
||||||
|
#define SSL_INFO_LEN 512
|
||||||
|
|
||||||
|
struct dynamic_bypass_ssl_feature{
|
||||||
|
size_t vlen;
|
||||||
|
char value[SSL_INFO_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct kni_handle *g_kni_handle;
|
||||||
|
extern struct kni_field_stat_handle *g_kni_fs_handle;
|
||||||
|
|
||||||
|
char * stream_addr_to_str(struct pme_info *pmeinfo,struct pkt_info *pktinfo)
|
||||||
|
{
|
||||||
|
char * __str_ret = NULL;
|
||||||
|
if(pmeinfo==NULL || pktinfo == NULL) return NULL;
|
||||||
|
if (pmeinfo->addr_type == ADDR_TYPE_IPV4)
|
||||||
|
{
|
||||||
|
char __src_addr[INET_ADDRSTRLEN];
|
||||||
|
char __dst_addr[INET_ADDRSTRLEN];
|
||||||
|
uint16_t __src_port;
|
||||||
|
uint16_t __dst_port;
|
||||||
|
if(pktinfo->iphdr.v4->saddr < pktinfo->iphdr.v4->daddr){
|
||||||
|
__src_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->source);
|
||||||
|
__dst_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->dest);
|
||||||
|
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->saddr), __src_addr, sizeof(__src_addr));
|
||||||
|
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->daddr), __dst_addr, sizeof(__dst_addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__src_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->dest);
|
||||||
|
__dst_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->source);
|
||||||
|
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->daddr), __src_addr, sizeof(__src_addr));
|
||||||
|
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->saddr), __dst_addr, sizeof(__dst_addr));
|
||||||
|
}
|
||||||
|
asprintf(&__str_ret, "%s %u %s %u", __src_addr, __src_port, __dst_addr, __dst_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmeinfo->addr_type == ADDR_TYPE_IPV6)
|
||||||
|
{
|
||||||
|
char __src_addr[INET6_ADDRSTRLEN];
|
||||||
|
char __dst_addr[INET6_ADDRSTRLEN];
|
||||||
|
uint16_t __src_port;
|
||||||
|
uint16_t __dst_port;
|
||||||
|
if(memcmp((void*)&(pktinfo->iphdr.v6->ip6_src), (void*)&(pktinfo->iphdr.v6->ip6_dst), IPV6_ADDR_LEN) < 0){
|
||||||
|
__src_port = ntohs((uint16_t) pktinfo->tcphdr->source);
|
||||||
|
__dst_port = ntohs((uint16_t) pktinfo->tcphdr->dest);
|
||||||
|
memcpy(__src_addr, &(pktinfo->iphdr.v6->ip6_src), sizeof(__src_addr));
|
||||||
|
memcpy(__dst_addr, &(pktinfo->iphdr.v6->ip6_dst), sizeof(__dst_addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__src_port = ntohs((uint16_t) pktinfo->tcphdr->dest);
|
||||||
|
__dst_port = ntohs((uint16_t) pktinfo->tcphdr->source);
|
||||||
|
memcpy(__src_addr, &(pktinfo->iphdr.v6->ip6_dst), sizeof(__src_addr));
|
||||||
|
memcpy(__dst_addr, &(pktinfo->iphdr.v6->ip6_src), sizeof(__dst_addr));
|
||||||
|
}
|
||||||
|
asprintf(&__str_ret, "%s %u %s %u", __src_addr, __src_port, __dst_addr, __dst_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return __str_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stream_addr_str_split(char* addr_str, const char** sip, const char** sport, const char** dip, const char** dport)
|
||||||
|
{
|
||||||
|
const char* seps=" ";
|
||||||
|
char* saveptr=NULL, *subtoken=NULL, *str=NULL;
|
||||||
|
int i=0;
|
||||||
|
for (str = addr_str, i=0; ; str = NULL, i++)
|
||||||
|
{
|
||||||
|
subtoken = strtok_r(str, seps, &saveptr);
|
||||||
|
if (subtoken == NULL)
|
||||||
|
break;
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if(sip!=NULL) *sip=subtoken;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if(sport!=NULL) *sport=subtoken;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(dip!=NULL) *dip=subtoken;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if(dport!=NULL) *dport=subtoken;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static long sslinfo2bypass_htable_search_cb(void *data, const uchar *key, uint size, void *user_args){
|
||||||
|
if(data != NULL)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sslinfo2bypass_htable_search(MESA_htable_handle htable,char *key, int klen, struct pme_info *pmeinfo)
|
||||||
|
{
|
||||||
|
void *logger = g_kni_handle->local_logger;
|
||||||
|
long cb_ret = -1;
|
||||||
|
void *value;
|
||||||
|
value = MESA_htable_search_cb(htable, (const unsigned char *)key, (unsigned int )klen, sslinfo2bypass_htable_search_cb, NULL, &cb_ret);
|
||||||
|
if(cb_ret == 0)
|
||||||
|
{
|
||||||
|
pmeinfo->ssl_pinningst = *((uint64_t *)value);
|
||||||
|
KNI_LOG_DEBUG(logger, "MESA_htable: success to search, table = sslinfo2bypass_htable,key = %s, key_size = %d, ret =%d", key, klen,cb_ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KNI_LOG_DEBUG(logger, "MESA_htable:Search result value is null, table = sslinfo2bypass_htable,key = %s, key_size = %d, ret =%d", key, klen,cb_ret);
|
||||||
|
}
|
||||||
|
return cb_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int traceid2sslinfo_htable_add(char *key, uint klen, void * value,int thread_seq)
|
||||||
|
{
|
||||||
|
void *logger = g_kni_handle->local_logger;
|
||||||
|
int ret;
|
||||||
|
MESA_htable_handle traceid2sslinfo_htable = g_kni_handle->threads_handle[thread_seq].traceid2sslinfo_htable;
|
||||||
|
ret = MESA_htable_add(traceid2sslinfo_htable, (const unsigned char *)key, klen, (const void*)value);
|
||||||
|
if(ret >= 0)
|
||||||
|
{
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_ADD_SUCC], 0, FS_OP_ADD, 1);
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_CNT], 0, FS_OP_ADD, 1);
|
||||||
|
KNI_LOG_DEBUG(logger, "MESA_htable:Success to add, table = traceid2sslinfo_htable,key = %s, key_size = %d, ret =%d , thread_seq=%d", key, klen,ret, thread_seq);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KNI_LOG_ERROR(logger, "MESA_htable:Fail to add, table = traceid2sslinfo_htable,key = %s, key_size = %d, ret =%d , thread_seq=%d", key, klen,ret, thread_seq);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sslinfo2bypass_htable_add(char *key, uint klen, void * value, void *logger)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
MESA_htable_handle sslinfo2bypass_htable = g_kni_handle->sslinfo2bypass_htable;
|
||||||
|
ret = MESA_htable_add(sslinfo2bypass_htable, (const unsigned char *)key, klen, (const void*)value);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add, table = sslinfo2bypass_htable, key = %s, key_size = %d, ret = %d",key, klen, ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KNI_LOG_DEBUG(logger, "MESA_htable: Success at add, table = sslinfo2bypass_htable, key = %s, key_size = %d, ret = %d",key, klen, ret);
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_ADD_SUCC], 0, FS_OP_ADD, 1);
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_CNT], 0, FS_OP_ADD, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long traceid2sslinfo_htable_search_cb(void *data, const uchar *key, uint size, void *user_args)
|
||||||
|
{
|
||||||
|
struct dynamic_bypass_ssl_feature * ssl_feature = (struct dynamic_bypass_ssl_feature *)data;
|
||||||
|
void *logger = g_kni_handle->local_logger;
|
||||||
|
uint64_t * p_ssl_pinningst = (uint64_t *)user_args;
|
||||||
|
uint64_t *value = NULL;
|
||||||
|
long cb_ret = -1;
|
||||||
|
|
||||||
|
if(ssl_feature != NULL)
|
||||||
|
{
|
||||||
|
value = ALLOC(uint64_t, 1);
|
||||||
|
*value = *p_ssl_pinningst;
|
||||||
|
if(sslinfo2bypass_htable_add(ssl_feature->value, ssl_feature->vlen, (void *)value, logger) < 0)
|
||||||
|
{
|
||||||
|
KNI_LOG_ERROR(logger, "Dynamic bypass, fail add to table = sslinfo2bypass_htable, key = %s, key_size = %d",
|
||||||
|
ssl_feature->value, ssl_feature->vlen);
|
||||||
|
}
|
||||||
|
cb_ret = 0;
|
||||||
|
}
|
||||||
|
return cb_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int traceid2sslinfo_htable_search(MESA_htable_handle htable,char *key, int klen, int thread_seq,uint64_t ssl_pinningst)
|
||||||
|
{
|
||||||
|
long cb_ret = -1;
|
||||||
|
void *logger = g_kni_handle->local_logger;
|
||||||
|
MESA_htable_search_cb(htable, (const unsigned char *)key, (unsigned int )klen, traceid2sslinfo_htable_search_cb, &ssl_pinningst, &cb_ret);
|
||||||
|
if(cb_ret >= 0)
|
||||||
|
{
|
||||||
|
KNI_LOG_DEBUG(logger, "MESA_htable: success to search, table = traceid2sslinfo_htable,thread_seq = %d,key = %s, key_size = %d, ret = %d",
|
||||||
|
thread_seq, key, klen,cb_ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KNI_LOG_ERROR(logger, "MESA_htable: Fail to search, table = traceid2sslinfo_htable,thread_seq = %d,key = %s, key_size = %d, ret = %d",
|
||||||
|
thread_seq, key, klen,cb_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void traceid2sslinfo_htable_data_free_cb(void *data){
|
||||||
|
FREE(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sslinfo2bypass_htable_data_free_cb(void *data){
|
||||||
|
FREE(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int traceid2sslinfo_htable_expire_notify_cb(void *data, int eliminate_type)
|
||||||
|
{
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_DEL_SUCC], 0, FS_OP_ADD, 1);
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_CNT], 0, FS_OP_ADD, -1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sslinfo2bypass_htable_expire_notify_cb(void *data, int eliminate_type)
|
||||||
|
{
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_DEL_SUCC], 0, FS_OP_ADD, 1);
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_CNT], 0, FS_OP_ADD, -1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int get_ssl_conn_info(struct pme_info *pmeinfo,struct pkt_info *pktinfo, struct dynamic_bypass_ssl_feature *ssl_feature)
|
||||||
|
{
|
||||||
|
void *logger = g_kni_handle->local_logger;
|
||||||
|
|
||||||
|
const char *sip=NULL, *sport=NULL, *dip=NULL, *dport=NULL;
|
||||||
|
char *addr_str = NULL;
|
||||||
|
|
||||||
|
if(pmeinfo->session_attribute_label->ja3_fingerprint == NULL)
|
||||||
|
{
|
||||||
|
KNI_LOG_DEBUG(logger, "Dynamic bypass:get stream label ja3_fingerprint is null, stream traceid = %s", pmeinfo->stream_traceid);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_str = stream_addr_to_str(pmeinfo,pktinfo);
|
||||||
|
stream_addr_str_split(addr_str, &sip, &sport, &dip, &dport);
|
||||||
|
|
||||||
|
|
||||||
|
ssl_feature->vlen = snprintf(ssl_feature->value, SSL_INFO_LEN, "%s:%s:%s",
|
||||||
|
pmeinfo->session_attribute_label->ja3_fingerprint,sip,
|
||||||
|
pmeinfo->domain_len > 0 ? (char*)&(pmeinfo->domain): dip);
|
||||||
|
|
||||||
|
FREE(&addr_str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int first_data_ssl_dynamic_bypass(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq)
|
||||||
|
{
|
||||||
|
struct dynamic_bypass_ssl_feature *ssl_feature = NULL;
|
||||||
|
void *logger = g_kni_handle->local_logger;
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
if(pmeinfo->protocol != PROTO_SSL){
|
||||||
|
KNI_LOG_DEBUG(logger, "Dynamic bypass: stream protocol is not ssl: stream traceid = %s, protocol = %d", pmeinfo->stream_traceid,pmeinfo->protocol);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_feature = ALLOC(struct dynamic_bypass_ssl_feature,1);
|
||||||
|
if(get_ssl_conn_info(pmeinfo,pktinfo, ssl_feature) == 1){
|
||||||
|
FREE(&ssl_feature);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
KNI_LOG_DEBUG(logger, "Dynamic bypass: ssl_info: %s, ssl_info len:%d, stream traceid = %s", ssl_feature->value, ssl_feature->vlen, pmeinfo->stream_traceid);
|
||||||
|
|
||||||
|
if(sslinfo2bypass_htable_search(g_kni_handle->sslinfo2bypass_htable,ssl_feature->value, ssl_feature->vlen,pmeinfo) == 0)
|
||||||
|
{
|
||||||
|
KNI_LOG_DEBUG(logger, "Dynamic bypass: passthrough ok, stream traceid = %s,ssl_pinningst = %d", pmeinfo->stream_traceid, pmeinfo->ssl_pinningst);
|
||||||
|
FREE(&ssl_feature);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KNI_LOG_DEBUG(logger, "Dynamic bypass: not passthrough, stream traceid = %s", pmeinfo->stream_traceid);
|
||||||
|
if(traceid2sslinfo_htable_add(pmeinfo->stream_traceid, strlen(pmeinfo->stream_traceid),ssl_feature,thread_seq) >=0)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FREE(&ssl_feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void next_data_ssl_dynamic_bypass(struct pkt_info *pktinfo)
|
||||||
|
{
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ssl_dynamic_bypass_htable_add(struct pme_info *pmeinfo)
|
||||||
|
{
|
||||||
|
void *logger = g_kni_handle->local_logger;
|
||||||
|
long cb_ret;
|
||||||
|
int ret = -1;
|
||||||
|
MESA_htable_handle traceid2sslinfo_htable = g_kni_handle->threads_handle[pmeinfo->thread_seq].traceid2sslinfo_htable;
|
||||||
|
if(pmeinfo->ssl_intercept_state == 0)
|
||||||
|
{
|
||||||
|
cb_ret = traceid2sslinfo_htable_search(traceid2sslinfo_htable,pmeinfo->stream_traceid, strlen(pmeinfo->stream_traceid), pmeinfo->thread_seq, pmeinfo->ssl_pinningst);
|
||||||
|
if(cb_ret >= 0)
|
||||||
|
{
|
||||||
|
cb_ret = MESA_htable_del(traceid2sslinfo_htable, (const unsigned char *)pmeinfo->stream_traceid, strlen(pmeinfo->stream_traceid), NULL);
|
||||||
|
if(cb_ret < 0)
|
||||||
|
{
|
||||||
|
KNI_LOG_ERROR(logger, "Delete traceid2sslinfo_htable fail,key=%s",pmeinfo->stream_traceid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_DEL_SUCC], 0, FS_OP_ADD, 1);
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_CNT], 0, FS_OP_ADD, -1);
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ssl_dynamic_bypass_htable_init(const char *profile,void *local_logger)
|
||||||
|
{
|
||||||
|
struct kni_htable_opt opt;
|
||||||
|
MESA_htable_handle sslinfo2bypass_htable = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
int ssl_dynamic_bypass_enable = 1;
|
||||||
|
|
||||||
|
MESA_load_profile_int_def(profile, "ssl_dynamic_bypass", "enabled", &ssl_dynamic_bypass_enable, 1);
|
||||||
|
KNI_LOG_ERROR(local_logger, "Dynamic bypass: MESA_prof_load, [%s]:\n enabled: %d", "ssl_dynamic_bypass",ssl_dynamic_bypass_enable);
|
||||||
|
g_kni_handle->ssl_dynamic_bypass_enable = ssl_dynamic_bypass_enable;
|
||||||
|
|
||||||
|
if(ssl_dynamic_bypass_enable == 1){
|
||||||
|
//init traceid2sslinfo_htable
|
||||||
|
memset(&opt, 0, sizeof(opt));
|
||||||
|
kni_get_htable_opt(&opt, profile, "traceid2sslinfo_htable", (void*)traceid2sslinfo_htable_data_free_cb, (void *)traceid2sslinfo_htable_expire_notify_cb, local_logger);
|
||||||
|
for(int i = 0; i < g_kni_handle->thread_count; i++){
|
||||||
|
MESA_htable_handle traceid2sslinfo_htable = kni_create_htable((char*)"traceid2sslinfo_htable", &opt, local_logger);
|
||||||
|
if(traceid2sslinfo_htable == NULL){
|
||||||
|
KNI_LOG_ERROR(local_logger, "Failed at kni_create_htable, table = traceid2sslinfo_htable");
|
||||||
|
ret = -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
g_kni_handle->threads_handle[i].traceid2sslinfo_htable = traceid2sslinfo_htable;
|
||||||
|
}
|
||||||
|
|
||||||
|
//init sslinfo2bypass_htable
|
||||||
|
memset(&opt, 0, sizeof(opt));
|
||||||
|
kni_get_htable_opt(&opt, profile, "sslinfo2bypass_htable", (void*)sslinfo2bypass_htable_data_free_cb, (void *)sslinfo2bypass_htable_expire_notify_cb, local_logger);
|
||||||
|
sslinfo2bypass_htable = kni_create_htable((char*)"sslinfo2bypass_htable", &opt, local_logger);
|
||||||
|
if(sslinfo2bypass_htable == NULL){
|
||||||
|
KNI_LOG_ERROR(local_logger, "Failed at create sslinfo2bypass_htable");
|
||||||
|
ret = -2;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
g_kni_handle->sslinfo2bypass_htable = sslinfo2bypass_htable;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,7 +19,6 @@ bypass: drome: pme_new_fail: destroy_pme
|
|||||||
#include "tfe_mgr.h"
|
#include "tfe_mgr.h"
|
||||||
#include <tsg/tsg_rule.h>
|
#include <tsg/tsg_rule.h>
|
||||||
#include <tsg/tsg_send_log.h>
|
#include <tsg/tsg_send_log.h>
|
||||||
#include "ssl_utils.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -33,6 +32,7 @@ extern "C" {
|
|||||||
#include <MESA/stream_inc/stream_control.h>
|
#include <MESA/stream_inc/stream_control.h>
|
||||||
#include "kni_entry.h"
|
#include "kni_entry.h"
|
||||||
#include "kni_pxy_tcp_option.h"
|
#include "kni_pxy_tcp_option.h"
|
||||||
|
#include "kni_dynamic_bypass.h"
|
||||||
|
|
||||||
struct kni_handle *g_kni_handle = NULL;
|
struct kni_handle *g_kni_handle = NULL;
|
||||||
struct kni_field_stat_handle *g_kni_fs_handle = NULL;
|
struct kni_field_stat_handle *g_kni_fs_handle = NULL;
|
||||||
@@ -351,6 +351,10 @@ static int session_attribute_cmsg_set(struct kni_cmsg *cmsg, struct pme_info *pm
|
|||||||
ret = wrapped_kni_cmsg_set(cmsg,TFE_CMSG_DST_IP_LOCATION_CITY, (const unsigned char*)session_attribute_label->server_location->city_full, strlen(session_attribute_label->server_location->city_full), pmeinfo);
|
ret = wrapped_kni_cmsg_set(cmsg,TFE_CMSG_DST_IP_LOCATION_CITY, (const unsigned char*)session_attribute_label->server_location->city_full, strlen(session_attribute_label->server_location->city_full), pmeinfo);
|
||||||
if(ret < 0) break;
|
if(ret < 0) break;
|
||||||
}
|
}
|
||||||
|
if(session_attribute_label->ja3_fingerprint == NULL)
|
||||||
|
ret = wrapped_kni_cmsg_set(cmsg,TFE_CMSG_SSL_CLIENT_JA3_FINGERPRINT, (const unsigned char*)empty_arr, strlen(empty_arr), pmeinfo);
|
||||||
|
else
|
||||||
|
ret = wrapped_kni_cmsg_set(cmsg,TFE_CMSG_SSL_CLIENT_JA3_FINGERPRINT, (const unsigned char*)session_attribute_label->ja3_fingerprint, strlen(session_attribute_label->ja3_fingerprint), pmeinfo);
|
||||||
}while(0);
|
}while(0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -905,279 +909,9 @@ static int dabloom_add(struct pkt_info *pktinfo, int thread_seq){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int stream_addr_str_split(char* addr_str, const char** sip, const char** sport, const char** dip, const char** dport)
|
|
||||||
{
|
|
||||||
const char* seps=" ";
|
|
||||||
char* saveptr=NULL, *subtoken=NULL, *str=NULL;
|
|
||||||
int i=0;
|
|
||||||
for (str = addr_str, i=0; ; str = NULL, i++)
|
|
||||||
{
|
|
||||||
subtoken = strtok_r(str, seps, &saveptr);
|
|
||||||
if (subtoken == NULL)
|
|
||||||
break;
|
|
||||||
switch(i)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
if(sip!=NULL) *sip=subtoken;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if(sport!=NULL) *sport=subtoken;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if(dip!=NULL) *dip=subtoken;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if(dport!=NULL) *dport=subtoken;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char * stream_addr_to_str(struct pme_info *pmeinfo,struct pkt_info *pktinfo)
|
|
||||||
{
|
|
||||||
char * __str_ret = NULL;
|
|
||||||
if(pmeinfo==NULL || pktinfo == NULL) return NULL;
|
|
||||||
if (pmeinfo->addr_type == ADDR_TYPE_IPV4)
|
|
||||||
{
|
|
||||||
char __src_addr[INET_ADDRSTRLEN];
|
|
||||||
char __dst_addr[INET_ADDRSTRLEN];
|
|
||||||
uint16_t __src_port;
|
|
||||||
uint16_t __dst_port;
|
|
||||||
if(pktinfo->iphdr.v4->saddr < pktinfo->iphdr.v4->daddr){
|
|
||||||
__src_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->source);
|
|
||||||
__dst_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->dest);
|
|
||||||
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->saddr), __src_addr, sizeof(__src_addr));
|
|
||||||
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->daddr), __dst_addr, sizeof(__dst_addr));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
__src_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->dest);
|
|
||||||
__dst_port = ntohs((uint16_t) pmeinfo->stream->addr.tuple4_v4->source);
|
|
||||||
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->daddr), __src_addr, sizeof(__src_addr));
|
|
||||||
inet_ntop(AF_INET, &(pmeinfo->stream->addr.tuple4_v4->saddr), __dst_addr, sizeof(__dst_addr));
|
|
||||||
}
|
|
||||||
asprintf(&__str_ret, "%s %u %s %u", __src_addr, __src_port, __dst_addr, __dst_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pmeinfo->addr_type == ADDR_TYPE_IPV6)
|
|
||||||
{
|
|
||||||
char __src_addr[INET6_ADDRSTRLEN];
|
|
||||||
char __dst_addr[INET6_ADDRSTRLEN];
|
|
||||||
uint16_t __src_port;
|
|
||||||
uint16_t __dst_port;
|
|
||||||
if(memcmp((void*)&(pktinfo->iphdr.v6->ip6_src), (void*)&(pktinfo->iphdr.v6->ip6_dst), IPV6_ADDR_LEN) < 0){
|
|
||||||
__src_port = ntohs((uint16_t) pktinfo->tcphdr->source);
|
|
||||||
__dst_port = ntohs((uint16_t) pktinfo->tcphdr->dest);
|
|
||||||
memcpy(__src_addr, &(pktinfo->iphdr.v6->ip6_src), sizeof(__src_addr));
|
|
||||||
memcpy(__dst_addr, &(pktinfo->iphdr.v6->ip6_dst), sizeof(__dst_addr));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
__src_port = ntohs((uint16_t) pktinfo->tcphdr->dest);
|
|
||||||
__dst_port = ntohs((uint16_t) pktinfo->tcphdr->source);
|
|
||||||
memcpy(__src_addr, &(pktinfo->iphdr.v6->ip6_dst), sizeof(__src_addr));
|
|
||||||
memcpy(__dst_addr, &(pktinfo->iphdr.v6->ip6_src), sizeof(__dst_addr));
|
|
||||||
}
|
|
||||||
asprintf(&__str_ret, "%s %u %s %u", __src_addr, __src_port, __dst_addr, __dst_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
return __str_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static size_t ssl_svc_app_st_mk_key(struct ssl_chello* chello, struct pkt_info *pktinfo, struct pme_info *pmeinfo, char* key_buff, size_t sz)
|
|
||||||
{
|
|
||||||
size_t key_len=0;
|
|
||||||
const char* sip=NULL, *sport=NULL, *dip=NULL, *dport=NULL;
|
|
||||||
char * addr_str= stream_addr_to_str(pmeinfo,pktinfo);
|
|
||||||
stream_addr_str_split(addr_str, &sip, &sport, &dip, &dport);
|
|
||||||
|
|
||||||
key_len=snprintf(key_buff, sz, "%d:%d:%s:%s", chello->min_version.ossl_format,
|
|
||||||
chello->max_version.ossl_format,
|
|
||||||
chello->sni?chello->sni: dip ,
|
|
||||||
chello->alpn?chello->alpn:"null");
|
|
||||||
if(chello->cipher_suites && sz-key_len>chello->cipher_suites_len)
|
|
||||||
{
|
|
||||||
memcpy(key_buff+key_len, chello->cipher_suites, chello->cipher_suites_len);
|
|
||||||
key_len+=chello->cipher_suites_len;
|
|
||||||
}
|
|
||||||
if(chello->sign_algos && sz-key_len > chello->sign_algos_len)
|
|
||||||
{
|
|
||||||
memcpy(key_buff+key_len, chello->sign_algos, chello->sign_algos_len);
|
|
||||||
key_len+=chello->sign_algos_len;
|
|
||||||
}
|
|
||||||
if(chello->supported_groups && sz-key_len > chello->supported_groups_len)
|
|
||||||
{
|
|
||||||
memcpy(key_buff+key_len, chello->supported_groups, chello->supported_groups_len);
|
|
||||||
key_len+=chello->supported_groups_len;
|
|
||||||
}
|
|
||||||
free(addr_str);
|
|
||||||
return key_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static size_t ssl_svc_client_st_mk_key(struct ssl_chello* chello,struct pme_info *pmeinfo, struct pkt_info *pktinfo,char* key_buff, size_t sz)
|
|
||||||
{
|
|
||||||
size_t key_len=0;
|
|
||||||
const char *sip=NULL, *sport=NULL, *dip=NULL, *dport=NULL;
|
|
||||||
char *addr_str = stream_addr_to_str(pmeinfo,pktinfo);
|
|
||||||
stream_addr_str_split(addr_str, &sip, &sport, &dip, &dport);
|
|
||||||
char chello_id_buff[sz];
|
|
||||||
size_t chello_id_len=0;
|
|
||||||
|
|
||||||
key_len=snprintf(key_buff, sz, "%s:", sip);
|
|
||||||
chello_id_len=ssl_svc_app_st_mk_key(chello, pktinfo,pmeinfo, chello_id_buff, sizeof(chello_id_buff));
|
|
||||||
memcpy(key_buff+key_len, chello_id_buff, MIN(chello_id_len, sz-key_len));
|
|
||||||
key_len += MIN(chello_id_len, sz-key_len);
|
|
||||||
|
|
||||||
FREE(&addr_str);
|
|
||||||
return key_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ssl_chello * ssl_get_chello_info(struct streaminfo *stream)
|
|
||||||
{
|
|
||||||
enum chello_parse_result chello_status = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
struct ssl_chello *chello = NULL;
|
|
||||||
chello = ssl_chello_parse((unsigned char *)stream->ptcpdetail->pdata, (unsigned int)stream->ptcpdetail->datalen, &chello_status);
|
|
||||||
if(chello_status == CHELLO_PARSE_SUCCESS)
|
|
||||||
{
|
|
||||||
return chello;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(chello)
|
|
||||||
ssl_chello_free(chello);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static long sslinfo2bypass_htable_search_cb(void *data, const uchar *key, uint size, void *user_args){
|
|
||||||
if(data != NULL)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int sslinfo2bypass_htable_search(MESA_htable_handle htable,char *key, int klen, struct pme_info *pmeinfo)
|
|
||||||
{
|
|
||||||
void *logger = g_kni_handle->local_logger;
|
|
||||||
long cb_ret = -1;
|
|
||||||
void *value;
|
|
||||||
value = MESA_htable_search_cb(htable, (const unsigned char *)key, (unsigned int )klen, sslinfo2bypass_htable_search_cb, NULL, &cb_ret);
|
|
||||||
if(cb_ret == 0)
|
|
||||||
{
|
|
||||||
pmeinfo->ssl_pinningst = *((uint64_t *)value);
|
|
||||||
KNI_LOG_DEBUG(logger, "MESA_htable: success to search, table = sslinfo2bypass_htable,key = %s, key_size = %d, ret =%d", key, klen,cb_ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KNI_LOG_DEBUG(logger, "MESA_htable:Search result value is null, table = sslinfo2bypass_htable,key = %s, key_size = %d, ret =%d", key, klen,cb_ret);
|
|
||||||
}
|
|
||||||
return cb_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int traceid2sslinfo_htable_add(char *key, uint klen, void * value,int thread_seq)
|
|
||||||
{
|
|
||||||
void *logger = g_kni_handle->local_logger;
|
|
||||||
int ret;
|
|
||||||
MESA_htable_handle traceid2sslinfo_htable = g_kni_handle->threads_handle[thread_seq].traceid2sslinfo_htable;
|
|
||||||
ret = MESA_htable_add(traceid2sslinfo_htable, (const unsigned char *)key, klen, (const void*)value);
|
|
||||||
if(ret >= 0)
|
|
||||||
{
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_ADD_SUCC], 0, FS_OP_ADD, 1);
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_CNT], 0, FS_OP_ADD, 1);
|
|
||||||
KNI_LOG_DEBUG(logger, "MESA_htable:Success to add, table = traceid2sslinfo_htable,key = %s, key_size = %d, ret =%d , thread_seq=%d", key, klen,ret, thread_seq);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KNI_LOG_ERROR(logger, "MESA_htable:Fail to add, table = traceid2sslinfo_htable,key = %s, key_size = %d, ret =%d , thread_seq=%d", key, klen,ret, thread_seq);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int first_data_ssl_dynamic_bypass(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq)
|
|
||||||
{
|
|
||||||
struct dynamic_bypass_ssl_feature *ssl_feature = NULL;
|
|
||||||
struct ssl_chello *chello = NULL;
|
|
||||||
void *logger = g_kni_handle->local_logger;
|
|
||||||
|
|
||||||
int ret = -1;
|
|
||||||
if(pmeinfo->protocol != PROTO_SSL)
|
|
||||||
{
|
|
||||||
KNI_LOG_DEBUG(logger, "Dynamic bypass: stream protocol is not ssl: stream traceid = %s, protocol = %d", pmeinfo->stream_traceid,pmeinfo->protocol);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
chello = ssl_get_chello_info(stream);
|
|
||||||
if(!chello)
|
|
||||||
{
|
|
||||||
KNI_LOG_ERROR(logger, "Dynamic bypass: fail to get ssl stream client hello info, stream traceid = %s", pmeinfo->stream_traceid);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssl_feature = ALLOC(struct dynamic_bypass_ssl_feature,1);
|
|
||||||
ssl_feature->vlen = ssl_svc_client_st_mk_key(chello, pmeinfo, pktinfo,ssl_feature->value,SSL_INFO_LEN);
|
|
||||||
|
|
||||||
KNI_LOG_DEBUG(logger, "Dynamic bypass: chello info=%s, info len = %d", ssl_feature->value, ssl_feature->vlen);
|
|
||||||
ssl_chello_free(chello);
|
|
||||||
if(sslinfo2bypass_htable_search(g_kni_handle->sslinfo2bypass_htable,ssl_feature->value, ssl_feature->vlen,pmeinfo) == 0)
|
|
||||||
{
|
|
||||||
KNI_LOG_DEBUG(logger, "Dynamic bypass: passthrough ok, stream traceid = %s,ssl_pinningst = %d", pmeinfo->stream_traceid, pmeinfo->ssl_pinningst);
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KNI_LOG_DEBUG(logger, "Dynamic bypass: not passthrough, stream traceid = %s", pmeinfo->stream_traceid);
|
|
||||||
if(traceid2sslinfo_htable_add(pmeinfo->stream_traceid, strlen(pmeinfo->stream_traceid),ssl_feature,thread_seq) >=0)
|
|
||||||
{
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FREE(&ssl_feature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(ret == 0)
|
|
||||||
{
|
|
||||||
//dynamic bypass fs stat
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_STM], 0, FS_OP_ADD, 1);
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen);
|
|
||||||
//dynamic bypass ipv4 or ipv6
|
|
||||||
if(stream->addr.addrtype == ADDR_TYPE_IPV6){
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_IPV6_STM], 0, FS_OP_ADD, 1);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_IPV4_STM], 0, FS_OP_ADD, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pmeinfo->has_dup_traffic == 1){
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DUP_TFC_STM], 0, FS_OP_ADD, 1);
|
|
||||||
KNI_LOG_DEBUG(logger, "stream has dup traffic, traceid = %s", pmeinfo->stream_traceid);
|
|
||||||
}
|
|
||||||
|
|
||||||
pmeinfo->ssl_intercept_state = 0;
|
|
||||||
pmeinfo->is_dynamic_bypass = 1;
|
|
||||||
if(g_kni_handle->dup_traffic_switch == 1){
|
|
||||||
if(pmeinfo->has_dup_traffic == 1){
|
|
||||||
ret = dabloom_add(pktinfo, thread_seq);
|
|
||||||
if(ret < 0){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct _session_attribute_label_t * kni_pull_session_attribute_results(struct streaminfo *a_stream,struct pme_info *pmeinfo)
|
static struct _session_attribute_label_t * kni_pull_session_attribute_results(struct streaminfo *a_stream,struct pme_info *pmeinfo)
|
||||||
{
|
{
|
||||||
@@ -1231,7 +965,10 @@ static struct _session_attribute_label_t * kni_pull_session_attribute_results(st
|
|||||||
KNI_LOG_DEBUG(logger, "share-session-attribute: destination ip location province is: %s,stream traceid = %s",session_attribute_label->server_location->province_full,pmeinfo->stream_traceid);
|
KNI_LOG_DEBUG(logger, "share-session-attribute: destination ip location province is: %s,stream traceid = %s",session_attribute_label->server_location->province_full,pmeinfo->stream_traceid);
|
||||||
KNI_LOG_DEBUG(logger, "share-session-attribute: destination ip location city is: %s,stream traceid = %s",session_attribute_label->server_location->city_full,pmeinfo->stream_traceid);
|
KNI_LOG_DEBUG(logger, "share-session-attribute: destination ip location city is: %s,stream traceid = %s",session_attribute_label->server_location->city_full,pmeinfo->stream_traceid);
|
||||||
}
|
}
|
||||||
|
if(session_attribute_label->ja3_fingerprint == NULL)
|
||||||
|
KNI_LOG_DEBUG(logger, "share-session-attribute: ja3_fingerprint is NULL,stream traceid = %s",pmeinfo->stream_traceid);
|
||||||
|
else
|
||||||
|
KNI_LOG_DEBUG(logger, "share-session-attribute: ja3_fingerprint is %s,stream traceid = %s",session_attribute_label->ja3_fingerprint,pmeinfo->stream_traceid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1361,10 +1098,38 @@ static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmei
|
|||||||
}
|
}
|
||||||
|
|
||||||
//dynamic bypass
|
//dynamic bypass
|
||||||
|
if(g_kni_handle->ssl_dynamic_bypass_enable == 1){
|
||||||
if(first_data_ssl_dynamic_bypass(stream, pmeinfo, pktinfo, thread_seq) == 0)
|
if(first_data_ssl_dynamic_bypass(stream, pmeinfo, pktinfo, thread_seq) == 0)
|
||||||
{
|
{
|
||||||
|
//dynamic bypass fs stat
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_STM], 0, FS_OP_ADD, 1);
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen);
|
||||||
|
//dynamic bypass ipv4 or ipv6
|
||||||
|
if(stream->addr.addrtype == ADDR_TYPE_IPV6){
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_IPV6_STM], 0, FS_OP_ADD, 1);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DY_PASS_IPV4_STM], 0, FS_OP_ADD, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pmeinfo->has_dup_traffic == 1){
|
||||||
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_DUP_TFC_STM], 0, FS_OP_ADD, 1);
|
||||||
|
KNI_LOG_DEBUG(logger, "stream has dup traffic, traceid = %s", pmeinfo->stream_traceid);
|
||||||
|
}
|
||||||
|
|
||||||
|
pmeinfo->ssl_intercept_state = 0;
|
||||||
|
pmeinfo->is_dynamic_bypass = 1;
|
||||||
|
if(g_kni_handle->dup_traffic_switch == 1){
|
||||||
|
if(pmeinfo->has_dup_traffic == 1){
|
||||||
|
ret = dabloom_add(pktinfo, thread_seq);
|
||||||
|
if(ret < 0){
|
||||||
|
KNI_LOG_DEBUG(logger, "stream add dabloom fail, ret=%d, traceid = %s",ret, pmeinfo->stream_traceid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return APP_STATE_FAWPKT | APP_STATE_KILL_OTHER | APP_STATE_GIVEME;
|
return APP_STATE_FAWPKT | APP_STATE_KILL_OTHER | APP_STATE_GIVEME;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//add cmsg
|
//add cmsg
|
||||||
len = 0;
|
len = 0;
|
||||||
@@ -1482,12 +1247,6 @@ char* kni_maat_action_trans(enum kni_action action){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void next_data_ssl_dynamic_bypass(struct pkt_info *pktinfo)
|
|
||||||
{
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct pkt_info *pktinfo, int thread_seq){
|
char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct pkt_info *pktinfo, int thread_seq){
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_READY_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen);
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_READY_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen);
|
||||||
int ret, len;
|
int ret, len;
|
||||||
@@ -1527,11 +1286,12 @@ char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct
|
|||||||
pmeinfo->stream_traceid, pmeinfo->stream_addr);
|
pmeinfo->stream_traceid, pmeinfo->stream_addr);
|
||||||
return APP_STATE_DROPPKT | APP_STATE_KILL_OTHER | APP_STATE_GIVEME;
|
return APP_STATE_DROPPKT | APP_STATE_KILL_OTHER | APP_STATE_GIVEME;
|
||||||
}
|
}
|
||||||
if(pmeinfo->is_dynamic_bypass)
|
if(g_kni_handle->ssl_dynamic_bypass_enable == 1){
|
||||||
{
|
if(pmeinfo->is_dynamic_bypass){
|
||||||
next_data_ssl_dynamic_bypass(pktinfo);
|
next_data_ssl_dynamic_bypass(pktinfo);
|
||||||
return APP_STATE_FAWPKT | APP_STATE_KILL_OTHER | APP_STATE_GIVEME;
|
return APP_STATE_FAWPKT | APP_STATE_KILL_OTHER | APP_STATE_GIVEME;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = send_to_tfe((char*)a_packet, len, thread_seq, pmeinfo->tfe_id, pmeinfo->addr_type);
|
ret = send_to_tfe((char*)a_packet, len, thread_seq, pmeinfo->tfe_id, pmeinfo->addr_type);
|
||||||
if(ret < 0){
|
if(ret < 0){
|
||||||
@@ -1987,93 +1747,6 @@ static int wrapped_kni_cmsg_get(struct pme_info *pmeinfo, struct kni_cmsg *cmsg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int sslinfo2bypass_htable_add(char *key, uint klen, void * value, void *logger)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
MESA_htable_handle sslinfo2bypass_htable = g_kni_handle->sslinfo2bypass_htable;
|
|
||||||
ret = MESA_htable_add(sslinfo2bypass_htable, (const unsigned char *)key, klen, (const void*)value);
|
|
||||||
if(ret < 0)
|
|
||||||
{
|
|
||||||
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add, table = sslinfo2bypass_htable, key = %s, key_size = %d, ret = %d",key, klen, ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KNI_LOG_DEBUG(logger, "MESA_htable: Success at add, table = sslinfo2bypass_htable, key = %s, key_size = %d, ret = %d",key, klen, ret);
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_ADD_SUCC], 0, FS_OP_ADD, 1);
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_CNT], 0, FS_OP_ADD, 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long traceid2sslinfo_htable_search_cb(void *data, const uchar *key, uint size, void *user_args)
|
|
||||||
{
|
|
||||||
struct dynamic_bypass_ssl_feature * ssl_feature = (struct dynamic_bypass_ssl_feature *)data;
|
|
||||||
void *logger = g_kni_handle->local_logger;
|
|
||||||
uint64_t * p_ssl_pinningst = (uint64_t *)user_args;
|
|
||||||
uint64_t *value = NULL;
|
|
||||||
long cb_ret = -1;
|
|
||||||
|
|
||||||
if(ssl_feature != NULL)
|
|
||||||
{
|
|
||||||
value = ALLOC(uint64_t, 1);
|
|
||||||
*value = *p_ssl_pinningst;
|
|
||||||
if(sslinfo2bypass_htable_add(ssl_feature->value, ssl_feature->vlen, (void *)value, logger) < 0)
|
|
||||||
{
|
|
||||||
KNI_LOG_ERROR(logger, "Dynamic bypass, fail add to table = sslinfo2bypass_htable, key = %s, key_size = %d",
|
|
||||||
ssl_feature->value, ssl_feature->vlen);
|
|
||||||
}
|
|
||||||
cb_ret = 0;
|
|
||||||
}
|
|
||||||
return cb_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int traceid2sslinfo_htable_search(MESA_htable_handle htable,char *key, int klen, int thread_seq,uint64_t ssl_pinningst)
|
|
||||||
{
|
|
||||||
long cb_ret = -1;
|
|
||||||
void *logger = g_kni_handle->local_logger;
|
|
||||||
MESA_htable_search_cb(htable, (const unsigned char *)key, (unsigned int )klen, traceid2sslinfo_htable_search_cb, &ssl_pinningst, &cb_ret);
|
|
||||||
if(cb_ret >= 0)
|
|
||||||
{
|
|
||||||
KNI_LOG_DEBUG(logger, "MESA_htable: success to search, table = traceid2sslinfo_htable,thread_seq = %d,key = %s, key_size = %d, ret = %d",
|
|
||||||
thread_seq, key, klen,cb_ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KNI_LOG_ERROR(logger, "MESA_htable: Fail to search, table = traceid2sslinfo_htable,thread_seq = %d,key = %s, key_size = %d, ret = %d",
|
|
||||||
thread_seq, key, klen,cb_ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cb_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ssl_dynamic_bypass_htable_add(struct pme_info *pmeinfo)
|
|
||||||
{
|
|
||||||
void *logger = g_kni_handle->local_logger;
|
|
||||||
long cb_ret;
|
|
||||||
int ret = -1;
|
|
||||||
MESA_htable_handle traceid2sslinfo_htable = g_kni_handle->threads_handle[pmeinfo->thread_seq].traceid2sslinfo_htable;
|
|
||||||
if(pmeinfo->ssl_intercept_state == 0)
|
|
||||||
{
|
|
||||||
cb_ret = traceid2sslinfo_htable_search(traceid2sslinfo_htable,pmeinfo->stream_traceid, strlen(pmeinfo->stream_traceid), pmeinfo->thread_seq, pmeinfo->ssl_pinningst);
|
|
||||||
if(cb_ret >= 0)
|
|
||||||
{
|
|
||||||
cb_ret = MESA_htable_del(traceid2sslinfo_htable, (const unsigned char *)pmeinfo->stream_traceid, strlen(pmeinfo->stream_traceid), NULL);
|
|
||||||
if(cb_ret < 0)
|
|
||||||
{
|
|
||||||
KNI_LOG_ERROR(logger, "Delete traceid2sslinfo_htable fail,key=%s",pmeinfo->stream_traceid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_DEL_SUCC], 0, FS_OP_ADD, 1);
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_CNT], 0, FS_OP_ADD, -1);
|
|
||||||
}
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long traceid2pme_htable_search_cb(void *data, const uchar *key, uint size, void *user_args){
|
static long traceid2pme_htable_search_cb(void *data, const uchar *key, uint size, void *user_args){
|
||||||
struct traceid2pme_search_cb_args *args = (struct traceid2pme_search_cb_args*)user_args;
|
struct traceid2pme_search_cb_args *args = (struct traceid2pme_search_cb_args*)user_args;
|
||||||
@@ -2093,7 +1766,9 @@ static long traceid2pme_htable_search_cb(void *data, const uchar *key, uint size
|
|||||||
KNI_LOG_DEBUG(logger, "recv cmsg from tfe, stream traceid = %s, stream addr = %s, stream ssl intercept state = %d ,pinning state = %d",
|
KNI_LOG_DEBUG(logger, "recv cmsg from tfe, stream traceid = %s, stream addr = %s, stream ssl intercept state = %d ,pinning state = %d",
|
||||||
pmeinfo->stream_traceid, pmeinfo->stream_addr,pmeinfo->ssl_intercept_state,pmeinfo->ssl_pinningst);
|
pmeinfo->stream_traceid, pmeinfo->stream_addr,pmeinfo->ssl_intercept_state,pmeinfo->ssl_pinningst);
|
||||||
|
|
||||||
|
if(g_kni_handle->ssl_dynamic_bypass_enable == 1){
|
||||||
ssl_dynamic_bypass_htable_add(pmeinfo);
|
ssl_dynamic_bypass_htable_add(pmeinfo);
|
||||||
|
}
|
||||||
|
|
||||||
can_destroy = judge_stream_can_destroy(pmeinfo, CALLER_TFE);
|
can_destroy = judge_stream_can_destroy(pmeinfo, CALLER_TFE);
|
||||||
if(can_destroy == 1){
|
if(can_destroy == 1){
|
||||||
@@ -2462,27 +2137,6 @@ static void tuple2stream_htable_data_free_cb(void *data){
|
|||||||
FREE(&data);
|
FREE(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void traceid2sslinfo_htable_data_free_cb(void *data){
|
|
||||||
FREE(&data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sslinfo2bypass_htable_data_free_cb(void *data){
|
|
||||||
FREE(&data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int traceid2sslinfo_htable_expire_notify_cb(void *data, int eliminate_type)
|
|
||||||
{
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_DEL_SUCC], 0, FS_OP_ADD, 1);
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2SSL_CNT], 0, FS_OP_ADD, -1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sslinfo2bypass_htable_expire_notify_cb(void *data, int eliminate_type)
|
|
||||||
{
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_DEL_SUCC], 0, FS_OP_ADD, 1);
|
|
||||||
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL2PASS_CNT], 0, FS_OP_ADD, -1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int dup_traffic_dabloom_init(const char *profile, void *logger){
|
int dup_traffic_dabloom_init(const char *profile, void *logger){
|
||||||
@@ -2546,7 +2200,6 @@ extern "C" int kni_init(){
|
|||||||
pthread_t thread_id = -1;
|
pthread_t thread_id = -1;
|
||||||
struct thread_tfe_cmsg_receiver_args *cmsg_receiver_args;
|
struct thread_tfe_cmsg_receiver_args *cmsg_receiver_args;
|
||||||
MESA_htable_handle traceid2pme_htable = NULL;
|
MESA_htable_handle traceid2pme_htable = NULL;
|
||||||
MESA_htable_handle sslinfo2bypass_htable = NULL;
|
|
||||||
struct tfe_mgr *_tfe_mgr = NULL;
|
struct tfe_mgr *_tfe_mgr = NULL;
|
||||||
char label_buff[MAX_STRING_LEN*4]={0};
|
char label_buff[MAX_STRING_LEN*4]={0};
|
||||||
tfe_cmsg_enum_to_string();
|
tfe_cmsg_enum_to_string();
|
||||||
@@ -2696,27 +2349,12 @@ extern "C" int kni_init(){
|
|||||||
}
|
}
|
||||||
g_kni_handle->threads_handle[i].tuple2stream_htable = tuple2stream_htable;
|
g_kni_handle->threads_handle[i].tuple2stream_htable = tuple2stream_htable;
|
||||||
}
|
}
|
||||||
//init traceid2sslinfo_htable
|
//init ssl dynamic bypass htable
|
||||||
memset(&opt, 0, sizeof(opt));
|
ret = ssl_dynamic_bypass_htable_init(profile, local_logger);
|
||||||
kni_get_htable_opt(&opt, profile, "traceid2sslinfo_htable", (void*)traceid2sslinfo_htable_data_free_cb, (void *)traceid2sslinfo_htable_expire_notify_cb, local_logger);
|
if(ret < 0){
|
||||||
for(int i = 0; i < g_kni_handle->thread_count; i++){
|
|
||||||
MESA_htable_handle traceid2sslinfo_htable = kni_create_htable((char*)"traceid2sslinfo_htable", &opt, local_logger);
|
|
||||||
if(traceid2sslinfo_htable == NULL){
|
|
||||||
KNI_LOG_ERROR(local_logger, "Failed at kni_create_htable, table = traceid2sslinfo_htable");
|
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
g_kni_handle->threads_handle[i].traceid2sslinfo_htable = traceid2sslinfo_htable;
|
|
||||||
}
|
|
||||||
|
|
||||||
//init sslinfo2bypass_htable
|
|
||||||
memset(&opt, 0, sizeof(opt));
|
|
||||||
kni_get_htable_opt(&opt, profile, "sslinfo2bypass_htable", (void*)sslinfo2bypass_htable_data_free_cb, (void *)sslinfo2bypass_htable_expire_notify_cb, local_logger);
|
|
||||||
sslinfo2bypass_htable = kni_create_htable((char*)"sslinfo2bypass_htable", &opt, local_logger);
|
|
||||||
if(sslinfo2bypass_htable == NULL){
|
|
||||||
KNI_LOG_ERROR(local_logger, "Failed at create sslinfo2bypass_htable");
|
|
||||||
goto error_out;
|
|
||||||
}
|
|
||||||
g_kni_handle->sslinfo2bypass_htable = sslinfo2bypass_htable;
|
|
||||||
//init dabloom_handle
|
//init dabloom_handle
|
||||||
ret = dup_traffic_dabloom_init(profile, local_logger);
|
ret = dup_traffic_dabloom_init(profile, local_logger);
|
||||||
if(ret < 0){
|
if(ret < 0){
|
||||||
|
|||||||
@@ -1,638 +0,0 @@
|
|||||||
#include <sys/types.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ssl_utils.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define ALLOC(type, number) ((type *)calloc(sizeof(type), number))
|
|
||||||
#define FREE(p) {free(*p);*p=NULL;}
|
|
||||||
#define TFE_SYMBOL_MAX 64
|
|
||||||
|
|
||||||
void ssl_chello_free(struct ssl_chello* chello)
|
|
||||||
{
|
|
||||||
if(chello == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FREE(&(chello->sni));
|
|
||||||
chello->sni = NULL;
|
|
||||||
FREE(&(chello->alpn));
|
|
||||||
chello->alpn = NULL;
|
|
||||||
FREE(&(chello->sign_algos));
|
|
||||||
chello->sign_algos = NULL;
|
|
||||||
FREE(&(chello->supported_groups));
|
|
||||||
chello->supported_groups = NULL;
|
|
||||||
FREE(&(chello->cipher_suites));
|
|
||||||
chello->cipher_suites = NULL;
|
|
||||||
FREE(&chello);
|
|
||||||
}
|
|
||||||
static int cipher_is_grease(uint16_t cipher)
|
|
||||||
{
|
|
||||||
uint16_t a=cipher>>8;
|
|
||||||
uint16_t b=cipher&0x00ff;
|
|
||||||
//https://tools.ietf.org/html/draft-davidben-tls-grease-01#section-5
|
|
||||||
if(a==b && (a&0x0f)==0x0a)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_server_name_extension(const unsigned char *buff, uint16_t buff_len, struct ssl_chello* chello)
|
|
||||||
{
|
|
||||||
size_t pos = 2; /* skip server name list length */
|
|
||||||
uint16_t len;
|
|
||||||
char *sni = NULL;
|
|
||||||
while (pos + 3 < buff_len)
|
|
||||||
{
|
|
||||||
len = (buff[pos + 1] << 8) | buff[pos + 2];
|
|
||||||
if (pos + 3 + len > buff_len)
|
|
||||||
{
|
|
||||||
chello->sni = sni;
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
switch (buff[pos])
|
|
||||||
{
|
|
||||||
case 0x00: /* host_name */
|
|
||||||
sni = ALLOC(char, len + 1);
|
|
||||||
strncpy(sni, (const char*)buff + pos + 3, len);
|
|
||||||
sni[len] = '\0';
|
|
||||||
chello->sni = sni;
|
|
||||||
return CHELLO_PARSE_SUCCESS;
|
|
||||||
}
|
|
||||||
pos += 3 + len;
|
|
||||||
}
|
|
||||||
chello->sni = sni;
|
|
||||||
if (pos != buff_len)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
return CHELLO_PARSE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_alpn_extension(const unsigned char* buff, uint16_t buff_len, struct ssl_chello* chello)
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
uint16_t len = (buff[pos] << 8) | buff[pos + 1];
|
|
||||||
char *alpn = NULL;
|
|
||||||
if(2 + len != buff_len)
|
|
||||||
{
|
|
||||||
chello->alpn = alpn;
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
alpn = ALLOC(char, len + 1);
|
|
||||||
strncpy((char*)alpn, (const char*)buff + 2, len);
|
|
||||||
alpn[len] = '\0';
|
|
||||||
chello->alpn = alpn;
|
|
||||||
return CHELLO_PARSE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_supported_versions_extension(const unsigned char* buff, uint16_t buff_len, struct ssl_chello* chello)
|
|
||||||
{
|
|
||||||
if(buff_len < 1)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
uint8_t len = buff[0];
|
|
||||||
if(len + 1 > buff_len || len % 2 != 0)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
uint16_t max_version = 0x0000, min_version = 0xffff;
|
|
||||||
for(int i = 1; i < len; i+=2)
|
|
||||||
{
|
|
||||||
uint16_t version = (buff[i] << 8) | buff[i + 1];
|
|
||||||
//unknown version
|
|
||||||
if(version < 0x0300 || version > 0x0304)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(version > max_version)
|
|
||||||
{
|
|
||||||
max_version = version;
|
|
||||||
}
|
|
||||||
if(version < min_version)
|
|
||||||
{
|
|
||||||
min_version = version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(max_version != 0x0000)
|
|
||||||
{
|
|
||||||
chello->max_version.ossl_format = max_version;
|
|
||||||
chello->max_version.major = (max_version >> 8);
|
|
||||||
chello->max_version.minor = max_version & 0x00ff;
|
|
||||||
chello->min_version.ossl_format = min_version;
|
|
||||||
chello->min_version.major = (min_version >> 8);
|
|
||||||
chello->min_version.minor = min_version & 0x00ff;
|
|
||||||
}
|
|
||||||
return CHELLO_PARSE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_sign_algos_extension(const unsigned char* buff, uint16_t buff_len, struct ssl_chello* chello)
|
|
||||||
{
|
|
||||||
if(buff_len < 2)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
uint16_t len = (buff[0] << 8) | buff[1];
|
|
||||||
if(len + 2 > buff_len)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
char *sign_algos = ALLOC(char, len);
|
|
||||||
memcpy(sign_algos, (void*)(buff + 2), len);
|
|
||||||
chello->sign_algos = sign_algos;
|
|
||||||
chello->sign_algos_len = len;
|
|
||||||
return CHELLO_PARSE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_supported_groups_extension(const unsigned char* buff, uint16_t buff_len, struct ssl_chello* chello)
|
|
||||||
{
|
|
||||||
if(buff_len < 2)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
uint16_t len = (buff[0] << 8) | buff[1];
|
|
||||||
if(len + 2 > buff_len)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
chello->supported_groups = ALLOC(char, len);
|
|
||||||
uint16_t* known_groups = (uint16_t*) chello->supported_groups;
|
|
||||||
uint16_t* raw_groups= (uint16_t*) (buff + 2);
|
|
||||||
size_t i=0, j=0;
|
|
||||||
for(i=0; i<len/2; i++)
|
|
||||||
{
|
|
||||||
if(!cipher_is_grease(raw_groups[i]))
|
|
||||||
{
|
|
||||||
known_groups[j++]=raw_groups[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chello->supported_groups_len = j*2;
|
|
||||||
return CHELLO_PARSE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_extensions(const unsigned char *buff, uint16_t buff_len, struct ssl_chello *chello) {
|
|
||||||
uint16_t pos = 0;
|
|
||||||
/* Parse each 4 bytes for the extension header */
|
|
||||||
while (pos + 4 <= buff_len)
|
|
||||||
{
|
|
||||||
uint16_t len = (buff[pos + 2] << 8) | buff[pos + 3];
|
|
||||||
if (pos + 4 + len > buff_len)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
uint16_t extension_type = (buff[pos] << 8) | buff[pos + 1];
|
|
||||||
int result = CHELLO_PARSE_SUCCESS;
|
|
||||||
switch(extension_type){
|
|
||||||
//server name extension
|
|
||||||
case 0x0000:
|
|
||||||
result = parse_server_name_extension(buff + pos + 4, len, chello);
|
|
||||||
break;
|
|
||||||
//alpn extension
|
|
||||||
case 0x0010:
|
|
||||||
result = parse_alpn_extension(buff + pos + 4, len, chello);
|
|
||||||
break;
|
|
||||||
//supported versions extension
|
|
||||||
case 0x002b:
|
|
||||||
result = parse_supported_versions_extension(buff + pos + 4, len, chello);
|
|
||||||
break;
|
|
||||||
//signature algorithms extension
|
|
||||||
case 0x000d:
|
|
||||||
result = parse_sign_algos_extension(buff + pos + 4, len, chello);
|
|
||||||
break;
|
|
||||||
//supported groups extensions
|
|
||||||
case 0x000a:
|
|
||||||
result = parse_supported_groups_extension(buff + pos + 4, len, chello);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(result != CHELLO_PARSE_SUCCESS)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
pos += (4 + len);
|
|
||||||
}
|
|
||||||
/* Check we ended where we expected to */
|
|
||||||
if (pos != buff_len)
|
|
||||||
{
|
|
||||||
return CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
}
|
|
||||||
return CHELLO_PARSE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct cipher_suite
|
|
||||||
{
|
|
||||||
uint16_t value;
|
|
||||||
const char* name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct cipher_suite cipher_suite_list[] =
|
|
||||||
{
|
|
||||||
{0xC030, "ECDHE-RSA-AES256-GCM-SHA384"},
|
|
||||||
{0xC02C, "ECDHE-ECDSA-AES256-GCM-SHA384"},
|
|
||||||
{0xC028, "ECDHE-RSA-AES256-SHA384"},
|
|
||||||
{0xC024, "ECDHE-ECDSA-AES256-SHA384"},
|
|
||||||
{0xC014, "ECDHE-RSA-AES256-SHA"},
|
|
||||||
{0xC00A, "ECDHE-ECDSA-AES256-SHA"},
|
|
||||||
{0x00A5, "DH-DSS-AES256-GCM-SHA384"},
|
|
||||||
{0x00A3, "DHE-DSS-AES256-GCM-SHA384"},
|
|
||||||
{0x00A1, "DH-RSA-AES256-GCM-SHA384"},
|
|
||||||
{0x009F, "DHE-RSA-AES256-GCM-SHA384"},
|
|
||||||
{0x006B, "DHE-RSA-AES256-SHA256"},
|
|
||||||
{0x006A, "DHE-DSS-AES256-SHA256"},
|
|
||||||
{0x0069, "DH-RSA-AES256-SHA256"},
|
|
||||||
{0x0068, "DH-DSS-AES256-SHA256"},
|
|
||||||
{0x0039, "DHE-RSA-AES256-SHA"},
|
|
||||||
{0x0038, "DHE-DSS-AES256-SHA"},
|
|
||||||
{0x0037, "DH-RSA-AES256-SHA"},
|
|
||||||
{0x0036, "DH-DSS-AES256-SHA"},
|
|
||||||
{0x0088, "DHE-RSA-CAMELLIA256-SHA"},
|
|
||||||
{0x0087, "DHE-DSS-CAMELLIA256-SHA"},
|
|
||||||
{0x0086, "DH-RSA-CAMELLIA256-SHA"},
|
|
||||||
{0x0085, "DH-DSS-CAMELLIA256-SHA"},
|
|
||||||
{0xC019, "AECDH-AES256-SHA"},
|
|
||||||
{0x00A7, "ADH-AES256-GCM-SHA384"},
|
|
||||||
{0x006D, "ADH-AES256-SHA256"},
|
|
||||||
{0x003A, "ADH-AES256-SHA"},
|
|
||||||
{0x0089, "ADH-CAMELLIA256-SHA"},
|
|
||||||
{0xC032, "ECDH-RSA-AES256-GCM-SHA384"},
|
|
||||||
{0xC02E, "ECDH-ECDSA-AES256-GCM-SHA384"},
|
|
||||||
{0xC02A, "ECDH-RSA-AES256-SHA384"},
|
|
||||||
{0xC026, "ECDH-ECDSA-AES256-SHA384"},
|
|
||||||
{0xC00F, "ECDH-RSA-AES256-SHA"},
|
|
||||||
{0xC005, "ECDH-ECDSA-AES256-SHA"},
|
|
||||||
{0x009D, "AES256-GCM-SHA384"},
|
|
||||||
{0x003D, "AES256-SHA256"},
|
|
||||||
{0x0035, "AES256-SHA"},
|
|
||||||
{0x0084, "CAMELLIA256-SHA"},
|
|
||||||
{0x008D, "PSK-AES256-CBC-SHA"},
|
|
||||||
{0xC02F, "ECDHE-RSA-AES128-GCM-SHA256"},
|
|
||||||
{0xC02B, "ECDHE-ECDSA-AES128-GCM-SHA256"},
|
|
||||||
{0xC027, "ECDHE-RSA-AES128-SHA256"},
|
|
||||||
{0xC023, "ECDHE-ECDSA-AES128-SHA256"},
|
|
||||||
{0xC013, "ECDHE-RSA-AES128-SHA"},
|
|
||||||
{0xC009, "ECDHE-ECDSA-AES128-SHA"},
|
|
||||||
{0x00A4, "DH-DSS-AES128-GCM-SHA256"},
|
|
||||||
{0x00A2, "DHE-DSS-AES128-GCM-SHA256"},
|
|
||||||
{0x00A0, "DH-RSA-AES128-GCM-SHA256"},
|
|
||||||
{0x009E, "DHE-RSA-AES128-GCM-SHA256"},
|
|
||||||
{0x0067, "DHE-RSA-AES128-SHA256"},
|
|
||||||
{0x0040, "DHE-DSS-AES128-SHA256"},
|
|
||||||
{0x003F, "DH-RSA-AES128-SHA256"},
|
|
||||||
{0x003E, "DH-DSS-AES128-SHA256"},
|
|
||||||
{0x0033, "DHE-RSA-AES128-SHA"},
|
|
||||||
{0x0032, "DHE-DSS-AES128-SHA"},
|
|
||||||
{0x0031, "DH-RSA-AES128-SHA"},
|
|
||||||
{0x0030, "DH-DSS-AES128-SHA"},
|
|
||||||
{0x009A, "DHE-RSA-SEED-SHA"},
|
|
||||||
{0x0099, "DHE-DSS-SEED-SHA"},
|
|
||||||
{0x0098, "DH-RSA-SEED-SHA"},
|
|
||||||
{0x0097, "DH-DSS-SEED-SHA"},
|
|
||||||
{0x0045, "DHE-RSA-CAMELLIA128-SHA"},
|
|
||||||
{0x0044, "DHE-DSS-CAMELLIA128-SHA"},
|
|
||||||
{0x0043, "DH-RSA-CAMELLIA128-SHA"},
|
|
||||||
{0x0042, "DH-DSS-CAMELLIA128-SHA"},
|
|
||||||
{0xC018, "AECDH-AES128-SHA"},
|
|
||||||
{0x00A6, "ADH-AES128-GCM-SHA256"},
|
|
||||||
{0x006C, "ADH-AES128-SHA256"},
|
|
||||||
{0x0034, "ADH-AES128-SHA"},
|
|
||||||
{0x009B, "ADH-SEED-SHA"},
|
|
||||||
{0x0046, "ADH-CAMELLIA128-SHA"},
|
|
||||||
{0xC031, "ECDH-RSA-AES128-GCM-SHA256"},
|
|
||||||
{0xC02D, "ECDH-ECDSA-AES128-GCM-SHA256"},
|
|
||||||
{0xC029, "ECDH-RSA-AES128-SHA256"},
|
|
||||||
{0xC025, "ECDH-ECDSA-AES128-SHA256"},
|
|
||||||
{0xC00E, "ECDH-RSA-AES128-SHA"},
|
|
||||||
{0xC004, "ECDH-ECDSA-AES128-SHA"},
|
|
||||||
{0x009C, "AES128-GCM-SHA256"},
|
|
||||||
{0x003C, "AES128-SHA256"},
|
|
||||||
{0x002F, "AES128-SHA"},
|
|
||||||
{0x0096, "SEED-SHA"},
|
|
||||||
{0x0041, "CAMELLIA128-SHA"},
|
|
||||||
{0x008C, "PSK-AES128-CBC-SHA"},
|
|
||||||
{0xC012, "ECDHE-RSA-DES-CBC3-SHA"},
|
|
||||||
{0xC008, "ECDHE-ECDSA-DES-CBC3-SHA"},
|
|
||||||
{0x0016, "EDH-RSA-DES-CBC3-SHA"},
|
|
||||||
{0x0013, "EDH-DSS-DES-CBC3-SHA"},
|
|
||||||
{0x0010, "DH-RSA-DES-CBC3-SHA"},
|
|
||||||
{0x000D, "DH-DSS-DES-CBC3-SHA"},
|
|
||||||
{0xC017, "AECDH-DES-CBC3-SHA"},
|
|
||||||
{0x001B, "ADH-DES-CBC3-SHA"},
|
|
||||||
{0xC00D, "ECDH-RSA-DES-CBC3-SHA"},
|
|
||||||
{0xC003, "ECDH-ECDSA-DES-CBC3-SHA"},
|
|
||||||
{0x000A, "DES-CBC3-SHA"},
|
|
||||||
{0x0007, "IDEA-CBC-SHA"},
|
|
||||||
{0x008B, "PSK-3DES-EDE-CBC-SHA"},
|
|
||||||
{0x0021, "KRB5-IDEA-CBC-SHA"},
|
|
||||||
{0x001F, "KRB5-DES-CBC3-SHA"},
|
|
||||||
{0x0025, "KRB5-IDEA-CBC-MD5"},
|
|
||||||
{0x0023, "KRB5-DES-CBC3-MD5"},
|
|
||||||
{0xC011, "ECDHE-RSA-RC4-SHA"},
|
|
||||||
{0xC007, "ECDHE-ECDSA-RC4-SHA"},
|
|
||||||
{0xC016, "AECDH-RC4-SHA"},
|
|
||||||
{0x0018, "ADH-RC4-MD5"},
|
|
||||||
{0xC00C, "ECDH-RSA-RC4-SHA"},
|
|
||||||
{0xC002, "ECDH-ECDSA-RC4-SHA"},
|
|
||||||
{0x0005, "RC4-SHA"},
|
|
||||||
{0x0004, "RC4-MD5"},
|
|
||||||
{0x008A, "PSK-RC4-SHA"},
|
|
||||||
{0x0020, "KRB5-RC4-SHA"},
|
|
||||||
{0x0024, "KRB5-RC4-MD5"},
|
|
||||||
{0xC010, "ECDHE-RSA-NULL-SHA"},
|
|
||||||
{0xC006, "ECDHE-ECDSA-NULL-SHA"},
|
|
||||||
{0xC015, "AECDH-NULL-SHA"},
|
|
||||||
{0xC00B, "ECDH-RSA-NULL-SHA"},
|
|
||||||
{0xC001, "ECDH-ECDSA-NULL-SHA"},
|
|
||||||
{0x003B, "NULL-SHA256"},
|
|
||||||
{0x0002, "NULL-SHA"},
|
|
||||||
{0x0001, "NULL-MD5"}
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct cipher_suite cipher_suite_list_tls13[] =
|
|
||||||
{
|
|
||||||
{0x1301, "TLS_AES_128_GCM_SHA256"},
|
|
||||||
{0x1302, "TLS_AES_256_GCM_SHA384"},
|
|
||||||
{0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
|
|
||||||
{0x1304, "TLS_AES_128_CCM_SHA256"},
|
|
||||||
{0x1305, "TLS_AES_128_CCM_8_SHA256"}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int cipher_suites_convert_helper(uint16_t value, char *name, size_t name_sz)
|
|
||||||
{
|
|
||||||
int n1 = sizeof(cipher_suite_list) / sizeof(struct cipher_suite);
|
|
||||||
int n2 = sizeof(cipher_suite_list_tls13) / sizeof(struct cipher_suite);
|
|
||||||
for(int i = 0; i < n1; i++)
|
|
||||||
{
|
|
||||||
if(value == cipher_suite_list[i].value)
|
|
||||||
{
|
|
||||||
if(name) memcpy(name, cipher_suite_list[i].name, strnlen(cipher_suite_list[i].name, name_sz));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int i = 0; i < n2; i++)
|
|
||||||
{
|
|
||||||
if(value == cipher_suite_list_tls13[i].value)
|
|
||||||
{
|
|
||||||
if(name) memcpy(name, cipher_suite_list_tls13[i].name, strnlen(cipher_suite_list_tls13[i].name, name_sz));
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssl_cipher_suites_to_name(const char *source, int source_len, char *result_common, size_t sz_common, char *result_tls13, size_t sz_tls13)
|
|
||||||
{
|
|
||||||
int target_common_reach_max = 0;
|
|
||||||
int target_tls13_reach_max = 0;
|
|
||||||
char name[TFE_SYMBOL_MAX] = "";
|
|
||||||
for(int i = 0; i < source_len - 1;)
|
|
||||||
{
|
|
||||||
uint16_t val = (source[i] << 8) | source[i + 1];
|
|
||||||
memset(name, 0, sizeof(name));
|
|
||||||
int ret = cipher_suites_convert_helper(val, name, sizeof(name));
|
|
||||||
//target common
|
|
||||||
if(ret == 1 && target_common_reach_max == 0)
|
|
||||||
{
|
|
||||||
if(strnlen(name, sizeof(name)) + strnlen(result_common, sz_common) + 1 > sz_common)
|
|
||||||
{
|
|
||||||
target_common_reach_max = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strncat(result_common, name, sz_common);
|
|
||||||
strncat(result_common, ":", sz_common);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//result_tls13
|
|
||||||
if(ret == 2 && target_tls13_reach_max == 0)
|
|
||||||
{
|
|
||||||
if(strnlen(name, sizeof(name)) + strnlen(result_tls13, sz_tls13) + 1 > sz_tls13)
|
|
||||||
{
|
|
||||||
target_tls13_reach_max = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strncat(result_tls13, name, sz_tls13);
|
|
||||||
strncat(result_tls13, ":", sz_tls13);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
int len1 = strnlen(result_common, sz_common);
|
|
||||||
if(len1 > 0)
|
|
||||||
{
|
|
||||||
result_common[len1 - 1] = '\0';
|
|
||||||
}
|
|
||||||
int len2 = strnlen(result_tls13, sz_tls13);
|
|
||||||
if(len2 > 0)
|
|
||||||
{
|
|
||||||
result_tls13[len2 - 1] = '\0';
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
|
|
||||||
{
|
|
||||||
if(buff == NULL)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if(buff_len < 1)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if(buff[0] != 0x80 && buff[0] != 0x16)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/* SSL 2.0 compatible Client Hello
|
|
||||||
* High bit of first byte (length) and content type is Client Hello
|
|
||||||
* See RFC5246 Appendix E.2
|
|
||||||
* if it is SSL 2.0, only parse version
|
|
||||||
*/
|
|
||||||
if(buff[0] == 0x80)
|
|
||||||
{
|
|
||||||
struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1);
|
|
||||||
_chello->min_version.major = 0x02;
|
|
||||||
if(buff_len < 2)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
size_t len = (size_t)buff[1];
|
|
||||||
if (buff_len < len + 2)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
buff_len = len + 2;
|
|
||||||
size_t pos = 2;
|
|
||||||
/* Handshark Message Type: Client Hello */
|
|
||||||
if (pos + 1 > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
if (buff[pos] != 0x01)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
/* Version */
|
|
||||||
if(pos + 2 > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
_chello->max_version.major = buff[pos];
|
|
||||||
_chello->max_version.minor = buff[pos + 1];
|
|
||||||
_chello->max_version.ossl_format=(uint16_t)_chello->max_version.major<<8|_chello->max_version.minor;
|
|
||||||
*result = CHELLO_PARSE_SUCCESS;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (buff_len < 5)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if(buff[1] != 3 || buff[2] > 4 || buff[2] < 0)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1);
|
|
||||||
_chello->min_version.major = buff[1];
|
|
||||||
_chello->min_version.minor = buff[2];
|
|
||||||
_chello->min_version.ossl_format=(uint16_t)_chello->min_version.major<<8|_chello->min_version.minor;
|
|
||||||
_chello->max_version.major = -1;
|
|
||||||
_chello->max_version.minor = -1;
|
|
||||||
_chello->sni = NULL;
|
|
||||||
_chello->alpn = NULL;
|
|
||||||
_chello->cipher_suites = NULL;
|
|
||||||
_chello->cipher_suites_len = 0;
|
|
||||||
_chello->sign_algos = NULL;
|
|
||||||
_chello->sign_algos_len = 0;
|
|
||||||
_chello->supported_groups = NULL;
|
|
||||||
_chello->supported_groups_len = 0;
|
|
||||||
|
|
||||||
/* TLS record length */
|
|
||||||
size_t len = ((size_t)buff[3] << 8) + (size_t)buff[4] + 5;
|
|
||||||
if (buff_len < len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
buff_len = len;
|
|
||||||
size_t pos = 5;
|
|
||||||
if (pos + 1 > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
if (buff[pos] != 0x01)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
pos += 4;
|
|
||||||
if(pos + 2 > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
_chello->max_version.major = buff[pos];
|
|
||||||
_chello->max_version.minor = buff[pos+1];
|
|
||||||
_chello->max_version.ossl_format=(uint16_t)_chello->max_version.major<<8|_chello->max_version.minor;
|
|
||||||
|
|
||||||
pos += 34;
|
|
||||||
/* Session ID */
|
|
||||||
if (pos + 1 > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
len = (size_t)buff[pos];
|
|
||||||
pos += 1 + len;
|
|
||||||
/* Cipher Suites */
|
|
||||||
if (pos + 2 > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
|
||||||
pos += 2;
|
|
||||||
if(pos + len > buff_len || len % 2 != 0)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
size_t i=0, j=0;
|
|
||||||
_chello->cipher_suites = ALLOC(char, len);
|
|
||||||
uint16_t* known_cipher=(uint16_t*)_chello->cipher_suites;
|
|
||||||
uint16_t* raw_cipher=(uint16_t*)(buff + pos);
|
|
||||||
for(i=0, j=0; i<len/2; i++)
|
|
||||||
{
|
|
||||||
//https://security.stackexchange.com/questions/176951/google-chrome-weird-random-cipher-suite
|
|
||||||
if(!cipher_is_grease(raw_cipher[i]))
|
|
||||||
{
|
|
||||||
known_cipher[j++]=raw_cipher[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_chello->cipher_suites_len = j*2;
|
|
||||||
|
|
||||||
pos += len;
|
|
||||||
|
|
||||||
/* Compression Methods */
|
|
||||||
if (pos >= buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
len = (size_t)buff[pos];
|
|
||||||
pos += 1 + len;
|
|
||||||
|
|
||||||
/* No extension */
|
|
||||||
if(pos == buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_SUCCESS;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extensions */
|
|
||||||
if (pos + 2 > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
|
|
||||||
pos += 2;
|
|
||||||
if (pos + len > buff_len)
|
|
||||||
{
|
|
||||||
*result = CHELLO_PARSE_INVALID_FORMAT;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
int ret = parse_extensions(buff + pos, len, _chello);
|
|
||||||
*result = (enum chello_parse_result)ret;
|
|
||||||
return _chello;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user