diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/ssl_decoder.cpp | 460 | ||||
| -rw-r--r-- | src/ssl_export.cpp | 255 | ||||
| -rw-r--r-- | src/ssl_internal.h | 65 | ||||
| -rw-r--r-- | src/version.map | 20 |
5 files changed, 692 insertions, 110 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9beb457..9ce76b0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,7 @@ include_directories(${PROJECT_SOURCE_DIR}/deps/) aux_source_directory(${PROJECT_SOURCE_DIR}/deps/toml DEPS_SRC) aux_source_directory(${PROJECT_SOURCE_DIR}/deps/yyjson DEPS_SRC) -set(SSL_DECODER_SRC ${DEPS_SRC} ssl_decoder.cpp) +set(SSL_DECODER_SRC ${DEPS_SRC} ssl_decoder.cpp ssl_export.cpp) add_library(ssl_decoder SHARED ${SSL_DECODER_SRC}) set_target_properties(ssl_decoder PROPERTIES LINK_FLAGS "-Wl,--version-script=${PROJECT_SOURCE_DIR}/src/version.map") diff --git a/src/ssl_decoder.cpp b/src/ssl_decoder.cpp index 3d86e50..ffbbe17 100644 --- a/src/ssl_decoder.cpp +++ b/src/ssl_decoder.cpp @@ -38,41 +38,14 @@ extern "C" #include "ssl_internal.h" #include "ssl_decoder.h" -#define SSL_DECODER_FALSE 0 -#define SSL_DECODER_TRUE 1 - -#define SSL_UUID_BYTES_SZ 16 - -#define SSL_RANDOM_TIME_LEN 4 -#define SSL_RANDOM_SIZE 28 - -#define SSL_HANDSHAKE_CLIENT_HELLO 1 -#define SSL_HANDSHAKE_SERVER_HELLO 2 -#define SSL_HANDSHAKE_CERTIFICATE 11 -#define SSL_HANDSHAKE_SERVER_KEY_EXCHANGE 12 - -#define SSL_CONTENT_TYPE_HANDSHAKE 0x16 -#define SSL_CONTENT_TYPE_ALERT 0x15 -#define SSL_CONTENT_TYPE_APPLICATION_DATA 0x17 -#define SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC 0x14 - -#define ALPN_EXT_TYPE 0x0010 -#define SERVER_NAME_EXT_TYPE 0x0000 -#define SERVER_NAME_HOST_TYPE 0x0000 -#define SERVER_NAME_OTHER_TYPE 0x0008 -#define SESSION_TICKET_EXT_TYPE 0x0023 -#define ENCRPTED_SERVER_NAME_EXT_TYPE 0xFFCE -#define ENCRPTED_CLIENT_HELLO_EXT_TYPE 0xFE0D -#define EC_POINT_FORMATS_EXT_TYPE 0x000B - -// https://datatracker.ietf.org/doc/html/rfc7919 -// Supported Groups -#define SUPPORTED_GROUPS_EXT_TYPE 0x000A - -#define SSL_DECODER_TOML_PATH "conf/ssl/ssl_decoder.toml" - UT_icd UT_ssl_hello_extension_icd={sizeof(struct ssl_decoder_ltv), NULL, NULL, NULL}; +struct ssl_certificate_chain +{ + uint8_t *data; + size_t data_sz; +}; + struct ssl_handshake_type { unsigned char content_type; @@ -133,15 +106,6 @@ struct ssl_decoder_context struct ssl_record_trunk record_trunk; }; -struct ssl_message -{ - int32_t magic; - enum ssl_message_type type; - char uuid_bytes[SSL_UUID_BYTES_SZ]; - struct session *ss; - struct ssl_decoder_plugin_env *plugin_env; -}; - void ssl_hello_md5sum(struct ssl_decoder_ltv *ltv, const char *str, size_t str_sz) { MD5_CTX ctx; @@ -169,7 +133,7 @@ void ssl_hello_md5sum(struct ssl_decoder_ltv *ltv, const char *str, size_t str_s // https://tools.ietf.org/html/draft-davidben-tls-grease-00 static int32_t ssl_is_grease_value(unsigned short val) { - if ((val & 0x0f)!=0x0a) + if((val & 0x0f)!=0x0a) { return SSL_DECODER_FALSE; } @@ -230,11 +194,6 @@ void ssl_recod_buff_get0(struct ssl_record_trunk *record_trunk, uint8_t **record (*record_buff_sz)=record_trunk->cache_len; } -void ssl_handshake_certificate_decode() -{ - -} - void ssl_handshake_server_key_exchange_decode() { @@ -348,6 +307,235 @@ int32_t ssl_decoder_ltv_get(struct ssl_decoder_ltv *ltv, uint16_t type, uint8_t return ret; } +uint32_t ssl_handshake_certificate_count_get(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset, struct ssl_certificate_chain *cert_chain, uint32_t cert_chain_num) +{ + if(NULL==pdata || 0==pdata_sz) + { + return 0; + } + + uint32_t count=0; + size_t offset=(*pdata_offset); + + while(pdata_sz > offset) + { + if(count>=cert_chain_num) + { + break; + } + + int32_t one_cert_sz=0; + int32_t ret=ssl_read_be_u24(pdata, pdata_sz, &offset, (uint8_t *)&(one_cert_sz)); + if(ret==SSL_DECODER_FALSE || one_cert_sz<=0 || (one_cert_sz+offset) > pdata_sz) + { + break; + } + + cert_chain[count].data=pdata+offset; + cert_chain[count].data_sz=one_cert_sz; + offset+=one_cert_sz; + count++; + } + + return count; +} + +enum ssl_certificate_type ssl_handshake_certificate_type_get(uint32_t count, uint32_t offset) +{ + if(offset>=count) + { + return SSL_CERTIFICATE_TYPE_UNKNOWN; + } + + switch(offset) + { + case 0: + return SSL_CERTIFICATE_TYPE_INDIVIDUAL; + case 1: + return ((count==2) ? SSL_CERTIFICATE_TYPE_ROOT : SSL_CERTIFICATE_TYPE_MIDDLE); + case 2: + return ((count==3) ? SSL_CERTIFICATE_TYPE_ROOT : SSL_CERTIFICATE_TYPE_CHAIN); + default: + break; + } + + return (offset==count-1) ? SSL_CERTIFICATE_TYPE_ROOT : SSL_CERTIFICATE_TYPE_CHAIN; +} + +int32_t ssl_x509_certificate_detail_decode(struct ssl_certificate *certificate, uint8_t *pdata, int32_t pdata_sz) +{ + X509_NAME *issuer=NULL; + X509_NAME *subject=NULL; + + ASN1_STRING *serial=NULL; + ASN1_STRING *san_name=NULL; + + GENERAL_NAME *generalName=NULL; + GENERAL_NAMES *subjectAltNames=NULL; + + ASN1_TIME *start=NULL; + ASN1_TIME *end=NULL; + + EVP_PKEY *pkey=NULL; + const ASN1_OBJECT *salg; + const X509_ALGOR *tsig_alg; + + X509 *x509_handle=d2i_X509(NULL, (unsigned char const **)&pdata, pdata_sz); + if(x509_handle==NULL) + { + return SSL_DECODER_FALSE; + } + + /*version*/ + certificate->version=X509_get_version(x509_handle); + if(certificate->version>SSL_CERTIFICATE_VERSION_MAX) + { + X509_free(x509_handle); + return SSL_DECODER_FALSE; + } + + /*serial num*/ + serial=X509_get_serialNumber(x509_handle); + if(NULL != serial) + { + certificate->serial.len=MIN(ASN1_STRING_length(serial), (int)(sizeof(certificate->serial.value)-1)); + memcpy(certificate->serial.value, ASN1_STRING_get0_data(serial), certificate->serial.len); + } + + /*SSL AgID*/ + tsig_alg=X509_get0_tbs_sigalg(x509_handle); + X509_ALGOR_get0(&salg, NULL, NULL, tsig_alg); + OBJ_obj2txt((char*)certificate->signature_algorithm.value, sizeof(certificate->signature_algorithm.value), salg, 1); + certificate->signature_algorithm.len=strlen((const char *)certificate->signature_algorithm.value); + + /*SSL Issuer*/ + issuer=X509_get_issuer_name(x509_handle); + if(NULL!=issuer) + { + X509_NAME_get_text_by_NID(issuer, NID_commonName, certificate->issuer.common, sizeof(certificate->issuer.common)); + X509_NAME_get_text_by_NID(issuer, NID_organizationName, certificate->issuer.organization, sizeof(certificate->issuer.organization)); + X509_NAME_get_text_by_NID(issuer, NID_organizationalUnitName, certificate->issuer.organizational_unit, sizeof(certificate->issuer.organizational_unit)); + X509_NAME_get_text_by_NID(issuer, NID_localityName, certificate->issuer.locality, sizeof(certificate->issuer.locality)); + X509_NAME_get_text_by_NID(issuer, NID_streetAddress, certificate->issuer.street_address, sizeof(certificate->issuer.street_address)); + X509_NAME_get_text_by_NID(issuer, NID_stateOrProvinceName, certificate->issuer.state_or_Province, sizeof(certificate->issuer.state_or_Province)); + X509_NAME_get_text_by_NID(issuer, NID_countryName, certificate->issuer.country, sizeof(certificate->issuer.country)); + + snprintf(certificate->issuer.rdn_sequence_list, + sizeof(certificate->issuer.rdn_sequence_list), + "%s;%s;%s;%s;%s;%s;%s", + certificate->issuer.common, + certificate->issuer.organization, + certificate->issuer.organizational_unit, + certificate->issuer.locality, + certificate->issuer.street_address, + certificate->issuer.state_or_Province, + certificate->issuer.country); + } + + /*SSL Subject*/ + subject=X509_get_subject_name(x509_handle); + if(NULL!=subject) + { + X509_NAME_get_text_by_NID(subject, NID_commonName, certificate->subject.common, sizeof(certificate->subject.common)); + X509_NAME_get_text_by_NID(subject, NID_organizationName, certificate->subject.organization, sizeof(certificate->subject.organization)); + X509_NAME_get_text_by_NID(subject, NID_countryName, certificate->subject.country, sizeof(certificate->subject.country)); + X509_NAME_get_text_by_NID(subject, NID_organizationalUnitName, certificate->subject.organizational_unit, sizeof(certificate->subject.organizational_unit)); + X509_NAME_get_text_by_NID(subject, NID_localityName, certificate->subject.locality, sizeof(certificate->subject.locality)); + X509_NAME_get_text_by_NID(subject, NID_streetAddress, certificate->subject.street_address, sizeof(certificate->subject.street_address)); + X509_NAME_get_text_by_NID(subject, NID_stateOrProvinceName, certificate->subject.state_or_Province, sizeof(certificate->subject.state_or_Province)); + + snprintf(certificate->subject.rdn_sequence_list, + sizeof(certificate->subject.rdn_sequence_list), + "%s;%s;%s;%s;%s;%s;%s", + certificate->subject.common, + certificate->subject.organization, + certificate->subject.organizational_unit, + certificate->subject.locality, + certificate->subject.street_address, + certificate->subject.state_or_Province, + certificate->subject.country); + } + + /*SSL Subject keyInfo*/ + pkey=X509_get_pubkey(x509_handle); + if(pkey!=NULL) + { + //https://www.openssl.org/docs/man3.0/man3/i2d_PublicKey.html + certificate->subject_key.len=i2d_PublicKey(pkey, NULL); + if(certificate->subject_key.len>0) + { + certificate->subject_key.value=(char *)malloc(certificate->subject_key.len); + int32_t ret=i2d_PublicKey(pkey, (unsigned char **)&(certificate->subject_key.value)); //!!! point32_t will be changed + if(ret>0) + { + certificate->subject_key.value=certificate->subject_key.value-certificate->subject_key.len; + } + else + { + free(certificate->subject_key.value); + certificate->subject_key.value=NULL; + certificate->subject_key.len=0; + } + } + EVP_PKEY_free(pkey); + } + + /*validity*/ + start=X509_get_notBefore(x509_handle); + end=X509_get_notAfter(x509_handle); + sprintf(certificate->validity.before, "%s", start->data); + sprintf(certificate->validity.after, "%s", end->data); + + /*subject bak*/ + subjectAltNames=(GENERAL_NAMES*)X509_get_ext_d2i(x509_handle, NID_subject_alt_name, NULL, NULL); + if(!subjectAltNames) + { + X509_free(x509_handle); + return SSL_DECODER_TRUE; + } + + int32_t san_count=sk_GENERAL_NAME_num(subjectAltNames); + if(san_count>0) + { + certificate->subject_alter.num=0; + certificate->subject_alter.name=(char (*)[MAX_ALTER_NAME_LEN])malloc(san_count * sizeof(char[MAX_ALTER_NAME_LEN])); + + for (int32_t i=0; i<san_count; i++) + { + generalName=sk_GENERAL_NAME_value(subjectAltNames, i); + if(!generalName) + { + break; + } + + if(GEN_DNS == generalName->type) + { + san_name=(ASN1_STRING*)GENERAL_NAME_get0_value(generalName, NULL); + if(ASN1_STRING_length(san_name)>0) + { + char *san=(char*)ASN1_STRING_get0_data(san_name); + int32_t length=MIN(strlen(san), sizeof(certificate->subject_alter.name[certificate->subject_alter.num])-1); + memcpy(certificate->subject_alter.name[certificate->subject_alter.num], san, length); + certificate->subject_alter.name[certificate->subject_alter.num][length]='\0'; + certificate->subject_alter.num++; + } + } + } + } + + if(subjectAltNames) + { + GENERAL_NAMES_free(subjectAltNames); + } + + //https://www.openssl.org/docs/man1.1.1/man3/X509_ALGOR_get0.html + X509_ALGOR_get0(&salg, NULL, NULL, X509_get0_tbs_sigalg(x509_handle)); + OBJ_obj2txt(certificate->algorithm_identifier.value, sizeof(certificate->algorithm_identifier.value), salg, 1); + certificate->algorithm_identifier.len=strlen((const char *)certificate->algorithm_identifier.value); + + return SSL_DECODER_TRUE; +} + int32_t ssl_decoder_random_bytes_get(struct ssl_decoder_ltv *ltv, uint16_t type, uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset) { if(pdata_sz<(*pdata_offset)+SSL_RANDOM_SIZE) @@ -402,18 +590,12 @@ int32_t ssl_server_name_decode(struct ssl_decoder_ltv *sni, uint8_t *pdata, uint struct ssl_server_hello *ssl_handshake_server_hello_decode(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset) { - int32_t total_len; //3 - int32_t ret=ssl_read_be_u24(pdata, pdata_sz, pdata_offset, (uint8_t *)&(total_len)); - if(total_len<0) /*CLIENT_HELLO_HDRLEN: 4 means client_type+len*/ - { - return NULL; - } - + int32_t ret=SSL_DECODER_FALSE; struct ssl_server_hello *shello=(struct ssl_server_hello *)CALLOC(struct ssl_server_hello, 1); ssl_read_be_u16(pdata, pdata_sz, pdata_offset, &(shello->version)); ssl_read_be_u32(pdata, pdata_sz, pdata_offset, &(shello->random_gmt_time)); - for(int i=1; i<SSL_HELLO_LTV_MAX; i++) + for(int32_t i=1; i<SSL_HELLO_LTV_MAX; i++) { struct ssl_decoder_ltv *ltv=&(shello->ltv[i]); switch(i) @@ -481,18 +663,12 @@ struct ssl_server_hello *ssl_handshake_server_hello_decode(uint8_t *pdata, size_ struct ssl_client_hello *ssl_handshake_client_hello_decode(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset) { - int32_t total_len; //3 - int32_t ret=ssl_read_be_u24(pdata, pdata_sz, pdata_offset, (uint8_t *)&(total_len)); - if(total_len<0) /*CLIENT_HELLO_HDRLEN: 4 means client_type+len*/ - { - return NULL; - } - + int32_t ret=SSL_DECODER_FALSE; struct ssl_client_hello *chello=(struct ssl_client_hello *)CALLOC(struct ssl_client_hello, 1); ssl_read_be_u16(pdata, pdata_sz, pdata_offset, &(chello->version)); ssl_read_be_u32(pdata, pdata_sz, pdata_offset, &(chello->random_gmt_time)); - for(int i=1; i<SSL_HELLO_LTV_MAX; i++) + for(int32_t i=1; i<SSL_HELLO_LTV_MAX; i++) { struct ssl_decoder_ltv *ltv=&(chello->ltv[i]); switch(i) @@ -724,29 +900,134 @@ int32_t ssl_client_hello_ja3_generate(struct ssl_client_hello *chello) return SSL_DECODER_TRUE; } -void ssl_handshake_decode(struct ssl_decoder_plugin_env *plugin_env, struct session *ss, uint8_t *segment_buff, size_t segment_buff_sz, size_t *segment_buff_offset) +void ssl_message_publish(struct ssl_decoder_plugin_env *plugin_env, struct session *ss, enum ssl_message_type type, void *data) +{ + struct ssl_message *message=(struct ssl_message *)malloc(sizeof(struct ssl_message)); + message->magic=SSL_MESSAGE_MAGIC; + message->type=type; + message->ss=ss; + message->plugin_env=plugin_env; + message->data=data; + + session_mq_publish_message(ss, plugin_env->ssl.topic_id, (void *)message); +} + + +void ssl_message_free(struct session *sess, void *msg, void *msg_free_arg) { - if(segment_buff==NULL || ((*segment_buff_offset)+1>segment_buff_sz)) + struct ssl_message *message=(struct ssl_message *)msg; + if(message==NULL || message->magic!=SSL_MESSAGE_MAGIC) + { + return ; + } + + if(message->data!=NULL) + { + switch(message->type) + { + case SSL_MESSAGE_CLIENT_HELLO: + { + struct ssl_client_hello *chello=(struct ssl_client_hello *)message->data; + if(chello->extensions!=NULL) + { + utarray_free(chello->extensions); + } + } + break; + case SSL_MESSAGE_SERVER_HELLO: + { + struct ssl_server_hello *shello=(struct ssl_server_hello *)message->data; + if(shello->extensions!=NULL) + { + utarray_free(shello->extensions); + } + } + break; + case SSL_MESSAGE_CERTIFICATE: + { + struct ssl_certificate *certificate=(struct ssl_certificate *)message->data; + if(certificate->subject_alter.name!=NULL) + { + FREE(certificate->subject_alter.name); + } + + if(certificate->subject_key.value!=NULL) + { + FREE(certificate->subject_key.value); + } + } + break; + default: + break; + } + + FREE(message->data); + } + + FREE(message); +} + + +void ssl_handshake_decode(struct ssl_decoder_plugin_env *plugin_env, struct session *ss, uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset) +{ + if(pdata==NULL || ((*pdata_offset)+1>pdata_sz)) + { + return ; + } + + struct ssl_handshake_type *handshake_type=(struct ssl_handshake_type *)(pdata+(*pdata_offset)); + (*pdata_offset)+=sizeof(struct ssl_handshake_type); + + int32_t total_len=0; + int32_t ret=ssl_read_be_u24(pdata, pdata_sz, pdata_offset, (uint8_t *)&total_len); + if(ret==SSL_DECODER_FALSE || total_len<0 || total_len+(*pdata_offset)>pdata_sz) { return ; } - struct ssl_client_hello *chello=NULL; - struct ssl_server_hello *shello=NULL; - struct ssl_handshake_type *handshake_type=(struct ssl_handshake_type *)(segment_buff+(*segment_buff_offset)); - (*segment_buff_offset)+=sizeof(struct ssl_handshake_type); switch(handshake_type->content_type) { case SSL_HANDSHAKE_CLIENT_HELLO: - chello=ssl_handshake_client_hello_decode(segment_buff, segment_buff_sz, segment_buff_offset); - ssl_client_hello_ja3_generate(chello); + { + struct ssl_client_hello *chello=ssl_handshake_client_hello_decode(pdata, pdata_sz, pdata_offset); + ssl_client_hello_ja3_generate(chello); + ssl_message_publish(plugin_env, ss, SSL_MESSAGE_CLIENT_HELLO, (void *)chello); + } break; case SSL_HANDSHAKE_SERVER_HELLO: - shello=ssl_handshake_server_hello_decode(segment_buff, segment_buff_sz, segment_buff_offset); - ssl_server_hello_ja3s_generate(shello); + { + struct ssl_server_hello *shello=ssl_handshake_server_hello_decode(pdata, pdata_sz, pdata_offset); + ssl_server_hello_ja3s_generate(shello); + ssl_message_publish(plugin_env, ss, SSL_MESSAGE_SERVER_HELLO, (void *)shello); + } break; case SSL_HANDSHAKE_CERTIFICATE: - // ssl_handshake_certificate_decode(); + { + int32_t cert_total_len=0; + ret=ssl_read_be_u24(pdata, pdata_sz, pdata_offset, (uint8_t *)&cert_total_len); + if(ret==SSL_DECODER_FALSE || cert_total_len<0 || cert_total_len+(*pdata_offset)>pdata_sz || (cert_total_len+3)!=total_len) + { + return ; + } + + struct ssl_certificate_chain cert_unit[SSL_CERTIFICATE_NUM_MAX]; + uint32_t cert_count=ssl_handshake_certificate_count_get(pdata, pdata_sz, pdata_offset, cert_unit, SSL_CERTIFICATE_NUM_MAX); + + for(uint32_t i=0, cert_offset=0; i<cert_count; i++, cert_offset++) + { + struct ssl_certificate *certificate=(struct ssl_certificate *)CALLOC(struct ssl_certificate, 1); + + certificate->type=ssl_handshake_certificate_type_get(cert_count, cert_offset); + int32_t state=ssl_x509_certificate_detail_decode(certificate, cert_unit[i].data, cert_unit[i].data_sz); + if(state==SSL_DECODER_FALSE) + { + FREE(certificate); + return ; + } + + ssl_message_publish(plugin_env, ss, SSL_MESSAGE_CERTIFICATE, (void *)certificate); + } + } break; case SSL_HANDSHAKE_SERVER_KEY_EXCHANGE: // ssl_handshake_server_key_exchange_decode(); @@ -773,11 +1054,11 @@ int32_t ssl_record_header_get(struct ssl_record_header *record_hdr, uint8_t *pda void ssl_tcp_stream_session_segment_data_cb(struct session *ss, int32_t topic_id, const void *msg, void *per_session_ctx, void *penv) { - size_t segment_buff_offset=0; - size_t segment_buff_sz=0; - uint8_t *segment_buff=NULL; - segment_buff=(uint8_t *)session_get0_current_payload(ss, &segment_buff_sz); - if(segment_buff_sz==0 || segment_buff==NULL) + size_t pdata_offset=0; + size_t pdata_sz=0; + uint8_t *pdata=NULL; + pdata=(uint8_t *)session_get0_current_payload(ss, &pdata_sz); + if(pdata_sz==0 || pdata==NULL) { return ; } @@ -790,17 +1071,17 @@ void ssl_tcp_stream_session_segment_data_cb(struct session *ss, int32_t topic_id struct ssl_decoder_context *per_ss_ctx=(struct ssl_decoder_context *)(per_session_ctx); - ssl_recod_buff_get0(&(per_ss_ctx->record_trunk), &segment_buff, &segment_buff_sz); - if(segment_buff_sz<=SSL_RECORD_HEADER_SZ) + ssl_recod_buff_get0(&(per_ss_ctx->record_trunk), &pdata, &pdata_sz); + if(pdata_sz<=SSL_RECORD_HEADER_SZ) { return ; } struct ssl_record_header record_hdr={0}; - ssl_record_header_get(&record_hdr, segment_buff, segment_buff_sz, &segment_buff_offset); - if(!is_trunk_cache(&(per_ss_ctx->record_trunk)) && segment_buff_sz<record_hdr.total_len) + ssl_record_header_get(&record_hdr, pdata, pdata_sz, &pdata_offset); + if(!is_trunk_cache(&(per_ss_ctx->record_trunk)) && pdata_sz<record_hdr.total_len) { - ssl_trunk_cache(&(per_ss_ctx->record_trunk), segment_buff, segment_buff_sz); + ssl_trunk_cache(&(per_ss_ctx->record_trunk), pdata, pdata_sz); return ; } @@ -809,7 +1090,7 @@ void ssl_tcp_stream_session_segment_data_cb(struct session *ss, int32_t topic_id switch(record_hdr.content_type) { case SSL_CONTENT_TYPE_HANDSHAKE: - ssl_handshake_decode(plugin_env, ss, segment_buff, segment_buff_sz, &segment_buff_offset); + ssl_handshake_decode(plugin_env, ss, pdata, pdata_sz, &pdata_offset); break; case SSL_CONTENT_TYPE_ALERT: break; @@ -827,11 +1108,6 @@ void ssl_tcp_stream_session_segment_data_cb(struct session *ss, int32_t topic_id } } -void ssl_message_free(struct session *sess, void *msg, void *msg_free_arg) -{ - -} - void *ssl_decoder_per_session_context_new(struct session *ss, void *penv) { uint64_t inner_flag=0; @@ -858,7 +1134,7 @@ void ssl_decoder_per_session_context_free(struct session *ss, void *per_session_ int32_t ssl_decoder_config_load(const char *cfg_path, struct ssl_decoder_plugin_env *plugin_env) { FILE *fp=fopen(cfg_path, "r"); - if (NULL==fp) + if(NULL==fp) { fprintf(stderr, "[%s:%d] Can't open config file: %s", __FUNCTION__, __LINE__, cfg_path); return -1; diff --git a/src/ssl_export.cpp b/src/ssl_export.cpp new file mode 100644 index 0000000..a87bf2e --- /dev/null +++ b/src/ssl_export.cpp @@ -0,0 +1,255 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ssl_internal.h" +#include "ssl_decoder.h" + +enum ssl_message_type ssl_message_type_get(const struct ssl_message *msg) +{ + return ((msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC) ? SSL_MSG_MAX : msg->type); +} + +// SSL_MESSAGE_CLIENT_HELLO +int32_t ssl_message_esni_is_true(const struct ssl_message *msg) +{ + if(msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_CLIENT_HELLO) + { + return -1; + } + + return ((msg->chello->esni==NULL) ? 1 : 0); +} + +int32_t ssl_message_ech_is_true(const struct ssl_message *msg) +{ + if(msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_CLIENT_HELLO) + { + return -1; + } + + return ((msg->chello->ech==NULL) ? 1 : 0); +} + +void ssl_message_sni_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + if(msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_CLIENT_HELLO) + { + return; + } + + if(msg->chello->sni==NULL) + { + return; + } + + *value=(char *)msg->chello->sni->value; + *value_sz=msg->chello->sni->lv_u32; +} + +const char *ssl_message_readable_version_get0(const struct ssl_message *msg) +{ + if(msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC) + { + return NULL; + } + + uint16_t version=0; + switch(msg->type) + { + case SSL_MESSAGE_CLIENT_HELLO: + if(msg->chello==NULL) + { + return NULL; + } + version=msg->chello->version; + break; + case SSL_MESSAGE_SERVER_HELLO: + if(msg->shello==NULL) + { + return NULL; + } + version=msg->shello->version; + break; + default: + return NULL; + } + + switch(version) + { + case SSL_DECODER_VERSION_SSL_V2_0: + return "SSLv2.0"; + case SSL_DECODER_VERSION_SSL_V3_0: + return "SSLv3.0"; + case SSL_DECODER_VERSION_TLS_V1_0: + return "TLSv1.0"; + case SSL_DECODER_VERSION_TLS_V1_1: + return "TLSv1.1"; + case SSL_DECODER_VERSION_TLS_V1_2: + return "TLSv1.2"; + case SSL_DECODER_VERSION_TLS_V1_3: + return "TLSv1.3"; + case SSL_DECODER_VERSION_TLCP_V1_0: + return "TLCPv1.0"; + default: + break; + } + + return NULL; +} + +void ssl_message_ja3hash_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + if(msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_CLIENT_HELLO) + { + *value=NULL; + *value_sz=0; + return ; + } + + if(msg->chello->ja3.value==NULL || msg->chello->ja3.lv_u32==0) + { + *value=NULL; + *value_sz=0; + return ; + } + + *value=(char *)msg->chello->ja3.value; + *value_sz=msg->chello->ja3.lv_u32; +} + +// SSL_MESSAGE_SERVER_HELLO +void ssl_message_ja3shash_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + if(msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_SERVER_HELLO) + { + *value=NULL; + *value_sz=0; + return; + } + + if(msg->shello->ja3s.value==NULL || msg->shello->ja3s.lv_u32==0) + { + *value=NULL; + *value_sz=0; + return; + } + + *value=(char *)msg->shello->ja3s.value; + *value_sz=msg->shello->ja3s.lv_u32; +} + +void ssl_message_extensions_next(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +int ssl_message_reset_extensions_iter(struct ssl_message *msg) +{ + return 0; +} + +enum ssl_certificate_type ssl_certificate_type_get(const struct ssl_message *msg) +{ + return ((msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_CERTIFICATE) ? msg->certificate->type : SSL_CERTIFICATE_TYPE_UNKNOWN); +} + +void ssl_message_validity_before_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +void ssl_message_validity_after_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +void ssl_message_issuer_serial_number_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +void ssl_message_subject_public_key_algorithm_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +void ssl_message_ssl_algorithm_identifier_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +void ssl_message_ssl_signature_algorithm_id_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +void ssl_message_subject_alter_next(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +} + +int ssl_message_reset_subject_alter_iter(struct ssl_message *msg) +{ + return 0; +} + +struct ssl_rdn_sequence *ssl_message_issuer_rdn_sequence_get0(const struct ssl_message *msg) +{ + return ((msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_CERTIFICATE) ? &(msg->certificate->issuer) : NULL); +} + +struct ssl_rdn_sequence *ssl_message_subject_rdn_sequence_get0(const struct ssl_message *msg) +{ + return ((msg==NULL || msg->magic!=SSL_MESSAGE_MAGIC || msg->type!=SSL_MESSAGE_CERTIFICATE) ? &(msg->certificate->subject) : NULL); +} + +void ssl_rdn_sequence_common_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_country_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_locality_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_postal_code_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_organization_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_street_address_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_state_or_province_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_organizational_unit_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_rdn_sequence_list_get0(struct ssl_rdn_sequence *rdn, char **value, size_t *value_sz) +{ + +} + +void ssl_message_protected_payload_get0(const struct ssl_message *msg, char **value, size_t *value_sz) +{ + +}
\ No newline at end of file diff --git a/src/ssl_internal.h b/src/ssl_internal.h index 9e7dad1..2891b68 100644 --- a/src/ssl_internal.h +++ b/src/ssl_internal.h @@ -4,6 +4,44 @@ #include <stddef.h> #include <uthash/utarray.h> +#include "ssl_decoder.h" + +#define SSL_DECODER_TOML_PATH "conf/ssl/ssl_decoder.toml" + +#define SSL_DECODER_FALSE 0 +#define SSL_DECODER_TRUE 1 + +#define SSL_UUID_BYTES_SZ 16 + +#define SSL_RANDOM_TIME_LEN 4 +#define SSL_RANDOM_SIZE 28 + +#define SSL_HANDSHAKE_CLIENT_HELLO 1 +#define SSL_HANDSHAKE_SERVER_HELLO 2 +#define SSL_HANDSHAKE_CERTIFICATE 11 +#define SSL_HANDSHAKE_SERVER_KEY_EXCHANGE 12 + +#define SSL_CONTENT_TYPE_HANDSHAKE 0x16 +#define SSL_CONTENT_TYPE_ALERT 0x15 +#define SSL_CONTENT_TYPE_APPLICATION_DATA 0x17 +#define SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC 0x14 + +#define ALPN_EXT_TYPE 0x0010 +#define SERVER_NAME_EXT_TYPE 0x0000 +#define SERVER_NAME_HOST_TYPE 0x0000 +#define SERVER_NAME_OTHER_TYPE 0x0008 +#define SESSION_TICKET_EXT_TYPE 0x0023 +#define ENCRPTED_SERVER_NAME_EXT_TYPE 0xFFCE +#define ENCRPTED_CLIENT_HELLO_EXT_TYPE 0xFE0D +#define EC_POINT_FORMATS_EXT_TYPE 0x000B + +// https://datatracker.ietf.org/doc/html/rfc7919 +// Supported Groups +#define SUPPORTED_GROUPS_EXT_TYPE 0x000A + + +#define SSL_CERTIFICATE_NUM_MAX 8 +#define SSL_CERTIFICATE_VERSION_MAX 3 #define SSL_DECODER_VERSION_UNKNOWN 0x0000 #define SSL_DECODER_VERSION_SSL_V2_0 0x0002 @@ -132,11 +170,8 @@ struct ssl_algorithm_identifier struct ssl_certificate { - int total_len; - int cert_len; - char cert_type; - - //struct ssl_l1v version; + uint16_t version; + enum ssl_certificate_type type; struct ssl_validity validity; struct ssl_serial_number serial; struct ssl_rdn_sequence issuer; @@ -147,3 +182,23 @@ struct ssl_certificate struct ssl_algorithm_identifier algorithm_identifier; struct ssl_signature_algorithm_id signature_algorithm; }; + + +#define SSL_MESSAGE_MAGIC 0xEF53534C + +struct ssl_message +{ + uint32_t magic; + enum ssl_message_type type; + char uuid_bytes[SSL_UUID_BYTES_SZ]; + struct session *ss; + struct ssl_decoder_plugin_env *plugin_env; + union + { + struct ssl_client_hello *chello; + struct ssl_server_hello *shello; + struct ssl_certificate *certificate; + void *data; + }; + +}; diff --git a/src/version.map b/src/version.map index 9df1ad1..ed97cda 100644 --- a/src/version.map +++ b/src/version.map @@ -4,19 +4,15 @@ global: *ssl_decoder_init*; *ssl_decoder_exit*; *ssl_message_type_get*; - *ssl_message_header_id_get*; - *ssl_message_header_flag_get0*; - *ssl_message_query_question_get0*; - *ssl_query_question_qname_get0*; - *ssl_query_question_qtype_get0*; - *ssl_query_question_qclass_get0*; - *ssl_message_answer_resource_record_get0*; - *ssl_message_authority_resource_record_get0*; - *ssl_message_additional_resource_record_get0*; - *ssl_message_resource_record_json_exporter*; *ssl_message_uuid_get0*; - *ssl_message_resource_record_is_sslsec*; - *ssl_message_resource_record_cname_json_exporter*; + *ssl_message_esni_is_true*; + *ssl_message_ech_is_true*; + *ssl_message_sni_get0*; + *ssl_message_ja3hash_get0*; + *ssl_message_readable_version_get0*; + *ssl_message_ja3shash_get0*; + *ssl_message_extensions_next*; + *ssl_message_reset_extensions_iter*; *GIT*; }; local: *; |
